From 98218dfde37ce595401a0c1446d9e40418cc15d6 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 12 Mar 2024 04:15:21 -0400 Subject: initial stages stuff --- .../channellist/cellrendererchannels.cpp | 12 +++-- .../channellist/cellrendererchannels.hpp | 4 +- src/components/channellist/channellisttree.cpp | 52 +++++++++++++++++++--- src/components/channellist/channellisttree.hpp | 5 +++ 4 files changed, 64 insertions(+), 9 deletions(-) (limited to 'src/components/channellist') diff --git a/src/components/channellist/cellrendererchannels.cpp b/src/components/channellist/cellrendererchannels.cpp index b049252..edbe5bb 100644 --- a/src/components/channellist/cellrendererchannels.cpp +++ b/src/components/channellist/cellrendererchannels.cpp @@ -122,6 +122,7 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m return get_preferred_width_vfunc_thread(widget, minimum_width, natural_width); #ifdef WITH_VOICE case RenderType::VoiceChannel: + case RenderType::VoiceStage: return get_preferred_width_vfunc_voice_channel(widget, minimum_width, natural_width); case RenderType::VoiceParticipant: return get_preferred_width_vfunc_voice_participant(widget, minimum_width, natural_width); @@ -147,6 +148,7 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid return get_preferred_width_for_height_vfunc_thread(widget, height, minimum_width, natural_width); #ifdef WITH_VOICE case RenderType::VoiceChannel: + case RenderType::VoiceStage: return get_preferred_width_for_height_vfunc_voice_channel(widget, height, minimum_width, natural_width); case RenderType::VoiceParticipant: return get_preferred_width_for_height_vfunc_voice_participant(widget, height, minimum_width, natural_width); @@ -172,6 +174,7 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int & return get_preferred_height_vfunc_thread(widget, minimum_height, natural_height); #ifdef WITH_VOICE case RenderType::VoiceChannel: + case RenderType::VoiceStage: return get_preferred_height_vfunc_voice_channel(widget, minimum_height, natural_height); case RenderType::VoiceParticipant: return get_preferred_height_vfunc_voice_participant(widget, minimum_height, natural_height); @@ -197,6 +200,7 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid return get_preferred_height_for_width_vfunc_thread(widget, width, minimum_height, natural_height); #ifdef WITH_VOICE case RenderType::VoiceChannel: + case RenderType::VoiceStage: return get_preferred_height_for_width_vfunc_voice_channel(widget, width, minimum_height, natural_height); case RenderType::VoiceParticipant: return get_preferred_height_for_width_vfunc_voice_participant(widget, width, minimum_height, natural_height); @@ -222,7 +226,9 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr &cr, return render_vfunc_thread(cr, widget, background_area, cell_area, flags); #ifdef WITH_VOICE case RenderType::VoiceChannel: - return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags); + return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags, "\U0001F50A"); + case RenderType::VoiceStage: + return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags, "\U0001F4E1"); case RenderType::VoiceParticipant: return render_vfunc_voice_participant(cr, widget, background_area, cell_area, flags); #endif @@ -581,7 +587,7 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc_voice_channel(Gt m_renderer_text.get_preferred_height_for_width(widget, width, minimum_height, natural_height); } -void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) { +void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags, const char *emoji) { // channel name text Gtk::Requisition minimum_size, natural_size; m_renderer_text.get_preferred_size(widget, minimum_size, natural_size); @@ -598,7 +604,7 @@ void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtrset_font_description(font); layout->set_alignment(Pango::ALIGN_LEFT); cr->set_source_rgba(1.0, 1.0, 1.0, 1.0); diff --git a/src/components/channellist/cellrendererchannels.hpp b/src/components/channellist/cellrendererchannels.hpp index e142b2a..a1c020b 100644 --- a/src/components/channellist/cellrendererchannels.hpp +++ b/src/components/channellist/cellrendererchannels.hpp @@ -19,6 +19,7 @@ enum class RenderType : uint8_t { // TODO: maybe enable anyways but without ability to join if no voice support #ifdef WITH_VOICE VoiceChannel, + VoiceStage, // identical to non-stage except for icon VoiceParticipant, #endif @@ -117,7 +118,8 @@ protected: Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, - Gtk::CellRendererState flags); + Gtk::CellRendererState flags, + const char *emoji); // voice participant void get_preferred_width_vfunc_voice_participant(Gtk::Widget &widget, int &minimum_width, int &natural_width) const; diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index 4816b42..8b313a3 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -29,6 +29,8 @@ ChannelListTree::ChannelListTree() #ifdef WITH_VOICE , m_menu_voice_channel_join("_Join", true) , m_menu_voice_channel_disconnect("_Disconnect", true) + , m_menu_voice_stage_join("_Join", true) + , m_menu_voice_stage_disconnect("_Disconnect", true) #endif , m_menu_dm_copy_id("_Copy ID", true) , m_menu_dm_close("") // changes depending on if group or not @@ -212,6 +214,19 @@ ChannelListTree::ChannelListTree() 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(); + + m_menu_voice_stage_join.signal_activate().connect([this]() { + const auto id = static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); + m_signal_action_join_voice_channel.emit(id); + }); + + m_menu_voice_stage_disconnect.signal_activate().connect([this]() { + m_signal_action_disconnect_voice.emit(); + }); + + m_menu_voice_stage.append(m_menu_voice_stage_join); + m_menu_voice_stage.append(m_menu_voice_stage_disconnect); + m_menu_voice_stage.show_all(); #endif m_menu_dm_copy_id.signal_activate().connect([this] { @@ -356,8 +371,8 @@ int ChannelListTree::SortFunc(const Gtk::TreeModel::iterator &a, const Gtk::Tree if (a_type == RenderType::DMHeader) return -1; if (b_type == RenderType::DMHeader) return 1; #ifdef WITH_VOICE - if (a_type == RenderType::TextChannel && b_type == RenderType::VoiceChannel) return -1; - if (b_type == RenderType::TextChannel && a_type == RenderType::VoiceChannel) return 1; + if (a_type == RenderType::TextChannel && (b_type == RenderType::VoiceChannel || b_type == RenderType::VoiceStage)) return -1; + if (b_type == RenderType::TextChannel && (a_type == RenderType::VoiceChannel || a_type == RenderType::VoiceStage)) return 1; #endif return static_cast(std::clamp(a_sort - b_sort, int64_t(-1), int64_t(1))); } @@ -624,6 +639,7 @@ void ChannelListTree::OnThreadListSync(const ThreadListSyncData &data) { #ifdef WITH_VOICE void ChannelListTree::OnVoiceUserConnect(Snowflake user_id, Snowflake channel_id) { auto parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::VoiceChannel); + if (!parent_iter) parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::VoiceStage); if (!parent_iter) parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::DM); if (!parent_iter) return; const auto user = Abaddon::Get().GetDiscordClient().GetUser(user_id); @@ -906,7 +922,7 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const const auto channel = discord.GetChannel(channel_.ID); if (!channel.has_value()) continue; #ifdef WITH_VOICE - if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE) { + if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE || channel->Type == ChannelType::GUILD_STAGE_VOICE) { #else if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS) { #endif @@ -953,10 +969,14 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); } #ifdef WITH_VOICE - else { + else if (channel.Type == ChannelType::GUILD_VOICE) { channel_row[m_columns.m_type] = RenderType::VoiceChannel; channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); add_voice_participants(channel, channel_row->children()); + } else if (channel.Type == ChannelType::GUILD_STAGE_VOICE) { + channel_row[m_columns.m_type] = RenderType::VoiceStage; + channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); + add_voice_participants(channel, channel_row->children()); } #endif channel_row[m_columns.m_id] = channel.ID; @@ -985,10 +1005,14 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); } #ifdef WITH_VOICE - else { + else if (channel.Type == ChannelType::GUILD_VOICE) { channel_row[m_columns.m_type] = RenderType::VoiceChannel; channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); add_voice_participants(channel, channel_row->children()); + } else if (channel.Type == ChannelType::GUILD_STAGE_VOICE) { + channel_row[m_columns.m_type] = RenderType::VoiceStage; + channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); + add_voice_participants(channel, channel_row->children()); } #endif channel_row[m_columns.m_id] = channel.ID; @@ -1333,6 +1357,10 @@ bool ChannelListTree::OnButtonPressEvent(GdkEventButton *ev) { OnVoiceChannelSubmenuPopup(); m_menu_voice_channel.popup_at_pointer(reinterpret_cast(ev)); break; + case RenderType::VoiceStage: + OnVoiceStageSubmenuPopup(); + m_menu_voice_stage.popup_at_pointer(reinterpret_cast(ev)); + break; #endif case RenderType::DM: { OnDMSubmenuPopup(); @@ -1440,6 +1468,20 @@ void ChannelListTree::OnVoiceChannelSubmenuPopup() { m_menu_voice_channel_disconnect.set_sensitive(false); } } + +void ChannelListTree::OnVoiceStageSubmenuPopup() { + const auto iter = m_model->get_iter(m_path_for_menu); + if (!iter) return; + const auto id = static_cast((*iter)[m_columns.m_id]); + auto &discord = Abaddon::Get().GetDiscordClient(); + if (discord.IsVoiceConnected() || discord.IsVoiceConnecting()) { + m_menu_voice_stage_join.set_sensitive(false); + m_menu_voice_stage_disconnect.set_sensitive(discord.GetVoiceChannelID() == id); + } else { + m_menu_voice_stage_join.set_sensitive(true); + m_menu_voice_stage_disconnect.set_sensitive(false); + } +} #endif void ChannelListTree::OnDMSubmenuPopup() { diff --git a/src/components/channellist/channellisttree.hpp b/src/components/channellist/channellisttree.hpp index 136522b..3841e3c 100644 --- a/src/components/channellist/channellisttree.hpp +++ b/src/components/channellist/channellisttree.hpp @@ -165,6 +165,10 @@ protected: Gtk::Menu m_menu_voice_channel; Gtk::MenuItem m_menu_voice_channel_join; Gtk::MenuItem m_menu_voice_channel_disconnect; + + Gtk::Menu m_menu_voice_stage; + Gtk::MenuItem m_menu_voice_stage_join; + Gtk::MenuItem m_menu_voice_stage_disconnect; #endif Gtk::Menu m_menu_dm; @@ -196,6 +200,7 @@ protected: #ifdef WITH_VOICE void OnVoiceChannelSubmenuPopup(); + void OnVoiceStageSubmenuPopup(); #endif bool m_updating_listing = false; -- cgit v1.2.3 From 533157ece22c020dbf09d991b23d1cf4e5281e7a Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 14 Mar 2024 01:08:13 -0400 Subject: preliminary speaker checks --- .../channellist/cellrendererchannels.hpp | 2 +- src/components/channellist/channellisttree.cpp | 2 +- src/discord/discord.cpp | 9 +++++-- src/discord/discord.hpp | 7 +++--- src/discord/objects.cpp | 1 + src/discord/objects.hpp | 1 + src/discord/voicestate.cpp | 5 ++++ src/discord/voicestate.hpp | 29 ++++++++++++++++++++++ src/discord/voicestateflags.hpp | 19 -------------- src/misc/bitwise.hpp | 7 ++++++ src/windows/voice/voicewindow.cpp | 18 ++++++++++---- src/windows/voice/voicewindow.hpp | 1 + 12 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 src/discord/voicestate.cpp create mode 100644 src/discord/voicestate.hpp delete mode 100644 src/discord/voicestateflags.hpp (limited to 'src/components/channellist') diff --git a/src/components/channellist/cellrendererchannels.hpp b/src/components/channellist/cellrendererchannels.hpp index a1c020b..813a996 100644 --- a/src/components/channellist/cellrendererchannels.hpp +++ b/src/components/channellist/cellrendererchannels.hpp @@ -6,7 +6,7 @@ #include #include #include "discord/snowflake.hpp" -#include "discord/voicestateflags.hpp" +#include "discord/voicestate.hpp" #include "misc/bitwise.hpp" enum class RenderType : uint8_t { diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index 8b313a3..9233941 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -1061,7 +1061,7 @@ Gtk::TreeModel::iterator ChannelListTree::CreateVoiceParticipantRow(const UserDa const auto voice_state = Abaddon::Get().GetDiscordClient().GetVoiceState(user.ID); if (voice_state.has_value()) { - row[m_columns.m_voice_flags] = voice_state->second; + row[m_columns.m_voice_flags] = voice_state->second.Flags; } auto &img = Abaddon::Get().GetImageManager(); diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index ab0374d..d997bc2 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1290,13 +1290,18 @@ std::optional DiscordClient::GetSSRCOfUser(Snowflake id) const { return m_voice.GetSSRCOfUser(id); } -std::optional> DiscordClient::GetVoiceState(Snowflake user_id) const { +std::optional> DiscordClient::GetVoiceState(Snowflake user_id) const { if (const auto it = m_voice_states.find(user_id); it != m_voice_states.end()) { return it->second; } return std::nullopt; } +bool DiscordClient::IsUserSpeaker(Snowflake user_id) const { + const auto state = GetVoiceState(user_id); + return state.has_value() && state->second.IsSpeaker(); +} + DiscordVoiceClient &DiscordClient::GetVoiceClient() { return m_voice; } @@ -2962,7 +2967,7 @@ void DiscordClient::SetVoiceState(Snowflake user_id, const VoiceState &state) { if (state.IsSelfVideo) flags |= VoiceStateFlags::SelfVideo; if (state.IsSuppressed) flags |= VoiceStateFlags::Suppressed; - m_voice_states[user_id] = std::make_pair(*state.ChannelID, flags); + m_voice_states[user_id] = std::make_pair(*state.ChannelID, PackedVoiceState { flags, state.RequestToSpeakTimestamp }); m_voice_state_channel_users[*state.ChannelID].insert(user_id); m_signal_voice_state_set.emit(user_id, *state.ChannelID, flags); diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index a74b5f6..155079f 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -5,7 +5,7 @@ #include "objects.hpp" #include "store.hpp" #include "voiceclient.hpp" -#include "voicestateflags.hpp" +#include "voicestate.hpp" #include "websocket.hpp" #include #include @@ -202,7 +202,8 @@ public: [[nodiscard]] Snowflake GetVoiceChannelID() const noexcept; [[nodiscard]] std::unordered_set GetUsersInVoiceChannel(Snowflake channel_id); [[nodiscard]] std::optional GetSSRCOfUser(Snowflake id) const; - [[nodiscard]] std::optional> GetVoiceState(Snowflake user_id) const; + [[nodiscard]] std::optional> GetVoiceState(Snowflake user_id) const; + [[nodiscard]] bool IsUserSpeaker(Snowflake user_id) const; DiscordVoiceClient &GetVoiceClient(); @@ -380,7 +381,7 @@ private: Snowflake m_voice_channel_id; // todo sql i guess - std::unordered_map> m_voice_states; + std::unordered_map> m_voice_states; std::unordered_map> m_voice_state_channel_users; void SendVoiceStateUpdate(); diff --git a/src/discord/objects.cpp b/src/discord/objects.cpp index 804f10d..1c5dd39 100644 --- a/src/discord/objects.cpp +++ b/src/discord/objects.cpp @@ -714,4 +714,5 @@ void from_json(const nlohmann::json &j, VoiceState &m) { JS_D("user_id", m.UserID); JS_ON("member", m.Member); JS_D("session_id", m.SessionID); + JS_ON("request_to_speak_timestamp", m.RequestToSpeakTimestamp); } diff --git a/src/discord/objects.hpp b/src/discord/objects.hpp index 67474a3..e026311 100644 --- a/src/discord/objects.hpp +++ b/src/discord/objects.hpp @@ -921,6 +921,7 @@ struct VoiceState { std::string SessionID; bool IsSuppressed; Snowflake UserID; + std::optional RequestToSpeakTimestamp; friend void from_json(const nlohmann::json &j, VoiceState &m); }; diff --git a/src/discord/voicestate.cpp b/src/discord/voicestate.cpp new file mode 100644 index 0000000..05c050d --- /dev/null +++ b/src/discord/voicestate.cpp @@ -0,0 +1,5 @@ +#include "voicestate.hpp" + +bool PackedVoiceState::IsSpeaker() const noexcept { + return ((Flags & VoiceStateFlags::Suppressed) != VoiceStateFlags::Suppressed) && !RequestToSpeakTimestamp.has_value(); +} diff --git a/src/discord/voicestate.hpp b/src/discord/voicestate.hpp new file mode 100644 index 0000000..cc75b0c --- /dev/null +++ b/src/discord/voicestate.hpp @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include +#include "misc/bitwise.hpp" + +// this is packed into a enum cuz it makes implementing tree models easier +enum class VoiceStateFlags : uint8_t { + Clear = 0, + Deaf = 1 << 0, + Mute = 1 << 1, + SelfDeaf = 1 << 2, + SelfMute = 1 << 3, + SelfStream = 1 << 4, + SelfVideo = 1 << 5, + Suppressed = 1 << 6, +}; + +struct PackedVoiceState { + VoiceStateFlags Flags; + std::optional RequestToSpeakTimestamp; + + [[nodiscard]] bool IsSpeaker() const noexcept; +}; + +template<> +struct Bitwise { + static const bool enable = true; +}; diff --git a/src/discord/voicestateflags.hpp b/src/discord/voicestateflags.hpp deleted file mode 100644 index e725d9a..0000000 --- a/src/discord/voicestateflags.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include "misc/bitwise.hpp" - -enum class VoiceStateFlags : uint8_t { - Clear = 0, - Deaf = 1 << 0, - Mute = 1 << 1, - SelfDeaf = 1 << 2, - SelfMute = 1 << 3, - SelfStream = 1 << 4, - SelfVideo = 1 << 5, - Suppressed = 1 << 6, -}; - -template<> -struct Bitwise { - static const bool enable = true; -}; diff --git a/src/misc/bitwise.hpp b/src/misc/bitwise.hpp index ecce333..4d4cf8f 100644 --- a/src/misc/bitwise.hpp +++ b/src/misc/bitwise.hpp @@ -1,6 +1,13 @@ #pragma once #include +namespace util { +template +bool FlagSet(T flags, T value) { + return (flags & value) == value; +} +} // namespace util + template struct Bitwise { static const bool enable = false; diff --git a/src/windows/voice/voicewindow.cpp b/src/windows/voice/voicewindow.cpp index 05b2ade..1ada8ee 100644 --- a/src/windows/voice/voicewindow.cpp +++ b/src/windows/voice/voicewindow.cpp @@ -29,14 +29,17 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) auto &discord = Abaddon::Get().GetDiscordClient(); auto &audio = Abaddon::Get().GetAudio(); + const auto channel = discord.GetChannel(m_channel_id); + m_is_stage = channel.has_value() && channel->Type == ChannelType::GUILD_STAGE_VOICE; + SetUsers(discord.GetUsersInVoiceChannel(m_channel_id)); discord.signal_voice_user_disconnect().connect(sigc::mem_fun(*this, &VoiceWindow::OnUserDisconnect)); discord.signal_voice_user_connect().connect(sigc::mem_fun(*this, &VoiceWindow::OnUserConnect)); if (const auto self_state = discord.GetVoiceState(discord.GetUserData().ID); self_state.has_value()) { - m_mute.set_active((self_state->second & VoiceStateFlags::SelfMute) == VoiceStateFlags::SelfMute); - m_deafen.set_active((self_state->second & VoiceStateFlags::SelfDeaf) == VoiceStateFlags::SelfDeaf); + m_mute.set_active(util::FlagSet(self_state->second.Flags, VoiceStateFlags::SelfMute)); + m_deafen.set_active(util::FlagSet(self_state->second.Flags, VoiceStateFlags::SelfDeaf)); } m_mute.signal_toggled().connect(sigc::mem_fun(*this, &VoiceWindow::OnMuteChanged)); @@ -214,10 +217,13 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) } void VoiceWindow::SetUsers(const std::unordered_set &user_ids) { - const auto me = Abaddon::Get().GetDiscordClient().GetUserData().ID; + auto &discord = Abaddon::Get().GetDiscordClient(); + const auto me = discord.GetUserData().ID; for (auto id : user_ids) { if (id == me) continue; - m_user_list.add(*CreateRow(id)); + if (discord.IsUserSpeaker(id)) { + m_user_list.add(*CreateRow(id)); + } } } @@ -283,7 +289,9 @@ void VoiceWindow::UpdateVADParamValue() { void VoiceWindow::OnUserConnect(Snowflake user_id, Snowflake to_channel_id) { if (m_channel_id == to_channel_id) { if (auto it = m_rows.find(user_id); it == m_rows.end()) { - m_user_list.add(*CreateRow(user_id)); + if (Abaddon::Get().GetDiscordClient().IsUserSpeaker(user_id)) { + m_user_list.add(*CreateRow(user_id)); + } } } } diff --git a/src/windows/voice/voicewindow.hpp b/src/windows/voice/voicewindow.hpp index 202a0ac..5d73e97 100644 --- a/src/windows/voice/voicewindow.hpp +++ b/src/windows/voice/voicewindow.hpp @@ -62,6 +62,7 @@ private: Gtk::ComboBox m_capture_combo; Snowflake m_channel_id; + bool m_is_stage; std::unordered_map m_rows; -- cgit v1.2.3 From 837e25a0cf28f3a132e6e675bb0e6d376f3d83f9 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 25 Jun 2024 02:26:41 -0400 Subject: oops --- src/components/channellist/channellisttree.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/components/channellist') diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index e5f31fa..e824933 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -1485,9 +1485,10 @@ void ChannelListTree::OnVoiceStageSubmenuPopup() { m_menu_voice_stage_join.set_sensitive(true); m_menu_voice_stage_disconnect.set_sensitive(false); } -#endif +#else m_menu_voice_stage_join.set_sensitive(false); m_menu_voice_stage_disconnect.set_sensitive(false); +#endif } void ChannelListTree::OnDMSubmenuPopup() { -- cgit v1.2.3