Skip to content

Commit

Permalink
Add Discord presence ioctlv to /dev/dolphin
Browse files Browse the repository at this point in the history
  • Loading branch information
InvoxiPlayGames committed Aug 6, 2022
1 parent 7d2d5d9 commit f9e39cf
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 2 deletions.
15 changes: 15 additions & 0 deletions Source/Android/jni/MainAndroid.cpp
Expand Up @@ -131,6 +131,21 @@ void Host_UpdateTitle(const std::string& title)
__android_log_write(ANDROID_LOG_INFO, DOLPHIN_TAG, title.c_str());
}

void Host_UpdateDiscordClientID(const std::string& client_id)
{
}

bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
return false;
}

void Host_UpdateDisasmDialog()
{
}
Expand Down
10 changes: 10 additions & 0 deletions Source/Core/Core/Host.h
Expand Up @@ -64,4 +64,14 @@ void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI();
void Host_TitleChanged();

void Host_UpdateDiscordClientID(const std::string& client_id = {});
bool Host_UpdateDiscordPresenceRaw(const std::string& details = {}, const std::string& state = {},
const std::string& large_image_key = {},
const std::string& large_image_text = {},
const std::string& small_image_key = {},
const std::string& small_image_text = {},
const int64_t start_timestamp = 0,
const int64_t end_timestamp = 0, const int party_size = 0,
const int party_max = 0);

std::unique_ptr<GBAHostInterface> Host_CreateGBAHost(std::weak_ptr<HW::GBA::Core> core);
73 changes: 73 additions & 0 deletions Source/Core/Core/IOS/DolphinDevice.cpp
Expand Up @@ -15,8 +15,10 @@
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/UISettings.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/Host.h"

namespace IOS::HLE
{
Expand All @@ -30,6 +32,9 @@ enum
IOCTL_DOLPHIN_SET_SPEED_LIMIT = 0x04,
IOCTL_DOLPHIN_GET_CPU_SPEED = 0x05,
IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE = 0x06,
IOCTL_DOLPHIN_DISCORD_SET_CLIENT = 0x07,
IOCTL_DOLPHIN_DISCORD_SET_PRESENCE = 0x08,
IOCTL_DOLPHIN_DISCORD_RESET = 0x09

};

Expand Down Expand Up @@ -157,6 +162,67 @@ IPCReply GetRealProductCode(const IOCtlVRequest& request)
return IPCReply(IPC_SUCCESS);
}

IPCReply SetDiscordClient(const IOCtlVRequest& request)
{
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return IPCReply(IPC_EACCES);

if (!request.HasNumberOfValidVectors(1, 0))
return IPCReply(IPC_EINVAL);

std::string new_client_id =
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);

Host_UpdateDiscordClientID(new_client_id);

return IPCReply(IPC_SUCCESS);
}

IPCReply SetDiscordPresence(const IOCtlVRequest& request)
{
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return IPCReply(IPC_EACCES);

if (!request.HasNumberOfValidVectors(10, 0))
return IPCReply(IPC_EINVAL);

std::string details =
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
std::string state = Memory::GetString(request.in_vectors[1].address, request.in_vectors[1].size);
std::string large_image_key =
Memory::GetString(request.in_vectors[2].address, request.in_vectors[2].size);
std::string large_image_text =
Memory::GetString(request.in_vectors[3].address, request.in_vectors[3].size);
std::string small_image_key =
Memory::GetString(request.in_vectors[4].address, request.in_vectors[4].size);
std::string small_image_text =
Memory::GetString(request.in_vectors[5].address, request.in_vectors[5].size);

int64_t start_timestamp = Memory::Read_U64(request.in_vectors[6].address);
int64_t end_timestamp = Memory::Read_U64(request.in_vectors[7].address);
int party_size = Memory::Read_U32(request.in_vectors[8].address);
int party_max = Memory::Read_U32(request.in_vectors[9].address);

bool ret = Host_UpdateDiscordPresenceRaw(details, state, large_image_key, large_image_text,
small_image_key, small_image_text, start_timestamp,
end_timestamp, party_size, party_max);

if (!ret)
return IPCReply(IPC_EACCES);

return IPCReply(IPC_SUCCESS);
}

IPCReply ResetDiscord(const IOCtlVRequest& request)
{
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return IPCReply(IPC_EACCES);

Host_UpdateDiscordClientID();

return IPCReply(IPC_SUCCESS);
}

} // namespace

std::optional<IPCReply> DolphinDevice::IOCtlV(const IOCtlVRequest& request)
Expand All @@ -178,6 +244,13 @@ std::optional<IPCReply> DolphinDevice::IOCtlV(const IOCtlVRequest& request)
return GetCPUSpeed(request);
case IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE:
return GetRealProductCode(request);
case IOCTL_DOLPHIN_DISCORD_SET_CLIENT:
return SetDiscordClient(request);
case IOCTL_DOLPHIN_DISCORD_SET_PRESENCE:
return SetDiscordPresence(request);
case IOCTL_DOLPHIN_DISCORD_RESET:
return ResetDiscord(request);

default:
return IPCReply(IPC_EINVAL);
}
Expand Down
24 changes: 24 additions & 0 deletions Source/Core/DolphinNoGUI/MainNoGUI.cpp
Expand Up @@ -122,6 +122,30 @@ void Host_TitleChanged()
#endif
}

void Host_UpdateDiscordClientID(const std::string& client_id)
{
#ifdef USE_DISCORD_PRESENCE
Discord::UpdateClientID(client_id);
#endif
}

bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
#ifdef USE_DISCORD_PRESENCE
return Discord::UpdateDiscordPresenceRaw(details, state, large_image_key, large_image_text,
small_image_key, small_image_text, start_timestamp,
end_timestamp, party_size, party_max);
#else
return false;
#endif
}

std::unique_ptr<GBAHostInterface> Host_CreateGBAHost(std::weak_ptr<HW::GBA::Core> core)
{
return nullptr;
Expand Down
24 changes: 24 additions & 0 deletions Source/Core/DolphinQt/Host.cpp
Expand Up @@ -287,6 +287,30 @@ void Host_TitleChanged()
#endif
}

void Host_UpdateDiscordClientID(const std::string& client_id)
{
#ifdef USE_DISCORD_PRESENCE
Discord::UpdateClientID(client_id);
#endif
}

bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
#ifdef USE_DISCORD_PRESENCE
return Discord::UpdateDiscordPresenceRaw(details, state, large_image_key, large_image_text,
small_image_key, small_image_text, start_timestamp,
end_timestamp, party_size, party_max);
#else
return false;
#endif
}

#ifndef HAS_LIBMGBA
std::unique_ptr<GBAHostInterface> Host_CreateGBAHost(std::weak_ptr<HW::GBA::Core> core)
{
Expand Down
15 changes: 15 additions & 0 deletions Source/Core/DolphinTool/ToolHeadlessPlatform.cpp
Expand Up @@ -43,6 +43,21 @@ void Host_UpdateTitle(const std::string& title)
{
}

void Host_UpdateDiscordClientID(const std::string& client_id)
{
}

bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
return false;
}

void Host_UpdateDisasmDialog()
{
}
Expand Down
56 changes: 54 additions & 2 deletions Source/Core/UICommon/DiscordPresence.cpp
Expand Up @@ -189,12 +189,27 @@ void Init()
handlers.ready = HandleDiscordReady;
handlers.joinRequest = HandleDiscordJoinRequest;
handlers.joinGame = HandleDiscordJoin;
// The number is the client ID for Dolphin, it's used for images and the application name
Discord_Initialize("455712169795780630", &handlers, 1, nullptr);
Discord_Initialize(DEFAULT_CLIENT_ID.c_str(), &handlers, 1, nullptr);
UpdateDiscordPresence();
#endif
}

void UpdateClientID(const std::string& new_client)
{
#ifdef USE_DISCORD_PRESENCE
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return;

s_using_custom_client = new_client.empty() || new_client.compare(DEFAULT_CLIENT_ID) != 0;

Shutdown();
if (s_using_custom_client)
Discord_Initialize(new_client.c_str(), nullptr, 0, nullptr);
else // if initialising dolphin's client ID, make sure to restore event handlers
Init();
#endif
}

void CallPendingCallbacks()
{
#ifdef USE_DISCORD_PRESENCE
Expand All @@ -213,13 +228,50 @@ void InitNetPlayFunctionality(Handler& handler)
#endif
}

bool UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text, const int64_t start_timestamp,
const int64_t end_timestamp, const int party_size,
const int party_max)
{
#ifdef USE_DISCORD_PRESENCE
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return false;

// only /dev/dolphin sets this, don't let homebrew change official client ID raw presence
if (!s_using_custom_client)
return false;

DiscordRichPresence discord_presence = {};
discord_presence.details = details.c_str();
discord_presence.state = state.c_str();
discord_presence.largeImageKey = large_image_key.c_str();
discord_presence.largeImageText = large_image_text.c_str();
discord_presence.smallImageKey = small_image_key.c_str();
discord_presence.smallImageText = small_image_text.c_str();
discord_presence.startTimestamp = start_timestamp;
discord_presence.endTimestamp = end_timestamp;
discord_presence.partySize = party_size;
discord_presence.partyMax = party_max;
Discord_UpdatePresence(&discord_presence);

return true;
#endif
}

void UpdateDiscordPresence(int party_size, SecretType type, const std::string& secret,
const std::string& current_game)
{
#ifdef USE_DISCORD_PRESENCE
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return;

// reset the client ID if running homebrew has changed it
if (s_using_custom_client)
UpdateClientID(DEFAULT_CLIENT_ID);

const std::string& title =
current_game.empty() ? SConfig::GetInstance().GetTitleDescription() : current_game;
std::string game_artwork = ArtworkForGameId(SConfig::GetInstance().GetGameID());
Expand Down
13 changes: 13 additions & 0 deletions Source/Core/UICommon/DiscordPresence.h
Expand Up @@ -8,6 +8,9 @@

namespace Discord
{
// The number is the client ID for Dolphin, it's used for images and the application name
const std::string DEFAULT_CLIENT_ID = "455712169795780630";

class Handler
{
public:
Expand All @@ -24,9 +27,19 @@ enum class SecretType
RoomID,
};

static bool s_using_custom_client = false;

void Init();
void InitNetPlayFunctionality(Handler& handler);
void CallPendingCallbacks();
void UpdateClientID(const std::string& new_client = {});
bool UpdateDiscordPresenceRaw(const std::string& details = {}, const std::string& state = {},
const std::string& large_image_key = {},
const std::string& large_image_text = {},
const std::string& small_image_key = {},
const std::string& small_image_text = {},
const int64_t start_timestamp = 0, const int64_t end_timestamp = 0,
const int party_size = 0, const int party_max = 0);
void UpdateDiscordPresence(int party_size = 0, SecretType type = SecretType::Empty,
const std::string& secret = {}, const std::string& current_game = {});
std::string CreateSecretFromIPAddress(const std::string& ip_address, int port);
Expand Down
13 changes: 13 additions & 0 deletions Source/DSPTool/StubHost.cpp
Expand Up @@ -25,6 +25,19 @@ void Host_Message(HostMessageID)
void Host_UpdateTitle(const std::string&)
{
}
void Host_UpdateDiscordClientID(const std::string& client_id)
{
}
bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
return false;
}
void Host_UpdateDisasmDialog()
{
}
Expand Down
13 changes: 13 additions & 0 deletions Source/UnitTests/StubHost.cpp
Expand Up @@ -25,6 +25,19 @@ void Host_Message(HostMessageID)
void Host_UpdateTitle(const std::string&)
{
}
void Host_UpdateDiscordClientID(const std::string& client_id)
{
}
bool Host_UpdateDiscordPresenceRaw(const std::string& details, const std::string& state,
const std::string& large_image_key,
const std::string& large_image_text,
const std::string& small_image_key,
const std::string& small_image_text,
const int64_t start_timestamp, const int64_t end_timestamp,
const int party_size, const int party_max)
{
return false;
}
void Host_UpdateDisasmDialog()
{
}
Expand Down

0 comments on commit f9e39cf

Please sign in to comment.