Permalink
Browse files

Merge pull request #11296 from hrydgard/discord-presence

Discord presence - show the current game
  • Loading branch information...
hrydgard committed Aug 14, 2018
2 parents 187204d + c0ba66c commit 0684068c8178d9afc649f4667b0da5924782b996
View
@@ -19,3 +19,9 @@
[submodule "ext/SPIRV-Cross"]
path = ext/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross.git
[submodule "ext/discord-rpc"]
path = ext/discord-rpc
url = https://github.com/discordapp/discord-rpc.git
[submodule "ext/rapidjson"]
path = ext/rapidjson
url = https://github.com/Tencent/rapidjson.git
View
@@ -822,6 +822,7 @@ endif()
list(APPEND NativeAppSource
android/jni/TestRunner.cpp
UI/DiscordIntegration.cpp
UI/NativeApp.cpp
UI/BackgroundAudio.cpp
UI/DevScreens.cpp
View
@@ -396,6 +396,7 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("CheckForNewVersion", &g_Config.bCheckForNewVersion, true),
ConfigSetting("Language", &g_Config.sLanguageIni, &DefaultLangRegion),
ConfigSetting("ForceLagSync", &g_Config.bForceLagSync, false, true, true),
ConfigSetting("DiscordPresence", &g_Config.bDiscordPresence, true, true, false), // Or maybe it makes sense to have it per-game? Race conditions abound...
ReportedConfigSetting("NumWorkerThreads", &g_Config.iNumWorkerThreads, &DefaultNumWorkers, true, true),
ConfigSetting("AutoLoadSaveState", &g_Config.iAutoLoadSaveState, 0, true, true),
@@ -1162,8 +1163,8 @@ void Config::DownloadCompletedCallback(http::Download &download) {
return;
}
JsonReader reader(data.c_str(), data.size());
const JsonGet root = reader.root();
json::JsonReader reader(data.c_str(), data.size());
const json::JsonGet root = reader.root();
if (!root) {
ERROR_LOG(LOADER, "Failed to parse json");
return;
View
@@ -117,6 +117,8 @@ struct Config {
std::vector<std::string> vPinnedPaths;
std::string sLanguageIni;
bool bDiscordPresence; // Enables setting the Discord presence to the current game (or menu)
// GFX
int iGPUBackend;
// We have separate device parameters for each backend so it doesn't get erased if you switch backends.
@@ -24,6 +24,8 @@
#include "net/websocket_server.h"
#include "Common/Log.h"
using namespace json;
static inline void DebuggerJsonAddTicket(JsonWriter &writer, const JsonGet &data) {
const JsonNode *value = data.get("ticket");
if (value)
View
@@ -0,0 +1,131 @@
#include <ctime>
#include <cassert>
#include "ppsspp_config.h"
#include "Common/Log.h"
#include "Core/Config.h"
#include "DiscordIntegration.h"
#include "i18n/i18n.h"
#ifdef _WIN32
#define ENABLE_DISCORD
#else
// TODO
#endif
#ifdef ENABLE_DISCORD
#include "ext/discord-rpc/include/discord_rpc.h"
#endif
// TODO: Enable on more platforms. Make optional.
Discord g_Discord;
static const char *ppsspp_app_id = "423397985041383434";
// No context argument? What?
static void handleDiscordError(int errCode, const char *message) {
ERROR_LOG(SYSTEM, "Discord error code %d: '%s'", message);
}
Discord::~Discord() {
assert(!initialized_);
}
bool Discord::IsEnabled() const {
return g_Config.bDiscordPresence;
}
void Discord::Init() {
assert(IsEnabled());
assert(!initialized_);
#ifdef ENABLE_DISCORD
DiscordEventHandlers eventHandlers{};
eventHandlers.errored = &handleDiscordError;
Discord_Initialize(ppsspp_app_id, &eventHandlers, 0, nullptr);
#endif
initialized_ = true;
}
void Discord::Shutdown() {
assert(initialized_);
#ifdef ENABLE_DISCORD
Discord_Shutdown();
#endif
initialized_ = false;
}
void Discord::Update() {
if (!IsEnabled()) {
if (initialized_) {
Shutdown();
}
return;
} else {
if (!initialized_) {
Init();
}
}
#ifdef ENABLE_DISCORD
#ifdef DISCORD_DISABLE_IO_THREAD
Discord_UpdateConnection();
#endif
Discord_RunCallbacks();
#endif
}
void Discord::SetPresenceGame(const char *gameTitle) {
if (!IsEnabled())
return;
if (!initialized_) {
Init();
}
#ifdef ENABLE_DISCORD
I18NCategory *sc = GetI18NCategory("Screen");
DiscordRichPresence discordPresence{};
discordPresence.state = gameTitle;
std::string details = sc->T("Playing");
discordPresence.details = details.c_str();
discordPresence.startTimestamp = time(0);
#ifdef GOLD
discordPresence.largeImageKey = "icon_gold_png";
#else
discordPresence.largeImageKey = "icon_regular_png";
#endif
Discord_UpdatePresence(&discordPresence);
#endif
}
void Discord::SetPresenceMenu() {
if (!IsEnabled())
return;
if (!initialized_) {
Init();
}
#ifdef ENABLE_DISCORD
I18NCategory *sc = GetI18NCategory("Screen");
DiscordRichPresence discordPresence{};
discordPresence.state = sc->T("In menu");
discordPresence.details = "";
discordPresence.startTimestamp = time(0);
#ifdef GOLD
discordPresence.largeImageKey = "icon_gold_png";
#else
discordPresence.largeImageKey = "icon_regular_png";
#endif
Discord_UpdatePresence(&discordPresence);
#endif
}
View
@@ -0,0 +1,28 @@
#pragma once
#include <string>
// Simple wrapper around the Discord api.
// All platforms should call it, but we only actually take action on
// platforms where we want it enabled (only PC initially).
// All you need to call is FrameCallback, Shutdown, and UpdatePresence.
class Discord {
public:
~Discord();
void Update(); // Call every frame or at least regularly. Will initialize if necessary.
void Shutdown();
void SetPresenceGame(const char *gameTitle);
void SetPresenceMenu();
private:
void Init();
bool IsEnabled() const;
bool initialized_ = false;
};
extern Discord g_Discord;
View
@@ -77,6 +77,7 @@
#include "UI/GameSettingsScreen.h"
#include "UI/InstallZipScreen.h"
#include "UI/ProfilerDraw.h"
#include "UI/DiscordIntegration.h"
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
#include "Windows/MainWindow.h"
@@ -186,12 +187,18 @@ void EmuScreen::bootGame(const std::string &filename) {
if (!bootAllowStorage(filename))
return;
I18NCategory *sc = GetI18NCategory("Screen");
//pre-emptive loading of game specific config if possible, to get all the settings
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, filename, 0);
if (info && !info->id.empty()) {
g_Config.loadGameConfig(info->id);
// Reset views in case controls are in a different place.
RecreateViews();
g_Discord.SetPresenceGame(info->GetTitle().c_str());
} else {
g_Discord.SetPresenceGame(sc->T("Untitled PSP game"));
}
invalid_ = true;
@@ -333,6 +340,7 @@ EmuScreen::~EmuScreen() {
startDumping = false;
}
#endif
g_Discord.SetPresenceMenu();
}
void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) {
@@ -642,6 +642,7 @@ void GameSettingsScreen::CreateViews() {
networkingSettings->Add(new Choice(n->T("Adhoc Multiplayer forum")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides);
networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")));
networkingSettings->Add(new CheckBox(&g_Config.bDiscordPresence, n->T("Send Discord Presence information")));
#if !defined(MOBILE_DEVICE) && !defined(USING_QT_UI)
networkingSettings->Add(new PopupTextInputChoice(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), "", 255, screenManager()));
View
@@ -98,6 +98,7 @@
#include "UI/TiltEventProcessor.h"
#include "UI/BackgroundAudio.h"
#include "UI/TextureUtil.h"
#include "UI/DiscordIntegration.h"
#if !defined(MOBILE_DEVICE)
#include "Common/KeyMap.h"
@@ -352,6 +353,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
InitFastMath(cpu_info.bNEON);
SetupAudioFormats();
g_Discord.SetPresenceMenu();
// Make sure UI state is MENU.
ResetUIState();
@@ -1028,6 +1031,8 @@ void NativeUpdate() {
g_DownloadManager.Update();
screenManager->update();
g_Discord.Update();
}
bool NativeIsAtTopLevel() {
@@ -1213,6 +1218,8 @@ void NativeShutdown() {
net::Shutdown();
g_Discord.Shutdown();
delete logger;
logger = nullptr;
View
@@ -82,6 +82,8 @@ static bool FindServer(std::string &resultHost, int &resultPort) {
std::string json;
result.TakeAll(&json);
using namespace json;
JsonReader reader(json.c_str(), json.size());
if (!reader.ok()) {
return false;
View
@@ -391,6 +391,7 @@ void StoreScreen::update() {
}
void StoreScreen::ParseListing(std::string json) {
using namespace json;
JsonReader reader(json.c_str(), json.size());
if (!reader.ok() || !reader.root()) {
ELOG("Error parsing JSON from store");
@@ -540,8 +541,8 @@ std::string StoreScreen::GetStoreJsonURL(std::string storePath) const {
return path;
}
std::string StoreScreen::GetTranslatedString(const JsonGet json, std::string key, const char *fallback) const {
JsonGet dict = json.getDict("en_US");
std::string StoreScreen::GetTranslatedString(const json::JsonGet json, std::string key, const char *fallback) const {
json::JsonGet dict = json.getDict("en_US");
if (dict && json.hasChild(lang_.c_str(), JSON_OBJECT)) {
if (json.getDict(lang_.c_str()).hasChild(key.c_str(), JSON_STRING)) {
dict = json.getDict(lang_.c_str());
View
@@ -29,7 +29,10 @@
// set game specific settings, etc.
// Uses GameInfoCache heavily to implement the functionality.
struct JsonGet;
namespace json {
struct JsonGet;
}
class ProductItemView;
enum EntryType {
@@ -79,7 +82,7 @@ class StoreScreen : public UIDialogScreenWithBackground {
std::vector<StoreEntry> FilterEntries();
std::string GetStoreJsonURL(std::string storePath) const;
std::string GetTranslatedString(const JsonGet json, std::string key, const char *fallback = nullptr) const;
std::string GetTranslatedString(const json::JsonGet json, std::string key, const char *fallback = nullptr) const;
std::shared_ptr<http::Download> listing_;
std::shared_ptr<http::Download> image_;
View
@@ -24,6 +24,7 @@
<ClCompile Include="ControlMappingScreen.cpp" />
<ClCompile Include="CwCheatScreen.cpp" />
<ClCompile Include="DevScreens.cpp" />
<ClCompile Include="DiscordIntegration.cpp" />
<ClCompile Include="DisplayLayoutEditor.cpp" />
<ClCompile Include="DisplayLayoutScreen.cpp" />
<ClCompile Include="EmuScreen.cpp" />
@@ -54,6 +55,7 @@
<ClInclude Include="ComboKeyMappingScreen.h" />
<ClInclude Include="ControlMappingScreen.h" />
<ClInclude Include="DevScreens.h" />
<ClInclude Include="DiscordIntegration.h" />
<ClInclude Include="DisplayLayoutEditor.h" />
<ClInclude Include="DisplayLayoutScreen.h" />
<ClInclude Include="EmuScreen.h" />
@@ -80,11 +82,17 @@
<ClInclude Include="InstallZipScreen.h" />
<ClInclude Include="ui_atlas.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ext\discord-rpc-build\discord-rpc.vcxproj">
<Project>{beb0a821-3c7f-410f-a525-63afbc69bf8f}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{004B8D11-2BE3-4BD9-AB40-2BE04CF2096F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>UI</RootNamespace>
<WindowsTargetPlatformVersion></WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>
</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
View
@@ -70,6 +70,7 @@
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="TextureUtil.cpp" />
<ClCompile Include="DiscordIntegration.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@@ -141,6 +142,7 @@
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="TextureUtil.h" />
<ClInclude Include="DiscordIntegration.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">
Oops, something went wrong.

0 comments on commit 0684068

Please sign in to comment.