diff --git a/Externals/discord-rpc/bin/discord-rpc.dll b/Externals/discord-rpc/bin/discord-rpc.dll new file mode 100644 index 0000000000..289d550306 Binary files /dev/null and b/Externals/discord-rpc/bin/discord-rpc.dll differ diff --git a/Externals/discord-rpc/include/discord_register.h b/Externals/discord-rpc/include/discord_register.h new file mode 100644 index 0000000000..4c16b68a7f --- /dev/null +++ b/Externals/discord-rpc/include/discord_register.h @@ -0,0 +1,26 @@ +#pragma once + +#if defined(DISCORD_DYNAMIC_LIB) +# if defined(_WIN32) +# if defined(DISCORD_BUILDING_SDK) +# define DISCORD_EXPORT __declspec(dllexport) +# else +# define DISCORD_EXPORT __declspec(dllimport) +# endif +# else +# define DISCORD_EXPORT __attribute__((visibility("default"))) +# endif +#else +# define DISCORD_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command); +DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId); + +#ifdef __cplusplus +} +#endif diff --git a/Externals/discord-rpc/include/discord_rpc.h b/Externals/discord-rpc/include/discord_rpc.h new file mode 100644 index 0000000000..3e1441e058 --- /dev/null +++ b/Externals/discord-rpc/include/discord_rpc.h @@ -0,0 +1,87 @@ +#pragma once +#include + +// clang-format off + +#if defined(DISCORD_DYNAMIC_LIB) +# if defined(_WIN32) +# if defined(DISCORD_BUILDING_SDK) +# define DISCORD_EXPORT __declspec(dllexport) +# else +# define DISCORD_EXPORT __declspec(dllimport) +# endif +# else +# define DISCORD_EXPORT __attribute__((visibility("default"))) +# endif +#else +# define DISCORD_EXPORT +#endif + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DiscordRichPresence { + const char* state; /* max 128 bytes */ + const char* details; /* max 128 bytes */ + int64_t startTimestamp; + int64_t endTimestamp; + const char* largeImageKey; /* max 32 bytes */ + const char* largeImageText; /* max 128 bytes */ + const char* smallImageKey; /* max 32 bytes */ + const char* smallImageText; /* max 128 bytes */ + const char* partyId; /* max 128 bytes */ + int partySize; + int partyMax; + const char* matchSecret; /* max 128 bytes */ + const char* joinSecret; /* max 128 bytes */ + const char* spectateSecret; /* max 128 bytes */ + int8_t instance; +} DiscordRichPresence; + +typedef struct DiscordUser { + const char* userId; + const char* username; + const char* discriminator; + const char* avatar; +} DiscordUser; + +typedef struct DiscordEventHandlers { + void (*ready)(const DiscordUser* request); + void (*disconnected)(int errorCode, const char* message); + void (*errored)(int errorCode, const char* message); + void (*joinGame)(const char* joinSecret); + void (*spectateGame)(const char* spectateSecret); + void (*joinRequest)(const DiscordUser* request); +} DiscordEventHandlers; + +#define DISCORD_REPLY_NO 0 +#define DISCORD_REPLY_YES 1 +#define DISCORD_REPLY_IGNORE 2 + +DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId); +DISCORD_EXPORT void Discord_Shutdown(void); + +/* checks for incoming messages, dispatches callbacks */ +DISCORD_EXPORT void Discord_RunCallbacks(void); + +/* If you disable the lib starting its own io thread, you'll need to call this from your own */ +#ifdef DISCORD_DISABLE_IO_THREAD +DISCORD_EXPORT void Discord_UpdateConnection(void); +#endif + +DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence); +DISCORD_EXPORT void Discord_ClearPresence(void); + +DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply); + +DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/Externals/discord-rpc/lib/discord-rpc.lib b/Externals/discord-rpc/lib/discord-rpc.lib new file mode 100644 index 0000000000..fdf4abe6d0 Binary files /dev/null and b/Externals/discord-rpc/lib/discord-rpc.lib differ diff --git a/Externals/discord-rpc/lib/libdiscord-rpc.dylib b/Externals/discord-rpc/lib/libdiscord-rpc.dylib new file mode 100644 index 0000000000..b48f5616cd Binary files /dev/null and b/Externals/discord-rpc/lib/libdiscord-rpc.dylib differ diff --git a/Externals/discord-rpc/lib/libdiscord-rpc.so b/Externals/discord-rpc/lib/libdiscord-rpc.so new file mode 100644 index 0000000000..43f56c753e Binary files /dev/null and b/Externals/discord-rpc/lib/libdiscord-rpc.so differ diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index ae841ca4d1..b84e98dd70 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -592,4 +592,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 944dfc1436..1dad1f08f2 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -1584,4 +1584,4 @@ - + \ No newline at end of file diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index decbae647a..2b0698682a 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -40,8 +40,8 @@ - $(ExternalsDir)ffmpeg\lib;%(AdditionalLibraryDirectories) - avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;%(AdditionalDependencies) + $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) $(ProjectDir)VideoInterface;$(ProjectDir)GameList;$(ProjectDir)Debugger;$(ProjectDir)Settings;$(ProjectDir)Config;$(ProjectDir)Config\Mapping;$(ProjectDir)Config\Graphics;$(ProjectDir)NetPlay;$(ProjectDir)QtUtils;$(ProjectDir)TAS;$(ProjectDir)FIFO;%(AdditionalIncludeDirectories) diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 524ec9114b..edd4bb199a 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -79,6 +79,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "UICommon/DiscordPresence.h" #include "UICommon/UICommon.h" #if defined(HAVE_XRANDR) && HAVE_XRANDR @@ -569,6 +570,7 @@ void MainWindow::OnStopComplete() m_stop_requested = false; HideRenderWidget(); EnableScreenSaver(true); + Discord::UpdateDiscordPresence(); SetFullScreenResolution(false); @@ -719,6 +721,7 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) return; } ShowRenderWidget(); + Discord::UpdateDiscordPresence(); #ifdef Q_OS_WIN // Prevents Windows from sleeping, turning off the display, or idling diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index d7d7519f16..1aabf572a2 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -38,8 +38,8 @@ - $(ExternalsDir)ffmpeg\lib;%(AdditionalLibraryDirectories) - avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;%(AdditionalDependencies) + $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) $(ExternalsDir)wxWidgets3\include;%(AdditionalIncludeDirectories) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index ea6f504e7c..63dcdc16c5 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -91,6 +91,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "UICommon/DiscordPresence.h" #include "UICommon/GameFile.h" #include "UICommon/UICommon.h" @@ -744,6 +745,7 @@ void CFrame::StartGame(std::unique_ptr boot) else { EnableScreenSaver(false); + Discord::UpdateDiscordPresence(); // We need this specifically to support setting the focus properly when using // the 'render to main window' feature on Windows @@ -930,6 +932,7 @@ void CFrame::OnStopped() wxPostEvent(GetMenuBar(), wxCommandEvent{DOLPHIN_EVT_UPDATE_LOAD_WII_MENU_ITEM}); EnableScreenSaver(true); + Discord::UpdateDiscordPresence(); m_render_frame->SetTitle(StrToWxStr(Common::scm_rev_str)); diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index ed94341182..8b3976fb0c 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(uicommon AutoUpdate.cpp CommandLineParse.cpp Disassembler.cpp + DiscordPresence.cpp GameFile.cpp GameFileCache.cpp UICommon.cpp diff --git a/Source/Core/UICommon/DiscordPresence.cpp b/Source/Core/UICommon/DiscordPresence.cpp new file mode 100644 index 0000000000..0ec4cdb5b8 --- /dev/null +++ b/Source/Core/UICommon/DiscordPresence.cpp @@ -0,0 +1,48 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#ifdef USE_DISCORD_PRESENCE + +#include "UICommon/DiscordPresence.h" + +#include +#include + +#include "Core/ConfigManager.h" + +#endif + +namespace Discord +{ +void Init() +{ +#ifdef USE_DISCORD_PRESENCE + DiscordEventHandlers handlers = {}; + // The number is the client ID for Dolphin, it's used for images and the appication name + Discord_Initialize("450033159212630028", &handlers, 1, nullptr); + UpdateDiscordPresence(); +#endif +} + +void UpdateDiscordPresence() +{ +#ifdef USE_DISCORD_PRESENCE + const std::string& title = SConfig::GetInstance().GetTitleDescription(); + + DiscordRichPresence discord_presence = {}; + discord_presence.largeImageKey = "dolphin_logo"; + discord_presence.largeImageText = "Dolphin is an emulator for the GameCube and the Wii."; + discord_presence.details = title.empty() ? "Not in-game" : title.c_str(); + discord_presence.startTimestamp = std::time(nullptr); + Discord_UpdatePresence(&discord_presence); +#endif +} + +void Shutdown() +{ +#ifdef USE_DISCORD_PRESENCE + Discord_Shutdown(); +#endif +} +} // namespace Discord diff --git a/Source/Core/UICommon/DiscordPresence.h b/Source/Core/UICommon/DiscordPresence.h new file mode 100644 index 0000000000..dc516fd655 --- /dev/null +++ b/Source/Core/UICommon/DiscordPresence.h @@ -0,0 +1,12 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +namespace Discord +{ +void Init(); +void UpdateDiscordPresence(); +void Shutdown(); +} // namespace Discord diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 16fd08bad0..24a60b27a8 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -33,6 +33,7 @@ #include "InputCommon/GCAdapter.h" +#include "UICommon/DiscordPresence.h" #include "UICommon/UICommon.h" #include "UICommon/USBUtils.h" @@ -75,6 +76,7 @@ void Init() Config::AddConfigChangedCallback(InitCustomPaths); Config::AddLayer(ConfigLoaders::GenerateBaseConfigLoader()); SConfig::Init(); + Discord::Init(); LogManager::Init(); VideoBackendBase::PopulateList(); WiimoteReal::LoadSettings(); @@ -90,6 +92,7 @@ void Shutdown() WiimoteReal::Shutdown(); VideoBackendBase::ClearList(); LogManager::Shutdown(); + Discord::Shutdown(); SConfig::Shutdown(); Config::Shutdown(); } diff --git a/Source/Core/UICommon/UICommon.vcxproj b/Source/Core/UICommon/UICommon.vcxproj index 4ee5a357c0..1a650b3a0c 100644 --- a/Source/Core/UICommon/UICommon.vcxproj +++ b/Source/Core/UICommon/UICommon.vcxproj @@ -35,6 +35,16 @@ + + + USE_DISCORD_PRESENCE;%(PreprocessorDefinitions) + + + + + USE_DISCORD_PRESENCE;%(PreprocessorDefinitions) + + @@ -49,6 +59,7 @@ + @@ -61,6 +72,7 @@ + diff --git a/Source/UnitTests/UnitTests.vcxproj b/Source/UnitTests/UnitTests.vcxproj index d356803905..cb5c37b863 100644 --- a/Source/UnitTests/UnitTests.vcxproj +++ b/Source/UnitTests/UnitTests.vcxproj @@ -45,8 +45,8 @@ The following libs are needed since we pull in pretty much the entire dolphin codebase. --> - $(ExternalsDir)ffmpeg\lib;%(AdditionalLibraryDirectories) - avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;%(AdditionalDependencies) + $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) Console