forked from OpenGamers/abaddon
make voice disconnect/reconnect work
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user