persist voice settings, handle volume w/ no ssrc

This commit is contained in:
ouwou 2023-01-16 22:52:39 -05:00
parent 5e85d16cd6
commit ea04035f0d
8 changed files with 74 additions and 13 deletions

View File

@ -474,9 +474,8 @@ void Abaddon::ShowVoiceWindow() {
});
wnd->signal_user_volume_changed().connect([this](Snowflake id, double volume) {
if (const auto ssrc = m_discord.GetSSRCOfUser(id); ssrc.has_value()) {
m_audio->SetVolumeSSRC(*ssrc, volume);
}
auto &vc = m_discord.GetVoiceClient();
vc.SetUserVolume(id, volume);
});
wnd->set_position(Gtk::WIN_POS_CENTER);

View File

@ -278,13 +278,21 @@ void AudioManager::SetPlayback(bool playback) {
}
void AudioManager::SetCaptureGate(double gate) {
m_capture_gate = gate * 0.01;
m_capture_gate = gate;
}
void AudioManager::SetCaptureGain(double gain) {
m_capture_gain = gain;
}
double AudioManager::GetCaptureGate() const noexcept {
return m_capture_gate;
}
double AudioManager::GetCaptureGain() const noexcept {
return m_capture_gain;
}
void AudioManager::SetMuteSSRC(uint32_t ssrc, bool mute) {
std::lock_guard<std::mutex> _(m_mutex);
if (mute) {
@ -296,9 +304,15 @@ void AudioManager::SetMuteSSRC(uint32_t ssrc, bool mute) {
void AudioManager::SetVolumeSSRC(uint32_t ssrc, double volume) {
std::lock_guard<std::mutex> _(m_mutex);
volume *= 0.01;
constexpr const double E = 2.71828182845904523536;
m_volume_ssrc[ssrc] = (std::exp(volume) - 1) / (E - 1);
m_volume_ssrc[ssrc] = volume;
}
double AudioManager::GetVolumeSSRC(uint32_t ssrc) const {
std::lock_guard<std::mutex> _(m_mutex);
if (const auto iter = m_volume_ssrc.find(ssrc); iter != m_volume_ssrc.end()) {
return iter->second;
}
return 1.0;
}
void AudioManager::SetEncodingApplication(int application) {
@ -463,4 +477,5 @@ AudioDevices &AudioManager::GetDevices() {
AudioManager::type_signal_opus_packet AudioManager::signal_opus_packet() {
return m_signal_opus_packet;
}
#endif

View File

@ -40,9 +40,12 @@ public:
void SetCaptureGate(double gate);
void SetCaptureGain(double gain);
[[nodiscard]] double GetCaptureGate() const noexcept;
[[nodiscard]] double GetCaptureGain() const noexcept;
void SetMuteSSRC(uint32_t ssrc, bool mute);
void SetVolumeSSRC(uint32_t ssrc, double volume);
[[nodiscard]] double GetVolumeSSRC(uint32_t ssrc) const;
void SetEncodingApplication(int application);
[[nodiscard]] int GetEncodingApplication();

View File

@ -1226,6 +1226,10 @@ std::optional<Snowflake> DiscordClient::GetVoiceState(Snowflake user_id) const {
return std::nullopt;
}
DiscordVoiceClient &DiscordClient::GetVoiceClient() {
return m_voice;
}
void DiscordClient::SetVoiceMuted(bool is_mute) {
m_mute_requested = is_mute;
SendVoiceStateUpdate();

View File

@ -191,6 +191,8 @@ public:
[[nodiscard]] std::optional<uint32_t> GetSSRCOfUser(Snowflake id) const;
[[nodiscard]] std::optional<Snowflake> GetVoiceState(Snowflake user_id) const;
DiscordVoiceClient &GetVoiceClient();
void SetVoiceMuted(bool is_mute);
void SetVoiceDeafened(bool is_deaf);
#endif

View File

@ -167,6 +167,7 @@ DiscordVoiceClient::~DiscordVoiceClient() {
void DiscordVoiceClient::Start() {
SetState(State::ConnectingToWebsocket);
m_ssrc_map.clear();
m_heartbeat_waiter.revive();
m_keepalive_waiter.revive();
m_ws.StartConnection("wss://" + m_endpoint + "/?v=7");
@ -188,6 +189,8 @@ void DiscordVoiceClient::Stop() {
m_keepalive_waiter.kill();
if (m_keepalive_thread.joinable()) m_keepalive_thread.join();
m_ssrc_map.clear();
m_signal_disconnected.emit();
}
@ -211,6 +214,20 @@ void DiscordVoiceClient::SetUserID(Snowflake id) {
m_user_id = id;
}
void DiscordVoiceClient::SetUserVolume(Snowflake id, float volume) {
m_user_volumes[id] = volume;
if (const auto ssrc = GetSSRCOfUser(id); ssrc.has_value()) {
Abaddon::Get().GetAudio().SetVolumeSSRC(*ssrc, volume);
}
}
[[nodiscard]] float DiscordVoiceClient::GetUserVolume(Snowflake id) const {
if (const auto it = m_user_volumes.find(id); it != m_user_volumes.end()) {
return it->second;
}
return 1.0f;
}
std::optional<uint32_t> DiscordVoiceClient::GetSSRCOfUser(Snowflake id) const {
if (const auto it = m_ssrc_map.find(id); it != m_ssrc_map.end()) {
return it->second;
@ -315,6 +332,14 @@ void DiscordVoiceClient::HandleGatewaySessionDescription(const VoiceGatewayMessa
void DiscordVoiceClient::HandleGatewaySpeaking(const VoiceGatewayMessage &m) {
VoiceSpeakingData d = m.Data;
// set volume if already set but ssrc just found
if (const auto iter = m_user_volumes.find(d.UserID); iter != m_user_volumes.end()) {
if (m_ssrc_map.find(d.UserID) == m_ssrc_map.end()) {
Abaddon::Get().GetAudio().SetVolumeSSRC(d.SSRC, iter->second);
}
}
m_ssrc_map[d.UserID] = d.SSRC;
m_signal_speaking.emit(d);
}

View File

@ -195,6 +195,9 @@ public:
void SetServerID(Snowflake id);
void SetUserID(Snowflake id);
// todo serialize
void SetUserVolume(Snowflake id, float volume);
[[nodiscard]] float GetUserVolume(Snowflake id) const;
[[nodiscard]] std::optional<uint32_t> GetSSRCOfUser(Snowflake id) const;
// Is a websocket and udp connection fully established
@ -241,6 +244,7 @@ private:
Snowflake m_user_id;
std::unordered_map<Snowflake, uint32_t> m_ssrc_map;
std::unordered_map<Snowflake, float> m_user_volumes;
std::array<uint8_t, 32> m_secret_key;

View File

@ -24,7 +24,7 @@ public:
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());
m_signal_volume.emit(m_volume.get_value() * 0.01);
});
m_horz.add(m_avatar);
@ -54,6 +54,10 @@ public:
m_meter.SetVolume(frac);
}
void RestoreGain(double frac) {
m_volume.set_value(frac * 100.0);
}
private:
Gtk::Box m_main;
Gtk::Box m_horz;
@ -92,6 +96,8 @@ VoiceWindow::VoiceWindow(Snowflake channel_id)
set_default_size(300, 300);
auto &discord = Abaddon::Get().GetDiscordClient();
auto &audio = Abaddon::Get().GetAudio();
SetUsers(discord.GetUsersInVoiceChannel(m_channel_id));
discord.signal_voice_user_disconnect().connect(sigc::mem_fun(*this, &VoiceWindow::OnUserDisconnect));
@ -108,17 +114,16 @@ VoiceWindow::VoiceWindow(Snowflake channel_id)
m_capture_gate.set_range(0.0, 100.0);
m_capture_gate.set_value_pos(Gtk::POS_LEFT);
m_capture_gate.set_value(0.0);
m_capture_gate.set_value(audio.GetCaptureGate() * 100.0);
m_capture_gate.signal_value_changed().connect([this]() {
// todo this should probably emit 0-1 i dont think the mgr should be responsible for scaling down
const double val = m_capture_gate.get_value();
const double val = m_capture_gate.get_value() * 0.01;
m_signal_gate.emit(val);
m_capture_volume.SetTick(val / 100.0);
m_capture_volume.SetTick(val);
});
m_capture_gain.set_range(0.0, 200.0);
m_capture_gain.set_value_pos(Gtk::POS_LEFT);
m_capture_gain.set_value(100.0);
m_capture_gain.set_value(audio.GetCaptureGain() * 100.0);
m_capture_gain.signal_value_changed().connect([this]() {
const double val = m_capture_gain.get_value();
m_signal_gain.emit(val / 100.0);
@ -174,7 +179,9 @@ VoiceWindow::VoiceWindow(Snowflake channel_id)
}
void VoiceWindow::SetUsers(const std::unordered_set<Snowflake> &user_ids) {
const auto me = Abaddon::Get().GetDiscordClient().GetUserData().ID;
for (auto id : user_ids) {
if (id == me) continue;
m_user_list.add(*CreateRow(id));
}
}
@ -182,6 +189,8 @@ void VoiceWindow::SetUsers(const std::unordered_set<Snowflake> &user_ids) {
Gtk::ListBoxRow *VoiceWindow::CreateRow(Snowflake id) {
auto *row = Gtk::make_managed<VoiceWindowUserListEntry>(id);
m_rows[id] = row;
auto &vc = Abaddon::Get().GetDiscordClient().GetVoiceClient();
row->RestoreGain(vc.GetUserVolume(id));
row->signal_mute_cs().connect([this, id](bool is_muted) {
m_signal_mute_user_cs.emit(id, is_muted);
});