mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-04 08:49:13 +00:00
Add Discord Rich Presence integration for Windows
This commit is contained in:
parent
82b6b60b31
commit
0a5051f959
15 changed files with 243 additions and 0 deletions
|
@ -108,6 +108,10 @@ win32 {
|
||||||
}
|
}
|
||||||
win32:!winrt {
|
win32:!winrt {
|
||||||
CONFIG += soundio
|
CONFIG += soundio
|
||||||
|
|
||||||
|
# Discord RPC for rich presence
|
||||||
|
LIBS += -ldiscord-rpc
|
||||||
|
DEFINES += HAVE_DISCORD
|
||||||
}
|
}
|
||||||
macx {
|
macx {
|
||||||
LIBS += -lssl -lcrypto -lavcodec.58 -lavutil.56 -lopus -framework SDL2 -framework SDL2_ttf
|
LIBS += -lssl -lcrypto -lavcodec.58 -lavutil.56 -lopus -framework SDL2 -framework SDL2_ttf
|
||||||
|
@ -128,6 +132,7 @@ SOURCES += \
|
||||||
backend/nvpairingmanager.cpp \
|
backend/nvpairingmanager.cpp \
|
||||||
backend/computermanager.cpp \
|
backend/computermanager.cpp \
|
||||||
backend/boxartmanager.cpp \
|
backend/boxartmanager.cpp \
|
||||||
|
backend/richpresencemanager.cpp \
|
||||||
cli/commandlineparser.cpp \
|
cli/commandlineparser.cpp \
|
||||||
cli/quitstream.cpp \
|
cli/quitstream.cpp \
|
||||||
cli/startstream.cpp \
|
cli/startstream.cpp \
|
||||||
|
@ -155,6 +160,7 @@ HEADERS += \
|
||||||
backend/nvpairingmanager.h \
|
backend/nvpairingmanager.h \
|
||||||
backend/computermanager.h \
|
backend/computermanager.h \
|
||||||
backend/boxartmanager.h \
|
backend/boxartmanager.h \
|
||||||
|
backend/richpresencemanager.h \
|
||||||
cli/commandlineparser.h \
|
cli/commandlineparser.h \
|
||||||
cli/quitstream.h \
|
cli/quitstream.h \
|
||||||
cli/startstream.h \
|
cli/startstream.h \
|
||||||
|
|
63
app/backend/richpresencemanager.cpp
Normal file
63
app/backend/richpresencemanager.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include "richpresencemanager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
RichPresenceManager::RichPresenceManager(StreamingPreferences& prefs, QString gameName)
|
||||||
|
: m_DiscordActive(false)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
if (prefs.richPresence) {
|
||||||
|
DiscordEventHandlers handlers = {};
|
||||||
|
handlers.ready = discordReady;
|
||||||
|
handlers.disconnected = discordDisconnected;
|
||||||
|
handlers.errored = discordErrored;
|
||||||
|
Discord_Initialize("594668102021677159", &handlers, 0, nullptr);
|
||||||
|
m_DiscordActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_DiscordActive) {
|
||||||
|
QByteArray stateStr = (QString("Streaming ") + gameName).toUtf8();
|
||||||
|
|
||||||
|
DiscordRichPresence discordPresence = {};
|
||||||
|
discordPresence.state = stateStr.data();
|
||||||
|
discordPresence.startTimestamp = time(nullptr);
|
||||||
|
Discord_UpdatePresence(&discordPresence);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
RichPresenceManager::~RichPresenceManager()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
if (m_DiscordActive) {
|
||||||
|
Discord_ClearPresence();
|
||||||
|
Discord_Shutdown();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichPresenceManager::runCallbacks()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
if (m_DiscordActive) {
|
||||||
|
Discord_RunCallbacks();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
void RichPresenceManager::discordReady(const DiscordUser* request)
|
||||||
|
{
|
||||||
|
qInfo() << "Discord integration ready for user:" << request->username;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichPresenceManager::discordDisconnected(int errorCode, const char *message)
|
||||||
|
{
|
||||||
|
qInfo() << "Discord integration disconnected:" << errorCode << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichPresenceManager::discordErrored(int errorCode, const char *message)
|
||||||
|
{
|
||||||
|
qWarning() << "Discord integration error:" << errorCode << message;
|
||||||
|
}
|
||||||
|
#endif
|
26
app/backend/richpresencemanager.h
Normal file
26
app/backend/richpresencemanager.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "settings/streamingpreferences.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
#include <discord_rpc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class RichPresenceManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RichPresenceManager(StreamingPreferences& prefs, QString gameName);
|
||||||
|
~RichPresenceManager();
|
||||||
|
|
||||||
|
void runCallbacks();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
static void discordReady(const DiscordUser* request);
|
||||||
|
static void discordDisconnected(int errorCode, const char* message);
|
||||||
|
static void discordErrored(int errorCode, const char* message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool m_DiscordActive;
|
||||||
|
};
|
||||||
|
|
|
@ -22,6 +22,12 @@ SystemProperties::SystemProperties()
|
||||||
hasBrowser = false;
|
hasBrowser = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DISCORD
|
||||||
|
hasDiscordIntegration = true;
|
||||||
|
#else
|
||||||
|
hasDiscordIntegration = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
unmappedGamepads = SdlInputHandler::getUnmappedGamepads();
|
unmappedGamepads = SdlInputHandler::getUnmappedGamepads();
|
||||||
|
|
||||||
// Populate data that requires talking to SDL. We do it all in one shot
|
// Populate data that requires talking to SDL. We do it all in one shot
|
||||||
|
|
|
@ -15,6 +15,7 @@ public:
|
||||||
Q_PROPERTY(bool isRunningXWayland MEMBER isRunningXWayland CONSTANT)
|
Q_PROPERTY(bool isRunningXWayland MEMBER isRunningXWayland CONSTANT)
|
||||||
Q_PROPERTY(bool isWow64 MEMBER isWow64 CONSTANT)
|
Q_PROPERTY(bool isWow64 MEMBER isWow64 CONSTANT)
|
||||||
Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT)
|
Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT)
|
||||||
|
Q_PROPERTY(bool hasDiscordIntegration MEMBER hasDiscordIntegration CONSTANT)
|
||||||
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
||||||
Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT)
|
Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT)
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ private:
|
||||||
bool isRunningXWayland;
|
bool isRunningXWayland;
|
||||||
bool isWow64;
|
bool isWow64;
|
||||||
bool hasBrowser;
|
bool hasBrowser;
|
||||||
|
bool hasDiscordIntegration;
|
||||||
QString unmappedGamepads;
|
QString unmappedGamepads;
|
||||||
int maximumStreamingFrameRate;
|
int maximumStreamingFrameRate;
|
||||||
QList<QRect> monitorDesktopResolutions;
|
QList<QRect> monitorDesktopResolutions;
|
||||||
|
|
|
@ -499,6 +499,22 @@ Flickable {
|
||||||
StreamingPreferences.connectionWarnings = checked
|
StreamingPreferences.connectionWarnings = checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
visible: SystemProperties.hasDiscordIntegration
|
||||||
|
id: discordPresenceCheck
|
||||||
|
text: "Discord Rich Presence integration"
|
||||||
|
font.pointSize: 12
|
||||||
|
checked: StreamingPreferences.richPresence
|
||||||
|
onCheckedChanged: {
|
||||||
|
StreamingPreferences.richPresence = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTip.delay: 1000
|
||||||
|
ToolTip.timeout: 5000
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: "Updates your Discord status to display the name of the game you're streaming."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define SER_STARTWINDOWED "startwindowed"
|
#define SER_STARTWINDOWED "startwindowed"
|
||||||
#define SER_FRAMEPACING "framepacing"
|
#define SER_FRAMEPACING "framepacing"
|
||||||
#define SER_CONNWARNINGS "connwarnings"
|
#define SER_CONNWARNINGS "connwarnings"
|
||||||
|
#define SER_RICHPRESENCE "richpresence"
|
||||||
|
|
||||||
StreamingPreferences::StreamingPreferences(QObject *parent)
|
StreamingPreferences::StreamingPreferences(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
@ -55,6 +56,7 @@ void StreamingPreferences::reload()
|
||||||
startWindowed = settings.value(SER_STARTWINDOWED, false).toBool();
|
startWindowed = settings.value(SER_STARTWINDOWED, false).toBool();
|
||||||
framePacing = settings.value(SER_FRAMEPACING, false).toBool();
|
framePacing = settings.value(SER_FRAMEPACING, false).toBool();
|
||||||
connectionWarnings = settings.value(SER_CONNWARNINGS, true).toBool();
|
connectionWarnings = settings.value(SER_CONNWARNINGS, true).toBool();
|
||||||
|
richPresence = settings.value(SER_RICHPRESENCE, true).toBool();
|
||||||
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
|
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
|
||||||
static_cast<int>(AudioConfig::AC_STEREO)).toInt());
|
static_cast<int>(AudioConfig::AC_STEREO)).toInt());
|
||||||
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
|
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
|
||||||
|
@ -86,6 +88,7 @@ void StreamingPreferences::save()
|
||||||
settings.setValue(SER_STARTWINDOWED, startWindowed);
|
settings.setValue(SER_STARTWINDOWED, startWindowed);
|
||||||
settings.setValue(SER_FRAMEPACING, framePacing);
|
settings.setValue(SER_FRAMEPACING, framePacing);
|
||||||
settings.setValue(SER_CONNWARNINGS, connectionWarnings);
|
settings.setValue(SER_CONNWARNINGS, connectionWarnings);
|
||||||
|
settings.setValue(SER_RICHPRESENCE, richPresence);
|
||||||
settings.setValue(SER_AUDIOCFG, static_cast<int>(audioConfig));
|
settings.setValue(SER_AUDIOCFG, static_cast<int>(audioConfig));
|
||||||
settings.setValue(SER_VIDEOCFG, static_cast<int>(videoCodecConfig));
|
settings.setValue(SER_VIDEOCFG, static_cast<int>(videoCodecConfig));
|
||||||
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));
|
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
Q_PROPERTY(bool startWindowed MEMBER startWindowed NOTIFY startWindowedChanged)
|
Q_PROPERTY(bool startWindowed MEMBER startWindowed NOTIFY startWindowedChanged)
|
||||||
Q_PROPERTY(bool framePacing MEMBER framePacing NOTIFY framePacingChanged)
|
Q_PROPERTY(bool framePacing MEMBER framePacing NOTIFY framePacingChanged)
|
||||||
Q_PROPERTY(bool connectionWarnings MEMBER connectionWarnings NOTIFY connectionWarningsChanged)
|
Q_PROPERTY(bool connectionWarnings MEMBER connectionWarnings NOTIFY connectionWarningsChanged)
|
||||||
|
Q_PROPERTY(bool richPresence MEMBER richPresence NOTIFY richPresenceChanged);
|
||||||
Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged)
|
Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged)
|
||||||
Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged)
|
Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged)
|
||||||
Q_PROPERTY(VideoDecoderSelection videoDecoderSelection MEMBER videoDecoderSelection NOTIFY videoDecoderSelectionChanged)
|
Q_PROPERTY(VideoDecoderSelection videoDecoderSelection MEMBER videoDecoderSelection NOTIFY videoDecoderSelectionChanged)
|
||||||
|
@ -86,6 +87,7 @@ public:
|
||||||
bool startWindowed;
|
bool startWindowed;
|
||||||
bool framePacing;
|
bool framePacing;
|
||||||
bool connectionWarnings;
|
bool connectionWarnings;
|
||||||
|
bool richPresence;
|
||||||
AudioConfig audioConfig;
|
AudioConfig audioConfig;
|
||||||
VideoCodecConfig videoCodecConfig;
|
VideoCodecConfig videoCodecConfig;
|
||||||
VideoDecoderSelection videoDecoderSelection;
|
VideoDecoderSelection videoDecoderSelection;
|
||||||
|
@ -110,5 +112,6 @@ signals:
|
||||||
void startWindowedChanged();
|
void startWindowedChanged();
|
||||||
void framePacingChanged();
|
void framePacingChanged();
|
||||||
void connectionWarningsChanged();
|
void connectionWarningsChanged();
|
||||||
|
void richPresenceChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "settings/streamingpreferences.h"
|
#include "settings/streamingpreferences.h"
|
||||||
#include "streaming/streamutils.h"
|
#include "streaming/streamutils.h"
|
||||||
|
#include "backend/richpresencemanager.h"
|
||||||
|
|
||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
@ -1047,6 +1048,9 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||||
// (m_UnexpectedTermination is set back to true).
|
// (m_UnexpectedTermination is set back to true).
|
||||||
m_UnexpectedTermination = false;
|
m_UnexpectedTermination = false;
|
||||||
|
|
||||||
|
// Start rich presence to indicate we're in game
|
||||||
|
RichPresenceManager presence(prefs, m_App.name);
|
||||||
|
|
||||||
// Hijack this thread to be the SDL main thread. We have to do this
|
// Hijack this thread to be the SDL main thread. We have to do this
|
||||||
// because we want to suspend all Qt processing until the stream is over.
|
// because we want to suspend all Qt processing until the stream is over.
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
@ -1063,6 +1067,7 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||||
// ARM core in the Steam Link, so we will wait 10 ms instead.
|
// ARM core in the Steam Link, so we will wait 10 ms instead.
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
#endif
|
#endif
|
||||||
|
presence.runCallbacks();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
|
26
libs/windows/include/discord_register.h
Normal file
26
libs/windows/include/discord_register.h
Normal file
|
@ -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
|
87
libs/windows/include/discord_rpc.h
Normal file
87
libs/windows/include/discord_rpc.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 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
|
BIN
libs/windows/lib/x64/discord-rpc.dll
Normal file
BIN
libs/windows/lib/x64/discord-rpc.dll
Normal file
Binary file not shown.
BIN
libs/windows/lib/x64/discord-rpc.lib
Normal file
BIN
libs/windows/lib/x64/discord-rpc.lib
Normal file
Binary file not shown.
BIN
libs/windows/lib/x86/discord-rpc.dll
Normal file
BIN
libs/windows/lib/x86/discord-rpc.dll
Normal file
Binary file not shown.
BIN
libs/windows/lib/x86/discord-rpc.lib
Normal file
BIN
libs/windows/lib/x86/discord-rpc.lib
Normal file
Binary file not shown.
Loading…
Reference in a new issue