summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2022-09-28 22:10:36 -0400
committerouwou <26526779+ouwou@users.noreply.github.com>2022-09-28 22:10:36 -0400
commita96d96b3aa883c5ee5892e4ff94e3c539989c66a (patch)
treed2d874aac3e2ba5daa2edb6ee682dce2345e7a5f /src
parentd57d822aa9f85ee023e2a50bd525d530b39a7186 (diff)
downloadabaddon-portaudio-a96d96b3aa883c5ee5892e4ff94e3c539989c66a.tar.gz
abaddon-portaudio-a96d96b3aa883c5ee5892e4ff94e3c539989c66a.zip
basic mute/deafen
Diffstat (limited to 'src')
-rw-r--r--src/abaddon.cpp20
-rw-r--r--src/audio/manager.cpp12
-rw-r--r--src/audio/manager.hpp7
-rw-r--r--src/discord/discord.cpp27
-rw-r--r--src/discord/discord.hpp14
-rw-r--r--src/windows/voicewindow.cpp36
-rw-r--r--src/windows/voicewindow.hpp30
7 files changed, 145 insertions, 1 deletions
diff --git a/src/abaddon.cpp b/src/abaddon.cpp
index 3245ad4..678353c 100644
--- a/src/abaddon.cpp
+++ b/src/abaddon.cpp
@@ -18,6 +18,7 @@
#include "windows/profilewindow.hpp"
#include "windows/pinnedwindow.hpp"
#include "windows/threadswindow.hpp"
+#include "windows/voicewindow.hpp"
#include "startup.hpp"
#ifdef WITH_LIBHANDY
@@ -418,6 +419,25 @@ void Abaddon::DiscordOnThreadUpdate(const ThreadUpdateData &data) {
#ifdef WITH_VOICE
void Abaddon::OnVoiceConnected() {
+ auto *wnd = new VoiceWindow;
+
+ wnd->signal_mute().connect([this](bool is_mute) {
+ m_discord.SetVoiceMuted(is_mute);
+ m_audio->SetCapture(!is_mute);
+ });
+
+ wnd->signal_deafen().connect([this](bool is_deaf) {
+ m_discord.SetVoiceDeafened(is_deaf);
+ m_audio->SetPlayback(!is_deaf);
+ });
+
+ wnd->show();
+ wnd->signal_hide().connect([this, wnd]() {
+ m_discord.DisconnectFromVoice();
+ delete wnd;
+ delete m_user_menu;
+ SetupUserMenu();
+ });
}
void Abaddon::OnVoiceDisconnected() {
diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp
index 797d899..35a9c76 100644
--- a/src/audio/manager.cpp
+++ b/src/audio/manager.cpp
@@ -137,6 +137,8 @@ void AudioManager::SetOpusBuffer(uint8_t *ptr) {
}
void AudioManager::FeedMeOpus(uint32_t ssrc, const std::vector<uint8_t> &data) {
+ if (!m_should_playback) return;
+
size_t payload_size = 0;
const auto *opus_encoded = StripRTPExtensionHeader(data.data(), static_cast<int>(data.size()), payload_size);
static std::array<opus_int16, 120 * 48 * 2> pcm;
@@ -152,8 +154,16 @@ void AudioManager::FeedMeOpus(uint32_t ssrc, const std::vector<uint8_t> &data) {
}
}
+void AudioManager::SetCapture(bool capture) {
+ m_should_capture = capture;
+}
+
+void AudioManager::SetPlayback(bool playback) {
+ m_should_playback = playback;
+}
+
void AudioManager::OnCapturedPCM(const int16_t *pcm, ma_uint32 frames) {
- if (m_opus_buffer == nullptr) return;
+ if (m_opus_buffer == nullptr || !m_should_capture) return;
int payload_len = opus_encode(m_encoder, pcm, 480, static_cast<unsigned char *>(m_opus_buffer), 1275);
if (payload_len < 0) {
diff --git a/src/audio/manager.hpp b/src/audio/manager.hpp
index 3ba6e29..4986da6 100644
--- a/src/audio/manager.hpp
+++ b/src/audio/manager.hpp
@@ -1,6 +1,7 @@
#pragma once
#ifdef WITH_VOICE
// clang-format off
+
#include <array>
#include <atomic>
#include <deque>
@@ -25,6 +26,9 @@ public:
void SetOpusBuffer(uint8_t *ptr);
void FeedMeOpus(uint32_t ssrc, const std::vector<uint8_t> &data);
+ void SetCapture(bool capture);
+ void SetPlayback(bool playback);
+
[[nodiscard]] bool OK() const;
private:
@@ -51,6 +55,9 @@ private:
uint8_t *m_opus_buffer = nullptr;
+ std::atomic<bool> m_should_capture = true;
+ std::atomic<bool> m_should_playback = true;
+
public:
using type_signal_opus_packet = sigc::signal<void(int payload_size)>;
type_signal_opus_packet signal_opus_packet();
diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp
index 4202f85..f5a1e1b 100644
--- a/src/discord/discord.cpp
+++ b/src/discord/discord.cpp
@@ -1202,6 +1202,16 @@ bool DiscordClient::IsConnectedToVoice() const noexcept {
Snowflake DiscordClient::GetVoiceChannelID() const noexcept {
return m_voice_channel_id;
}
+
+void DiscordClient::SetVoiceMuted(bool is_mute) {
+ m_mute_requested = is_mute;
+ SendVoiceStateUpdate();
+}
+
+void DiscordClient::SetVoiceDeafened(bool is_deaf) {
+ m_deaf_requested = is_deaf;
+ SendVoiceStateUpdate();
+}
#endif
void DiscordClient::SetReferringChannel(Snowflake id) {
@@ -2625,6 +2635,21 @@ void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) {
}
#ifdef WITH_VOICE
+void DiscordClient::SendVoiceStateUpdate() {
+ VoiceStateUpdateMessage msg;
+ msg.ChannelID = m_voice_channel_id;
+ const auto channel = GetChannel(m_voice_channel_id);
+ if (channel.has_value() && channel->GuildID.has_value()) {
+ msg.GuildID = *channel->GuildID;
+ }
+
+ msg.SelfMute = m_mute_requested;
+ msg.SelfDeaf = m_deaf_requested;
+ msg.SelfVideo = false;
+
+ m_websocket.Send(msg);
+}
+
void DiscordClient::SetVoiceState(Snowflake user_id, Snowflake channel_id) {
m_voice_state_user_channel[user_id] = channel_id;
m_voice_state_channel_users[channel_id].insert(user_id);
@@ -2904,6 +2929,7 @@ DiscordClient::type_signal_message_send_fail DiscordClient::signal_message_send_
return m_signal_message_send_fail;
}
+#ifdef WITH_VOICE
DiscordClient::type_signal_voice_connected DiscordClient::signal_voice_connected() {
return m_signal_voice_connected;
}
@@ -2915,3 +2941,4 @@ DiscordClient::type_signal_voice_disconnected DiscordClient::signal_voice_discon
DiscordClient::type_signal_voice_speaking DiscordClient::signal_voice_speaking() {
return m_signal_voice_speaking;
}
+#endif
diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp
index fb0b46d..b0fecab 100644
--- a/src/discord/discord.hpp
+++ b/src/discord/discord.hpp
@@ -186,6 +186,9 @@ public:
void DisconnectFromVoice();
[[nodiscard]] bool IsConnectedToVoice() const noexcept;
[[nodiscard]] Snowflake GetVoiceChannelID() const noexcept;
+
+ void SetVoiceMuted(bool is_mute);
+ void SetVoiceDeafened(bool is_deaf);
#endif
void SetReferringChannel(Snowflake id);
@@ -338,11 +341,16 @@ private:
#ifdef WITH_VOICE
DiscordVoiceClient m_voice;
+ bool m_mute_requested = false;
+ bool m_deaf_requested = false;
+
Snowflake m_voice_channel_id;
// todo sql i guess
std::unordered_map<Snowflake, Snowflake> m_voice_state_user_channel;
std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_voice_state_channel_users;
+ void SendVoiceStateUpdate();
+
void SetVoiceState(Snowflake user_id, Snowflake channel_id);
void ClearVoiceState(Snowflake user_id);
@@ -422,9 +430,11 @@ public:
typedef sigc::signal<void> type_signal_connected;
typedef sigc::signal<void, std::string, float> type_signal_message_progress;
+#ifdef WITH_VOICE
using type_signal_voice_connected = sigc::signal<void()>;
using type_signal_voice_disconnected = sigc::signal<void()>;
using type_signal_voice_speaking = sigc::signal<void(VoiceSpeakingData)>;
+#endif
type_signal_gateway_ready signal_gateway_ready();
type_signal_message_create signal_message_create();
@@ -480,9 +490,11 @@ public:
type_signal_connected signal_connected();
type_signal_message_progress signal_message_progress();
+#ifdef WITH_VOICE
type_signal_voice_connected signal_voice_connected();
type_signal_voice_disconnected signal_voice_disconnected();
type_signal_voice_speaking signal_voice_speaking();
+#endif
protected:
type_signal_gateway_ready m_signal_gateway_ready;
@@ -539,7 +551,9 @@ protected:
type_signal_connected m_signal_connected;
type_signal_message_progress m_signal_message_progress;
+#ifdef WITH_VOICE
type_signal_voice_connected m_signal_voice_connected;
type_signal_voice_disconnected m_signal_voice_disconnected;
type_signal_voice_speaking m_signal_voice_speaking;
+#endif
};
diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp
new file mode 100644
index 0000000..b352c86
--- /dev/null
+++ b/src/windows/voicewindow.cpp
@@ -0,0 +1,36 @@
+#include "voicewindow.hpp"
+
+VoiceWindow::VoiceWindow()
+ : m_main(Gtk::ORIENTATION_VERTICAL)
+ , m_controls(Gtk::ORIENTATION_HORIZONTAL)
+ , m_mute("Mute")
+ , m_deafen("Deafen") {
+ get_style_context()->add_class("app-window");
+
+ set_default_size(300, 300);
+
+ m_mute.signal_toggled().connect(sigc::mem_fun(*this, &VoiceWindow::OnMuteChanged));
+ m_deafen.signal_toggled().connect(sigc::mem_fun(*this, &VoiceWindow::OnDeafenChanged));
+
+ m_controls.add(m_mute);
+ m_controls.add(m_deafen);
+ m_main.add(m_controls);
+ add(m_main);
+ show_all_children();
+}
+
+void VoiceWindow::OnMuteChanged() {
+ m_signal_mute.emit(m_mute.get_active());
+}
+
+void VoiceWindow::OnDeafenChanged() {
+ m_signal_deafen.emit(m_deafen.get_active());
+}
+
+VoiceWindow::type_signal_mute VoiceWindow::signal_mute() {
+ return m_signal_mute;
+}
+
+VoiceWindow::type_signal_deafen VoiceWindow::signal_deafen() {
+ return m_signal_deafen;
+}
diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp
new file mode 100644
index 0000000..bee0a84
--- /dev/null
+++ b/src/windows/voicewindow.hpp
@@ -0,0 +1,30 @@
+#pragma once
+#include <gtkmm/box.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/window.h>
+
+class VoiceWindow : public Gtk::Window {
+public:
+ VoiceWindow();
+
+private:
+ void OnMuteChanged();
+ void OnDeafenChanged();
+
+ Gtk::Box m_main;
+ Gtk::Box m_controls;
+
+ Gtk::CheckButton m_mute;
+ Gtk::CheckButton m_deafen;
+
+public:
+ using type_signal_mute = sigc::signal<void(bool)>;
+ using type_signal_deafen = sigc::signal<void(bool)>;
+
+ type_signal_mute signal_mute();
+ type_signal_deafen signal_deafen();
+
+private:
+ type_signal_mute m_signal_mute;
+ type_signal_deafen m_signal_deafen;
+};