Merge branch 'master' into rnnoise
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -362,3 +362,6 @@ fonts/fonts.conf
|
|||||||
*.zip
|
*.zip
|
||||||
*.tar.*
|
*.tar.*
|
||||||
*.rar
|
*.rar
|
||||||
|
|
||||||
|
#macOS resource forks
|
||||||
|
.DS_Store
|
||||||
|
@@ -207,10 +207,17 @@ endif ()
|
|||||||
|
|
||||||
if (USE_MINIAUDIO)
|
if (USE_MINIAUDIO)
|
||||||
find_path(MINIAUDIO_INCLUDE_DIR
|
find_path(MINIAUDIO_INCLUDE_DIR
|
||||||
NAMES miniaudio.h
|
NAMES miniaudio.h
|
||||||
HINTS subprojects
|
HINTS subprojects
|
||||||
PATH_SUFFIXES miniaudio
|
PATH_SUFFIXES miniaudio
|
||||||
REQUIRED)
|
REQUIRED)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
target_link_libraries(abaddon "-framework CoreFoundation")
|
||||||
|
target_link_libraries(abaddon "-framework CoreAudio")
|
||||||
|
target_link_libraries(abaddon "-framework AudioToolbox")
|
||||||
|
endif ()
|
||||||
|
|
||||||
target_include_directories(abaddon PUBLIC ${MINIAUDIO_INCLUDE_DIR})
|
target_include_directories(abaddon PUBLIC ${MINIAUDIO_INCLUDE_DIR})
|
||||||
target_compile_definitions(abaddon PRIVATE WITH_MINIAUDIO)
|
target_compile_definitions(abaddon PRIVATE WITH_MINIAUDIO)
|
||||||
endif ()
|
endif ()
|
||||||
|
@@ -68,7 +68,7 @@ the result of fundamental issues with Discord's thread implementation.
|
|||||||
#### Mac:
|
#### Mac:
|
||||||
|
|
||||||
1. `git clone https://github.com/uowuo/abaddon --recurse-submodules="subprojects" && cd abaddon`
|
1. `git clone https://github.com/uowuo/abaddon --recurse-submodules="subprojects" && cd abaddon`
|
||||||
2. `brew install gtkmm3 nlohmann-json libhandy opus libsodium spdlog`
|
2. `brew install gtkmm3 nlohmann-json libhandy opus libsodium spdlog adwaita-icon-theme`
|
||||||
3. `mkdir build && cd build`
|
3. `mkdir build && cd build`
|
||||||
4. `cmake ..`
|
4. `cmake ..`
|
||||||
5. `make`
|
5. `make`
|
||||||
|
@@ -83,7 +83,8 @@ AudioManager::AudioManager() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::get("audio")->info("Audio backend: {}", ma_get_backend_name(m_context.backend));
|
const auto backend_name = ma_get_backend_name(m_context.backend);
|
||||||
|
spdlog::get("audio")->info("Audio backend: {}", backend_name);
|
||||||
|
|
||||||
Enumerate();
|
Enumerate();
|
||||||
|
|
||||||
|
@@ -149,11 +149,6 @@ void ChatInputTextContainer::ShowFileChooser() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto filter_all = Gtk::FileFilter::create();
|
|
||||||
filter_all->set_name("All files (*.*)");
|
|
||||||
filter_all->add_pattern("*.*");
|
|
||||||
dlg->add_filter(filter_all);
|
|
||||||
|
|
||||||
dlg->run();
|
dlg->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@ void from_json(const nlohmann::json &j, MessageDeleteBulkData &m) {
|
|||||||
void from_json(const nlohmann::json &j, GuildMemberListUpdateMessage::GroupItem &m) {
|
void from_json(const nlohmann::json &j, GuildMemberListUpdateMessage::GroupItem &m) {
|
||||||
m.Type = "group";
|
m.Type = "group";
|
||||||
JS_D("id", m.ID);
|
JS_D("id", m.ID);
|
||||||
JS_D("count", m.Count);
|
JS_ON("count", m.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuildMember GuildMemberListUpdateMessage::MemberItem::GetAsMemberData() const {
|
GuildMember GuildMemberListUpdateMessage::MemberItem::GetAsMemberData() const {
|
||||||
@@ -54,16 +54,16 @@ void from_json(const nlohmann::json &j, GuildMemberListUpdateMessage::OpObject &
|
|||||||
m.Items.emplace();
|
m.Items.emplace();
|
||||||
JS_D("range", m.Range);
|
JS_D("range", m.Range);
|
||||||
for (const auto &ij : j.at("items")) {
|
for (const auto &ij : j.at("items")) {
|
||||||
if (ij.contains("group"))
|
if (ij.contains("member")) {
|
||||||
m.Items->push_back(std::make_unique<GuildMemberListUpdateMessage::GroupItem>(ij.at("group")));
|
|
||||||
else if (ij.contains("member"))
|
|
||||||
m.Items->push_back(std::make_unique<GuildMemberListUpdateMessage::MemberItem>(ij.at("member")));
|
m.Items->push_back(std::make_unique<GuildMemberListUpdateMessage::MemberItem>(ij.at("member")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (m.Op == "UPDATE") {
|
} else if (m.Op == "UPDATE") {
|
||||||
JS_D("index", m.Index);
|
JS_D("index", m.Index);
|
||||||
const auto &ij = j.at("item");
|
const auto &ij = j.at("item");
|
||||||
if (ij.contains("member"))
|
if (ij.contains("member")) {
|
||||||
m.OpItem = std::make_unique<GuildMemberListUpdateMessage::MemberItem>(ij.at("member"));
|
m.OpItem = std::make_unique<GuildMemberListUpdateMessage::MemberItem>(ij.at("member"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -182,7 +182,8 @@ void DiscordVoiceClient::Start() {
|
|||||||
|
|
||||||
void DiscordVoiceClient::Stop() {
|
void DiscordVoiceClient::Stop() {
|
||||||
if (!IsConnected() && !IsConnecting()) {
|
if (!IsConnected() && !IsConnecting()) {
|
||||||
m_log->warn("Requested stop while not connected (from {})", GetStateName(m_state));
|
const auto state_name = GetStateName(m_state);
|
||||||
|
m_log->warn("Requested stop while not connected (from {})", state_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +265,8 @@ void DiscordVoiceClient::OnGatewayMessage(const std::string &str) {
|
|||||||
HandleGatewaySpeaking(msg);
|
HandleGatewaySpeaking(msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_log->warn("Unhandled opcode: {}", static_cast<int>(msg.Opcode));
|
const auto opcode_int = static_cast<int>(msg.Opcode);
|
||||||
|
m_log->warn("Unhandled opcode: {}", opcode_int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +320,8 @@ void DiscordVoiceClient::HandleGatewayReady(const VoiceGatewayMessage &m) {
|
|||||||
void DiscordVoiceClient::HandleGatewaySessionDescription(const VoiceGatewayMessage &m) {
|
void DiscordVoiceClient::HandleGatewaySessionDescription(const VoiceGatewayMessage &m) {
|
||||||
VoiceSessionDescriptionData d = m.Data;
|
VoiceSessionDescriptionData d = m.Data;
|
||||||
|
|
||||||
m_log->debug("Received session description (mode: {}) (key: {:ns}) ", d.Mode, spdlog::to_hex(d.SecretKey.begin(), d.SecretKey.end()));
|
const auto key_hex = spdlog::to_hex(d.SecretKey.begin(), d.SecretKey.end());
|
||||||
|
m_log->debug("Received session description (mode: {}) (key: {:ns}) ", d.Mode, key_hex);
|
||||||
|
|
||||||
VoiceSpeakingMessage msg;
|
VoiceSpeakingMessage msg;
|
||||||
msg.Delay = 0;
|
msg.Delay = 0;
|
||||||
@@ -379,7 +382,7 @@ void DiscordVoiceClient::Discovery() {
|
|||||||
m_udp.Send(payload.data(), payload.size());
|
m_udp.Send(payload.data(), payload.size());
|
||||||
|
|
||||||
constexpr int MAX_TRIES = 100;
|
constexpr int MAX_TRIES = 100;
|
||||||
for (int i = 0; i < MAX_TRIES; i++) {
|
for (int i = 1; i <= MAX_TRIES; i++) {
|
||||||
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);
|
||||||
@@ -388,7 +391,7 @@ void DiscordVoiceClient::Discovery() {
|
|||||||
SelectProtocol(ip, port);
|
SelectProtocol(ip, port);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
m_log->error("Received non-discovery packet after sending request (try {}/{})", i + 1, MAX_TRIES);
|
m_log->error("Received non-discovery packet after sending request (try {}/{})", i, MAX_TRIES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,7 +454,8 @@ void DiscordVoiceClient::KeepaliveThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DiscordVoiceClient::SetState(State state) {
|
void DiscordVoiceClient::SetState(State state) {
|
||||||
m_log->debug("Changing state to {}", GetStateName(state));
|
const auto state_name = GetStateName(state);
|
||||||
|
m_log->debug("Changing state to {}", state_name);
|
||||||
m_state = state;
|
m_state = state;
|
||||||
m_signal_state_update.emit(state);
|
m_signal_state_update.emit(state);
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,8 @@ void Websocket::OnMessage(const ix::WebSocketMessagePtr &msg) {
|
|||||||
m_open_dispatcher.emit();
|
m_open_dispatcher.emit();
|
||||||
} break;
|
} break;
|
||||||
case ix::WebSocketMessageType::Close: {
|
case ix::WebSocketMessageType::Close: {
|
||||||
m_log->debug("Received close frame, dispatching. {} ({}){}", msg->closeInfo.code, msg->closeInfo.reason, msg->closeInfo.remote ? " Remote" : "");
|
const auto remote = msg->closeInfo.remote ? " Remote" : "";
|
||||||
|
m_log->debug("Received close frame, dispatching. {} ({}){}", msg->closeInfo.code, msg->closeInfo.reason, remote);
|
||||||
m_close_info = msg->closeInfo;
|
m_close_info = msg->closeInfo;
|
||||||
m_close_dispatcher.emit();
|
m_close_dispatcher.emit();
|
||||||
} break;
|
} break;
|
||||||
|
@@ -103,7 +103,7 @@ std::string Platform::FindResourceFolder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("cant find a resources folder, will try to load from cwd");
|
spdlog::get("discord")->warn("cant find a resources folder, will try to load from cwd");
|
||||||
found_path = ".";
|
found_path = ".";
|
||||||
found = true;
|
found = true;
|
||||||
return found_path;
|
return found_path;
|
||||||
@@ -133,7 +133,7 @@ std::string Platform::FindConfigFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fallback to cwd if cant find + cant make in ~/.config
|
// fallback to cwd if cant find + cant make in ~/.config
|
||||||
puts("can't find configuration file!");
|
spdlog::get("discord")->warn("can't find configuration file!");
|
||||||
return "./abaddon.ini";
|
return "./abaddon.ini";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,13 +147,78 @@ std::string Platform::FindStateCacheFolder() {
|
|||||||
if (util::IsFolder(home_path))
|
if (util::IsFolder(home_path))
|
||||||
return home_path;
|
return home_path;
|
||||||
}
|
}
|
||||||
puts("can't find cache folder!");
|
spdlog::get("discord")->warn("can't find cache folder!");
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
std::string Platform::FindResourceFolder() {
|
||||||
|
static std::string found_path;
|
||||||
|
static bool found = false;
|
||||||
|
if (found) return found_path;
|
||||||
|
|
||||||
|
CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
||||||
|
char resourcePath[PATH_MAX];
|
||||||
|
if (CFURLGetFileSystemRepresentation(resourceURL, true, (UInt8 *)resourcePath, PATH_MAX)) {
|
||||||
|
if (resourceURL != NULL) {
|
||||||
|
CFRelease(resourceURL);
|
||||||
|
}
|
||||||
|
found_path = resourcePath;
|
||||||
|
found = true;
|
||||||
|
return found_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::get("discord")->warn("cant find a resources folder, will try to load from cwd");
|
||||||
|
found_path = ".";
|
||||||
|
found = true;
|
||||||
|
return found_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Platform::FindConfigFile() {
|
||||||
|
const auto cfg = std::getenv("ABADDON_CONFIG");
|
||||||
|
if (cfg != nullptr) return cfg;
|
||||||
|
|
||||||
|
passwd *home = getpwuid(getuid());
|
||||||
|
const char *homeDir = home->pw_dir;
|
||||||
|
|
||||||
|
char appSupportPath[PATH_MAX];
|
||||||
|
snprintf(appSupportPath, sizeof(appSupportPath), "%s/Library/Application Support", homeDir);
|
||||||
|
|
||||||
|
char homefolder_path[PATH_MAX];
|
||||||
|
snprintf(homefolder_path, sizeof(homefolder_path), "%s/%s", appSupportPath, "com.github.uowuo.abaddon");
|
||||||
|
|
||||||
|
if (mkdir(homefolder_path, 0755) == 0) {
|
||||||
|
spdlog::get("discord")->warn("created Application Support dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
char home_path[PATH_MAX];
|
||||||
|
snprintf(home_path, sizeof(home_path), "%s/%s", homefolder_path, "/abaddon.ini");
|
||||||
|
|
||||||
|
return home_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Platform::FindStateCacheFolder() {
|
||||||
|
|
||||||
|
passwd *home = getpwuid(getuid());
|
||||||
|
const char *homeDir = home->pw_dir;
|
||||||
|
|
||||||
|
char appSupportPath[PATH_MAX];
|
||||||
|
snprintf(appSupportPath, sizeof(appSupportPath), "%s/Library/Application Support", homeDir);
|
||||||
|
|
||||||
|
char home_path[PATH_MAX];
|
||||||
|
snprintf(home_path, sizeof(home_path), "%s/%s", appSupportPath, "com.github.uowuo.abaddon");
|
||||||
|
|
||||||
|
return home_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
std::string Platform::FindResourceFolder() {
|
std::string Platform::FindResourceFolder() {
|
||||||
puts("unknown OS, trying to load resources from cwd");
|
spdlog::get("discord")->warn("unknown OS, trying to load resources from cwd");
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,12 +226,12 @@ std::string Platform::FindConfigFile() {
|
|||||||
const auto x = std::getenv("ABADDON_CONFIG");
|
const auto x = std::getenv("ABADDON_CONFIG");
|
||||||
if (x != nullptr)
|
if (x != nullptr)
|
||||||
return x;
|
return x;
|
||||||
puts("unknown OS, trying to load config from cwd");
|
spdlog::get("discord")->warn("unknown OS, trying to load config from cwd");
|
||||||
return "./abaddon.ini";
|
return "./abaddon.ini";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Platform::FindStateCacheFolder() {
|
std::string Platform::FindStateCacheFolder() {
|
||||||
puts("unknown OS, setting state cache folder to cwd");
|
spdlog::get("discord")->warn("unknown OS, setting state cache folder to cwd");
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -111,9 +111,10 @@ void RemoteAuthClient::HandleGatewayPendingTicket(const nlohmann::json &j) {
|
|||||||
const auto encrypted_payload = Glib::Base64::decode(j.at("encrypted_user_payload").get<std::string>());
|
const auto encrypted_payload = Glib::Base64::decode(j.at("encrypted_user_payload").get<std::string>());
|
||||||
const auto payload = Decrypt(reinterpret_cast<const unsigned char *>(encrypted_payload.data()), encrypted_payload.size());
|
const auto payload = Decrypt(reinterpret_cast<const unsigned char *>(encrypted_payload.data()), encrypted_payload.size());
|
||||||
|
|
||||||
m_log->trace("User payload: {}", std::string(payload.begin(), payload.end()));
|
const auto payload_str = std::string(payload.begin(), payload.end());
|
||||||
|
m_log->trace("User payload: {}", payload_str);
|
||||||
|
|
||||||
const std::vector<Glib::ustring> user_info = Glib::Regex::split_simple(":", std::string(payload.begin(), payload.end()));
|
const std::vector<Glib::ustring> user_info = Glib::Regex::split_simple(":", payload_str);
|
||||||
Snowflake user_id;
|
Snowflake user_id;
|
||||||
std::string discriminator;
|
std::string discriminator;
|
||||||
std::string avatar_hash;
|
std::string avatar_hash;
|
||||||
@@ -140,7 +141,8 @@ void RemoteAuthClient::HandleGatewayCancel(const nlohmann::json &j) {
|
|||||||
|
|
||||||
void RemoteAuthClient::OnRemoteAuthLoginResponse(const std::optional<std::string> &encrypted_token, DiscordError err) {
|
void RemoteAuthClient::OnRemoteAuthLoginResponse(const std::optional<std::string> &encrypted_token, DiscordError err) {
|
||||||
if (!encrypted_token.has_value()) {
|
if (!encrypted_token.has_value()) {
|
||||||
m_log->error("Remote auth login failed: {}", static_cast<int>(err));
|
const auto err_int = static_cast<int>(err);
|
||||||
|
m_log->error("Remote auth login failed: {}", err_int);
|
||||||
if (err == DiscordError::CAPTCHA_REQUIRED) {
|
if (err == DiscordError::CAPTCHA_REQUIRED) {
|
||||||
m_signal_error.emit("Discord is requiring a captcha. You must use a web browser to log in.");
|
m_signal_error.emit("Discord is requiring a captcha. You must use a web browser to log in.");
|
||||||
} else {
|
} else {
|
||||||
|
@@ -160,7 +160,10 @@ std::string GetExtension(std::string url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsURLViewableImage(const std::string &url) {
|
bool IsURLViewableImage(const std::string &url) {
|
||||||
const auto ext = GetExtension(url);
|
std::string lw_url = url;
|
||||||
|
std::transform(lw_url.begin(), lw_url.end(), lw_url.begin(), ::tolower);
|
||||||
|
|
||||||
|
const auto ext = GetExtension(lw_url);
|
||||||
static const char *exts[] = { ".jpeg",
|
static const char *exts[] = { ".jpeg",
|
||||||
".jpg",
|
".jpg",
|
||||||
".png", nullptr };
|
".png", nullptr };
|
||||||
|
@@ -35,7 +35,6 @@ VoiceSettingsWindow::VoiceSettingsWindow()
|
|||||||
m_encoding_mode.signal_changed().connect([this]() {
|
m_encoding_mode.signal_changed().connect([this]() {
|
||||||
const auto mode = m_encoding_mode.get_active_text();
|
const auto mode = m_encoding_mode.get_active_text();
|
||||||
auto &audio = Abaddon::Get().GetAudio();
|
auto &audio = Abaddon::Get().GetAudio();
|
||||||
spdlog::get("audio")->debug("Chose encoding mode: {}", mode.c_str());
|
|
||||||
if (mode == "Voice") {
|
if (mode == "Voice") {
|
||||||
audio.SetEncodingApplication(OPUS_APPLICATION_VOIP);
|
audio.SetEncodingApplication(OPUS_APPLICATION_VOIP);
|
||||||
} else if (mode == "Music") {
|
} else if (mode == "Music") {
|
||||||
@@ -67,7 +66,6 @@ VoiceSettingsWindow::VoiceSettingsWindow()
|
|||||||
m_signal.signal_changed().connect([this]() {
|
m_signal.signal_changed().connect([this]() {
|
||||||
const auto signal = m_signal.get_active_text();
|
const auto signal = m_signal.get_active_text();
|
||||||
auto &audio = Abaddon::Get().GetAudio();
|
auto &audio = Abaddon::Get().GetAudio();
|
||||||
spdlog::get("audio")->debug("Chose signal hint: {}", signal.c_str());
|
|
||||||
if (signal == "Auto") {
|
if (signal == "Auto") {
|
||||||
audio.SetSignalHint(OPUS_AUTO);
|
audio.SetSignalHint(OPUS_AUTO);
|
||||||
} else if (signal == "Voice") {
|
} else if (signal == "Voice") {
|
||||||
|
Reference in New Issue
Block a user