From 5f7a2fa65f77f3f118cb2c52db621b6c2d97827a Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Tue, 27 Aug 2024 22:31:55 +0200 Subject: [PATCH] More nice touches to DiscordRPC --- .../src/discord_register_linux.cpp | 12 +-- src/Discord.hpp | 98 ++++++++++++------- src/backend/Core.cpp | 2 +- src/backend/core/mmio/PIF/MupenMovie.cpp | 1 + src/backend/core/mmio/PIF/MupenMovie.hpp | 4 +- src/frontend/EmuThread.hpp | 6 +- src/frontend/KaizenQt.cpp | 6 +- 7 files changed, 83 insertions(+), 46 deletions(-) diff --git a/external/discord_rpc/src/discord_register_linux.cpp b/external/discord_rpc/src/discord_register_linux.cpp index dd92eea0..dfc5340c 100644 --- a/external/discord_rpc/src/discord_register_linux.cpp +++ b/external/discord_rpc/src/discord_register_linux.cpp @@ -42,12 +42,12 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const } const char* desktopFileFormat = "[Desktop Entry]\n" - "Name=Game %s\n" - "Exec=%s %%u\n" // note: it really wants that %u in there - "Type=Application\n" - "NoDisplay=true\n" - "Categories=Discord;Games;\n" - "MimeType=x-scheme-handler/discord-%s;\n"; + "Name=Game %s\n" + "Exec=%s %%u\n" // note: it really wants that %u in there + "Type=Application\n" + "NoDisplay=true\n" + "Categories=Discord;Games;\n" + "MimeType=x-scheme-handler/discord-%s;\n"; char desktopFile[2048]; int fileLen = snprintf( desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId); diff --git a/src/Discord.hpp b/src/Discord.hpp index 434e3a41..02b92aca 100644 --- a/src/Discord.hpp +++ b/src/Discord.hpp @@ -5,42 +5,72 @@ #include namespace Util { -enum State { - Idling, - Playing, - MovieReplay, - Paused, -}; +struct RPC { + enum State { + Idling, + Playing, + MovieReplay, + Paused, + }; -FORCE_INLINE void UpdateRPC(State state, const std::string &game = "", const std::string &movieName = "") { - DiscordRichPresence presence{}; - std::string textState, textDetails; - - switch (state) { - case Idling: - textDetails = "Idling"; - break; - case Playing: - textDetails = "In-game"; - textState = "Playing \"" + game + "\""; - break; - case MovieReplay: - textDetails = "In-game"; - textState = "Replaying movie \"" + movieName + "\" in \"" + game + "\""; - break; - case Paused: - textDetails = "In-game"; - textState = "Playing \"" + game + "\" (Paused)"; - break; + RPC() { + Discord_Initialize("1049669178124148806", &handlers, 1, nullptr); + startTimestamp = time(nullptr); } - presence.details = textDetails.c_str(); - presence.state = textState.c_str(); - presence.startTimestamp = time(nullptr); - presence.largeImageText = "Kaizen"; - presence.largeImageKey = "logo"; - Discord_UpdatePresence(&presence); -} + static RPC &GetInstance() { + static RPC instance; + return instance; + } -FORCE_INLINE void ClearRPC() { Discord_ClearPresence(); } + [[nodiscard]] FORCE_INLINE const State &GetState() const { return currentState; } + + FORCE_INLINE void Update(State state, const std::string &game = "", const std::string &movieName = "") { + DiscordRichPresence presence{}; + std::string textState, textDetails; + currentState = state == Paused ? currentState : state; + + switch (state) { + case Idling: + textDetails = "Idling"; + break; + case Playing: + textDetails = "In-game"; + textState = "Playing \"" + game + "\""; + break; + case MovieReplay: + textDetails = "In-game"; + textState = "Replaying movie \"" + movieName + "\" in \"" + game + "\""; + break; + case Paused: + switch (currentState) { + case Playing: + textDetails = "In-game"; + textState = "Playing \"" + game + "\""; + break; + case MovieReplay: + textDetails = "In-game"; + textState = "Replaying movie \"" + movieName + "\" in \"" + game + "\""; + break; + default:; + } + textState += " (Paused)"; + break; + } + + presence.details = textDetails.c_str(); + presence.state = textState.c_str(); + presence.startTimestamp = startTimestamp; + presence.largeImageText = "Kaizen"; + presence.largeImageKey = "logo"; + Discord_UpdatePresence(&presence); + } + + FORCE_INLINE void Clear() { Discord_ClearPresence(); } + +private: + DiscordEventHandlers handlers{}; + s64 startTimestamp{}; + State currentState; +}; } // namespace Util diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index b938b1de..6552af13 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -3,7 +3,7 @@ #include namespace n64 { -Core::Core(ParallelRDP ¶llel) : cpu(std::make_unique(parallel)) {} +Core::Core(ParallelRDP ¶llel) : cpu(std::make_unique(parallel)) {} void Core::Stop() { render = false; diff --git a/src/backend/core/mmio/PIF/MupenMovie.cpp b/src/backend/core/mmio/PIF/MupenMovie.cpp index 1ecf9e00..92fbd104 100644 --- a/src/backend/core/mmio/PIF/MupenMovie.cpp +++ b/src/backend/core/mmio/PIF/MupenMovie.cpp @@ -29,6 +29,7 @@ union TASMovieControllerData { static_assert(sizeof(TASMovieControllerData) == 4); bool MupenMovie::Load(const fs::path &path) { + filename = path.stem().string(); loadedTasMovie = Util::ReadFileBinary(path.string()); if (!IsLoaded()) { Util::error("Error loading movie!"); diff --git a/src/backend/core/mmio/PIF/MupenMovie.hpp b/src/backend/core/mmio/PIF/MupenMovie.hpp index ac2cc5d4..e4c5c60c 100644 --- a/src/backend/core/mmio/PIF/MupenMovie.hpp +++ b/src/backend/core/mmio/PIF/MupenMovie.hpp @@ -51,9 +51,11 @@ struct MupenMovie { bool Load(const fs::path &); void Reset(); n64::Controller NextInputs(); - bool IsLoaded() const { return !loadedTasMovie.empty(); } + [[nodiscard]] bool IsLoaded() const { return !loadedTasMovie.empty(); } + [[nodiscard]] const std::string &GetFilename() const { return filename; } private: + std::string filename{}; std::vector loadedTasMovie = {}; TASMovieHeader loadedTasMovieHeader = {}; uint32_t loadedTasMovieIndex = 0; diff --git a/src/frontend/EmuThread.hpp b/src/frontend/EmuThread.hpp index fe1d0877..3e36c98e 100644 --- a/src/frontend/EmuThread.hpp +++ b/src/frontend/EmuThread.hpp @@ -27,7 +27,9 @@ public: void TogglePause() { core.pause = !core.pause; - Util::UpdateRPC(core.pause ? Util::Idling : Util::Playing); + Util::RPC::GetInstance().Update(core.pause ? Util::RPC::Paused : Util::RPC::GetInstance().GetState(), + core.cpu->GetMem().rom.gameNameDB, + core.cpu->GetMem().mmio.si.pif.movie.GetFilename()); } void SetRender(bool v) { core.render = v; } @@ -40,7 +42,7 @@ public: } void Stop() { - Discord_ClearPresence(); + Util::RPC::GetInstance().Update(Util::RPC::Idling); core.rom = {}; core.pause = true; core.Stop(); diff --git a/src/frontend/KaizenQt.cpp b/src/frontend/KaizenQt.cpp index f739f49d..f61dc71a 100644 --- a/src/frontend/KaizenQt.cpp +++ b/src/frontend/KaizenQt.cpp @@ -15,6 +15,7 @@ KaizenQt::KaizenQt() noexcept : QWidget(nullptr) { std::move(mainWindow->view.vulkanWidget->windowInfo), *settingsWindow); ConnectMainWindowSignalsToSlots(); + Util::RPC::GetInstance().Update(Util::RPC::Idling); setAcceptDrops(true); setFocusPolicy(Qt::StrongFocus); @@ -54,7 +55,7 @@ void KaizenQt::LoadROM(const QString &fileName) noexcept { emuThread->core.LoadROM(fileName.toStdString()); auto gameNameDB = emuThread->core.cpu->GetMem().rom.gameNameDB; mainWindow->setWindowTitle(emuThread->core.cpu->GetMem().rom.gameNameDB.c_str()); - UpdateRPC(Util::Playing, gameNameDB); + Util::RPC::GetInstance().Update(Util::RPC::Playing, gameNameDB); } void KaizenQt::Quit() noexcept { @@ -69,7 +70,8 @@ void KaizenQt::Quit() noexcept { void KaizenQt::LoadTAS(const QString &fileName) const noexcept { emuThread->core.LoadTAS(fs::path(fileName.toStdString())); auto gameNameDB = emuThread->core.cpu->GetMem().rom.gameNameDB; - UpdateRPC(Util::MovieReplay, gameNameDB, fileName.toStdString()); + auto movieName = fs::path(fileName.toStdString()).stem().string(); + Util::RPC::GetInstance().Update(Util::RPC::MovieReplay, gameNameDB, movieName); } void KaizenQt::keyPressEvent(QKeyEvent *e) {