summaryrefslogtreecommitdiff
path: root/src/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows')
-rw-r--r--src/windows/voice/voicewindow.cpp (renamed from src/windows/voicewindow.cpp)171
-rw-r--r--src/windows/voice/voicewindow.hpp (renamed from src/windows/voicewindow.hpp)18
-rw-r--r--src/windows/voice/voicewindowaudiencelistentry.cpp22
-rw-r--r--src/windows/voice/voicewindowaudiencelistentry.hpp18
-rw-r--r--src/windows/voice/voicewindowspeakerlistentry.cpp58
-rw-r--r--src/windows/voice/voicewindowspeakerlistentry.hpp38
6 files changed, 229 insertions, 96 deletions
diff --git a/src/windows/voicewindow.cpp b/src/windows/voice/voicewindow.cpp
index 18f4a41..5e91aad 100644
--- a/src/windows/voicewindow.cpp
+++ b/src/windows/voice/voicewindow.cpp
@@ -2,88 +2,17 @@
// clang-format off
+#include "voicewindow.hpp"
+
#include "abaddon.hpp"
#include "audio/manager.hpp"
#include "components/lazyimage.hpp"
-#include "voicesettingswindow.hpp"
-#include "voicewindow.hpp"
+#include "voicewindowaudiencelistentry.hpp"
+#include "voicewindowspeakerlistentry.hpp"
+#include "windows/voicesettingswindow.hpp"
// clang-format on
-class VoiceWindowUserListEntry : public Gtk::ListBoxRow {
-public:
- VoiceWindowUserListEntry(Snowflake id)
- : m_main(Gtk::ORIENTATION_VERTICAL)
- , m_horz(Gtk::ORIENTATION_HORIZONTAL)
- , m_avatar(32, 32)
- , m_mute("Mute") {
- m_name.set_halign(Gtk::ALIGN_START);
- m_name.set_hexpand(true);
- m_mute.set_halign(Gtk::ALIGN_END);
-
- m_volume.set_range(0.0, 200.0);
- m_volume.set_value_pos(Gtk::POS_LEFT);
- m_volume.set_value(100.0);
- m_volume.signal_value_changed().connect([this]() {
- m_signal_volume.emit(m_volume.get_value() * 0.01);
- });
-
- m_horz.add(m_avatar);
- m_horz.add(m_name);
- m_horz.add(m_mute);
- m_main.add(m_horz);
- m_main.add(m_volume);
- m_main.add(m_meter);
- add(m_main);
- show_all_children();
-
- auto &discord = Abaddon::Get().GetDiscordClient();
- const auto user = discord.GetUser(id);
- if (user.has_value()) {
- m_name.set_text(user->GetUsername());
- m_avatar.SetURL(user->GetAvatarURL("png", "32"));
- } else {
- m_name.set_text("Unknown user");
- }
-
- m_mute.signal_toggled().connect([this]() {
- m_signal_mute_cs.emit(m_mute.get_active());
- });
- }
-
- void SetVolumeMeter(double frac) {
- m_meter.SetVolume(frac);
- }
-
- void RestoreGain(double frac) {
- m_volume.set_value(frac * 100.0);
- }
-
-private:
- Gtk::Box m_main;
- Gtk::Box m_horz;
- LazyImage m_avatar;
- Gtk::Label m_name;
- Gtk::CheckButton m_mute;
- Gtk::Scale m_volume;
- VolumeMeter m_meter;
-
-public:
- using type_signal_mute_cs = sigc::signal<void(bool)>;
- using type_signal_volume = sigc::signal<void(double)>;
- type_signal_mute_cs signal_mute_cs() {
- return m_signal_mute_cs;
- }
-
- type_signal_volume signal_volume() {
- return m_signal_volume;
- }
-
-private:
- type_signal_mute_cs m_signal_mute_cs;
- type_signal_volume m_signal_volume;
-};
-
VoiceWindow::VoiceWindow(Snowflake channel_id)
: m_main(Gtk::ORIENTATION_VERTICAL)
, m_controls(Gtk::ORIENTATION_HORIZONTAL)
@@ -101,14 +30,18 @@ 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));
+ discord.signal_voice_speaker_state_changed().connect(sigc::mem_fun(*this, &VoiceWindow::OnSpeakerStateChanged));
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));
@@ -248,12 +181,35 @@ VoiceWindow::VoiceWindow(Snowflake channel_id)
combos_combos->pack_start(m_playback_combo);
combos_combos->pack_start(m_capture_combo);
- m_scroll.add(m_user_list);
+ discord.signal_stage_instance_create().connect(sigc::track_obj([this](const StageInstance &instance) {
+ m_TMP_stagelabel.show();
+ m_TMP_stagelabel.set_markup("<span foreground='green'>" + instance.Topic + "</span>");
+ },
+ *this));
+
+ discord.signal_stage_instance_update().connect(sigc::track_obj([this](const StageInstance &instance) {
+ m_TMP_stagelabel.set_markup("<span foreground='green'>" + instance.Topic + "</span>");
+ },
+ *this));
+
+ discord.signal_stage_instance_delete().connect(sigc::track_obj([this](const StageInstance &instance) {
+ m_TMP_stagelabel.hide();
+ },
+ *this));
+
+ m_TMP_speakers_label.set_markup("<b>Speakers</b>");
+ m_listing.pack_start(m_TMP_speakers_label, false, true);
+ m_listing.pack_start(m_speakers_list, false, true);
+ m_TMP_audience_label.set_markup("<b>Audience</b>");
+ m_listing.pack_start(m_TMP_audience_label, false, true);
+ m_listing.pack_start(m_audience_list, false, true);
+ m_scroll.add(m_listing);
m_controls.add(m_mute);
m_controls.add(m_deafen);
m_controls.add(m_noise_suppression);
m_controls.add(m_mix_mono);
m_main.pack_start(m_menu_bar, false, true);
+ m_main.pack_start(m_TMP_stagelabel, false, true);
m_main.pack_start(m_controls, false, true);
m_main.pack_start(m_vad_value, false, true);
m_main.pack_start(*Gtk::make_managed<Gtk::Label>("Input Settings"), false, true);
@@ -263,19 +219,25 @@ VoiceWindow::VoiceWindow(Snowflake channel_id)
add(m_main);
show_all_children();
+ m_TMP_stagelabel.hide();
+
Glib::signal_timeout().connect(sigc::mem_fun(*this, &VoiceWindow::UpdateVoiceMeters), 40);
}
void VoiceWindow::SetUsers(const std::unordered_set<Snowflake> &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)) {
+ if (id != me) m_speakers_list.add(*CreateSpeakerRow(id));
+ } else {
+ m_audience_list.add(*CreateAudienceRow(id));
+ }
}
}
-Gtk::ListBoxRow *VoiceWindow::CreateRow(Snowflake id) {
- auto *row = Gtk::make_managed<VoiceWindowUserListEntry>(id);
+Gtk::ListBoxRow *VoiceWindow::CreateSpeakerRow(Snowflake id) {
+ auto *row = Gtk::make_managed<VoiceWindowSpeakerListEntry>(id);
m_rows[id] = row;
auto &vc = Abaddon::Get().GetDiscordClient().GetVoiceClient();
row->RestoreGain(vc.GetUserVolume(id));
@@ -285,7 +247,14 @@ Gtk::ListBoxRow *VoiceWindow::CreateRow(Snowflake id) {
row->signal_volume().connect([this, id](double volume) {
m_signal_user_volume_changed.emit(id, volume);
});
- row->show_all();
+ row->show();
+ return row;
+}
+
+Gtk::ListBoxRow *VoiceWindow::CreateAudienceRow(Snowflake id) {
+ auto *row = Gtk::make_managed<VoiceWindowAudienceListEntry>(id);
+ m_rows[id] = row;
+ row->show();
return row;
}
@@ -297,6 +266,13 @@ void VoiceWindow::OnDeafenChanged() {
m_signal_deafen.emit(m_deafen.get_active());
}
+void VoiceWindow::TryDeleteRow(Snowflake id) {
+ if (auto it = m_rows.find(id); it != m_rows.end()) {
+ delete it->second;
+ m_rows.erase(it);
+ }
+}
+
bool VoiceWindow::UpdateVoiceMeters() {
auto &audio = Abaddon::Get().GetAudio();
switch (audio.GetVADMethod()) {
@@ -313,7 +289,9 @@ bool VoiceWindow::UpdateVoiceMeters() {
for (auto [id, row] : m_rows) {
const auto ssrc = Abaddon::Get().GetDiscordClient().GetSSRCOfUser(id);
if (ssrc.has_value()) {
- row->SetVolumeMeter(audio.GetSSRCVolumeLevel(*ssrc));
+ if (auto *speaker_row = dynamic_cast<VoiceWindowSpeakerListEntry *>(row)) {
+ speaker_row->SetVolumeMeter(audio.GetSSRCVolumeLevel(*ssrc));
+ }
}
}
return true;
@@ -336,17 +314,26 @@ 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_speakers_list.add(*CreateSpeakerRow(user_id));
+ } else {
+ m_audience_list.add(*CreateAudienceRow(user_id));
+ }
}
}
}
void VoiceWindow::OnUserDisconnect(Snowflake user_id, Snowflake from_channel_id) {
- if (m_channel_id == from_channel_id) {
- if (auto it = m_rows.find(user_id); it != m_rows.end()) {
- delete it->second;
- m_rows.erase(it);
- }
+ if (m_channel_id == from_channel_id) TryDeleteRow(user_id);
+}
+
+void VoiceWindow::OnSpeakerStateChanged(Snowflake channel_id, Snowflake user_id, bool is_speaker) {
+ if (m_channel_id != channel_id) return;
+ TryDeleteRow(user_id);
+ if (is_speaker) {
+ m_speakers_list.add(*CreateSpeakerRow(user_id));
+ } else {
+ m_audience_list.add(*CreateAudienceRow(user_id));
}
}
diff --git a/src/windows/voicewindow.hpp b/src/windows/voice/voicewindow.hpp
index 018934b..7008f9a 100644
--- a/src/windows/voicewindow.hpp
+++ b/src/windows/voice/voicewindow.hpp
@@ -16,7 +16,6 @@
#include <unordered_set>
// clang-format on
-class VoiceWindowUserListEntry;
class VoiceWindow : public Gtk::Window {
public:
VoiceWindow(Snowflake channel_id);
@@ -24,14 +23,18 @@ public:
private:
void SetUsers(const std::unordered_set<Snowflake> &user_ids);
- Gtk::ListBoxRow *CreateRow(Snowflake id);
+ Gtk::ListBoxRow *CreateSpeakerRow(Snowflake id);
+ Gtk::ListBoxRow *CreateAudienceRow(Snowflake id);
void OnUserConnect(Snowflake user_id, Snowflake to_channel_id);
void OnUserDisconnect(Snowflake user_id, Snowflake from_channel_id);
+ void OnSpeakerStateChanged(Snowflake channel_id, Snowflake user_id, bool is_speaker);
void OnMuteChanged();
void OnDeafenChanged();
+ void TryDeleteRow(Snowflake id);
+
bool UpdateVoiceMeters();
void UpdateVADParamValue();
@@ -43,7 +46,9 @@ private:
Gtk::CheckButton m_deafen;
Gtk::ScrolledWindow m_scroll;
- Gtk::ListBox m_user_list;
+ Gtk::VBox m_listing;
+ Gtk::ListBox m_speakers_list;
+ Gtk::ListBox m_audience_list;
// Shows volume for gate VAD method
// Shows probability for RNNoise VAD method
@@ -61,14 +66,19 @@ private:
Gtk::ComboBox m_capture_combo;
Snowflake m_channel_id;
+ bool m_is_stage;
- std::unordered_map<Snowflake, VoiceWindowUserListEntry *> m_rows;
+ std::unordered_map<Snowflake, Gtk::ListBoxRow *> m_rows;
Gtk::MenuBar m_menu_bar;
Gtk::MenuItem m_menu_view;
Gtk::Menu m_menu_view_sub;
Gtk::MenuItem m_menu_view_settings;
+ Gtk::Label m_TMP_stagelabel;
+ Gtk::Label m_TMP_speakers_label;
+ Gtk::Label m_TMP_audience_label;
+
public:
using type_signal_mute = sigc::signal<void(bool)>;
using type_signal_deafen = sigc::signal<void(bool)>;
diff --git a/src/windows/voice/voicewindowaudiencelistentry.cpp b/src/windows/voice/voicewindowaudiencelistentry.cpp
new file mode 100644
index 0000000..aa7dad6
--- /dev/null
+++ b/src/windows/voice/voicewindowaudiencelistentry.cpp
@@ -0,0 +1,22 @@
+#include "voicewindowaudiencelistentry.hpp"
+
+VoiceWindowAudienceListEntry::VoiceWindowAudienceListEntry(Snowflake id)
+ : m_main(Gtk::ORIENTATION_HORIZONTAL)
+ , m_avatar(32, 32) {
+ m_name.set_halign(Gtk::ALIGN_START);
+ m_name.set_hexpand(true);
+
+ m_main.add(m_avatar);
+ m_main.add(m_name);
+ add(m_main);
+ show_all_children();
+
+ auto &discord = Abaddon::Get().GetDiscordClient();
+ const auto user = discord.GetUser(id);
+ if (user.has_value()) {
+ m_name.set_text(user->GetUsername());
+ m_avatar.SetURL(user->GetAvatarURL("png", "32"));
+ } else {
+ m_name.set_text("Unknown user");
+ }
+}
diff --git a/src/windows/voice/voicewindowaudiencelistentry.hpp b/src/windows/voice/voicewindowaudiencelistentry.hpp
new file mode 100644
index 0000000..e7bdbb1
--- /dev/null
+++ b/src/windows/voice/voicewindowaudiencelistentry.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "components/lazyimage.hpp"
+#include "discord/snowflake.hpp"
+
+#include <gtkmm/box.h>
+#include <gtkmm/label.h>
+#include <gtkmm/listboxrow.h>
+
+class VoiceWindowAudienceListEntry : public Gtk::ListBoxRow {
+public:
+ VoiceWindowAudienceListEntry(Snowflake id);
+
+private:
+ Gtk::Box m_main;
+ LazyImage m_avatar;
+ Gtk::Label m_name;
+};
diff --git a/src/windows/voice/voicewindowspeakerlistentry.cpp b/src/windows/voice/voicewindowspeakerlistentry.cpp
new file mode 100644
index 0000000..a7bf2b8
--- /dev/null
+++ b/src/windows/voice/voicewindowspeakerlistentry.cpp
@@ -0,0 +1,58 @@
+#include "voicewindowspeakerlistentry.hpp"
+
+#include "abaddon.hpp"
+
+VoiceWindowSpeakerListEntry::VoiceWindowSpeakerListEntry(Snowflake id)
+ : m_main(Gtk::ORIENTATION_VERTICAL)
+ , m_horz(Gtk::ORIENTATION_HORIZONTAL)
+ , m_avatar(32, 32)
+ , m_mute("Mute") {
+ m_name.set_halign(Gtk::ALIGN_START);
+ m_name.set_hexpand(true);
+ m_mute.set_halign(Gtk::ALIGN_END);
+
+ m_volume.set_range(0.0, 200.0);
+ m_volume.set_value_pos(Gtk::POS_LEFT);
+ m_volume.set_value(100.0);
+ m_volume.signal_value_changed().connect([this]() {
+ m_signal_volume.emit(m_volume.get_value() * 0.01);
+ });
+
+ m_horz.add(m_avatar);
+ m_horz.add(m_name);
+ m_horz.add(m_mute);
+ m_main.add(m_horz);
+ m_main.add(m_volume);
+ m_main.add(m_meter);
+ add(m_main);
+ show_all_children();
+
+ auto &discord = Abaddon::Get().GetDiscordClient();
+ const auto user = discord.GetUser(id);
+ if (user.has_value()) {
+ m_name.set_text(user->GetUsername());
+ m_avatar.SetURL(user->GetAvatarURL("png", "32"));
+ } else {
+ m_name.set_text("Unknown user");
+ }
+
+ m_mute.signal_toggled().connect([this]() {
+ m_signal_mute_cs.emit(m_mute.get_active());
+ });
+}
+
+void VoiceWindowSpeakerListEntry::SetVolumeMeter(double frac) {
+ m_meter.SetVolume(frac);
+}
+
+void VoiceWindowSpeakerListEntry::RestoreGain(double frac) {
+ m_volume.set_value(frac * 100.0);
+}
+
+VoiceWindowSpeakerListEntry::type_signal_mute_cs VoiceWindowSpeakerListEntry::signal_mute_cs() {
+ return m_signal_mute_cs;
+}
+
+VoiceWindowSpeakerListEntry::type_signal_volume VoiceWindowSpeakerListEntry::signal_volume() {
+ return m_signal_volume;
+}
diff --git a/src/windows/voice/voicewindowspeakerlistentry.hpp b/src/windows/voice/voicewindowspeakerlistentry.hpp
new file mode 100644
index 0000000..a3b6429
--- /dev/null
+++ b/src/windows/voice/voicewindowspeakerlistentry.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "components/lazyimage.hpp"
+#include "components/volumemeter.hpp"
+#include "discord/snowflake.hpp"
+
+#include <gtkmm/box.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/label.h>
+#include <gtkmm/listboxrow.h>
+#include <gtkmm/scale.h>
+
+class VoiceWindowSpeakerListEntry : public Gtk::ListBoxRow {
+public:
+ VoiceWindowSpeakerListEntry(Snowflake id);
+
+ void SetVolumeMeter(double frac);
+ void RestoreGain(double frac);
+
+private:
+ Gtk::Box m_main;
+ Gtk::Box m_horz;
+ LazyImage m_avatar;
+ Gtk::Label m_name;
+ Gtk::CheckButton m_mute;
+ Gtk::Scale m_volume;
+ VolumeMeter m_meter;
+
+public:
+ using type_signal_mute_cs = sigc::signal<void(bool)>;
+ using type_signal_volume = sigc::signal<void(double)>;
+ type_signal_mute_cs signal_mute_cs();
+ type_signal_volume signal_volume();
+
+private:
+ type_signal_mute_cs m_signal_mute_cs;
+ type_signal_volume m_signal_volume;
+};