mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
commit
90baac517d
11
command.c
11
command.c
@ -1834,9 +1834,6 @@ void command_playlist_update_write(
|
||||
**/
|
||||
bool command_event(enum event_command cmd, void *data)
|
||||
{
|
||||
#ifdef HAVE_DISCORD
|
||||
static bool discord_inited = false;
|
||||
#endif
|
||||
bool boolean = false;
|
||||
|
||||
switch (cmd)
|
||||
@ -2986,26 +2983,24 @@ TODO: Add a setting for these tweaks */
|
||||
|
||||
if (!settings->bools.discord_enable)
|
||||
return false;
|
||||
if (discord_inited)
|
||||
if (discord_is_ready())
|
||||
return true;
|
||||
|
||||
discord_init();
|
||||
discord_inited = true;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case CMD_EVENT_DISCORD_DEINIT:
|
||||
#ifdef HAVE_DISCORD
|
||||
if (!discord_inited)
|
||||
if (!discord_is_ready())
|
||||
return false;
|
||||
|
||||
discord_shutdown();
|
||||
discord_inited = false;
|
||||
#endif
|
||||
break;
|
||||
case CMD_EVENT_DISCORD_UPDATE:
|
||||
#ifdef HAVE_DISCORD
|
||||
if (!data || !discord_inited)
|
||||
if (!data || !discord_is_ready())
|
||||
return false;
|
||||
|
||||
{
|
||||
|
@ -129,20 +129,20 @@ public class DiscordRpc
|
||||
FreeMem();
|
||||
}
|
||||
|
||||
_presence.state = StrToPtr(state, 128);
|
||||
_presence.details = StrToPtr(details, 128);
|
||||
_presence.state = StrToPtr(state);
|
||||
_presence.details = StrToPtr(details);
|
||||
_presence.startTimestamp = startTimestamp;
|
||||
_presence.endTimestamp = endTimestamp;
|
||||
_presence.largeImageKey = StrToPtr(largeImageKey, 32);
|
||||
_presence.largeImageText = StrToPtr(largeImageText, 128);
|
||||
_presence.smallImageKey = StrToPtr(smallImageKey, 32);
|
||||
_presence.smallImageText = StrToPtr(smallImageText, 128);
|
||||
_presence.partyId = StrToPtr(partyId, 128);
|
||||
_presence.largeImageKey = StrToPtr(largeImageKey);
|
||||
_presence.largeImageText = StrToPtr(largeImageText);
|
||||
_presence.smallImageKey = StrToPtr(smallImageKey);
|
||||
_presence.smallImageText = StrToPtr(smallImageText);
|
||||
_presence.partyId = StrToPtr(partyId);
|
||||
_presence.partySize = partySize;
|
||||
_presence.partyMax = partyMax;
|
||||
_presence.matchSecret = StrToPtr(matchSecret, 128);
|
||||
_presence.joinSecret = StrToPtr(joinSecret, 128);
|
||||
_presence.spectateSecret = StrToPtr(spectateSecret, 128);
|
||||
_presence.matchSecret = StrToPtr(matchSecret);
|
||||
_presence.joinSecret = StrToPtr(joinSecret);
|
||||
_presence.spectateSecret = StrToPtr(spectateSecret);
|
||||
_presence.instance = instance;
|
||||
|
||||
return _presence;
|
||||
@ -152,16 +152,18 @@ public class DiscordRpc
|
||||
/// Returns a pointer to a representation of the given string with a size of maxbytes
|
||||
/// </summary>
|
||||
/// <param name="input">String to convert</param>
|
||||
/// <param name="maxbytes">Max number of bytes to use</param>
|
||||
/// <returns>Pointer to the UTF-8 representation of <see cref="input"/></returns>
|
||||
private IntPtr StrToPtr(string input, int maxbytes)
|
||||
private IntPtr StrToPtr(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input)) return IntPtr.Zero;
|
||||
var convstr = StrClampBytes(input, maxbytes);
|
||||
var convbytecnt = Encoding.UTF8.GetByteCount(convstr);
|
||||
var buffer = Marshal.AllocHGlobal(convbytecnt);
|
||||
var convbytecnt = Encoding.UTF8.GetByteCount(input);
|
||||
var buffer = Marshal.AllocHGlobal(convbytecnt + 1);
|
||||
for (int i = 0; i < convbytecnt + 1; i++)
|
||||
{
|
||||
Marshal.WriteByte(buffer, i , 0);
|
||||
}
|
||||
_buffers.Add(buffer);
|
||||
Marshal.Copy(Encoding.UTF8.GetBytes(convstr), 0, buffer, convbytecnt);
|
||||
Marshal.Copy(Encoding.UTF8.GetBytes(input), 0, buffer, convbytecnt);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -181,30 +183,6 @@ public class DiscordRpc
|
||||
return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp the string to the given byte length preserving null termination
|
||||
/// </summary>
|
||||
/// <param name="toclamp">string to clamp</param>
|
||||
/// <param name="maxbytes">max bytes the resulting string should have (including null termination)</param>
|
||||
/// <returns>null terminated string with a byte length less or equal to <see cref="maxbytes"/></returns>
|
||||
private static string StrClampBytes(string toclamp, int maxbytes)
|
||||
{
|
||||
var str = StrToUtf8NullTerm(toclamp);
|
||||
var strbytes = Encoding.UTF8.GetBytes(str);
|
||||
|
||||
if (strbytes.Length <= maxbytes)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
var newstrbytes = new byte[] { };
|
||||
Array.Copy(strbytes, 0, newstrbytes, 0, maxbytes - 1);
|
||||
newstrbytes[newstrbytes.Length - 1] = 0;
|
||||
newstrbytes[newstrbytes.Length - 2] = 0;
|
||||
|
||||
return Encoding.UTF8.GetString(newstrbytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the allocated memory for conversion to <see cref="RichPresenceStruct"/>
|
||||
/// </summary>
|
||||
|
@ -24,6 +24,16 @@ struct FDiscordUserData {
|
||||
FString avatar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Valid response codes for Respond function
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDiscordJoinResponseCodes : uint8
|
||||
{
|
||||
DISCORD_REPLY_NO UMETA(DisplayName="No"),
|
||||
DISCORD_REPLY_YES UMETA(DisplayName="Yes"),
|
||||
DISCORD_REPLY_IGNORE UMETA(DisplayName="Ignore")
|
||||
};
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
|
||||
|
||||
|
@ -33,9 +33,11 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
|
||||
|
||||
char exePath[1024];
|
||||
if (!command || !command[0]) {
|
||||
if (readlink("/proc/self/exe", exePath, sizeof(exePath)) <= 0) {
|
||||
ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||
if (size <= 0 || size >= (ssize_t)sizeof(exePath)) {
|
||||
return;
|
||||
}
|
||||
exePath[size] = '\0';
|
||||
command = exePath;
|
||||
}
|
||||
|
||||
|
3
deps/discord-rpc/src/discord_rpc.cpp
vendored
3
deps/discord-rpc/src/discord_rpc.cpp
vendored
@ -89,10 +89,11 @@ public:
|
||||
keepRunning.store(true);
|
||||
ioThread = std::thread([&]() {
|
||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||
Discord_UpdateConnection();
|
||||
while (keepRunning.load()) {
|
||||
Discord_UpdateConnection();
|
||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||
waitForIOActivity.wait_for(lock, maxWait);
|
||||
Discord_UpdateConnection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -37,25 +37,104 @@
|
||||
#include "../cheevos/cheevos.h"
|
||||
#endif
|
||||
|
||||
static int FrustrationLevel = 0;
|
||||
#ifdef HAVE_MENU
|
||||
#include "../../menu/widgets/menu_input_dialog.h"
|
||||
#include "../../menu/menu_cbs.h"
|
||||
#endif
|
||||
|
||||
#include <net/net_http.h>
|
||||
#include "../network/net_http_special.h"
|
||||
#include "../tasks/tasks_internal.h"
|
||||
#include <streams/file_stream.h>
|
||||
#include <file/file_path.h>
|
||||
#include "../file_path_special.h"
|
||||
|
||||
static int64_t start_time = 0;
|
||||
static int64_t pause_time = 0;
|
||||
static int64_t ellapsed_time = 0;
|
||||
|
||||
static bool discord_ready = false;
|
||||
static bool discord_avatar_ready = false;
|
||||
static unsigned discord_status = 0;
|
||||
|
||||
struct netplay_room *room;
|
||||
|
||||
static char user_id[128];
|
||||
static char user_name[128];
|
||||
static char user_avatar[PATH_MAX_LENGTH];
|
||||
|
||||
static char cdn_url[] = "https://cdn.discordapp.com/avatars";
|
||||
|
||||
DiscordRichPresence discord_presence;
|
||||
|
||||
char* discord_get_own_username(void)
|
||||
{
|
||||
return user_name;
|
||||
}
|
||||
|
||||
char* discord_get_own_avatar(void)
|
||||
{
|
||||
return user_avatar;
|
||||
}
|
||||
|
||||
bool discord_avatar_is_ready()
|
||||
{
|
||||
return discord_avatar_ready;
|
||||
}
|
||||
|
||||
void discord_avatar_set_ready(bool ready)
|
||||
{
|
||||
discord_avatar_ready = ready;
|
||||
}
|
||||
|
||||
bool discord_is_ready()
|
||||
{
|
||||
return discord_ready;
|
||||
}
|
||||
|
||||
static bool discord_download_avatar(const char* user_id, const char* avatar_id)
|
||||
{
|
||||
static char url[PATH_MAX_LENGTH];
|
||||
static char url_encoded[PATH_MAX_LENGTH];
|
||||
static char full_path[PATH_MAX_LENGTH];
|
||||
|
||||
static char buf[PATH_MAX_LENGTH];
|
||||
|
||||
file_transfer_t *transf = NULL;
|
||||
|
||||
fill_pathname_application_special(buf,
|
||||
sizeof(buf),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS);
|
||||
fill_pathname_join(full_path, buf, avatar_id, sizeof(full_path));
|
||||
strlcpy(user_avatar, avatar_id, sizeof(user_avatar));
|
||||
|
||||
if(filestream_exists(full_path))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
snprintf(url, sizeof(url), "%s/%s/%s.png", cdn_url, user_id, avatar_id);
|
||||
net_http_urlencode_full(url_encoded, url, sizeof(url_encoded));
|
||||
snprintf(buf, sizeof(buf), "%s.png", avatar_id);
|
||||
|
||||
transf = (file_transfer_t*)calloc(1, sizeof(*transf));
|
||||
transf->enum_idx = MENU_ENUM_LABEL_CB_DISCORD_AVATAR;
|
||||
strlcpy(transf->path, buf, sizeof(transf->path));
|
||||
|
||||
RARCH_LOG("[Discord] downloading avatar from: %s\n", url_encoded);
|
||||
task_push_http_transfer(url_encoded, true, NULL, cb_generic_download, transf);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_discord_ready(const DiscordUser* connectedUser)
|
||||
{
|
||||
strlcpy(user_name, connectedUser->username, sizeof(user_name));
|
||||
RARCH_LOG("[Discord] connected to user: %s#%s - avatar id: %s\n",
|
||||
connectedUser->username,
|
||||
connectedUser->discriminator,
|
||||
connectedUser->userId);
|
||||
discord_download_avatar(connectedUser->userId, connectedUser->avatar);
|
||||
}
|
||||
|
||||
static void handle_discord_disconnected(int errcode, const char* message)
|
||||
@ -93,14 +172,55 @@ static void handle_discord_spectate(const char* secret)
|
||||
RARCH_LOG("[Discord] spectate (%s)\n", secret);
|
||||
}
|
||||
|
||||
static void handle_discord_join_response(void *ignore, const char *line)
|
||||
{
|
||||
/* To-Do: needs in-game widgets
|
||||
if (strstr(line, "yes"))
|
||||
Discord_Respond(user_id, DISCORD_REPLY_YES);
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
menu_input_dialog_end();
|
||||
rarch_menu_running_finished();
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
static void handle_discord_join_request(const DiscordUser* request)
|
||||
{
|
||||
int response = -1;
|
||||
char yn[4];
|
||||
RARCH_LOG("[Discord] join request from %s#%s - %s\n",
|
||||
static char url[PATH_MAX_LENGTH];
|
||||
static char url_encoded[PATH_MAX_LENGTH];
|
||||
static char filename[PATH_MAX_LENGTH];
|
||||
char buf[PATH_MAX_LENGTH];
|
||||
|
||||
RARCH_LOG("[Discord] join request from %s#%s - %s %s\n",
|
||||
request->username,
|
||||
request->discriminator,
|
||||
request->userId);
|
||||
request->userId,
|
||||
request->avatar);
|
||||
|
||||
discord_download_avatar(request->userId, request->avatar);
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
menu_input_ctx_line_t line;
|
||||
/* To-Do: needs in-game widgets
|
||||
rarch_menu_running();
|
||||
*/
|
||||
|
||||
memset(&line, 0, sizeof(line));
|
||||
snprintf(buf, sizeof(buf), "%s %s?", msg_hash_to_str(MSG_DISCORD_CONNECTION_REQUEST), request->username);
|
||||
line.label = buf;
|
||||
line.label_setting = "no_setting";
|
||||
line.cb = handle_discord_join_response;
|
||||
|
||||
/* To-Do: needs in-game widgets
|
||||
To-Do: bespoke dialog, should show while in-game and have a hotkey to accept
|
||||
To-Do: show avatar of the user connecting
|
||||
if (!menu_input_dialog_start(&line))
|
||||
return;
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void discord_update(enum discord_presence presence)
|
||||
@ -192,10 +312,11 @@ void discord_update(enum discord_presence presence)
|
||||
room->gamename, room->gamecrc, room->corename);
|
||||
RARCH_LOG("%s\n", join_secret);
|
||||
discord_presence.joinSecret = strdup(join_secret);
|
||||
discord_presence.spectateSecret = "SPECSPECSPEC";
|
||||
discord_presence.partyId = party_id;
|
||||
/* discord_presence.spectateSecret = "SPECSPECSPEC"; */
|
||||
discord_presence.partyId = strdup(party_id);
|
||||
discord_presence.partyMax = 0;
|
||||
discord_presence.partySize = 0;
|
||||
RARCH_LOG("[Discord] joining: \n Secret: %s\n Party: %s\n", discord_presence.joinSecret, discord_presence.partyId);
|
||||
break;
|
||||
case DISCORD_PRESENCE_NETPLAY_HOSTING_STOPPED:
|
||||
case DISCORD_PRESENCE_NETPLAY_CLIENT:
|
||||
@ -226,13 +347,14 @@ void discord_init(void)
|
||||
handlers.spectateGame = handle_discord_spectate;
|
||||
handlers.joinRequest = handle_discord_join_request;
|
||||
|
||||
/* To-Do: Add the arguments RetroArch was started with to the register URI*/
|
||||
const char command[256] = "retroarch";
|
||||
|
||||
Discord_Initialize(settings->arrays.discord_app_id, &handlers, 0, NULL);
|
||||
Discord_Register(settings->arrays.discord_app_id, NULL);
|
||||
|
||||
discord_ready = true;
|
||||
char command[PATH_MAX_LENGTH];
|
||||
strlcpy(command, get_retroarch_launch_arguments(), sizeof(command));
|
||||
|
||||
RARCH_LOG("[Discord] registering startup command: %s\n", command);
|
||||
Discord_Register(settings->arrays.discord_app_id, command);
|
||||
discord_ready = true;
|
||||
}
|
||||
|
||||
void discord_shutdown(void)
|
||||
|
@ -55,4 +55,14 @@ void discord_update(enum discord_presence presence);
|
||||
|
||||
void discord_run_callbacks();
|
||||
|
||||
bool discord_is_ready();
|
||||
|
||||
void discord_avatar_set_ready(bool ready);
|
||||
|
||||
bool discord_avatar_is_ready();
|
||||
|
||||
char* discord_get_own_username(void);
|
||||
|
||||
char* discord_get_own_avatar(void);
|
||||
|
||||
#endif /* __RARCH_DISCORD_H */
|
||||
|
@ -338,6 +338,31 @@ void fill_pathname_application_special(char *s,
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS:
|
||||
{
|
||||
char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||
char *s2 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
s1[0] = s2[0] = '\0';
|
||||
|
||||
fill_pathname_join(s1,
|
||||
settings->paths.directory_thumbnails,
|
||||
"discord",
|
||||
len);
|
||||
fill_pathname_join(s2,
|
||||
s1, "avatars",
|
||||
PATH_MAX_LENGTH * sizeof(char)
|
||||
);
|
||||
fill_pathname_slash(s2,
|
||||
PATH_MAX_LENGTH * sizeof(char)
|
||||
);
|
||||
strlcpy(s, s2, len);
|
||||
free(s1);
|
||||
free(s2);
|
||||
}
|
||||
break;
|
||||
|
||||
case APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES:
|
||||
{
|
||||
char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||
|
@ -111,7 +111,8 @@ enum application_special_type
|
||||
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH,
|
||||
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_FONT,
|
||||
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS,
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES,
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -133,6 +133,10 @@ MSG_HASH(
|
||||
MSG_NETPLAY_ENTER_PASSWORD,
|
||||
"Enter netplay server password:"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_DISCORD_CONNECTION_REQUEST,
|
||||
"Do you want to allow connection from user:"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_INCORRECT_PASSWORD,
|
||||
"Incorrect password"
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
#include "../../discord/discord.h"
|
||||
#endif
|
||||
|
||||
#include "../../config.def.h"
|
||||
#include "../../config.def.keybinds.h"
|
||||
#include "../../wifi/wifi_driver.h"
|
||||
@ -3343,7 +3347,7 @@ static void cb_generic_dir_download(void *task_data,
|
||||
}
|
||||
|
||||
/* expects http_transfer_t*, file_transfer_t* */
|
||||
static void cb_generic_download(void *task_data,
|
||||
void cb_generic_download(void *task_data,
|
||||
void *user_data, const char *err)
|
||||
{
|
||||
char output_path[PATH_MAX_LENGTH];
|
||||
@ -3359,6 +3363,7 @@ static void cb_generic_download(void *task_data,
|
||||
goto finish;
|
||||
|
||||
output_path[0] = '\0';
|
||||
char buf[PATH_MAX_LENGTH];;
|
||||
|
||||
/* we have to determine dir_path at the time of writting or else
|
||||
* we'd run into races when the user changes the setting during an
|
||||
@ -3423,6 +3428,14 @@ static void cb_generic_download(void *task_data,
|
||||
case MENU_ENUM_LABEL_CB_LAKKA_DOWNLOAD:
|
||||
dir_path = LAKKA_UPDATE_DIR;
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CB_DISCORD_AVATAR:
|
||||
{
|
||||
fill_pathname_application_special(buf,
|
||||
PATH_MAX_LENGTH * sizeof(char),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS);
|
||||
dir_path = buf;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RARCH_WARN("Unknown transfer type '%s' bailing out.\n",
|
||||
msg_hash_to_str(transf->enum_idx));
|
||||
@ -3495,6 +3508,10 @@ finish:
|
||||
RARCH_ERR("Download of '%s' failed: %s\n",
|
||||
(transf ? transf->path: "unknown"), err);
|
||||
}
|
||||
#ifdef HAVE_DISCORD
|
||||
else if (transf->enum_idx == MENU_ENUM_LABEL_CB_DISCORD_AVATAR)
|
||||
discord_avatar_set_ready(true);
|
||||
#endif
|
||||
|
||||
if (data)
|
||||
{
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include "ozone_texture.h"
|
||||
#include "ozone_sidebar.h"
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
#include "discord/discord.h"
|
||||
#endif
|
||||
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <encodings/utf.h>
|
||||
@ -348,14 +352,37 @@ static void ozone_context_reset(void *data, bool is_threaded)
|
||||
for (i = 0; i < OZONE_TEXTURE_LAST; i++)
|
||||
{
|
||||
char filename[PATH_MAX_LENGTH];
|
||||
strlcpy(filename, OZONE_TEXTURES_FILES[i], sizeof(filename));
|
||||
#ifdef HAVE_DISCORD
|
||||
if (i == OZONE_TEXTURE_DISCORD_OWN_AVATAR)
|
||||
strlcpy(filename, discord_get_own_avatar(), sizeof(filename));
|
||||
else
|
||||
#endif
|
||||
strlcpy(filename, OZONE_TEXTURES_FILES[i], sizeof(filename));
|
||||
|
||||
strlcat(filename, ".png", sizeof(filename));
|
||||
|
||||
if (!menu_display_reset_textures_list(filename, ozone->png_path, &ozone->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR))
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
if (i == OZONE_TEXTURE_DISCORD_OWN_AVATAR && discord_avatar_is_ready())
|
||||
{
|
||||
ozone->has_all_assets = false;
|
||||
RARCH_WARN("[OZONE] Asset missing: %s%s%s\n", ozone->png_path, path_default_slash(), filename);
|
||||
char buf[PATH_MAX_LENGTH];
|
||||
fill_pathname_application_special(buf,
|
||||
sizeof(buf),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS);
|
||||
if (!menu_display_reset_textures_list(filename, buf, &ozone->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR))
|
||||
RARCH_WARN("[OZONE] Asset missing: %s%s%s\n", ozone->png_path, path_default_slash(), filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
if (!menu_display_reset_textures_list(filename, ozone->png_path, &ozone->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR))
|
||||
{
|
||||
ozone->has_all_assets = false;
|
||||
RARCH_WARN("[OZONE] Asset missing: %s%s%s\n", ozone->png_path, path_default_slash(), filename);
|
||||
}
|
||||
#ifdef HAVE_DISCORD
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sidebar textures */
|
||||
@ -930,7 +957,12 @@ static void ozone_draw_header(ozone_handle_t *ozone, video_frame_info_t *video_i
|
||||
|
||||
/* Icon */
|
||||
menu_display_blend_begin(video_info);
|
||||
ozone_draw_icon(video_info, 60, 60, ozone->textures[OZONE_TEXTURE_RETROARCH], 47, 14, video_info->width, video_info->height, 0, 1, ozone->theme->entries_icon);
|
||||
#ifdef HAVE_DISCORD
|
||||
if (discord_avatar_is_ready())
|
||||
ozone_draw_icon(video_info, 60, 60, ozone->textures[OZONE_TEXTURE_DISCORD_OWN_AVATAR], 47, 14, video_info->width, video_info->height, 0, 1, ozone->theme->entries_icon);
|
||||
else
|
||||
#endif
|
||||
ozone_draw_icon(video_info, 60, 60, ozone->textures[OZONE_TEXTURE_RETROARCH], 47, 14, video_info->width, video_info->height, 0, 1, ozone->theme->entries_icon);
|
||||
menu_display_blend_end(video_info);
|
||||
|
||||
/* Battery */
|
||||
@ -1117,6 +1149,16 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
|
||||
bool draw_osk = menu_input_dialog_get_display_kb();
|
||||
static bool draw_osk_old = false;
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
static bool reset = false;
|
||||
|
||||
if (discord_avatar_is_ready() && !reset)
|
||||
{
|
||||
ozone_context_reset(data, false);
|
||||
reset = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
menu_animation_ctx_entry_t entry;
|
||||
|
||||
if (!ozone)
|
||||
|
@ -28,7 +28,9 @@
|
||||
enum OZONE_TEXTURE {
|
||||
OZONE_TEXTURE_RETROARCH = 0,
|
||||
OZONE_TEXTURE_CURSOR_BORDER,
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
OZONE_TEXTURE_DISCORD_OWN_AVATAR,
|
||||
#endif
|
||||
OZONE_TEXTURE_LAST
|
||||
};
|
||||
|
||||
|
@ -286,6 +286,10 @@ void menu_cbs_init(void *data,
|
||||
|
||||
int menu_cbs_exit(void);
|
||||
|
||||
void cb_generic_download(void *task_data,
|
||||
void *user_data, const char *err);
|
||||
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -189,6 +189,7 @@ enum msg_hash_enums
|
||||
MSG_RESAMPLER_QUALITY_NORMAL,
|
||||
MSG_RESAMPLER_QUALITY_HIGHER,
|
||||
MSG_RESAMPLER_QUALITY_HIGHEST,
|
||||
MSG_DISCORD_CONNECTION_REQUEST,
|
||||
MSG_ADDED_TO_FAVORITES,
|
||||
MSG_RESET_CORE_ASSOCIATION,
|
||||
MSG_CORE_ASSOCIATION_RESET,
|
||||
@ -1933,6 +1934,7 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_CB_UPDATE_SHADERS_CG,
|
||||
MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL,
|
||||
MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG,
|
||||
MENU_ENUM_LABEL_CB_DISCORD_AVATAR,
|
||||
|
||||
/* Sublabels */
|
||||
MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY,
|
||||
|
16
retroarch.c
16
retroarch.c
@ -279,6 +279,8 @@ static retro_time_t frame_limit_last_time = 0.0;
|
||||
|
||||
extern bool input_driver_flushing_input;
|
||||
|
||||
static char launch_arguments[4096];
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
bool retroarch_core_set_on_cmdline(void)
|
||||
{
|
||||
@ -640,6 +642,15 @@ static void retroarch_parse_input_and_config(int argc, char *argv[])
|
||||
bool explicit_menu = false;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
/* Nasty hack to copy the args into a global so discord can register the same arguments for launch */
|
||||
char buf[4096];
|
||||
for (unsigned i = 0; i < argc; i++)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%s %s", launch_arguments, argv[i]);
|
||||
strlcpy(launch_arguments, buf, sizeof(launch_arguments));
|
||||
}
|
||||
string_trim_whitespace_left(launch_arguments);
|
||||
|
||||
const struct option opts[] = {
|
||||
#ifdef HAVE_DYNAMIC
|
||||
{ "libretro", 1, NULL, 'L' },
|
||||
@ -3667,3 +3678,8 @@ struct retro_system_info *runloop_get_libretro_system_info(void)
|
||||
struct retro_system_info *system = &runloop_system.info;
|
||||
return system;
|
||||
}
|
||||
|
||||
char *get_retroarch_launch_arguments(void)
|
||||
{
|
||||
return launch_arguments;
|
||||
}
|
@ -391,6 +391,8 @@ void rarch_menu_running_finished(void);
|
||||
|
||||
bool retroarch_is_on_main_thread(void);
|
||||
|
||||
char *get_retroarch_launch_arguments(void);
|
||||
|
||||
rarch_system_info_t *runloop_get_system_info(void);
|
||||
|
||||
struct retro_system_info *runloop_get_libretro_system_info(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user