From ce38e7b0b14a31904c7d31a91596befb87e776df Mon Sep 17 00:00:00 2001 From: Wes Taylor Date: Fri, 2 Aug 2019 09:06:02 -0500 Subject: [PATCH] [App] Add support for Discord rich presence. --- .gitmodules | 6 +++ premake5.lua | 2 + src/xenia/app/discord/discord_presence.cc | 56 +++++++++++++++++++++++ src/xenia/app/discord/discord_presence.h | 29 ++++++++++++ src/xenia/app/discord/premake5.lua | 20 ++++++++ src/xenia/app/emulator_window.cc | 16 +++++++ src/xenia/app/premake5.lua | 2 + third_party/discord-rpc | 1 + third_party/discord-rpc.lua | 37 +++++++++++++++ third_party/rapidjson | 1 + 10 files changed, 170 insertions(+) create mode 100644 src/xenia/app/discord/discord_presence.cc create mode 100644 src/xenia/app/discord/discord_presence.h create mode 100644 src/xenia/app/discord/premake5.lua create mode 160000 third_party/discord-rpc create mode 100644 third_party/discord-rpc.lua create mode 160000 third_party/rapidjson diff --git a/.gitmodules b/.gitmodules index 5474a9e62..5041aa634 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,6 +40,12 @@ [submodule "third_party/volk"] path = third_party/volk url = https://github.com/zeux/volk.git +[submodule "third_party/discord-rpc"] + path = third_party/discord-rpc + url = https://github.com/discordapp/discord-rpc +[submodule "third_party/rapidjson"] + path = third_party/rapidjson + url = https://github.com/Tencent/rapidjson.git [submodule "third_party/aes_128"] path = third_party/aes_128 url = https://github.com/openluopworld/aes_128.git diff --git a/premake5.lua b/premake5.lua index 96072c4c4..2e1d73e2e 100644 --- a/premake5.lua +++ b/premake5.lua @@ -232,6 +232,7 @@ solution("xenia") -- Include third party files first so they don't have to deal with gflags. include("third_party/aes_128.lua") include("third_party/capstone.lua") + include("third_party/discord-rpc.lua") include("third_party/gflags.lua") include("third_party/glew.lua") include("third_party/glslang-spirv.lua") @@ -246,6 +247,7 @@ solution("xenia") include("src/xenia") include("src/xenia/app") + include("src/xenia/app/discord") include("src/xenia/apu") include("src/xenia/apu/nop") include("src/xenia/base") diff --git a/src/xenia/app/discord/discord_presence.cc b/src/xenia/app/discord/discord_presence.cc new file mode 100644 index 000000000..1bf93c177 --- /dev/null +++ b/src/xenia/app/discord/discord_presence.cc @@ -0,0 +1,56 @@ +/** +****************************************************************************** +* Xenia : Xbox 360 Emulator Research Project * +****************************************************************************** +* Copyright 2015 Ben Vanik. All rights reserved. * +* Released under the BSD license - see LICENSE in the root for more details. * +****************************************************************************** +*/ + +#include "discord_presence.h" +#include "third_party/discord-rpc/include/discord_rpc.h" +#include "xenia/base/string.h" + +namespace xe { +namespace discord { + +void HandleDiscordReady(const DiscordUser* request) {} +void HandleDiscordError(int errorCode, const char* message) {} +void HandleDiscordJoinGame(const char* joinSecret) {} +void HandleDiscordJoinRequest(const DiscordUser* request) {} +void HandleDiscordSpectateGame(const char* spectateSecret) {} + +void DiscordPresence::InitializeDiscord() { + DiscordEventHandlers handlers = {}; + handlers.ready = &HandleDiscordReady; + handlers.errored = &HandleDiscordError; + handlers.joinGame = &HandleDiscordJoinGame; + handlers.joinRequest = &HandleDiscordJoinRequest; + handlers.spectateGame = &HandleDiscordSpectateGame; + Discord_Initialize("606840046649081857", &handlers, 0, ""); +} + +void DiscordPresence::NotPlaying() { + DiscordRichPresence discordPresence = {}; + discordPresence.state = "Idle"; + discordPresence.details = "Standby"; + discordPresence.largeImageKey = "default"; + discordPresence.instance = 1; + Discord_UpdatePresence(&discordPresence); +} + +void DiscordPresence::PlayingTitle(std::wstring game_title) { + auto discord_game_title = xe::to_string(game_title); + DiscordRichPresence discordPresence = {}; + discordPresence.state = "In Game"; + discordPresence.details = discord_game_title.c_str(); + discordPresence.smallImageKey = "default"; + discordPresence.largeImageKey = "defaultgame"; + discordPresence.instance = 1; + Discord_UpdatePresence(&discordPresence); +} + +void DiscordPresence::ShutdownDiscord() { Discord_Shutdown(); } + +} // namespace discord +} // namespace xe diff --git a/src/xenia/app/discord/discord_presence.h b/src/xenia/app/discord/discord_presence.h new file mode 100644 index 000000000..9e7d67f59 --- /dev/null +++ b/src/xenia/app/discord/discord_presence.h @@ -0,0 +1,29 @@ +/** +****************************************************************************** +* Xenia : Xbox 360 Emulator Research Project * +****************************************************************************** +* Copyright 2015 Ben Vanik. All rights reserved. * +* Released under the BSD license - see LICENSE in the root for more details. * +****************************************************************************** +*/ + +#ifndef XENIA_DISCORD_DISCORD_PRESENCE_H_ +#define XENIA_DISCORD_DISCORD_PRESENCE_H_ + +#include + +namespace xe { +namespace discord { + +class DiscordPresence { + public: + static void InitializeDiscord(); + static void NotPlaying(); + static void PlayingTitle(std::wstring game_title); + static void ShutdownDiscord(); +}; + +} // namespace discord +} // namespace xe + +#endif // XENIA_DISCORD_DISCORD_PRESENCE_H_ diff --git a/src/xenia/app/discord/premake5.lua b/src/xenia/app/discord/premake5.lua new file mode 100644 index 000000000..cd9cf12c5 --- /dev/null +++ b/src/xenia/app/discord/premake5.lua @@ -0,0 +1,20 @@ +project_root = "../../../.." +include(project_root.."/tools/build") + +group("src") +project("xenia-app-discord") + uuid("d14c0885-22d2-40de-ab28-7b234ef2b949") + kind("StaticLib") + language("C++") + links({ + "discord-rpc" + }) + defines({ + }) + includedirs({ + project_root.."/third_party/discord-rpc/src" + }) + files({ + "discord_presence.cc", + "discord_presence.h" + }) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index e15a97da9..882f4caa9 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -7,12 +7,15 @@ ****************************************************************************** */ +#include + #include "xenia/app/emulator_window.h" // Autogenerated by `xb premake`. #include "build/version.h" #include "third_party/imgui/imgui.h" +#include "xenia/app/discord/discord_presence.h" #include "xenia/base/clock.h" #include "xenia/base/debugging.h" #include "xenia/base/logging.h" @@ -26,6 +29,8 @@ #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +DEFINE_bool(discord, false, "Enable Discord rich presence"); + namespace xe { namespace app { @@ -80,6 +85,11 @@ bool EmulatorWindow::Initialize() { return false; } + if (FLAGS_discord) { + discord::DiscordPresence::InitializeDiscord(); + discord::DiscordPresence::NotPlaying(); + } + UpdateTitle(); window_->on_closed.AddListener([this](UIEvent* e) { loop_->Quit(); }); @@ -334,6 +344,9 @@ void EmulatorWindow::FileOpen() { void EmulatorWindow::FileClose() { if (emulator_->is_title_open()) { emulator_->TerminateTitle(); + if (FLAGS_discord) { + discord::DiscordPresence::NotPlaying(); + } } } @@ -431,6 +444,9 @@ void EmulatorWindow::UpdateTitle() { auto game_title = emulator()->game_title(); title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(), game_title.c_str()); + if (FLAGS_discord) { + discord::DiscordPresence::PlayingTitle(game_title); + } } auto graphics_system = emulator()->graphics_system(); diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 35361d011..2db66ffeb 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -10,6 +10,7 @@ project("xenia-app") links({ "aes_128", "capstone", + "discord-rpc", "gflags", "glew", "glslang-spirv", @@ -20,6 +21,7 @@ project("xenia-app") "snappy", "spirv-tools", "volk", + "xenia-app-discord", "xenia-apu", "xenia-apu-nop", "xenia-base", diff --git a/third_party/discord-rpc b/third_party/discord-rpc new file mode 160000 index 000000000..ba9fe00c4 --- /dev/null +++ b/third_party/discord-rpc @@ -0,0 +1 @@ +Subproject commit ba9fe00c4de1d680cdc56605d9c0d2b4cf8e7a07 diff --git a/third_party/discord-rpc.lua b/third_party/discord-rpc.lua new file mode 100644 index 000000000..1f6e795f8 --- /dev/null +++ b/third_party/discord-rpc.lua @@ -0,0 +1,37 @@ +group("third_party") +project("discord-rpc") + uuid("012f6131-efc0-4abd-852d-a33640732d4c") + kind("StaticLib") + language("C++") + links({ + }) + defines({ + "_LIB", + }) + includedirs({ + "discord-rpc/include", + "rapidjson/include" + }) + files({ + "discord-rpc/src/connection.h", + "discord-rpc/src/discord_rpc.cpp", + "discord-rpc/src/msg_queue.h", + "discord-rpc/src/rpc_connection.cpp", + "discord-rpc/src/rpc_connection.h", + "discord-rpc/src/serialization.cpp", + "discord-rpc/src/serialization.h" + }) + filter("platforms:Linux") + files({ + "discord-rpc/src/connection_unix.cpp", + "discord-rpc/src/discord_register_linux.cpp" + }) + filter("platforms:Mac") + files({ + "discord-rpc/src/discord_register_osx.m" + }) + filter("platforms:Windows") + files({ + "discord-rpc/src/connection_win.cpp", + "discord-rpc/src/discord_register_win.cpp" + }) \ No newline at end of file diff --git a/third_party/rapidjson b/third_party/rapidjson new file mode 160000 index 000000000..af223d44f --- /dev/null +++ b/third_party/rapidjson @@ -0,0 +1 @@ +Subproject commit af223d44f4e8d3772cb1ac0ce8bc2a132b51717f