mirror of
https://github.com/uowuo/abaddon.git
synced 2024-09-20 06:51:51 +00:00
Merge branch 'master' into rnnoise
This commit is contained in:
commit
0f3814586e
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -95,6 +95,8 @@ jobs:
|
||||||
mkdir -p 16x16/devices 24x24/devices 32x32/devices 48x48/devices 64x64/devices 96x96/devices scalable/devices
|
mkdir -p 16x16/devices 24x24/devices 32x32/devices 48x48/devices 64x64/devices 96x96/devices scalable/devices
|
||||||
mkdir -p 16x16/status 24x24/status 32x32/status 48x48/status 64x64/status 96x96/status scalable/status
|
mkdir -p 16x16/status 24x24/status 32x32/status 48x48/status 64x64/status 96x96/status scalable/status
|
||||||
cd ${GITHUB_WORKSPACE}
|
cd ${GITHUB_WORKSPACE}
|
||||||
|
cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/icon-theme.cache ${artifact_dir}/share/icons/Adwaita/icon-theme.cache
|
||||||
|
cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/index.theme ${artifact_dir}/share/icons/Adwaita/index.theme
|
||||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/16x16/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/16x16/%.symbolic.png || :
|
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/16x16/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/16x16/%.symbolic.png || :
|
||||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/24x24/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/24x24/%.symbolic.png || :
|
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/24x24/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/24x24/%.symbolic.png || :
|
||||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/32x32/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/32x32/%.symbolic.png || :
|
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/32x32/%.symbolic.png ${artifact_dir}/share/icons/Adwaita/32x32/%.symbolic.png || :
|
||||||
|
|
|
@ -58,8 +58,8 @@ Abaddon::Abaddon()
|
||||||
m_discord.signal_voice_connected().connect(sigc::mem_fun(*this, &Abaddon::OnVoiceConnected));
|
m_discord.signal_voice_connected().connect(sigc::mem_fun(*this, &Abaddon::OnVoiceConnected));
|
||||||
m_discord.signal_voice_disconnected().connect(sigc::mem_fun(*this, &Abaddon::OnVoiceDisconnected));
|
m_discord.signal_voice_disconnected().connect(sigc::mem_fun(*this, &Abaddon::OnVoiceDisconnected));
|
||||||
m_discord.signal_voice_speaking().connect([this](const VoiceSpeakingData &m) {
|
m_discord.signal_voice_speaking().connect([this](const VoiceSpeakingData &m) {
|
||||||
printf("%llu has ssrc %u\n", (uint64_t)m.UserID, m.SSRC);
|
spdlog::get("voice")->debug("{} SSRC: {}", m.UserID, m.SSRC);
|
||||||
m_audio->AddSSRC(m.SSRC);
|
m_audio.AddSSRC(m.SSRC);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -244,8 +244,7 @@ int Abaddon::StartGTK() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_VOICE
|
#ifdef WITH_VOICE
|
||||||
m_audio = std::make_unique<AudioManager>();
|
if (!m_audio.OK()) {
|
||||||
if (!m_audio->OK()) {
|
|
||||||
Gtk::MessageDialog dlg(*m_main_window, "The audio engine could not be initialized!", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
Gtk::MessageDialog dlg(*m_main_window, "The audio engine could not be initialized!", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
dlg.set_position(Gtk::WIN_POS_CENTER);
|
dlg.set_position(Gtk::WIN_POS_CENTER);
|
||||||
dlg.run();
|
dlg.run();
|
||||||
|
@ -341,8 +340,8 @@ void Abaddon::StartDiscord() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Abaddon::StopDiscord() {
|
void Abaddon::StopDiscord() {
|
||||||
if (m_discord.Stop())
|
if (m_discord.IsStarted()) SaveState();
|
||||||
SaveState();
|
m_discord.Stop();
|
||||||
m_main_window->UpdateMenus();
|
m_main_window->UpdateMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,13 +440,13 @@ void Abaddon::DiscordOnThreadUpdate(const ThreadUpdateData &data) {
|
||||||
|
|
||||||
#ifdef WITH_VOICE
|
#ifdef WITH_VOICE
|
||||||
void Abaddon::OnVoiceConnected() {
|
void Abaddon::OnVoiceConnected() {
|
||||||
m_audio->StartCaptureDevice();
|
m_audio.StartCaptureDevice();
|
||||||
ShowVoiceWindow();
|
ShowVoiceWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Abaddon::OnVoiceDisconnected() {
|
void Abaddon::OnVoiceDisconnected() {
|
||||||
m_audio->StopCaptureDevice();
|
m_audio.StopCaptureDevice();
|
||||||
m_audio->RemoveAllSSRCs();
|
m_audio.RemoveAllSSRCs();
|
||||||
if (m_voice_window != nullptr) {
|
if (m_voice_window != nullptr) {
|
||||||
m_voice_window->close();
|
m_voice_window->close();
|
||||||
}
|
}
|
||||||
|
@ -461,25 +460,25 @@ void Abaddon::ShowVoiceWindow() {
|
||||||
|
|
||||||
wnd->signal_mute().connect([this](bool is_mute) {
|
wnd->signal_mute().connect([this](bool is_mute) {
|
||||||
m_discord.SetVoiceMuted(is_mute);
|
m_discord.SetVoiceMuted(is_mute);
|
||||||
m_audio->SetCapture(!is_mute);
|
m_audio.SetCapture(!is_mute);
|
||||||
});
|
});
|
||||||
|
|
||||||
wnd->signal_deafen().connect([this](bool is_deaf) {
|
wnd->signal_deafen().connect([this](bool is_deaf) {
|
||||||
m_discord.SetVoiceDeafened(is_deaf);
|
m_discord.SetVoiceDeafened(is_deaf);
|
||||||
m_audio->SetPlayback(!is_deaf);
|
m_audio.SetPlayback(!is_deaf);
|
||||||
});
|
});
|
||||||
|
|
||||||
wnd->signal_gate().connect([this](double gate) {
|
wnd->signal_gate().connect([this](double gate) {
|
||||||
m_audio->SetCaptureGate(gate);
|
m_audio.SetCaptureGate(gate);
|
||||||
});
|
});
|
||||||
|
|
||||||
wnd->signal_gain().connect([this](double gain) {
|
wnd->signal_gain().connect([this](double gain) {
|
||||||
m_audio->SetCaptureGain(gain);
|
m_audio.SetCaptureGain(gain);
|
||||||
});
|
});
|
||||||
|
|
||||||
wnd->signal_mute_user_cs().connect([this](Snowflake id, bool is_mute) {
|
wnd->signal_mute_user_cs().connect([this](Snowflake id, bool is_mute) {
|
||||||
if (const auto ssrc = m_discord.GetSSRCOfUser(id); ssrc.has_value()) {
|
if (const auto ssrc = m_discord.GetSSRCOfUser(id); ssrc.has_value()) {
|
||||||
m_audio->SetMuteSSRC(*ssrc, is_mute);
|
m_audio.SetMuteSSRC(*ssrc, is_mute);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1080,7 +1079,7 @@ EmojiResource &Abaddon::GetEmojis() {
|
||||||
|
|
||||||
#ifdef WITH_VOICE
|
#ifdef WITH_VOICE
|
||||||
AudioManager &Abaddon::GetAudio() {
|
AudioManager &Abaddon::GetAudio() {
|
||||||
return *m_audio;
|
return m_audio;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "imgmanager.hpp"
|
#include "imgmanager.hpp"
|
||||||
#include "emojis.hpp"
|
#include "emojis.hpp"
|
||||||
#include "notifications/notifications.hpp"
|
#include "notifications/notifications.hpp"
|
||||||
|
#include "audio/manager.hpp"
|
||||||
|
|
||||||
#define APP_TITLE "Abaddon"
|
#define APP_TITLE "Abaddon"
|
||||||
|
|
||||||
|
@ -173,7 +174,7 @@ private:
|
||||||
EmojiResource m_emojis;
|
EmojiResource m_emojis;
|
||||||
|
|
||||||
#ifdef WITH_VOICE
|
#ifdef WITH_VOICE
|
||||||
std::unique_ptr<AudioManager> m_audio;
|
AudioManager m_audio;
|
||||||
Gtk::Window *m_voice_window = nullptr;
|
Gtk::Window *m_voice_window = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,15 @@ void capture_data_callback(ma_device *pDevice, void *pOutput, const void *pInput
|
||||||
if (mgr == nullptr) return;
|
if (mgr == nullptr) return;
|
||||||
|
|
||||||
mgr->OnCapturedPCM(static_cast<const int16_t *>(pInput), frameCount);
|
mgr->OnCapturedPCM(static_cast<const int16_t *>(pInput), frameCount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You can simply increment it by 480 in UDPSocket::SendEncrypted but this is wrong
|
||||||
|
* The timestamp is supposed to be strictly linear eg. if there's discontinuous
|
||||||
|
* transmission for 1 second then the timestamp should be 48000 greater than the
|
||||||
|
* last packet. So it's incremented here because this is fired 100x per second
|
||||||
|
* and is always called in sync with UDPSocket::SendEncrypted
|
||||||
|
*/
|
||||||
|
mgr->m_rtp_timestamp += 480;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioManager::AudioManager() {
|
AudioManager::AudioManager() {
|
||||||
|
@ -484,6 +493,10 @@ AudioDevices &AudioManager::GetDevices() {
|
||||||
return m_devices;
|
return m_devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t AudioManager::GetRTPTimestamp() const noexcept {
|
||||||
|
return m_rtp_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
AudioManager::type_signal_opus_packet AudioManager::signal_opus_packet() {
|
AudioManager::type_signal_opus_packet AudioManager::signal_opus_packet() {
|
||||||
return m_signal_opus_packet;
|
return m_signal_opus_packet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] AudioDevices &GetDevices();
|
[[nodiscard]] AudioDevices &GetDevices();
|
||||||
|
|
||||||
|
[[nodiscard]] uint32_t GetRTPTimestamp() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames);
|
void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames);
|
||||||
|
|
||||||
|
@ -116,6 +118,7 @@ private:
|
||||||
AudioDevices m_devices;
|
AudioDevices m_devices;
|
||||||
|
|
||||||
DenoiseState *m_rnnoise;
|
DenoiseState *m_rnnoise;
|
||||||
|
std::atomic<uint32_t> m_rtp_timestamp = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using type_signal_opus_packet = sigc::signal<void(int payload_size)>;
|
using type_signal_opus_packet = sigc::signal<void(int payload_size)>;
|
||||||
|
|
|
@ -2813,7 +2813,6 @@ void DiscordClient::SetVoiceState(Snowflake user_id, const VoiceState &state) {
|
||||||
spdlog::get("discord")->error("SetVoiceState called with missing channel ID");
|
spdlog::get("discord")->error("SetVoiceState called with missing channel ID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spdlog::get("discord")->debug("SetVoiceState: {} -> {}", user_id, *state.ChannelID);
|
|
||||||
|
|
||||||
auto flags = VoiceStateFlags::Clear;
|
auto flags = VoiceStateFlags::Clear;
|
||||||
if (state.IsSelfMuted) flags |= VoiceStateFlags::SelfMute;
|
if (state.IsSelfMuted) flags |= VoiceStateFlags::SelfMute;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <glibmm/ustring.h>
|
#include <glibmm/ustring.h>
|
||||||
|
#include <spdlog/fmt/fmt.h>
|
||||||
|
#include <spdlog/fmt/ostr.h>
|
||||||
|
|
||||||
struct Snowflake {
|
struct Snowflake {
|
||||||
Snowflake();
|
Snowflake();
|
||||||
|
@ -39,6 +41,13 @@ private:
|
||||||
unsigned long long m_num;
|
unsigned long long m_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<Snowflake> : fmt::formatter<std::string> {
|
||||||
|
auto format(Snowflake id, format_context &ctx) -> decltype(ctx.out()) {
|
||||||
|
return format_to(ctx.out(), "[id: {}]", static_cast<uint64_t>(id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
struct hash<Snowflake> {
|
struct hash<Snowflake> {
|
||||||
|
|
|
@ -49,17 +49,18 @@ void UDPSocket::SetSSRC(uint32_t ssrc) {
|
||||||
|
|
||||||
void UDPSocket::SendEncrypted(const uint8_t *data, size_t len) {
|
void UDPSocket::SendEncrypted(const uint8_t *data, size_t len) {
|
||||||
m_sequence++;
|
m_sequence++;
|
||||||
m_timestamp += 480; // this is important
|
|
||||||
|
const uint32_t timestamp = Abaddon::Get().GetAudio().GetRTPTimestamp();
|
||||||
|
|
||||||
std::vector<uint8_t> rtp(12 + len + crypto_secretbox_MACBYTES, 0);
|
std::vector<uint8_t> rtp(12 + len + crypto_secretbox_MACBYTES, 0);
|
||||||
rtp[0] = 0x80; // ver 2
|
rtp[0] = 0x80; // ver 2
|
||||||
rtp[1] = 0x78; // payload type 0x78
|
rtp[1] = 0x78; // payload type 0x78
|
||||||
rtp[2] = (m_sequence >> 8) & 0xFF;
|
rtp[2] = (m_sequence >> 8) & 0xFF;
|
||||||
rtp[3] = (m_sequence >> 0) & 0xFF;
|
rtp[3] = (m_sequence >> 0) & 0xFF;
|
||||||
rtp[4] = (m_timestamp >> 24) & 0xFF;
|
rtp[4] = (timestamp >> 24) & 0xFF;
|
||||||
rtp[5] = (m_timestamp >> 16) & 0xFF;
|
rtp[5] = (timestamp >> 16) & 0xFF;
|
||||||
rtp[6] = (m_timestamp >> 8) & 0xFF;
|
rtp[6] = (timestamp >> 8) & 0xFF;
|
||||||
rtp[7] = (m_timestamp >> 0) & 0xFF;
|
rtp[7] = (timestamp >> 0) & 0xFF;
|
||||||
rtp[8] = (m_ssrc >> 24) & 0xFF;
|
rtp[8] = (m_ssrc >> 24) & 0xFF;
|
||||||
rtp[9] = (m_ssrc >> 16) & 0xFF;
|
rtp[9] = (m_ssrc >> 16) & 0xFF;
|
||||||
rtp[10] = (m_ssrc >> 8) & 0xFF;
|
rtp[10] = (m_ssrc >> 8) & 0xFF;
|
||||||
|
@ -382,7 +383,7 @@ void DiscordVoiceClient::Discovery() {
|
||||||
const auto response = m_udp.Receive();
|
const auto response = m_udp.Receive();
|
||||||
if (response.size() >= 74 && response[0] == 0x00 && response[1] == 0x02) {
|
if (response.size() >= 74 && response[0] == 0x00 && response[1] == 0x02) {
|
||||||
const char *ip = reinterpret_cast<const char *>(response.data() + 8);
|
const char *ip = reinterpret_cast<const char *>(response.data() + 8);
|
||||||
uint16_t port = (response[73] << 8) | response[74];
|
uint16_t port = (response[72] << 8) | response[73];
|
||||||
m_log->info("Discovered IP and port: {}:{}", ip, port);
|
m_log->info("Discovered IP and port: {}:{}", ip, port);
|
||||||
SelectProtocol(ip, port);
|
SelectProtocol(ip, port);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -171,7 +171,6 @@ private:
|
||||||
uint32_t m_ssrc;
|
uint32_t m_ssrc;
|
||||||
|
|
||||||
uint16_t m_sequence = 0;
|
uint16_t m_sequence = 0;
|
||||||
uint32_t m_timestamp = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using type_signal_data = sigc::signal<void, std::vector<uint8_t>>;
|
using type_signal_data = sigc::signal<void, std::vector<uint8_t>>;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user