make voice disconnect/reconnect work

This commit is contained in:
ouwou
2022-09-06 03:29:13 -04:00
parent 654e225093
commit 90437de2c0
10 changed files with 93 additions and 16 deletions

View File

@@ -252,6 +252,7 @@ int Abaddon::StartGTK() {
#ifdef WITH_VOICE
m_main_window->GetChannelList()->signal_action_join_voice_channel().connect(sigc::mem_fun(*this, &Abaddon::ActionJoinVoiceChannel));
m_main_window->GetChannelList()->signal_action_disconnect_voice().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnectVoice));
#endif
m_main_window->GetChatWindow()->signal_action_message_edit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatEditMessage));
@@ -917,6 +918,10 @@ void Abaddon::ActionViewThreads(Snowflake channel_id) {
void Abaddon::ActionJoinVoiceChannel(Snowflake channel_id) {
m_discord.ConnectToVoice(channel_id);
}
void Abaddon::ActionDisconnectVoice() {
m_discord.DisconnectFromVoice();
}
#endif
std::optional<Glib::ustring> Abaddon::ShowTextPrompt(const Glib::ustring &prompt, const Glib::ustring &title, const Glib::ustring &placeholder, Gtk::Window *window) {

View File

@@ -56,6 +56,7 @@ public:
#ifdef WITH_VOICE
void ActionJoinVoiceChannel(Snowflake channel_id);
void ActionDisconnectVoice();
#endif
std::optional<Glib::ustring> ShowTextPrompt(const Glib::ustring &prompt, const Glib::ustring &title, const Glib::ustring &placeholder = "", Gtk::Window *window = nullptr);

View File

@@ -20,6 +20,10 @@ ChannelList::ChannelList()
#ifdef WITH_LIBHANDY
, m_menu_channel_open_tab("Open in New _Tab", true)
, m_menu_dm_open_tab("Open in New _Tab", true)
#endif
#ifdef WITH_VOICE
, m_menu_voice_channel_join("_Join", true)
, m_menu_voice_channel_disconnect("_Disconnect", true)
#endif
, m_menu_dm_copy_id("_Copy ID", true)
, m_menu_dm_close("") // changes depending on if group or not
@@ -168,11 +172,15 @@ ChannelList::ChannelList()
#ifdef WITH_VOICE
m_menu_voice_channel_join.signal_activate().connect([this]() {
const auto id = static_cast<Snowflake>((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]);
printf("join voice: %llu\n", static_cast<uint64_t>(id));
m_signal_action_join_voice_channel.emit(id);
});
m_menu_voice_channel_disconnect.signal_activate().connect([this]() {
m_signal_action_disconnect_voice.emit();
});
m_menu_voice_channel.append(m_menu_voice_channel_join);
m_menu_voice_channel.append(m_menu_voice_channel_disconnect);
m_menu_voice_channel.show_all();
#endif
@@ -984,6 +992,17 @@ void ChannelList::OnChannelSubmenuPopup() {
#ifdef WITH_VOICE
void ChannelList::OnVoiceChannelSubmenuPopup() {
const auto iter = m_model->get_iter(m_path_for_menu);
if (!iter) return;
const auto id = static_cast<Snowflake>((*iter)[m_columns.m_id]);
auto &discord = Abaddon::Get().GetDiscordClient();
if (discord.IsConnectedToVoice()) {
m_menu_voice_channel_join.set_sensitive(false);
m_menu_voice_channel_disconnect.set_sensitive(discord.GetVoiceChannelID() == id);
} else {
m_menu_voice_channel_join.set_sensitive(true);
m_menu_voice_channel_disconnect.set_sensitive(false);
}
}
#endif
@@ -1041,6 +1060,10 @@ ChannelList::type_signal_action_open_new_tab ChannelList::signal_action_open_new
ChannelList::type_signal_action_join_voice_channel ChannelList::signal_action_join_voice_channel() {
return m_signal_action_join_voice_channel;
}
ChannelList::type_signal_action_disconnect_voice ChannelList::signal_action_disconnect_voice() {
return m_signal_action_disconnect_voice;
}
#endif
ChannelList::ModelColumns::ModelColumns() {

View File

@@ -128,6 +128,7 @@ protected:
#ifdef WITH_VOICE
Gtk::Menu m_menu_voice_channel;
Gtk::MenuItem m_menu_voice_channel_join;
Gtk::MenuItem m_menu_voice_channel_disconnect;
#endif
Gtk::Menu m_menu_dm;
@@ -177,7 +178,10 @@ public:
#ifdef WITH_VOICE
using type_signal_action_join_voice_channel = sigc::signal<void, Snowflake>;
using type_signal_action_disconnect_voice = sigc::signal<void>;
type_signal_action_join_voice_channel signal_action_join_voice_channel();
type_signal_action_disconnect_voice signal_action_disconnect_voice();
#endif
type_signal_action_channel_item_select signal_action_channel_item_select();
@@ -195,5 +199,6 @@ private:
#ifdef WITH_VOICE
type_signal_action_join_voice_channel m_signal_action_join_voice_channel;
type_signal_action_disconnect_voice m_signal_action_disconnect_voice;
#endif
};

View File

@@ -1173,12 +1173,27 @@ void DiscordClient::AcceptVerificationGate(Snowflake guild_id, VerificationGateI
void DiscordClient::ConnectToVoice(Snowflake channel_id) {
auto channel = GetChannel(channel_id);
if (!channel.has_value() || !channel->GuildID.has_value()) return;
m_voice_channel_id = channel_id;
VoiceStateUpdateMessage m;
m.GuildID = *channel->GuildID;
m.ChannelID = channel_id;
m.PreferredRegion = "newark";
m_websocket.Send(m);
}
void DiscordClient::DisconnectFromVoice() {
m_voice.Stop();
VoiceStateUpdateMessage m;
m_websocket.Send(m);
}
bool DiscordClient::IsConnectedToVoice() const noexcept {
return m_voice.IsConnected();
}
Snowflake DiscordClient::GetVoiceChannelID() const noexcept {
return m_voice_channel_id;
}
#endif
void DiscordClient::SetReferringChannel(Snowflake id) {

View File

@@ -183,6 +183,9 @@ public:
#ifdef WITH_VOICE
void ConnectToVoice(Snowflake channel_id);
void DisconnectFromVoice();
[[nodiscard]] bool IsConnectedToVoice() const noexcept;
[[nodiscard]] Snowflake GetVoiceChannelID() const noexcept;
#endif
void SetReferringChannel(Snowflake id);
@@ -334,6 +337,8 @@ private:
#ifdef WITH_VOICE
DiscordVoiceClient m_voice;
Snowflake m_voice_channel_id;
#endif
mutable std::mutex m_msg_mutex;

View File

@@ -644,8 +644,14 @@ void from_json(const nlohmann::json &j, GuildMembersChunkData &m) {
#ifdef WITH_VOICE
void to_json(nlohmann::json &j, const VoiceStateUpdateMessage &m) {
j["op"] = GatewayOp::VoiceStateUpdate;
j["d"]["guild_id"] = m.GuildID;
j["d"]["channel_id"] = m.ChannelID;
if (m.GuildID.has_value())
j["d"]["guild_id"] = *m.GuildID;
else
j["d"]["guild_id"] = nullptr;
if (m.ChannelID.has_value())
j["d"]["channel_id"] = *m.ChannelID;
else
j["d"]["channel_id"] = nullptr;
j["d"]["self_mute"] = m.SelfMute;
j["d"]["self_deaf"] = m.SelfDeaf;
j["d"]["self_video"] = m.SelfVideo;

View File

@@ -869,8 +869,8 @@ struct GuildMembersChunkData {
#ifdef WITH_VOICE
struct VoiceStateUpdateMessage {
Snowflake GuildID;
Snowflake ChannelID;
std::optional<Snowflake> GuildID;
std::optional<Snowflake> ChannelID;
bool SelfMute = false;
bool SelfDeaf = false;
bool SelfVideo = false;

View File

@@ -168,25 +168,34 @@ DiscordVoiceClient::DiscordVoiceClient() {
m_udp_dispatch_mutex.unlock();
OnUDPData(data);
});
Glib::signal_idle().connect_once([this]() {
// cant put in ctor or deadlock in singleton initialization
auto &aud = Abaddon::Get().GetAudio();
aud.SetOpusBuffer(m_opus_buffer.data());
aud.signal_opus_packet().connect([this](int payload_size) {
if (m_connected)
m_udp.SendEncrypted(m_opus_buffer.data(), payload_size);
});
});
}
DiscordVoiceClient::~DiscordVoiceClient() {
m_ws.Stop();
m_udp.Stop();
m_heartbeat_waiter.kill();
if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join();
Stop();
}
void DiscordVoiceClient::Start() {
m_ws.StartConnection("wss://" + m_endpoint + "/?v=7");
}
// cant put in ctor or deadlock in singleton initialization
auto &aud = Abaddon::Get().GetAudio();
aud.SetOpusBuffer(m_opus_buffer.data());
aud.signal_opus_packet().connect([this](int payload_size) {
if (m_connected)
m_udp.SendEncrypted(m_opus_buffer.data(), payload_size);
});
void DiscordVoiceClient::Stop() {
if (m_connected) {
m_ws.Stop();
m_udp.Stop();
m_heartbeat_waiter.kill();
if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join();
m_connected = false;
}
}
void DiscordVoiceClient::SetSessionID(std::string_view session_id) {
@@ -209,6 +218,10 @@ void DiscordVoiceClient::SetUserID(Snowflake id) {
m_user_id = id;
}
bool DiscordVoiceClient::IsConnected() const noexcept {
return m_connected;
}
void DiscordVoiceClient::OnGatewayMessage(const std::string &str) {
VoiceGatewayMessage msg = nlohmann::json::parse(str);
puts(msg.Data.dump(4).c_str());

View File

@@ -173,6 +173,7 @@ public:
~DiscordVoiceClient();
void Start();
void Stop();
void SetSessionID(std::string_view session_id);
void SetEndpoint(std::string_view endpoint);
@@ -180,6 +181,8 @@ public:
void SetServerID(Snowflake id);
void SetUserID(Snowflake id);
[[nodiscard]] bool IsConnected() const noexcept;
private:
void OnGatewayMessage(const std::string &str);
void HandleGatewayHello(const VoiceGatewayMessage &m);
@@ -198,6 +201,7 @@ private:
std::string m_endpoint;
std::string m_token;
Snowflake m_server_id;
Snowflake m_channel_id;
Snowflake m_user_id;
std::string m_ip;