mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Merge branch 'master' into send_debug
This commit is contained in:
commit
9279d06f93
@ -39,7 +39,7 @@ RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS += -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L.
|
||||
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lpad -lmc -lhdd -lsdl -lfileXio -lpatches -lpoweroff
|
||||
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lmf -lpad -lmc -lhdd -lsdl -lfileXio -lpatches -lpoweroff
|
||||
|
||||
#IRX modules
|
||||
# IRX modules - modules have to be in IRX_DIR
|
||||
|
@ -23,13 +23,12 @@
|
||||
|
||||
#include "../audio_driver.h"
|
||||
|
||||
#define AUDIO_BUFFER 64 * 1024
|
||||
#define AUDIO_BUFFER 128 * 1024
|
||||
#define AUDIO_CHANNELS 2
|
||||
#define AUDIO_BITS 16
|
||||
|
||||
typedef struct ps2_audio
|
||||
{
|
||||
fifo_buffer_t* buffer;
|
||||
bool nonblocking;
|
||||
bool running;
|
||||
|
||||
@ -82,21 +81,15 @@ static void ps2_audio_free(void *data)
|
||||
|
||||
static ssize_t ps2_audio_write(void *data, const void *buf, size_t size)
|
||||
{
|
||||
int bytes_sent;
|
||||
ps2_audio_t* ps2 = (ps2_audio_t*)data;
|
||||
|
||||
if (!ps2->running)
|
||||
return -1;
|
||||
|
||||
if (ps2->nonblocking)
|
||||
{
|
||||
if (fifo_write_avail(ps2->buffer) < size)
|
||||
return 0;
|
||||
}
|
||||
bytes_sent = audsrv_play_audio(buf, size);
|
||||
|
||||
audsrv_wait_audio(size);
|
||||
audsrv_play_audio(buf, size);
|
||||
|
||||
return size;
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
static bool ps2_audio_alive(void *data)
|
||||
|
106
command.c
Normal file → Executable file
106
command.c
Normal file → Executable file
@ -277,66 +277,45 @@ bool command_set_shader(const char *arg)
|
||||
#define SMY_CMD_STR "READ_CORE_RAM"
|
||||
static bool command_read_ram(const char *arg)
|
||||
{
|
||||
#if defined(HAVE_NEW_CHEEVOS)
|
||||
#if !defined(HAVE_NEW_CHEEVOS)
|
||||
cheevos_var_t var;
|
||||
#endif
|
||||
unsigned i;
|
||||
char *reply = NULL;
|
||||
const uint8_t * data = NULL;
|
||||
char *reply = NULL;
|
||||
const uint8_t *data = NULL;
|
||||
char *reply_at = NULL;
|
||||
unsigned int nbytes = 0;
|
||||
unsigned int alloc_size = 0;
|
||||
unsigned int addr = -1;
|
||||
unsigned int addr = -1;
|
||||
|
||||
if (sscanf(arg, "%x %d", &addr, &nbytes) != 2)
|
||||
return true;
|
||||
alloc_size = 40 + nbytes * 3; /* We alloc more than needed, saving 20 bytes is not really relevant */
|
||||
reply = (char*) malloc(alloc_size);
|
||||
reply[0] = '\0';
|
||||
reply_at = reply + snprintf(reply, alloc_size - 1, SMY_CMD_STR " %x", addr);
|
||||
|
||||
#if defined(HAVE_NEW_CHEEVOS)
|
||||
data = cheevos_patch_address(addr, cheevos_get_console());
|
||||
|
||||
if (data)
|
||||
{
|
||||
for (i = 0; i < nbytes; i++)
|
||||
sprintf(reply_at+3*i, " %.2X", data[i]);
|
||||
reply_at[3*nbytes] = '\n';
|
||||
command_reply(reply, reply_at+3*nbytes+1 - reply);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(reply_at, " -1\n", sizeof(reply)-strlen(reply));
|
||||
command_reply(reply, reply_at+strlen(" -1\n") - reply);
|
||||
}
|
||||
free(reply);
|
||||
#else
|
||||
cheevos_var_t var;
|
||||
unsigned i;
|
||||
char reply[256] = {0};
|
||||
const uint8_t * data = NULL;
|
||||
char *reply_at = NULL;
|
||||
|
||||
reply[0] = '\0';
|
||||
|
||||
strlcpy(reply, "READ_CORE_RAM ", sizeof(reply));
|
||||
reply_at = reply + strlen("READ_CORE_RAM ");
|
||||
strlcpy(reply_at, arg, sizeof(reply)-strlen(reply));
|
||||
|
||||
var.value = strtoul(reply_at, (char**)&reply_at, 16);
|
||||
var.value = addr;
|
||||
cheevos_var_patch_addr(&var, cheevos_get_console());
|
||||
data = cheevos_var_get_memory(&var);
|
||||
#endif
|
||||
|
||||
if (data)
|
||||
{
|
||||
unsigned nbytes = strtol(reply_at, NULL, 10);
|
||||
|
||||
for (i = 0; i < nbytes; i++)
|
||||
sprintf(reply_at+3*i, " %.2X", data[i]);
|
||||
reply_at[3*nbytes] = '\n';
|
||||
command_reply(reply, reply_at+3*nbytes+1 - reply);
|
||||
snprintf(reply_at + 3 * i, 4, " %.2X", data[i]);
|
||||
reply_at[3 * nbytes] = '\n';
|
||||
command_reply(reply, reply_at + 3 * nbytes + 1 - reply);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(reply_at, " -1\n", sizeof(reply)-strlen(reply));
|
||||
command_reply(reply, reply_at+strlen(" -1\n") - reply);
|
||||
strlcpy(reply_at, " -1\n", sizeof(reply) - strlen(reply));
|
||||
command_reply(reply, reply_at + strlen(" -1\n") - reply);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(reply);
|
||||
return true;
|
||||
}
|
||||
#undef SMY_CMD_STR
|
||||
@ -2412,44 +2391,25 @@ TODO: Add a setting for these tweaks */
|
||||
break;
|
||||
case CMD_EVENT_ADD_TO_FAVORITES:
|
||||
{
|
||||
/* TODO/FIXME - does path_get(RARCH_PATH_CORE) depend on the system info struct? Investigate */
|
||||
global_t *global = global_get_ptr();
|
||||
struct retro_system_info *system = runloop_get_libretro_system_info();
|
||||
const char *label = NULL;
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char core_name[PATH_MAX_LENGTH];
|
||||
struct string_list *str_list = (struct string_list*)data;
|
||||
|
||||
core_path[0] = '\0';
|
||||
core_name[0] = '\0';
|
||||
|
||||
if (system)
|
||||
if (str_list)
|
||||
{
|
||||
if (!string_is_empty(path_get(RARCH_PATH_CORE)))
|
||||
strlcpy(core_path, path_get(RARCH_PATH_CORE), sizeof(core_path));
|
||||
|
||||
if (!string_is_empty(system->library_name))
|
||||
strlcpy(core_name, system->library_name, sizeof(core_name));
|
||||
if (str_list->size >= 4)
|
||||
{
|
||||
/* Write playlist entry */
|
||||
command_playlist_push_write(
|
||||
g_defaults.content_favorites,
|
||||
str_list->elems[0].data, /* content_path */
|
||||
str_list->elems[1].data, /* content_label */
|
||||
str_list->elems[2].data, /* core_path */
|
||||
str_list->elems[3].data /* core_name */
|
||||
);
|
||||
runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
if (string_is_empty(core_path))
|
||||
strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path));
|
||||
|
||||
if (string_is_empty(core_name))
|
||||
strlcpy(core_name, file_path_str(FILE_PATH_DETECT), sizeof(core_name));
|
||||
|
||||
if (!string_is_empty(global->name.label))
|
||||
label = global->name.label;
|
||||
|
||||
command_playlist_push_write(
|
||||
g_defaults.content_favorites,
|
||||
(const char*)data,
|
||||
label,
|
||||
core_path,
|
||||
core_name
|
||||
);
|
||||
runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
break;
|
||||
|
||||
}
|
||||
case CMD_EVENT_RESET_CORE_ASSOCIATION:
|
||||
{
|
||||
|
@ -717,6 +717,9 @@ static const bool playlist_show_core_name = false;
|
||||
|
||||
static const bool playlist_show_sublabels = false;
|
||||
|
||||
/* Specifies which runtime record to use on playlist sublabels */
|
||||
static unsigned playlist_sublabel_runtime_type = PLAYLIST_RUNTIME_PER_CORE;
|
||||
|
||||
/* Show Menu start-up screen on boot. */
|
||||
static const bool default_menu_show_start_screen = true;
|
||||
|
||||
@ -794,6 +797,9 @@ static const bool desktop_menu_enable = true;
|
||||
/* Keep track of how long each core+content has been running for over time */
|
||||
static const bool content_runtime_log = false;
|
||||
|
||||
/* Keep track of how long each content has been running for over time (ignores core) */
|
||||
static const bool content_runtime_log_aggregate = false;
|
||||
|
||||
#if defined(__QNX__) || defined(_XBOX1) || defined(_XBOX360) || defined(__CELLOS_LV2__) || (defined(__MACH__) && defined(IOS)) || defined(ANDROID) || defined(WIIU) || defined(HAVE_NEON) || defined(GEKKO) || defined(__ARM_NEON__)
|
||||
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_LOWER;
|
||||
#elif defined(PSP) || defined(_3DS) || defined(VITA) || defined(PS2)
|
||||
|
@ -1578,7 +1578,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
#endif
|
||||
|
||||
SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, playlist_use_old_format, false);
|
||||
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, content_runtime_log, false);
|
||||
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, content_runtime_log, false);
|
||||
SETTING_BOOL("content_runtime_log_aggregate", &settings->bools.content_runtime_log_aggregate, true, content_runtime_log_aggregate, false);
|
||||
SETTING_BOOL("playlist_show_sublabels", &settings->bools.playlist_show_sublabels, true, playlist_show_sublabels, false);
|
||||
SETTING_BOOL("playlist_show_core_name", &settings->bools.playlist_show_core_name, true, playlist_show_core_name, false);
|
||||
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, playlist_sort_alphabetical, false);
|
||||
@ -1762,6 +1763,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("libnx_overclock", &settings->uints.libnx_overclock, true, SWITCH_DEFAULT_CPU_PROFILE, false);
|
||||
#endif
|
||||
|
||||
SETTING_UINT("playlist_sublabel_runtime_type", &settings->uints.playlist_sublabel_runtime_type, true, playlist_sublabel_runtime_type, false);
|
||||
|
||||
*size = count;
|
||||
|
||||
return tmp;
|
||||
|
@ -309,6 +309,7 @@ typedef struct settings
|
||||
bool sustained_performance_mode;
|
||||
bool playlist_use_old_format;
|
||||
bool content_runtime_log;
|
||||
bool content_runtime_log_aggregate;
|
||||
|
||||
bool playlist_show_core_name;
|
||||
bool playlist_sort_alphabetical;
|
||||
@ -438,6 +439,8 @@ typedef struct settings
|
||||
unsigned menu_rgui_internal_upscale_level;
|
||||
unsigned menu_ticker_type;
|
||||
|
||||
unsigned playlist_sublabel_runtime_type;
|
||||
|
||||
unsigned camera_width;
|
||||
unsigned camera_height;
|
||||
|
||||
|
12
core_info.c
12
core_info.c
@ -539,6 +539,7 @@ static core_info_t *core_info_find_internal(
|
||||
const char *core)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_path_basename = path_basename(core);
|
||||
|
||||
for (i = 0; i < list->count; i++)
|
||||
{
|
||||
@ -546,7 +547,7 @@ static core_info_t *core_info_find_internal(
|
||||
|
||||
if (!info || !info->path)
|
||||
continue;
|
||||
if (string_is_equal(info->path, core))
|
||||
if (string_is_equal(path_basename(info->path), core_path_basename))
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -799,13 +800,16 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
|
||||
|
||||
void core_info_get_name(const char *path, char *s, size_t len,
|
||||
const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool dir_show_hidden_files)
|
||||
const char *exts, bool dir_show_hidden_files,
|
||||
bool get_display_name)
|
||||
{
|
||||
size_t i;
|
||||
const char *path_basedir = !string_is_empty(path_info) ?
|
||||
path_info : dir_cores;
|
||||
struct string_list *contents = dir_list_new(
|
||||
dir_cores, exts, false, dir_show_hidden_files, false, false);
|
||||
const char *core_path_basename = path_basename(path);
|
||||
|
||||
if (!contents)
|
||||
return;
|
||||
|
||||
@ -817,7 +821,7 @@ void core_info_get_name(const char *path, char *s, size_t len,
|
||||
char *new_core_name = NULL;
|
||||
const char *current_path = contents->elems[i].data;
|
||||
|
||||
if (!string_is_equal(current_path, path))
|
||||
if (!string_is_equal(path_basename(current_path), core_path_basename))
|
||||
continue;
|
||||
|
||||
info_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||
@ -839,7 +843,7 @@ void core_info_get_name(const char *path, char *s, size_t len,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "corename",
|
||||
if (config_get_string(conf, get_display_name ? "display_name" : "corename",
|
||||
&new_core_name))
|
||||
{
|
||||
strlcpy(s, new_core_name, len);
|
||||
|
@ -101,7 +101,8 @@ bool core_info_get_display_name(const char *path, char *s, size_t len);
|
||||
|
||||
void core_info_get_name(const char *path, char *s, size_t len,
|
||||
const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool show_hidden_files);
|
||||
const char *exts, bool show_hidden_files,
|
||||
bool get_display_name);
|
||||
|
||||
core_info_t *core_info_get(core_info_list_t *list, size_t i);
|
||||
|
||||
|
@ -1279,6 +1279,14 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
|
||||
case RETRO_ENVIRONMENT_SHUTDOWN:
|
||||
RARCH_LOG("Environ SHUTDOWN.\n");
|
||||
|
||||
/* This case occurs when a core (internally) requests
|
||||
* a shutdown event. Must save runtime log file here,
|
||||
* since normal command.c CMD_EVENT_CORE_DEINIT event
|
||||
* will not occur until after the current content has
|
||||
* been cleared (causing log to be skipped) */
|
||||
rarch_ctl(RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT, NULL);
|
||||
|
||||
rarch_ctl(RARCH_CTL_SET_SHUTDOWN, NULL);
|
||||
rarch_ctl(RARCH_CTL_SET_CORE_SHUTDOWN, NULL);
|
||||
break;
|
||||
|
@ -241,21 +241,14 @@ static void frontend_ps2_init(void *data)
|
||||
static void frontend_ps2_deinit(void *data)
|
||||
{
|
||||
(void)data;
|
||||
#ifndef IS_SALAMANDER
|
||||
#if defined(HAVE_FILE_LOGGER)
|
||||
verbosity_disable();
|
||||
#ifdef HAVE_FILE_LOGGER
|
||||
command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
padEnd();
|
||||
audsrv_quit();
|
||||
|
||||
fileXioUmount("pfs0:");
|
||||
fileXioExit();
|
||||
|
||||
SifExitRpc();
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
static void frontend_ps2_exec(const char *path, bool should_load_game)
|
||||
|
@ -276,7 +276,11 @@ static bool ps2_gfx_frame(void *data, const void *frame,
|
||||
bool sendPalette = false;
|
||||
struct retro_hw_ps2_insets padding = empty_ps2_insets;
|
||||
if (frame != RETRO_HW_FRAME_BUFFER_VALID){ /* Checking if the transfer is done in the core */
|
||||
transfer_texture(ps2->coreTexture, frame, width, height, ps2->PSM, ps2->core_filter, 1);
|
||||
/* calculate proper width based in the pitch */
|
||||
int bytes_per_pixel = (ps2->PSM == GS_PSM_CT32) ? 4 : 2;
|
||||
int real_width = pitch / bytes_per_pixel;
|
||||
transfer_texture(ps2->coreTexture, frame, real_width, height, ps2->PSM, ps2->core_filter, 1);
|
||||
padding.right = real_width - width;
|
||||
} else {
|
||||
sendPalette = ps2->iface.updatedPalette;
|
||||
ps2->iface.updatedPalette = false;
|
||||
|
@ -43,8 +43,24 @@ static u32 gsKit_fontm_clut[16] = { 0x00000000, 0x11111111, 0x22222222, 0x333333
|
||||
0x80888888, 0x80999999, 0x80AAAAAA, 0x80BBBBBB, \
|
||||
0x80CCCCCC, 0x80DDDDDD, 0x80EEEEEE, 0x80FFFFFF };
|
||||
|
||||
static void ps2_prepare_font(GSGLOBAL *gsGlobal, GSFONTM *gsFontM)
|
||||
static void deinit_texture(GSTEXTURE *texture)
|
||||
{
|
||||
free(texture->Mem);
|
||||
free(texture->Clut);
|
||||
texture->Mem = NULL;
|
||||
texture->Clut = NULL;
|
||||
}
|
||||
|
||||
static void deinit_gsfont(GSFONTM *gsFontM)
|
||||
{
|
||||
deinit_texture(gsFontM->Texture);
|
||||
free(gsFontM->TexBase);
|
||||
gsFontM->TexBase = NULL;
|
||||
free(gsFontM);
|
||||
}
|
||||
|
||||
static void ps2_prepare_font(GSGLOBAL *gsGlobal, GSFONTM *gsFontM)
|
||||
{
|
||||
if(gsKit_fontm_unpack(gsFontM) == 0) {
|
||||
gsFontM->Texture->Width = FONTM_TEXTURE_WIDTH;
|
||||
gsFontM->Texture->Height = FONTM_TEXTURE_HEIGHT;
|
||||
@ -94,8 +110,9 @@ static void *ps2_font_init_font(void *gl_data, const char *font_path,
|
||||
static void ps2_font_free_font(void *data, bool is_threaded)
|
||||
{
|
||||
ps2_font_info_t *ps2 = (ps2_font_info_t *)data;
|
||||
free(ps2->gsFontM);
|
||||
free(ps2);
|
||||
deinit_gsfont(ps2->gsFontM);
|
||||
ps2->ps2_video = NULL;
|
||||
ps2 = NULL;
|
||||
}
|
||||
|
||||
static void ps2_font_render_msg(
|
||||
|
@ -1789,11 +1789,15 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_BGM,
|
||||
"menu_sound_bgm")
|
||||
MSG_HASH(MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG,
|
||||
"content_runtime_log")
|
||||
MSG_HASH(MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
"content_runtime_log_aggregate")
|
||||
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME,
|
||||
"playlist_show_core_name")
|
||||
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL,
|
||||
"playlist_sort_alphabetical")
|
||||
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS,
|
||||
"playlist_show_sublabels")
|
||||
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
"playlist_sublabel_runtime_type")
|
||||
MSG_HASH(MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO,
|
||||
"help_send_debug_info")
|
||||
|
@ -8312,11 +8312,19 @@ MSG_HASH(
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG,
|
||||
"Save content runtime log"
|
||||
"Save runtime log (per core)"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG,
|
||||
"Keeps track of how long your content has been running over time."
|
||||
"Keeps track of how long each item of content has run for, with records separated by core."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
"Save runtime log (aggregate)"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
"Keeps track of how long each item of content has run for, recorded as the aggregate total across all cores."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SHOW_SUBLABELS,
|
||||
@ -8324,7 +8332,7 @@ MSG_HASH(
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_SUBLABELS,
|
||||
"Shows additional information for each playlist entry, such as current core association and play time (if available). Has a variable performance impact."
|
||||
"Shows additional information for each playlist entry, such as current core association and runtime (if available). Has a variable performance impact."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE,
|
||||
@ -8338,6 +8346,22 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_LAST_PLAYED,
|
||||
"Last Played:"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
"Playlist sublabel runtime"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
"Selects which type of runtime log record to display on playlist sublabels. (Note that the corresponding runtime log must be enabled via the 'Saving' options menu)"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE,
|
||||
"Per Core"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE,
|
||||
"Aggregate"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO,
|
||||
"Send Debug Info"
|
||||
|
@ -222,8 +222,8 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
|
||||
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
|
||||
return fseek(stream->fp, (long)offset, whence);
|
||||
#elif defined(PS2)
|
||||
int64_t ret = fioLseek(fileno(stream->fp), (off_t)offset, whence);
|
||||
/* fioLseek could return positive numbers */
|
||||
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
|
||||
/* fileXioLseek could return positive numbers */
|
||||
if (ret > 0) {
|
||||
ret = 0;
|
||||
}
|
||||
|
@ -2672,7 +2672,8 @@ static int action_ok_core_deferred_set(const char *new_core_path,
|
||||
settings->paths.path_libretro_info,
|
||||
settings->paths.directory_libretro,
|
||||
ext_name,
|
||||
settings->bools.show_hidden_files);
|
||||
settings->bools.show_hidden_files,
|
||||
true);
|
||||
command_playlist_update_write(
|
||||
NULL,
|
||||
menu->scratchpad.unsigned_var,
|
||||
@ -3809,35 +3810,200 @@ static int action_ok_reset_core_association(const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is called when selecting 'add to favorites'
|
||||
* while viewing the quick menu (i.e. content is running) */
|
||||
static int action_ok_add_to_favorites(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
void *new_path = (void*)path_get(RARCH_PATH_CONTENT);
|
||||
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, new_path))
|
||||
return menu_cbs_exit();
|
||||
return 0;
|
||||
const char *content_path = path_get(RARCH_PATH_CONTENT);
|
||||
int ret = 0;
|
||||
|
||||
/* Error checking
|
||||
* > If content path is empty, cannot do anything... */
|
||||
if (!string_is_empty(content_path))
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
struct retro_system_info *system = runloop_get_libretro_system_info();
|
||||
struct string_list *str_list = NULL;
|
||||
|
||||
union string_list_elem_attr attr;
|
||||
char content_label[PATH_MAX_LENGTH];
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char core_name[PATH_MAX_LENGTH];
|
||||
|
||||
content_label[0] = '\0';
|
||||
core_path[0] = '\0';
|
||||
core_name[0] = '\0';
|
||||
|
||||
/* Create string list container for playlist parameters */
|
||||
attr.i = 0;
|
||||
str_list = string_list_new();
|
||||
if (!str_list)
|
||||
return 0;
|
||||
|
||||
/* Determine playlist parameters */
|
||||
|
||||
/* > content_label */
|
||||
if (global)
|
||||
if (!string_is_empty(global->name.label))
|
||||
strlcpy(content_label, global->name.label, sizeof(content_label));
|
||||
|
||||
if (string_is_empty(content_label)) /* Label is empty - use file name instead */
|
||||
fill_short_pathname_representation(content_label, content_path, sizeof(content_label));
|
||||
|
||||
/* > core_path + core_name */
|
||||
if (system)
|
||||
{
|
||||
if (!string_is_empty(path_get(RARCH_PATH_CORE)))
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
/* >> core_path */
|
||||
strlcpy(core_path, path_get(RARCH_PATH_CORE), sizeof(core_path));
|
||||
|
||||
/* >> core_name
|
||||
* (always use display name, if available) */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info, core_path))
|
||||
if (!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_name, core_info.inf->display_name, sizeof(core_name));
|
||||
}
|
||||
|
||||
/* >> core_name (continued) */
|
||||
if (string_is_empty(core_name) && !string_is_empty(system->library_name))
|
||||
strlcpy(core_name, system->library_name, sizeof(core_name));
|
||||
}
|
||||
|
||||
if (string_is_empty(core_path) || string_is_empty(core_name))
|
||||
{
|
||||
strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path));
|
||||
strlcpy(core_name, file_path_str(FILE_PATH_DETECT), sizeof(core_name));
|
||||
}
|
||||
|
||||
/* Copy playlist parameters into string list
|
||||
* [0]: content_path
|
||||
* [1]: content_label
|
||||
* [2]: core_path
|
||||
* [3]: core_name */
|
||||
string_list_append(str_list, content_path, attr);
|
||||
string_list_append(str_list, content_label, attr);
|
||||
string_list_append(str_list, core_path, attr);
|
||||
string_list_append(str_list, core_name, attr);
|
||||
|
||||
/* Trigger 'ADD_TO_FAVORITES' event */
|
||||
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
|
||||
ret = menu_cbs_exit();
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(str_list);
|
||||
str_list = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is called when selecting 'add to favorites'
|
||||
* while viewing a playlist entry */
|
||||
static int action_ok_add_to_favorites_playlist(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
const char *tmp_path = NULL;
|
||||
menu_handle_t *menu = NULL;
|
||||
playlist_t *tmp_playlist = playlist_get_cached();
|
||||
const char *content_path = NULL;
|
||||
const char *content_label = NULL;
|
||||
const char *core_path = NULL;
|
||||
const char *core_name = NULL;
|
||||
menu_handle_t *menu = NULL;
|
||||
playlist_t *tmp_playlist = playlist_get_cached();
|
||||
int ret = 0;
|
||||
|
||||
if (!tmp_playlist)
|
||||
return 0;
|
||||
if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
|
||||
return menu_cbs_exit();
|
||||
|
||||
playlist_get_index(tmp_playlist,
|
||||
menu->rpl_entry_selection_ptr, &tmp_path,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
/* Read current playlist parameters */
|
||||
playlist_get_index(tmp_playlist, menu->rpl_entry_selection_ptr,
|
||||
&content_path, &content_label, &core_path, &core_name,
|
||||
NULL, NULL);
|
||||
|
||||
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)tmp_path))
|
||||
return menu_cbs_exit();
|
||||
return 0;
|
||||
/* Error checking
|
||||
* > If content path is empty, cannot do anything... */
|
||||
if (!string_is_empty(content_path))
|
||||
{
|
||||
struct string_list *str_list = NULL;
|
||||
union string_list_elem_attr attr;
|
||||
char core_display_name[PATH_MAX_LENGTH];
|
||||
|
||||
core_display_name[0] = '\0';
|
||||
|
||||
/* Create string list container for playlist parameters */
|
||||
attr.i = 0;
|
||||
str_list = string_list_new();
|
||||
if (!str_list)
|
||||
return 0;
|
||||
|
||||
/* Copy playlist parameters into string list
|
||||
* [0]: content_path
|
||||
* [1]: content_label
|
||||
* [2]: core_path
|
||||
* [3]: core_name */
|
||||
|
||||
/* > content_path */
|
||||
string_list_append(str_list, content_path, attr);
|
||||
|
||||
/* > content_label */
|
||||
if (!string_is_empty(content_label))
|
||||
{
|
||||
string_list_append(str_list, content_label, attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Label is empty - use file name instead */
|
||||
char fallback_content_label[PATH_MAX_LENGTH];
|
||||
fallback_content_label[0] = '\0';
|
||||
fill_short_pathname_representation(fallback_content_label, content_path, sizeof(fallback_content_label));
|
||||
string_list_append(str_list, fallback_content_label, attr);
|
||||
}
|
||||
|
||||
/* > core_path + core_name */
|
||||
if (!string_is_empty(core_path) && !string_is_empty(core_name))
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
/* >> core_path */
|
||||
string_list_append(str_list, core_path, attr);
|
||||
|
||||
/* >> core_name
|
||||
* (always use display name, if available) */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info, core_path))
|
||||
if (!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_display_name, core_info.inf->display_name, sizeof(core_display_name));
|
||||
|
||||
if (!string_is_empty(core_display_name))
|
||||
string_list_append(str_list, core_display_name, attr);
|
||||
else
|
||||
string_list_append(str_list, core_name, attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_list_append(str_list, file_path_str(FILE_PATH_DETECT), attr);
|
||||
string_list_append(str_list, file_path_str(FILE_PATH_DETECT), attr);
|
||||
}
|
||||
|
||||
/* Trigger 'ADD_TO_FAVORITES' event */
|
||||
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
|
||||
ret = menu_cbs_exit();
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(str_list);
|
||||
str_list = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int action_ok_delete_entry(const char *path,
|
||||
|
@ -522,6 +522,8 @@ default_sublabel_macro(action_bind_sublabel_rgui_menu_color_theme,
|
||||
default_sublabel_macro(action_bind_sublabel_rgui_menu_theme_preset, MENU_ENUM_SUBLABEL_RGUI_MENU_THEME_PRESET)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER)
|
||||
default_sublabel_macro(action_bind_sublabel_content_runtime_log, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG)
|
||||
default_sublabel_macro(action_bind_sublabel_content_runtime_log_aggregate, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG_AGGREGATE)
|
||||
default_sublabel_macro(action_bind_sublabel_playlist_sublabel_runtime_type, MENU_ENUM_SUBLABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_rgui_internal_upscale_level, MENU_ENUM_SUBLABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_ticker_type, MENU_ENUM_SUBLABEL_MENU_TICKER_TYPE)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_ticker_speed, MENU_ENUM_SUBLABEL_MENU_TICKER_SPEED)
|
||||
@ -856,9 +858,12 @@ static int action_bind_sublabel_playlist_entry(
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE),
|
||||
core_name);
|
||||
|
||||
/* Get runtime info *if* runtime logging is enabled
|
||||
/* Get runtime info *if* required runtime log is enabled
|
||||
* *and* this is a valid playlist type */
|
||||
if (!settings->bools.content_runtime_log)
|
||||
if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) &&
|
||||
!settings->bools.content_runtime_log) ||
|
||||
((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) &&
|
||||
!settings->bools.content_runtime_log_aggregate))
|
||||
return 0;
|
||||
|
||||
/* Note: This looks heavy, but each string_is_equal() call will
|
||||
@ -2377,6 +2382,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log_aggregate);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_sublabel_runtime_type);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_internal_upscale_level);
|
||||
break;
|
||||
|
@ -303,6 +303,13 @@ enum menu_input_ctl_state
|
||||
MENU_INPUT_CTL_DEINIT
|
||||
};
|
||||
|
||||
enum playlist_sublabel_runtime
|
||||
{
|
||||
PLAYLIST_RUNTIME_PER_CORE = 0,
|
||||
PLAYLIST_RUNTIME_AGGREGATE,
|
||||
PLAYLIST_RUNTIME_LAST
|
||||
};
|
||||
|
||||
typedef uintptr_t menu_texture_item;
|
||||
|
||||
typedef struct menu_display_ctx_clearcolor
|
||||
|
@ -1302,7 +1302,10 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
|
||||
goto error;
|
||||
|
||||
/* Check whether runtime logging info should be parsed */
|
||||
if (settings->bools.content_runtime_log)
|
||||
if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) &&
|
||||
settings->bools.content_runtime_log) ||
|
||||
((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) &&
|
||||
settings->bools.content_runtime_log_aggregate))
|
||||
{
|
||||
/* Runtime logging is valid for every type of playlist *apart from*
|
||||
* images/music/video history */
|
||||
@ -1350,7 +1353,8 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
|
||||
if (get_runtime)
|
||||
{
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
runtime_log = runtime_log_init(path, core_path);
|
||||
runtime_log = runtime_log_init(path, core_path,
|
||||
settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE);
|
||||
|
||||
if (runtime_log)
|
||||
{
|
||||
@ -2954,15 +2958,6 @@ static int menu_displaylist_parse_horizontal_content_actions(
|
||||
|
||||
if (settings->bools.quick_menu_show_add_to_favorites)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
/* Have to update global->name.label here, otherwise
|
||||
* the 'Add to Favorites' option will produce nonsensical
|
||||
* playlist entries... */
|
||||
if (global)
|
||||
if (!string_is_empty(label))
|
||||
strlcpy(global->name.label, label, sizeof(global->name.label));
|
||||
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES_PLAYLIST),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST),
|
||||
@ -5355,6 +5350,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
|
||||
ret = menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS,
|
||||
PARSE_ONLY_BOOL, false);
|
||||
ret = menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
PARSE_ONLY_UINT, false);
|
||||
ret = menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME,
|
||||
PARSE_ONLY_BOOL, false);
|
||||
@ -5479,6 +5477,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
|
||||
menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG,
|
||||
PARSE_ONLY_BOOL, false);
|
||||
menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
PARSE_ONLY_BOOL, false);
|
||||
|
||||
info->need_refresh = true;
|
||||
info->need_push = true;
|
||||
|
@ -545,8 +545,7 @@ bool menu_display_libretro(bool is_idle,
|
||||
|
||||
command_event(CMD_EVENT_DISCORD_UPDATE, &userdata);
|
||||
#endif
|
||||
return true; /* Maybe return false here
|
||||
for indication of idleness? */
|
||||
return false; /* Return false here for indication of idleness */
|
||||
}
|
||||
return video_driver_cached_frame();
|
||||
}
|
||||
|
@ -337,16 +337,16 @@ static void setting_get_string_representation_video_stream_quality(
|
||||
/* TODO/FIXME - localize this */
|
||||
switch (*setting->value.target.unsigned_integer)
|
||||
{
|
||||
case 8:
|
||||
case RECORD_CONFIG_TYPE_STREAMING_CUSTOM:
|
||||
strlcpy(s, "Custom", len);
|
||||
break;
|
||||
case 9:
|
||||
case RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY:
|
||||
strlcpy(s, "Low", len);
|
||||
break;
|
||||
case 10:
|
||||
case RECORD_CONFIG_TYPE_STREAMING_MED_QUALITY:
|
||||
strlcpy(s, "Medium", len);
|
||||
break;
|
||||
case 11:
|
||||
case RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY:
|
||||
strlcpy(s, "High", len);
|
||||
break;
|
||||
}
|
||||
@ -361,28 +361,28 @@ static void setting_get_string_representation_video_record_quality(rarch_setting
|
||||
/* TODO/FIXME - localize this */
|
||||
switch (*setting->value.target.unsigned_integer)
|
||||
{
|
||||
case 0:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_CUSTOM:
|
||||
strlcpy(s, "Custom", len);
|
||||
break;
|
||||
case 1:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_LOW_QUALITY:
|
||||
strlcpy(s, "Low", len);
|
||||
break;
|
||||
case 2:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_MED_QUALITY:
|
||||
strlcpy(s, "Medium", len);
|
||||
break;
|
||||
case 3:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_HIGH_QUALITY:
|
||||
strlcpy(s, "High", len);
|
||||
break;
|
||||
case 4:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_LOSSLESS_QUALITY:
|
||||
strlcpy(s, "Lossless", len);
|
||||
break;
|
||||
case 5:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST:
|
||||
strlcpy(s, "WebM Fast", len);
|
||||
break;
|
||||
case 6:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_WEBM_HIGH_QUALITY:
|
||||
strlcpy(s, "WebM High Quality", len);
|
||||
break;
|
||||
case 7:
|
||||
case RECORD_CONFIG_TYPE_RECORDING_GIF:
|
||||
strlcpy(s, "GIF", len);
|
||||
break;
|
||||
}
|
||||
@ -1298,6 +1298,30 @@ static void setting_get_string_representation_crt_switch_resolution_super(
|
||||
snprintf(s, len, "%d", *setting->value.target.unsigned_integer);
|
||||
}
|
||||
|
||||
static void setting_get_string_representation_uint_playlist_sublabel_runtime_type(
|
||||
rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
switch (*setting->value.target.unsigned_integer)
|
||||
{
|
||||
case PLAYLIST_RUNTIME_PER_CORE:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE),
|
||||
len);
|
||||
break;
|
||||
case PLAYLIST_RUNTIME_AGGREGATE:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE),
|
||||
len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int setting_action_left_analog_dpad_mode(rarch_setting_t *setting, bool wraparound)
|
||||
{
|
||||
unsigned port = 0;
|
||||
@ -4967,6 +4991,21 @@ static bool setting_append_list(
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.content_runtime_log_aggregate,
|
||||
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG_AGGREGATE,
|
||||
content_runtime_log_aggregate,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
|
||||
END_SUB_GROUP(list, list_info, parent_group);
|
||||
END_GROUP(list, list_info, parent_group);
|
||||
}
|
||||
@ -7295,7 +7334,7 @@ static bool setting_append_list(
|
||||
(*list)[list_info->index - 1].offset_by = 1;
|
||||
menu_settings_list_current_add_range(list, list_info, 1, 65536, 1, true, true);
|
||||
|
||||
CONFIG_UINT(
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.video_stream_quality,
|
||||
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
|
||||
@ -9884,6 +9923,22 @@ static bool setting_append_list(
|
||||
SD_FLAG_NONE
|
||||
);
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.playlist_sublabel_runtime_type,
|
||||
MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
|
||||
playlist_sublabel_runtime_type,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].get_string_representation =
|
||||
&setting_get_string_representation_uint_playlist_sublabel_runtime_type;
|
||||
menu_settings_list_current_add_range(list, list_info, 0, PLAYLIST_RUNTIME_LAST-1, 1, true, true);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.playlist_show_core_name,
|
||||
|
@ -2276,15 +2276,20 @@ enum msg_hash_enums
|
||||
MENU_LABEL(MENU_SOUND_BGM),
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER_FALLBACK,
|
||||
MENU_LABEL(CONTENT_RUNTIME_LOG),
|
||||
MENU_LABEL(CONTENT_RUNTIME_LOG_AGGREGATE),
|
||||
|
||||
MENU_LABEL(PLAYLIST_SHOW_CORE_NAME),
|
||||
MENU_LABEL(PLAYLIST_SORT_ALPHABETICAL),
|
||||
MENU_LABEL(PLAYLIST_SHOW_SUBLABELS),
|
||||
MENU_LABEL(PLAYLIST_SUBLABEL_RUNTIME_TYPE),
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE,
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME,
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_LAST_PLAYED,
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE,
|
||||
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE,
|
||||
|
||||
MENU_LABEL(HELP_SEND_DEBUG_INFO),
|
||||
MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO_DESC,
|
||||
|
||||
|
73
playlist.c
73
playlist.c
@ -1567,13 +1567,76 @@ playlist_t *playlist_init(const char *path, size_t size)
|
||||
static int playlist_qsort_func(const struct playlist_entry *a,
|
||||
const struct playlist_entry *b)
|
||||
{
|
||||
const char *a_label = a ? a->label : NULL;
|
||||
const char *b_label = b ? b->label : NULL;
|
||||
char *a_str = NULL;
|
||||
char *b_str = NULL;
|
||||
char *a_fallback_label = NULL;
|
||||
char *b_fallback_label = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!a_label || !b_label)
|
||||
return 0;
|
||||
if (!a || !b)
|
||||
goto end;
|
||||
|
||||
return strcasecmp(a_label, b_label);
|
||||
a_str = a->label;
|
||||
b_str = b->label;
|
||||
|
||||
/* It is quite possible for playlist labels
|
||||
* to be blank. If that is the case, have to use
|
||||
* filename as a fallback (this is slow, but we
|
||||
* have no other option...) */
|
||||
if (string_is_empty(a_str))
|
||||
{
|
||||
if (string_is_empty(a->path))
|
||||
goto end;
|
||||
|
||||
a_fallback_label = (char*)calloc(PATH_MAX_LENGTH, sizeof(char));
|
||||
if (!a_fallback_label)
|
||||
goto end;
|
||||
|
||||
fill_short_pathname_representation(a_fallback_label, a->path, PATH_MAX_LENGTH * sizeof(char));
|
||||
|
||||
if (string_is_empty(a_fallback_label))
|
||||
goto end;
|
||||
|
||||
a_str = a_fallback_label;
|
||||
}
|
||||
|
||||
if (string_is_empty(b_str))
|
||||
{
|
||||
if (string_is_empty(b->path))
|
||||
goto end;
|
||||
|
||||
b_fallback_label = (char*)calloc(PATH_MAX_LENGTH, sizeof(char));
|
||||
if (!b_fallback_label)
|
||||
goto end;
|
||||
|
||||
fill_short_pathname_representation(b_fallback_label, b->path, PATH_MAX_LENGTH * sizeof(char));
|
||||
|
||||
if (string_is_empty(b_fallback_label))
|
||||
goto end;
|
||||
|
||||
b_str = b_fallback_label;
|
||||
}
|
||||
|
||||
ret = strcasecmp(a_str, b_str);
|
||||
|
||||
end:
|
||||
|
||||
a_str = NULL;
|
||||
b_str = NULL;
|
||||
|
||||
if (a_fallback_label)
|
||||
{
|
||||
free(a_fallback_label);
|
||||
a_fallback_label = NULL;
|
||||
}
|
||||
|
||||
if (b_fallback_label)
|
||||
{
|
||||
free(b_fallback_label);
|
||||
b_fallback_label = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void playlist_qsort(playlist_t *playlist)
|
||||
|
@ -158,7 +158,7 @@ bool waitUntilDeviceIsReady(enum BootDeviceIDs device_id)
|
||||
|
||||
while(openFile < 0 && retries > 0)
|
||||
{
|
||||
openFile = fioDopen(rootDevice);
|
||||
openFile = fileXioDopen(rootDevice);
|
||||
/* Wait untill the device is ready */
|
||||
nopdelay();
|
||||
nopdelay();
|
||||
@ -172,7 +172,7 @@ bool waitUntilDeviceIsReady(enum BootDeviceIDs device_id)
|
||||
retries--;
|
||||
};
|
||||
|
||||
fioDclose(openFile);
|
||||
fileXioDclose(openFile);
|
||||
|
||||
return openFile >= 0;
|
||||
}
|
||||
|
@ -571,7 +571,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
params->out_pix_fmt = PIX_FMT_YUV420P;
|
||||
|
||||
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
|
||||
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
|
||||
strlcpy(params->acodec, "aac", sizeof(params->acodec));
|
||||
|
||||
av_dict_set(¶ms->video_opts, "preset", "ultrafast", 0);
|
||||
av_dict_set(¶ms->video_opts, "tune", "animation", 0);
|
||||
@ -587,7 +587,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
params->out_pix_fmt = PIX_FMT_YUV420P;
|
||||
|
||||
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
|
||||
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
|
||||
strlcpy(params->acodec, "aac", sizeof(params->acodec));
|
||||
|
||||
av_dict_set(¶ms->video_opts, "preset", "superfast", 0);
|
||||
av_dict_set(¶ms->video_opts, "tune", "animation", 0);
|
||||
@ -603,7 +603,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
params->out_pix_fmt = PIX_FMT_YUV444P;
|
||||
|
||||
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
|
||||
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
|
||||
strlcpy(params->acodec, "aac", sizeof(params->acodec));
|
||||
|
||||
av_dict_set(¶ms->video_opts, "preset", "superfast", 0);
|
||||
av_dict_set(¶ms->video_opts, "tune", "animation", 0);
|
||||
@ -663,7 +663,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
strlcpy(params->vcodec, "gif", sizeof(params->vcodec));
|
||||
strlcpy(params->acodec, "", sizeof(params->acodec));
|
||||
|
||||
av_dict_set(¶ms->video_opts, "framerate", "50", 0);
|
||||
av_dict_set(¶ms->video_opts, "framerate", "30", 0);
|
||||
av_dict_set(¶ms->audio_opts, "audio_global_quality", "0", 0);
|
||||
break;
|
||||
case RECORD_CONFIG_TYPE_STREAMING_NETPLAY:
|
||||
@ -694,7 +694,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
params->scale_factor = 1;
|
||||
strlcpy(params->format, "matroska", sizeof(params->format));
|
||||
}
|
||||
else if (preset >= RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST && settings->uints.video_record_quality < RECORD_CONFIG_TYPE_RECORDING_GIF)
|
||||
else if (preset >= RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST && preset < RECORD_CONFIG_TYPE_RECORDING_GIF)
|
||||
{
|
||||
if (!settings->bools.video_gpu_record)
|
||||
params->scale_factor = settings->uints.video_record_scale_factor > 0 ?
|
||||
@ -705,11 +705,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
|
||||
}
|
||||
else if (preset <= RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY)
|
||||
{
|
||||
if (!settings->bools.video_gpu_record)
|
||||
params->scale_factor = settings->uints.video_record_scale_factor > 0 ?
|
||||
settings->uints.video_record_scale_factor : 1;
|
||||
else
|
||||
params->scale_factor = 1;
|
||||
params->scale_factor = 1;
|
||||
strlcpy(params->format, "gif", sizeof(params->format));
|
||||
}
|
||||
else if (preset <= RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY)
|
||||
|
126
retroarch.c
126
retroarch.c
@ -286,8 +286,12 @@ static unsigned fastforward_after_frames = 0;
|
||||
static retro_usec_t runloop_frame_time_last = 0;
|
||||
static retro_time_t frame_limit_minimum_time = 0.0;
|
||||
static retro_time_t frame_limit_last_time = 0.0;
|
||||
static retro_time_t libretro_core_runtime_last = 0;
|
||||
static retro_time_t libretro_core_runtime_usec = 0;
|
||||
|
||||
static char runtime_content_path[PATH_MAX_LENGTH] = {0};
|
||||
static char runtime_core_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
extern bool input_driver_flushing_input;
|
||||
|
||||
static char launch_arguments[4096];
|
||||
@ -816,10 +820,63 @@ bool driver_ctl(enum driver_ctl_state state, void *data)
|
||||
|
||||
void rarch_core_runtime_tick(void)
|
||||
{
|
||||
retro_time_t frame_time;
|
||||
struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
|
||||
|
||||
if (av_info && av_info->timing.fps)
|
||||
libretro_core_runtime_usec += (1.0 / av_info->timing.fps) * 1000 * 1000;
|
||||
{
|
||||
frame_time = (1.0 / av_info->timing.fps) * 1000000;
|
||||
|
||||
/* Account for slow motion */
|
||||
if (runloop_slowmotion)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
if (settings)
|
||||
frame_time = (retro_time_t)((double)frame_time * settings->floats.slowmotion_ratio);
|
||||
}
|
||||
/* Account for fast forward */
|
||||
else if (runloop_fastmotion)
|
||||
{
|
||||
/* Doing it this way means we miss the first frame after
|
||||
* turning fast forward on, but it saves the overhead of
|
||||
* having to do:
|
||||
* retro_time_t current_usec = cpu_features_get_time_usec();
|
||||
* libretro_core_runtime_last = current_usec;
|
||||
* every frame when fast forward is off. */
|
||||
retro_time_t current_usec = cpu_features_get_time_usec();
|
||||
|
||||
if (current_usec - libretro_core_runtime_last < frame_time)
|
||||
{
|
||||
frame_time = current_usec - libretro_core_runtime_last;
|
||||
}
|
||||
|
||||
libretro_core_runtime_last = current_usec;
|
||||
}
|
||||
|
||||
libretro_core_runtime_usec += frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_runtime_log(bool log_per_core)
|
||||
{
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
|
||||
/* Initialise runtime log file */
|
||||
runtime_log = runtime_log_init(runtime_content_path, runtime_core_path, log_per_core);
|
||||
if (runtime_log)
|
||||
{
|
||||
/* Add additional runtime */
|
||||
runtime_log_add_runtime_usec(runtime_log, libretro_core_runtime_usec);
|
||||
|
||||
/* Update 'last played' entry */
|
||||
runtime_log_set_last_played_now(runtime_log);
|
||||
|
||||
/* Save runtime log file */
|
||||
runtime_log_save(runtime_log);
|
||||
|
||||
/* Clean up */
|
||||
free(runtime_log);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
@ -2391,8 +2448,35 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
|
||||
}
|
||||
break;
|
||||
case RARCH_CTL_CONTENT_RUNTIME_LOG_INIT:
|
||||
{
|
||||
const char *content_path = path_get(RARCH_PATH_CONTENT);
|
||||
const char *core_path = path_get(RARCH_PATH_CORE);
|
||||
|
||||
libretro_core_runtime_last = cpu_features_get_time_usec();
|
||||
libretro_core_runtime_usec = 0;
|
||||
|
||||
/* Have to cache content and core path here, otherwise
|
||||
* logging fails if new content is loaded without
|
||||
* closing existing content
|
||||
* i.e. RARCH_PATH_CONTENT and RARCH_PATH_CORE get
|
||||
* updated when the new content is loaded, which
|
||||
* happens *before* RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
|
||||
* -> using RARCH_PATH_CONTENT and RARCH_PATH_CORE
|
||||
* directly in RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
|
||||
* can therefore lead to the runtime of the currently
|
||||
* loaded content getting written to the *new*
|
||||
* content's log file... */
|
||||
memset(runtime_content_path, 0, sizeof(runtime_content_path));
|
||||
memset(runtime_core_path, 0, sizeof(runtime_core_path));
|
||||
|
||||
if (!string_is_empty(content_path))
|
||||
strlcpy(runtime_content_path, content_path, sizeof(runtime_content_path));
|
||||
|
||||
if (!string_is_empty(core_path))
|
||||
strlcpy(runtime_core_path, core_path, sizeof(runtime_core_path));
|
||||
|
||||
break;
|
||||
}
|
||||
case RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT:
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
@ -2411,30 +2495,24 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
|
||||
n = 0; /* Just silence any potential gcc warnings... */
|
||||
RARCH_LOG("%s\n",log);
|
||||
|
||||
/* Only write to file if logging is enabled *and* content has run
|
||||
* for a non-zero length of time */
|
||||
if (settings->bools.content_runtime_log && libretro_core_runtime_usec > 0)
|
||||
/* Only write to file if content has run for a non-zero length of time */
|
||||
if (libretro_core_runtime_usec > 0)
|
||||
{
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
/* Per core logging */
|
||||
if (settings->bools.content_runtime_log)
|
||||
update_runtime_log(true);
|
||||
|
||||
/* Initialise runtime log file */
|
||||
runtime_log = runtime_log_init(path_get(RARCH_PATH_CONTENT), path_get(RARCH_PATH_CORE));
|
||||
if (runtime_log)
|
||||
{
|
||||
/* Add additional runtime */
|
||||
runtime_log_add_runtime_usec(runtime_log, libretro_core_runtime_usec);
|
||||
|
||||
/* Update 'last played' entry */
|
||||
runtime_log_set_last_played_now(runtime_log);
|
||||
|
||||
/* Save runtime log file */
|
||||
runtime_log_save(runtime_log);
|
||||
|
||||
/* Clean up */
|
||||
free(runtime_log);
|
||||
}
|
||||
/* Aggregate logging */
|
||||
if (settings->bools.content_runtime_log_aggregate)
|
||||
update_runtime_log(false);
|
||||
}
|
||||
|
||||
/* Reset runtime + content/core paths, to prevent any
|
||||
* possibility of duplicate logging */
|
||||
libretro_core_runtime_usec = 0;
|
||||
memset(runtime_content_path, 0, sizeof(runtime_content_path));
|
||||
memset(runtime_core_path, 0, sizeof(runtime_core_path));
|
||||
|
||||
break;
|
||||
}
|
||||
case RARCH_CTL_GET_PERFCNT:
|
||||
@ -4335,16 +4413,18 @@ int runloop_iterate(unsigned *sleep_ms)
|
||||
else
|
||||
{
|
||||
core_run();
|
||||
rarch_core_runtime_tick();
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
core_run();
|
||||
rarch_core_runtime_tick();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Increment runtime tick counter after each call to
|
||||
* core_run() or run_ahead() */
|
||||
rarch_core_runtime_tick();
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (runloop_check_cheevos())
|
||||
cheevos_test();
|
||||
|
@ -268,11 +268,12 @@ end:
|
||||
/* Initialise runtime log, loading current parameters
|
||||
* if log file exists. Returned object must be free()'d.
|
||||
* Returns NULL if content_path and/or core_path are invalid */
|
||||
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
|
||||
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path, bool log_per_core)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
core_info_list_t *core_info = NULL;
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
const char *core_path_basename = path_basename(core_path);
|
||||
|
||||
char content_name[PATH_MAX_LENGTH];
|
||||
char core_name[PATH_MAX_LENGTH];
|
||||
@ -298,13 +299,17 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (string_is_empty(content_path) || string_is_empty(core_path))
|
||||
if (string_is_empty(content_path) || string_is_empty(core_path_basename))
|
||||
return NULL;
|
||||
|
||||
if (string_is_equal(core_path, "builtin") || string_is_equal(core_path, file_path_str(FILE_PATH_DETECT)))
|
||||
return NULL;
|
||||
|
||||
/* Get core name */
|
||||
/* Get core name
|
||||
* Note: An annoyance - this is required even when
|
||||
* we are performing aggregate (not per core) logging,
|
||||
* since content name is sometimes dependent upon core
|
||||
* (e.g. see TyrQuake below) */
|
||||
core_info_get_list(&core_info);
|
||||
|
||||
if (!core_info)
|
||||
@ -312,7 +317,7 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
|
||||
|
||||
for (i = 0; i < core_info->count; i++)
|
||||
{
|
||||
if (string_is_equal(core_info->list[i].path, core_path))
|
||||
if (string_is_equal(path_basename(core_info->list[i].path), core_path_basename))
|
||||
{
|
||||
strlcpy(core_name, core_info->list[i].core_name, sizeof(core_name));
|
||||
break;
|
||||
@ -329,11 +334,18 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
|
||||
"logs",
|
||||
sizeof(tmp_buf));
|
||||
|
||||
fill_pathname_join(
|
||||
log_file_dir,
|
||||
tmp_buf,
|
||||
core_name,
|
||||
sizeof(log_file_dir));
|
||||
if (log_per_core)
|
||||
{
|
||||
fill_pathname_join(
|
||||
log_file_dir,
|
||||
tmp_buf,
|
||||
core_name,
|
||||
sizeof(log_file_dir));
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(log_file_dir, tmp_buf, sizeof(log_file_dir));
|
||||
}
|
||||
|
||||
if (string_is_empty(log_file_dir))
|
||||
return NULL;
|
||||
@ -650,6 +662,8 @@ void runtime_log_save(runtime_log_t *runtime_log)
|
||||
if (!runtime_log)
|
||||
return;
|
||||
|
||||
RARCH_LOG("Saving runtime log file: %s\n", runtime_log->path);
|
||||
|
||||
/* Attempt to open log file */
|
||||
file = filestream_open(runtime_log->path, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
|
||||
|
@ -60,7 +60,7 @@ typedef struct
|
||||
/* Initialise runtime log, loading current parameters
|
||||
* if log file exists. Returned object must be free()'d.
|
||||
* Returns NULL if content_path and/or core_path are invalid */
|
||||
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path);
|
||||
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path, bool log_per_core);
|
||||
|
||||
/* Setters */
|
||||
|
||||
|
@ -1041,9 +1041,24 @@ static bool task_load_content(content_ctx_info_t *content_info,
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
{
|
||||
core_info_t *core_info = NULL;
|
||||
|
||||
/* Set core path */
|
||||
core_path = path_get(RARCH_PATH_CORE);
|
||||
core_name = info->library_name;
|
||||
|
||||
/* Set core display name
|
||||
* (As far as I can tell, core_info_get_current_core()
|
||||
* should always provide a valid pointer here...) */
|
||||
core_info_get_current_core(&core_info);
|
||||
if (core_info)
|
||||
core_name = core_info->display_name;
|
||||
|
||||
if (string_is_empty(core_name))
|
||||
core_name = info->library_name;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (launched_from_cli)
|
||||
|
@ -1748,7 +1748,7 @@ QHash<QString, QString> MainWindow::getFileContentHash(const QModelIndex &index)
|
||||
QFileInfo fileInfo = m_fileModel->fileInfo(index);
|
||||
QHash<QString, QString> hash;
|
||||
|
||||
hash["path"] = m_fileModel->filePath(index);;
|
||||
hash["path"] = QDir::toNativeSeparators(m_fileModel->filePath(index));
|
||||
hash["label"] = hash["path"];
|
||||
hash["label_noext"] = fileInfo.completeBaseName();
|
||||
hash["db_name"] = fileInfo.dir().dirName();
|
||||
|
Loading…
x
Reference in New Issue
Block a user