mirror of
https://github.com/celisej567/abaddon.git
synced 2026-09-13 20:18:50 +03:00
basic mute/deafen
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
36
src/windows/voicewindow.cpp
Normal file
36
src/windows/voicewindow.cpp
Normal file
@@ -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;
|
||||
}
|
||||
30
src/windows/voicewindow.hpp
Normal file
30
src/windows/voicewindow.hpp
Normal file
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user