mirror of
https://github.com/libretro/RetroArch
synced 2025-01-31 15:32:59 +00:00
Merge pull request #10799 from jdgleaver/core-info-search
Core info search optimisations + improved core selection logic + clean-ups
This commit is contained in:
commit
2aeb95cbd4
96
core_info.c
96
core_info.c
@ -207,6 +207,8 @@ static void core_info_list_free(core_info_list_t *core_info_list)
|
||||
free(info->firmware[j].desc);
|
||||
}
|
||||
free(info->firmware);
|
||||
|
||||
free(info->core_file_id.str);
|
||||
}
|
||||
|
||||
free(core_info_list->all_ext);
|
||||
@ -504,11 +506,43 @@ static core_info_list_t *core_info_list_new(const char *path,
|
||||
}
|
||||
|
||||
if (!string_is_empty(base_path))
|
||||
{
|
||||
const char *core_filename = path_basename(base_path);
|
||||
|
||||
/* Cache core path */
|
||||
core_info[i].path = strdup(base_path);
|
||||
|
||||
if (!core_info[i].display_name)
|
||||
core_info[i].display_name =
|
||||
strdup(path_basename(core_info[i].path));
|
||||
/* Cache core file 'id'
|
||||
* > Filename without extension or platform-specific suffix */
|
||||
if (!string_is_empty(core_filename))
|
||||
{
|
||||
char *core_file_id = strdup(core_filename);
|
||||
path_remove_extension(core_file_id);
|
||||
|
||||
if (!string_is_empty(core_file_id))
|
||||
{
|
||||
#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(HW_WUP))
|
||||
char *last_underscore = strrchr(core_file_id, '_');
|
||||
if (last_underscore)
|
||||
*last_underscore = '\0';
|
||||
#endif
|
||||
core_info[i].core_file_id.str = core_file_id;
|
||||
core_info[i].core_file_id.len = strlen(core_file_id);
|
||||
|
||||
core_file_id = NULL;
|
||||
}
|
||||
|
||||
if (core_file_id)
|
||||
{
|
||||
free(core_file_id);
|
||||
core_file_id = NULL;
|
||||
}
|
||||
|
||||
/* Get fallback display name, if required */
|
||||
if (!core_info[i].display_name)
|
||||
core_info[i].display_name = strdup(core_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (core_info_list)
|
||||
@ -529,7 +563,13 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
core_info_t *out_info, const char *path)
|
||||
{
|
||||
size_t i;
|
||||
if (!core_info_list || !out_info)
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!core_info_list || !out_info || string_is_empty(path))
|
||||
return false;
|
||||
|
||||
core_filename = path_basename(path);
|
||||
if (string_is_empty(core_filename))
|
||||
return false;
|
||||
|
||||
memset(out_info, 0, sizeof(*out_info));
|
||||
@ -538,8 +578,10 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
{
|
||||
const core_info_t *info = &core_info_list->list[i];
|
||||
|
||||
if (string_is_equal(path_basename(info->path),
|
||||
path_basename(path)))
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
{
|
||||
*out_info = *info;
|
||||
return true;
|
||||
@ -605,15 +647,23 @@ static core_info_t *core_info_find_internal(
|
||||
const char *core)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_path_basename = path_basename(core);
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!list || string_is_empty(core))
|
||||
return NULL;
|
||||
|
||||
core_filename = path_basename(core);
|
||||
if (string_is_empty(core_filename))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < list->count; i++)
|
||||
{
|
||||
core_info_t *info = core_info_get(list, i);
|
||||
|
||||
if (!info || !info->path)
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
if (string_is_equal(path_basename(info->path), core_path_basename))
|
||||
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -753,14 +803,18 @@ bool core_info_load(core_info_ctx_find_t *info)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool core_info_find(core_info_ctx_find_t *info, const char *core_path)
|
||||
bool core_info_find(core_info_ctx_find_t *info)
|
||||
{
|
||||
core_info_state_t *p_coreinfo = coreinfo_get_ptr();
|
||||
|
||||
if (!info || !p_coreinfo->curr_list)
|
||||
return false;
|
||||
info->inf = core_info_find_internal(p_coreinfo->curr_list, core_path);
|
||||
|
||||
info->inf = core_info_find_internal(p_coreinfo->curr_list, info->path);
|
||||
|
||||
if (!info->inf)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -978,22 +1032,30 @@ bool core_info_list_get_display_name(core_info_list_t *core_info_list,
|
||||
const char *path, char *s, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!core_info_list)
|
||||
if (!core_info_list || string_is_empty(path))
|
||||
return false;
|
||||
|
||||
core_filename = path_basename(path);
|
||||
if (string_is_empty(core_filename))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
const core_info_t *info = &core_info_list->list[i];
|
||||
|
||||
if (!string_is_equal(path_basename(info->path), path_basename(path)))
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
|
||||
if (!info->display_name)
|
||||
continue;
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
{
|
||||
if (string_is_empty(info->display_name))
|
||||
break;
|
||||
|
||||
strlcpy(s, info->display_name, len);
|
||||
return true;
|
||||
strlcpy(s, info->display_name, len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
20
core_info.h
20
core_info.h
@ -35,6 +35,23 @@ typedef struct
|
||||
bool optional;
|
||||
} core_info_firmware_t;
|
||||
|
||||
/* Simple container/convenience struct for
|
||||
* holding the 'id' of a core file
|
||||
* > 'id' is the filename without extension or
|
||||
* platform-specific suffix
|
||||
* > 'id' is used for core info searches - enables
|
||||
* matching regardless of core file base path,
|
||||
* and is platform-independent (e.g. an Android
|
||||
* core file will be correctly identified on Linux)
|
||||
* > 'len' is used to cache the length of 'str', for
|
||||
* improved performance when performing string
|
||||
* comparisons */
|
||||
typedef struct
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
} core_file_id_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool supports_no_game;
|
||||
@ -67,6 +84,7 @@ typedef struct
|
||||
struct string_list *licenses_list;
|
||||
struct string_list *required_hw_api_list;
|
||||
core_info_firmware_t *firmware;
|
||||
core_file_id_t core_file_id;
|
||||
void *userdata;
|
||||
} core_info_t;
|
||||
|
||||
@ -152,7 +170,7 @@ bool core_info_get_list(core_info_list_t **core);
|
||||
bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
|
||||
bool *set_missing_bios);
|
||||
|
||||
bool core_info_find(core_info_ctx_find_t *info, const char *name);
|
||||
bool core_info_find(core_info_ctx_find_t *info);
|
||||
|
||||
bool core_info_load(core_info_ctx_find_t *info);
|
||||
|
||||
|
@ -462,7 +462,7 @@ static void menu_action_setting_disp_set_label_core_updater_entry(
|
||||
core_info.inf = NULL;
|
||||
core_info.path = entry->local_core_path;
|
||||
|
||||
if (core_info_find(&core_info, entry->local_core_path))
|
||||
if (core_info_find(&core_info))
|
||||
{
|
||||
strlcpy(s, "[#]", len);
|
||||
*w = (unsigned)STRLEN_CONST("[#]");
|
||||
|
@ -373,16 +373,18 @@ static int action_left_video_resolution(unsigned type, const char *label,
|
||||
static int playlist_association_left(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char core_filename[PATH_MAX_LENGTH];
|
||||
size_t i, next, current = 0;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool playlist_use_old_format = settings->bools.playlist_use_old_format;
|
||||
bool playlist_compression = settings->bools.playlist_compression;
|
||||
playlist_t *playlist = playlist_get_cached();
|
||||
const char *default_core_path = playlist_get_default_core_path(playlist);
|
||||
bool default_core_set = false;
|
||||
core_info_list_t *core_info_list = NULL;
|
||||
core_info_t *core_info = NULL;
|
||||
|
||||
core_path[0] = '\0';
|
||||
core_filename[0] = '\0';
|
||||
|
||||
if (!playlist)
|
||||
return -1;
|
||||
@ -392,52 +394,62 @@ static int playlist_association_left(unsigned type, const char *label,
|
||||
return menu_cbs_exit();
|
||||
|
||||
/* Get current core path association */
|
||||
if (string_is_empty(playlist_get_default_core_path(playlist)))
|
||||
if (!string_is_empty(default_core_path) &&
|
||||
!string_is_equal(default_core_path, "DETECT"))
|
||||
{
|
||||
core_path[0] = 'D';
|
||||
core_path[1] = 'E';
|
||||
core_path[2] = 'T';
|
||||
core_path[3] = 'E';
|
||||
core_path[4] = 'C';
|
||||
core_path[5] = 'T';
|
||||
core_path[6] = '\0';
|
||||
const char *default_core_filename = path_basename(default_core_path);
|
||||
if (!string_is_empty(default_core_filename))
|
||||
{
|
||||
strlcpy(core_filename, default_core_filename, sizeof(core_filename));
|
||||
default_core_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
strlcpy(core_path, playlist_get_default_core_path(playlist), sizeof(core_path));
|
||||
|
||||
/* Sort cores alphabetically */
|
||||
core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME);
|
||||
|
||||
/* Get the index of the currently associated core */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
/* If a core is currently associated... */
|
||||
if (default_core_set)
|
||||
{
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
if (!core_info)
|
||||
return -1;
|
||||
if (string_is_equal(core_info->path, core_path))
|
||||
current = i;
|
||||
/* ...get its index */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
if (!core_info)
|
||||
continue;
|
||||
if (string_starts_with(core_filename, core_info->core_file_id.str))
|
||||
current = i;
|
||||
}
|
||||
|
||||
/* ...then decrement it */
|
||||
if (current == 0)
|
||||
{
|
||||
/* Unset core association (DETECT) */
|
||||
next = 0;
|
||||
default_core_set = false;
|
||||
}
|
||||
else
|
||||
next = current - 1;
|
||||
}
|
||||
/* If a core is *not* currently associated and
|
||||
* wraparound is enabled, select last core in
|
||||
* the list */
|
||||
else if (wraparound && (core_info_list->count > 1))
|
||||
{
|
||||
next = core_info_list->count - 1;
|
||||
default_core_set = true;
|
||||
}
|
||||
|
||||
/* Decrement core index */
|
||||
if (current > 0)
|
||||
next = current - 1;
|
||||
else if (wraparound && (core_info_list->count > 1))
|
||||
next = core_info_list->count - 1;
|
||||
else
|
||||
next = 0; /* Silence 'next' may be used uninitialized warning */
|
||||
|
||||
/* Get new core info */
|
||||
/* If a core is now associated, get new core info */
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, next);
|
||||
if (!core_info)
|
||||
return -1;
|
||||
if (default_core_set)
|
||||
core_info = core_info_get(core_info_list, next);
|
||||
|
||||
/* Update playlist */
|
||||
playlist_set_default_core_path(playlist, core_info->path);
|
||||
playlist_set_default_core_name(playlist, core_info->display_name);
|
||||
playlist_write_file(
|
||||
playlist, playlist_use_old_format, playlist_compression);
|
||||
playlist_set_default_core_path(playlist, core_info ? core_info->path : "DETECT");
|
||||
playlist_set_default_core_name(playlist, core_info ? core_info->display_name : "DETECT");
|
||||
playlist_write_file(playlist, playlist_use_old_format, playlist_compression);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1308,60 +1308,6 @@ int generic_action_ok_displaylist_push(const char *path,
|
||||
return menu_cbs_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* menu_content_load_from_playlist:
|
||||
* @playlist : Playlist handle.
|
||||
* @idx : Index in playlist.
|
||||
*
|
||||
* Initializes core and loads content based on playlist entry.
|
||||
**/
|
||||
static bool menu_content_playlist_load(playlist_t *playlist, size_t idx)
|
||||
{
|
||||
char path[PATH_MAX_LENGTH];
|
||||
const struct playlist_entry *entry = NULL;
|
||||
|
||||
path[0] = '\0';
|
||||
|
||||
playlist_get_index(playlist, idx, &entry);
|
||||
|
||||
if (!entry || string_is_empty(entry->path))
|
||||
return false;
|
||||
|
||||
strlcpy(path, entry->path, sizeof(path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, path, sizeof(path));
|
||||
|
||||
if (!string_is_empty(path))
|
||||
{
|
||||
unsigned i;
|
||||
bool valid_path = false;
|
||||
char *path_check = NULL;
|
||||
char *path_tolower = strdup(path);
|
||||
|
||||
for (i = 0; i < strlen(path_tolower); ++i)
|
||||
path_tolower[i] = tolower((unsigned char)path_tolower[i]);
|
||||
|
||||
if (strstr(path_tolower, ".zip"))
|
||||
strstr(path_tolower, ".zip")[4] = '\0';
|
||||
else if (strstr(path_tolower, ".7z"))
|
||||
strstr(path_tolower, ".7z")[3] = '\0';
|
||||
|
||||
path_check = (char *)
|
||||
calloc(strlen(path_tolower) + 1, sizeof(char));
|
||||
|
||||
strlcpy(path_check, path, strlen(path_tolower) + 1);
|
||||
|
||||
valid_path = path_is_valid(path_check);
|
||||
|
||||
free(path_tolower);
|
||||
free(path_check);
|
||||
|
||||
if (valid_path)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* menu_content_find_first_core:
|
||||
* @core_info : Core info list handle.
|
||||
@ -2034,17 +1980,66 @@ static int action_ok_file_load(const char *path,
|
||||
CORE_TYPE_PLAIN);
|
||||
}
|
||||
|
||||
static bool playlist_entry_path_is_valid(const char *entry_path)
|
||||
{
|
||||
char *archive_delim = NULL;
|
||||
char *file_path = NULL;
|
||||
|
||||
if (string_is_empty(entry_path))
|
||||
goto error;
|
||||
|
||||
file_path = strdup(entry_path);
|
||||
|
||||
/* We need to check whether the file referenced by the
|
||||
* entry path actually exists. If it is a normal file,
|
||||
* we can do this directly. If the path contains an
|
||||
* archive delimiter, then we have to trim everything
|
||||
* after the archive extension
|
||||
* > Note: Have to do a nasty cast here, since
|
||||
* path_get_archive_delim() returns a const char *
|
||||
* (this cast is safe, though, and is done in many
|
||||
* places throughout the codebase...) */
|
||||
archive_delim = (char *)path_get_archive_delim(file_path);
|
||||
|
||||
if (archive_delim)
|
||||
{
|
||||
*archive_delim = '\0';
|
||||
if (string_is_empty(file_path))
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Path is 'sanitised' - can now check if it exists */
|
||||
if (!path_is_valid(file_path))
|
||||
goto error;
|
||||
|
||||
/* File is valid */
|
||||
free(file_path);
|
||||
file_path = NULL;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (file_path)
|
||||
{
|
||||
free(file_path);
|
||||
file_path = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_ok_playlist_entry_collection(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
char new_path[PATH_MAX_LENGTH];
|
||||
char new_core_path[PATH_MAX_LENGTH];
|
||||
size_t selection_ptr = 0;
|
||||
char content_path[PATH_MAX_LENGTH];
|
||||
char content_label[PATH_MAX_LENGTH];
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
size_t selection_ptr = entry_idx;
|
||||
bool playlist_initialized = false;
|
||||
playlist_t *playlist = NULL;
|
||||
playlist_t *tmp_playlist = NULL;
|
||||
const struct playlist_entry *entry = NULL;
|
||||
unsigned i = 0;
|
||||
core_info_t* core_info = NULL;
|
||||
menu_handle_t *menu = menu_driver_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool playlist_use_old_format = settings->bools.playlist_use_old_format;
|
||||
@ -2055,12 +2050,15 @@ static int action_ok_playlist_entry_collection(const char *path,
|
||||
const char *path_content_video_history = settings->paths.path_content_video_history;
|
||||
const char *path_content_image_history = settings->paths.path_content_image_history;
|
||||
|
||||
if (!menu)
|
||||
return menu_cbs_exit();
|
||||
content_path[0] = '\0';
|
||||
content_label[0] = '\0';
|
||||
core_path[0] = '\0';
|
||||
|
||||
new_path[0] = '\0';
|
||||
new_core_path[0] = '\0';
|
||||
tmp_playlist = playlist_get_cached();
|
||||
if (!menu)
|
||||
goto error;
|
||||
|
||||
/* Get playlist */
|
||||
tmp_playlist = playlist_get_cached();
|
||||
|
||||
if (!tmp_playlist)
|
||||
{
|
||||
@ -2076,11 +2074,10 @@ static int action_ok_playlist_entry_collection(const char *path,
|
||||
string_is_equal(menu->db_playlist_file, path_content_image_history);
|
||||
enum playlist_sort_mode current_sort_mode;
|
||||
|
||||
tmp_playlist = playlist_init(
|
||||
menu->db_playlist_file, COLLECTION_SIZE);
|
||||
tmp_playlist = playlist_init(menu->db_playlist_file, COLLECTION_SIZE);
|
||||
|
||||
if (!tmp_playlist)
|
||||
return menu_cbs_exit();
|
||||
goto error;
|
||||
|
||||
current_sort_mode = playlist_get_sort_mode(tmp_playlist);
|
||||
|
||||
@ -2092,83 +2089,57 @@ static int action_ok_playlist_entry_collection(const char *path,
|
||||
playlist_initialized = true;
|
||||
}
|
||||
|
||||
playlist = tmp_playlist;
|
||||
selection_ptr = entry_idx;
|
||||
playlist = tmp_playlist;
|
||||
|
||||
/* Get playlist entry */
|
||||
playlist_get_index(playlist, selection_ptr, &entry);
|
||||
if (!entry)
|
||||
goto error;
|
||||
|
||||
/* Subsystem codepath */
|
||||
if (!string_is_empty(entry->subsystem_ident))
|
||||
/* Cache entry path */
|
||||
if (!string_is_empty(entry->path))
|
||||
{
|
||||
content_ctx_info_t content_info = {0};
|
||||
|
||||
task_push_load_new_core(entry->core_path, NULL,
|
||||
&content_info, CORE_TYPE_PLAIN, NULL, NULL);
|
||||
|
||||
content_clear_subsystem();
|
||||
|
||||
if (!content_set_subsystem_by_name(entry->subsystem_ident))
|
||||
{
|
||||
RARCH_LOG("[playlist] subsystem not found in implementation\n");
|
||||
/* TODO: Add OSD message telling users that content can't be loaded */
|
||||
if (playlist_initialized)
|
||||
playlist_free(tmp_playlist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < entry->subsystem_roms->size; i++)
|
||||
content_add_subsystem(entry->subsystem_roms->elems[i].data);
|
||||
|
||||
task_push_load_subsystem_with_core_from_menu(
|
||||
NULL, &content_info,
|
||||
CORE_TYPE_PLAIN, NULL, NULL);
|
||||
/* TODO: update playlist entry? move to first position I guess? */
|
||||
if (playlist_initialized)
|
||||
playlist_free(tmp_playlist);
|
||||
return 1;
|
||||
strlcpy(content_path, entry->path, sizeof(content_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, content_path, sizeof(content_path));
|
||||
}
|
||||
|
||||
/* Check whether playlist already has core path/name
|
||||
* assignments
|
||||
* > Both core name and core path must be valid */
|
||||
if ( string_is_empty(entry->core_path)
|
||||
|| string_is_empty(entry->core_name)
|
||||
|| string_is_equal(entry->core_path, "DETECT")
|
||||
|| string_is_equal(entry->core_name, "DETECT"))
|
||||
/* Cache entry label */
|
||||
if (!string_is_empty(entry->label))
|
||||
strlcpy(content_label, entry->label, sizeof(content_label));
|
||||
|
||||
/* Get core path */
|
||||
if (!playlist_entry_has_core(entry))
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
const char *entry_path = NULL;
|
||||
const char *default_core_path =
|
||||
playlist_get_default_core_path(playlist);
|
||||
bool found_associated_core = false;
|
||||
struct playlist_entry update_entry = {0};
|
||||
struct playlist_entry update_entry = {0};
|
||||
|
||||
if (!string_is_empty(default_core_path))
|
||||
/* Entry core is not set - attempt to use
|
||||
* playlist default */
|
||||
core_info = playlist_get_default_core_info(playlist);
|
||||
|
||||
/* If default core is not set, prompt user
|
||||
* to select one */
|
||||
if (!core_info)
|
||||
{
|
||||
strlcpy(new_core_path, default_core_path, sizeof(new_core_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, new_core_path, sizeof(new_core_path));
|
||||
found_associated_core = true;
|
||||
}
|
||||
|
||||
core_info.inf = NULL;
|
||||
core_info.path = new_core_path;
|
||||
|
||||
if (!core_info_find(&core_info, new_core_path))
|
||||
found_associated_core = false;
|
||||
|
||||
if (!found_associated_core)
|
||||
{
|
||||
/* TODO: figure out if this should refer to the inner or outer entry_path */
|
||||
/* TODO: make sure there's only one entry_path in this function */
|
||||
int ret = action_ok_file_load_with_detect_core_collection(entry_path,
|
||||
/* TODO: figure out if this should refer to the inner or outer content_path */
|
||||
int ret = action_ok_file_load_with_detect_core_collection(content_path,
|
||||
label, type, selection_ptr, entry_idx);
|
||||
if (playlist_initialized)
|
||||
|
||||
if (playlist_initialized && tmp_playlist)
|
||||
{
|
||||
playlist_free(tmp_playlist);
|
||||
tmp_playlist = NULL;
|
||||
playlist = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
update_entry.core_path = (char*)default_core_path;
|
||||
update_entry.core_name = core_info.inf->display_name;
|
||||
/* Cache core path */
|
||||
strlcpy(core_path, core_info->path, sizeof(core_path));
|
||||
|
||||
/* Update playlist entry */
|
||||
update_entry.core_path = core_info->path;
|
||||
update_entry.core_name = core_info->display_name;
|
||||
|
||||
command_playlist_update_write(
|
||||
playlist,
|
||||
@ -2179,208 +2150,90 @@ static int action_ok_playlist_entry_collection(const char *path,
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(new_core_path, entry->core_path, sizeof(new_core_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, new_core_path, sizeof(new_core_path));
|
||||
}
|
||||
/* Entry does have a core assignment - ensure
|
||||
* it has corresponding core info entry */
|
||||
core_info = playlist_entry_get_core_info(entry);
|
||||
|
||||
if (!playlist || !menu_content_playlist_load(playlist, selection_ptr))
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
"File could not be loaded from playlist.\n",
|
||||
1, 100, true,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
if (playlist_initialized)
|
||||
playlist_free(tmp_playlist);
|
||||
return menu_cbs_exit();
|
||||
}
|
||||
|
||||
playlist_get_index(playlist, selection_ptr, &entry);
|
||||
|
||||
strlcpy(new_path, entry->path, sizeof(new_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, new_path, sizeof(new_path));
|
||||
|
||||
if (playlist_initialized)
|
||||
playlist_free(tmp_playlist);
|
||||
|
||||
return default_action_ok_load_content_from_playlist_from_menu(
|
||||
new_core_path, new_path, entry->label);
|
||||
}
|
||||
|
||||
static int action_ok_playlist_entry(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
char new_core_path[PATH_MAX_LENGTH];
|
||||
size_t selection_ptr = 0;
|
||||
const struct playlist_entry *entry = NULL;
|
||||
const char *entry_label = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
playlist_t *playlist = playlist_get_cached();
|
||||
menu_handle_t *menu = menu_driver_get_ptr();
|
||||
bool playlist_use_old_format = settings->bools.playlist_use_old_format;
|
||||
bool playlist_compression = settings->bools.playlist_compression;
|
||||
|
||||
new_core_path[0] = '\0';
|
||||
|
||||
if (!playlist || !menu)
|
||||
return menu_cbs_exit();
|
||||
|
||||
selection_ptr = entry_idx;
|
||||
|
||||
playlist_get_index(playlist, selection_ptr, &entry);
|
||||
|
||||
entry_label = entry->label;
|
||||
|
||||
/* Check whether playlist already has core path/name
|
||||
* assignments
|
||||
* > Both core name and core path must be valid */
|
||||
if ( string_is_empty(entry->core_path)
|
||||
|| string_is_empty(entry->core_name)
|
||||
|| string_is_equal(entry->core_path, "DETECT")
|
||||
|| string_is_equal(entry->core_name, "DETECT"))
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
const char *default_core_path =
|
||||
playlist_get_default_core_path(playlist);
|
||||
bool found_associated_core = false;
|
||||
|
||||
if (!string_is_empty(default_core_path))
|
||||
if (core_info && !string_is_empty(core_info->path))
|
||||
strlcpy(core_path, core_info->path, sizeof(core_path));
|
||||
else
|
||||
{
|
||||
strlcpy(new_core_path, default_core_path, sizeof(new_core_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, new_core_path, sizeof(new_core_path));
|
||||
found_associated_core = true;
|
||||
}
|
||||
|
||||
core_info.inf = NULL;
|
||||
core_info.path = new_core_path;
|
||||
|
||||
if (!core_info_find(&core_info, new_core_path))
|
||||
found_associated_core = false;
|
||||
|
||||
if (!found_associated_core)
|
||||
/* TODO: figure out if this should refer to the inner or outer entry_path */
|
||||
/* TODO: make sure there's only one entry_path in this function */
|
||||
return action_ok_file_load_with_detect_core(entry->path,
|
||||
label, type, selection_ptr, entry_idx);
|
||||
|
||||
{
|
||||
struct playlist_entry entry = {0};
|
||||
|
||||
entry.core_path = (char*)default_core_path;
|
||||
entry.core_name = core_info.inf->display_name;
|
||||
|
||||
command_playlist_update_write(NULL,
|
||||
selection_ptr,
|
||||
&entry,
|
||||
playlist_use_old_format,
|
||||
playlist_compression);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(new_core_path, entry->core_path, sizeof(new_core_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, new_core_path, sizeof(new_core_path));
|
||||
}
|
||||
|
||||
if (!playlist || !menu_content_playlist_load(playlist, selection_ptr))
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
"File could not be loaded from playlist.\n",
|
||||
1, 100, true,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
return menu_cbs_exit();
|
||||
}
|
||||
|
||||
playlist_get_index(playlist,
|
||||
selection_ptr, &entry);
|
||||
|
||||
return default_action_ok_load_content_from_playlist_from_menu(
|
||||
new_core_path, entry->path, entry_label);
|
||||
}
|
||||
|
||||
static int action_ok_playlist_entry_start_content(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
size_t selection_ptr = 0;
|
||||
const struct playlist_entry *entry = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
playlist_t *playlist = playlist_get_cached();
|
||||
menu_handle_t *menu = menu_driver_get_ptr();
|
||||
bool playlist_use_old_format = settings->bools.playlist_use_old_format;
|
||||
bool playlist_compression = settings->bools.playlist_compression;
|
||||
|
||||
if (!playlist || !menu)
|
||||
return menu_cbs_exit();
|
||||
|
||||
selection_ptr = menu->scratchpad.unsigned_var;
|
||||
|
||||
playlist_get_index(playlist, selection_ptr, &entry);
|
||||
|
||||
/* Check whether playlist already has core path/name
|
||||
* assignments
|
||||
* > Both core name and core path must be valid */
|
||||
if ( string_is_empty(entry->core_path)
|
||||
|| string_is_empty(entry->core_name)
|
||||
|| string_is_equal(entry->core_path, "DETECT")
|
||||
|| string_is_equal(entry->core_name, "DETECT"))
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
char new_core_path[PATH_MAX_LENGTH];
|
||||
const char *entry_path = NULL;
|
||||
const char *default_core_path =
|
||||
playlist_get_default_core_path(playlist);
|
||||
bool found_associated_core = false;
|
||||
|
||||
new_core_path[0] = '\0';
|
||||
|
||||
if (!string_is_empty(default_core_path))
|
||||
{
|
||||
strlcpy(new_core_path, default_core_path, sizeof(new_core_path));
|
||||
found_associated_core = true;
|
||||
}
|
||||
|
||||
core_info.inf = NULL;
|
||||
core_info.path = new_core_path;
|
||||
|
||||
if (!core_info_find(&core_info, new_core_path))
|
||||
found_associated_core = false;
|
||||
|
||||
/* TODO: figure out if this should refer to
|
||||
* the inner or outer entry_path. */
|
||||
/* TODO: make sure there's only one entry_path
|
||||
* in this function. */
|
||||
if (!found_associated_core)
|
||||
return action_ok_file_load_with_detect_core(entry_path,
|
||||
label, type, selection_ptr, entry_idx);
|
||||
|
||||
{
|
||||
struct playlist_entry entry = {0};
|
||||
|
||||
entry.core_path = new_core_path;
|
||||
entry.core_name = core_info.inf->display_name;
|
||||
|
||||
command_playlist_update_write(
|
||||
playlist,
|
||||
selection_ptr,
|
||||
&entry,
|
||||
playlist_use_old_format,
|
||||
playlist_compression);
|
||||
/* Core path is invalid - just copy what we have
|
||||
* and hope for the best... */
|
||||
strlcpy(core_path, entry->core_path, sizeof(core_path));
|
||||
playlist_resolve_path(PLAYLIST_LOAD, core_path, sizeof(core_path));
|
||||
}
|
||||
}
|
||||
|
||||
if (!menu_content_playlist_load(playlist, selection_ptr))
|
||||
{
|
||||
runloop_msg_queue_push("File could not be loaded from playlist.\n",
|
||||
1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
||||
MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
/* Ensure core path is valid */
|
||||
if (string_is_empty(core_path) || !path_is_valid(core_path))
|
||||
goto error;
|
||||
|
||||
/* Subsystem codepath */
|
||||
if (!string_is_empty(entry->subsystem_ident))
|
||||
{
|
||||
content_ctx_info_t content_info = {0};
|
||||
size_t i;
|
||||
|
||||
task_push_load_new_core(core_path, NULL,
|
||||
&content_info, CORE_TYPE_PLAIN, NULL, NULL);
|
||||
|
||||
content_clear_subsystem();
|
||||
|
||||
if (!content_set_subsystem_by_name(entry->subsystem_ident))
|
||||
{
|
||||
RARCH_LOG("[playlist] subsystem not found in implementation\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < entry->subsystem_roms->size; i++)
|
||||
content_add_subsystem(entry->subsystem_roms->elems[i].data);
|
||||
|
||||
task_push_load_subsystem_with_core_from_menu(
|
||||
NULL, &content_info,
|
||||
CORE_TYPE_PLAIN, NULL, NULL);
|
||||
|
||||
/* TODO: update playlist entry? move to first position I guess? */
|
||||
if (playlist_initialized && tmp_playlist)
|
||||
{
|
||||
playlist_free(tmp_playlist);
|
||||
tmp_playlist = NULL;
|
||||
playlist = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
playlist_get_index(playlist, selection_ptr, &entry);
|
||||
/* Ensure entry path is valid */
|
||||
if (!playlist_entry_path_is_valid(content_path))
|
||||
goto error;
|
||||
|
||||
/* Free temporary playlist, if required */
|
||||
if (playlist_initialized && tmp_playlist)
|
||||
{
|
||||
playlist_free(tmp_playlist);
|
||||
tmp_playlist = NULL;
|
||||
playlist = NULL;
|
||||
}
|
||||
|
||||
/* Note: Have to use cached entry label, since entry
|
||||
* may be free()'d by above playlist_free() - but need
|
||||
* to pass NULL explicitly if label is empty */
|
||||
return default_action_ok_load_content_from_playlist_from_menu(
|
||||
entry->core_path, entry->path, entry->label);
|
||||
core_path, content_path, string_is_empty(content_label) ? NULL : content_label);
|
||||
|
||||
error:
|
||||
runloop_msg_queue_push(
|
||||
"File could not be loaded from playlist.\n",
|
||||
1, 100, true,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
if (playlist_initialized && tmp_playlist)
|
||||
{
|
||||
playlist_free(tmp_playlist);
|
||||
tmp_playlist = NULL;
|
||||
playlist = NULL;
|
||||
}
|
||||
|
||||
return menu_cbs_exit();
|
||||
}
|
||||
|
||||
@ -4674,7 +4527,7 @@ static int action_ok_add_to_favorites(const char *path,
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info, core_path))
|
||||
if (core_info_find(&core_info))
|
||||
if (!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_name, core_info.inf->display_name, sizeof(core_name));
|
||||
}
|
||||
@ -4803,7 +4656,7 @@ static int action_ok_add_to_favorites_playlist(const char *path,
|
||||
core_info.inf = NULL;
|
||||
core_info.path = entry->core_path;
|
||||
|
||||
if (core_info_find(&core_info, entry->core_path))
|
||||
if (core_info_find(&core_info))
|
||||
if (!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_display_name, core_info.inf->display_name, sizeof(core_display_name));
|
||||
|
||||
@ -7121,18 +6974,7 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_OK(cbs, action_ok_push_default);
|
||||
break;
|
||||
case FILE_TYPE_PLAYLIST_ENTRY:
|
||||
if (string_is_equal(label, "collection"))
|
||||
{
|
||||
BIND_ACTION_OK(cbs, action_ok_playlist_entry_collection);
|
||||
}
|
||||
else if (string_is_equal(label, "rdb_entry_start_content"))
|
||||
{
|
||||
BIND_ACTION_OK(cbs, action_ok_playlist_entry_start_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIND_ACTION_OK(cbs, action_ok_playlist_entry);
|
||||
}
|
||||
BIND_ACTION_OK(cbs, action_ok_playlist_entry_collection);
|
||||
break;
|
||||
#ifdef HAVE_LAKKA_SWITCH
|
||||
case MENU_SET_SWITCH_GPU_PROFILE:
|
||||
|
@ -474,16 +474,18 @@ static int action_right_video_resolution(unsigned type, const char *label,
|
||||
static int playlist_association_right(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char core_filename[PATH_MAX_LENGTH];
|
||||
size_t i, next, current = 0;
|
||||
core_info_list_t *core_info_list = NULL;
|
||||
core_info_t *core_info = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
playlist_t *playlist = playlist_get_cached();
|
||||
const char *default_core_path = playlist_get_default_core_path(playlist);
|
||||
bool default_core_set = false;
|
||||
bool playlist_use_old_format = settings->bools.playlist_use_old_format;
|
||||
bool playlist_compression = settings->bools.playlist_compression;
|
||||
|
||||
core_path[0] = '\0';
|
||||
core_filename[0] = '\0';
|
||||
|
||||
if (!playlist)
|
||||
return -1;
|
||||
@ -493,59 +495,65 @@ static int playlist_association_right(unsigned type, const char *label,
|
||||
return menu_cbs_exit();
|
||||
|
||||
/* Get current core path association */
|
||||
if (string_is_empty(playlist_get_default_core_path(playlist)))
|
||||
if (!string_is_empty(default_core_path) &&
|
||||
!string_is_equal(default_core_path, "DETECT"))
|
||||
{
|
||||
core_path[0] = 'D';
|
||||
core_path[1] = 'E';
|
||||
core_path[2] = 'T';
|
||||
core_path[3] = 'E';
|
||||
core_path[4] = 'C';
|
||||
core_path[5] = 'T';
|
||||
core_path[6] = '\0';
|
||||
const char *default_core_filename = path_basename(default_core_path);
|
||||
if (!string_is_empty(default_core_filename))
|
||||
{
|
||||
strlcpy(core_filename, default_core_filename, sizeof(core_filename));
|
||||
default_core_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
strlcpy(core_path, playlist_get_default_core_path(playlist), sizeof(core_path));
|
||||
|
||||
/* Sort cores alphabetically */
|
||||
core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME);
|
||||
|
||||
/* Get the index of the currently associated core */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
/* If a core is currently associated... */
|
||||
if (default_core_set)
|
||||
{
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
if (!core_info)
|
||||
return -1;
|
||||
if (string_is_equal(core_info->path, core_path))
|
||||
current = i;
|
||||
}
|
||||
|
||||
/* Increment core index */
|
||||
next = current + 1;
|
||||
if (next >= core_info_list->count)
|
||||
{
|
||||
if (wraparound)
|
||||
next = 0;
|
||||
else
|
||||
/* ...get its index */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
if (core_info_list->count > 0)
|
||||
next = core_info_list->count - 1;
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
if (!core_info)
|
||||
continue;
|
||||
if (string_starts_with(core_filename, core_info->core_file_id.str))
|
||||
current = i;
|
||||
}
|
||||
|
||||
/* ...then increment it */
|
||||
next = current + 1;
|
||||
if (next >= core_info_list->count)
|
||||
{
|
||||
if (wraparound || (core_info_list->count < 1))
|
||||
{
|
||||
/* Unset core association (DETECT) */
|
||||
next = 0;
|
||||
default_core_set = false;
|
||||
}
|
||||
else
|
||||
next = 0;
|
||||
next = core_info_list->count - 1;
|
||||
}
|
||||
}
|
||||
/* If a core is *not* currently associated,
|
||||
* select first core in the list */
|
||||
else
|
||||
{
|
||||
next = 0;
|
||||
default_core_set = true;
|
||||
}
|
||||
|
||||
/* Get new core info */
|
||||
/* If a core is now associated, get new core info */
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, next);
|
||||
if (!core_info)
|
||||
return -1;
|
||||
if (default_core_set)
|
||||
core_info = core_info_get(core_info_list, next);
|
||||
|
||||
/* Update playlist */
|
||||
playlist_set_default_core_path(playlist, core_info->path);
|
||||
playlist_set_default_core_name(playlist, core_info->display_name);
|
||||
playlist_write_file(
|
||||
playlist, playlist_use_old_format, playlist_compression);
|
||||
playlist_set_default_core_path(playlist, core_info ? core_info->path : "DETECT");
|
||||
playlist_set_default_core_name(playlist, core_info ? core_info->display_name : "DETECT");
|
||||
playlist_write_file(playlist, playlist_use_old_format, playlist_compression);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ static int menu_action_sublabel_file_browser_core(file_list_t *list, unsigned ty
|
||||
core_info.inf = NULL;
|
||||
core_info.path = path;
|
||||
|
||||
if (core_info_find(&core_info, path) &&
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->licenses_list)
|
||||
{
|
||||
char tmp[MENU_SUBLABEL_MAX_LENGTH];
|
||||
|
@ -347,7 +347,7 @@ static int action_get_title_deferred_core_backup_list(
|
||||
core_info.path = core_path;
|
||||
|
||||
/* If core is found, add display name */
|
||||
if (core_info_find(&core_info, core_path) &&
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->display_name)
|
||||
strlcat(s, core_info.inf->display_name, len);
|
||||
else
|
||||
|
@ -157,7 +157,7 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info)
|
||||
core_info_finder.inf = NULL;
|
||||
core_info_finder.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info_finder, core_path))
|
||||
if (core_info_find(&core_info_finder))
|
||||
core_info = core_info_finder.inf;
|
||||
}
|
||||
else if (core_info_get_current_core(&core_info) && core_info)
|
||||
@ -3282,7 +3282,7 @@ static unsigned menu_displaylist_parse_content_information(
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info, core_path))
|
||||
if (core_info_find(&core_info))
|
||||
if (!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_name, core_info.inf->display_name, sizeof(core_name));
|
||||
}
|
||||
|
63
playlist.c
63
playlist.c
@ -2898,3 +2898,66 @@ void playlist_set_sort_mode(playlist_t *playlist, enum playlist_sort_mode sort_m
|
||||
playlist->modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if specified entry has a valid
|
||||
* core association (i.e. a non-empty string
|
||||
* other than DETECT) */
|
||||
bool playlist_entry_has_core(const struct playlist_entry *entry)
|
||||
{
|
||||
if (!entry ||
|
||||
string_is_empty(entry->core_path) ||
|
||||
string_is_empty(entry->core_name) ||
|
||||
string_is_equal(entry->core_path, "DETECT") ||
|
||||
string_is_equal(entry->core_name, "DETECT"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetches core info object corresponding to the
|
||||
* currently associated core of the specified
|
||||
* playlist entry.
|
||||
* Returns NULL if entry does not have a valid
|
||||
* core association */
|
||||
core_info_t *playlist_entry_get_core_info(const struct playlist_entry* entry)
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
if (!playlist_entry_has_core(entry))
|
||||
return NULL;
|
||||
|
||||
/* Search for associated core */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = entry->core_path;
|
||||
|
||||
if (core_info_find(&core_info))
|
||||
return core_info.inf;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Fetches core info object corresponding to the
|
||||
* currently associated default core of the
|
||||
* specified playlist.
|
||||
* Returns NULL if playlist does not have a valid
|
||||
* default core association */
|
||||
core_info_t *playlist_get_default_core_info(playlist_t* playlist)
|
||||
{
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
if (!playlist ||
|
||||
string_is_empty(playlist->default_core_path) ||
|
||||
string_is_empty(playlist->default_core_name) ||
|
||||
string_is_equal(playlist->default_core_path, "DETECT") ||
|
||||
string_is_equal(playlist->default_core_name, "DETECT"))
|
||||
return NULL;
|
||||
|
||||
/* Search for associated core */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = playlist->default_core_path;
|
||||
|
||||
if (core_info_find(&core_info))
|
||||
return core_info.inf;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
21
playlist.h
21
playlist.h
@ -24,6 +24,8 @@
|
||||
#include <boolean.h>
|
||||
#include <lists/string_list.h>
|
||||
|
||||
#include "core_info.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Default maximum playlist size */
|
||||
@ -317,6 +319,25 @@ void playlist_set_thumbnail_mode(
|
||||
playlist_t *playlist, enum playlist_thumbnail_id thumbnail_id, enum playlist_thumbnail_mode thumbnail_mode);
|
||||
void playlist_set_sort_mode(playlist_t *playlist, enum playlist_sort_mode sort_mode);
|
||||
|
||||
/* Returns true if specified entry has a valid
|
||||
* core association (i.e. a non-empty string
|
||||
* other than DETECT) */
|
||||
bool playlist_entry_has_core(const struct playlist_entry *entry);
|
||||
|
||||
/* Fetches core info object corresponding to the
|
||||
* currently associated core of the specified
|
||||
* playlist entry.
|
||||
* Returns NULL if entry does not have a valid
|
||||
* core association */
|
||||
core_info_t *playlist_entry_get_core_info(const struct playlist_entry* entry);
|
||||
|
||||
/* Fetches core info object corresponding to the
|
||||
* currently associated default core of the
|
||||
* specified playlist.
|
||||
* Returns NULL if playlist does not have a valid
|
||||
* default core association */
|
||||
core_info_t *playlist_get_default_core_info(playlist_t* playlist);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -281,15 +281,14 @@ runtime_log_t *runtime_log_init(
|
||||
char log_file_dir[PATH_MAX_LENGTH];
|
||||
char log_file_path[PATH_MAX_LENGTH];
|
||||
char tmp_buf[PATH_MAX_LENGTH];
|
||||
core_info_list_t *core_info = NULL;
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
const char *core_path_basename = NULL;
|
||||
core_info_ctx_find_t core_info;
|
||||
runtime_log_t *runtime_log = NULL;
|
||||
|
||||
content_name[0] = '\0';
|
||||
core_name[0] = '\0';
|
||||
log_file_dir[0] = '\0';
|
||||
log_file_path[0] = '\0';
|
||||
tmp_buf[0] = '\0';
|
||||
content_name[0] = '\0';
|
||||
core_name[0] = '\0';
|
||||
log_file_dir[0] = '\0';
|
||||
log_file_path[0] = '\0';
|
||||
tmp_buf[0] = '\0';
|
||||
|
||||
if ( string_is_empty(dir_runtime_log) &&
|
||||
string_is_empty(dir_playlist))
|
||||
@ -301,13 +300,8 @@ runtime_log_t *runtime_log_init(
|
||||
|
||||
if ( string_is_empty(core_path) ||
|
||||
string_is_equal(core_path, "builtin") ||
|
||||
string_is_equal(core_path, "DETECT"))
|
||||
return NULL;
|
||||
|
||||
core_path_basename = path_basename(core_path);
|
||||
|
||||
if ( string_is_empty(content_path) ||
|
||||
string_is_empty(core_path_basename))
|
||||
string_is_equal(core_path, "DETECT") ||
|
||||
string_is_empty(content_path))
|
||||
return NULL;
|
||||
|
||||
/* Get core name
|
||||
@ -315,24 +309,12 @@ runtime_log_t *runtime_log_init(
|
||||
* 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);
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (!core_info)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < core_info->count; i++)
|
||||
{
|
||||
const char *entry_core_name = core_info->list[i].core_name;
|
||||
if (!string_is_equal(
|
||||
path_basename(core_info->list[i].path), core_path_basename))
|
||||
continue;
|
||||
|
||||
if (string_is_empty(entry_core_name))
|
||||
return NULL;
|
||||
|
||||
strlcpy(core_name, entry_core_name, sizeof(core_name));
|
||||
break;
|
||||
}
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->core_name)
|
||||
strlcpy(core_name, core_info.inf->core_name, sizeof(core_name));
|
||||
|
||||
if (string_is_empty(core_name))
|
||||
return NULL;
|
||||
|
@ -1992,8 +1992,6 @@ static bool task_load_content_callback(content_ctx_info_t *content_info,
|
||||
|
||||
content_ctx.set_supports_no_game_enable = set_supports_no_game_enable;
|
||||
|
||||
if (!string_is_empty(path_dir_system))
|
||||
content_ctx.directory_system = strdup(path_dir_system);
|
||||
if (!string_is_empty(path_dir_cache))
|
||||
content_ctx.directory_cache = strdup(path_dir_cache);
|
||||
if (!string_is_empty(system->valid_extensions))
|
||||
|
@ -442,7 +442,7 @@ void *task_push_core_backup(const char *core_path,
|
||||
core_info.path = core_path;
|
||||
|
||||
/* If core is found, use display name */
|
||||
if (core_info_find(&core_info, core_path) &&
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->display_name)
|
||||
core_name = core_info.inf->display_name;
|
||||
else
|
||||
@ -881,7 +881,7 @@ bool task_push_core_restore(const char *backup_path, const char *dir_libretro,
|
||||
core_info.path = core_path;
|
||||
|
||||
/* If core is found, use display name */
|
||||
if (core_info_find(&core_info, core_path) &&
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->display_name)
|
||||
core_name = core_info.inf->display_name;
|
||||
else
|
||||
|
@ -463,35 +463,19 @@ static void pl_manager_validate_core_association(
|
||||
goto reset_core;
|
||||
else
|
||||
{
|
||||
const char *core_path_basename = path_basename(core_path);
|
||||
core_info_list_t *core_info = NULL;
|
||||
char core_display_name[PATH_MAX_LENGTH];
|
||||
size_t i;
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
core_display_name[0] = '\0';
|
||||
|
||||
if (string_is_empty(core_path_basename))
|
||||
goto reset_core;
|
||||
/* Search core info */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
/* Final check - search core info */
|
||||
core_info_get_list(&core_info);
|
||||
|
||||
if (core_info)
|
||||
{
|
||||
for (i = 0; i < core_info->count; i++)
|
||||
{
|
||||
const char *info_display_name = core_info->list[i].display_name;
|
||||
|
||||
if (!string_is_equal(
|
||||
path_basename(core_info->list[i].path), core_path_basename))
|
||||
continue;
|
||||
|
||||
if (!string_is_empty(info_display_name))
|
||||
strlcpy(core_display_name, info_display_name, sizeof(core_display_name));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (core_info_find(&core_info) &&
|
||||
!string_is_empty(core_info.inf->display_name))
|
||||
strlcpy(core_display_name, core_info.inf->display_name,
|
||||
sizeof(core_display_name));
|
||||
|
||||
/* If core_display_name string is empty, it means the
|
||||
* core wasn't found -> reset association */
|
||||
|
@ -988,7 +988,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
|
||||
coreInfo.inf = NULL;
|
||||
coreInfo.path = corePath;
|
||||
|
||||
if (core_info_find(&coreInfo, corePath))
|
||||
if (core_info_find(&coreInfo))
|
||||
{
|
||||
/* Set new core association */
|
||||
playlist_set_default_core_path(playlist, coreInfo.inf->path);
|
||||
|
@ -1395,25 +1395,21 @@ QVector<QHash<QString, QString> > MainWindow::getCoreInfo()
|
||||
{
|
||||
unsigned i;
|
||||
QVector<QHash<QString, QString> > infoList;
|
||||
QByteArray currentCorePathArray;
|
||||
core_info_ctx_find_t core_info_finder;
|
||||
QHash<QString, QString> currentCore = getSelectedCore();
|
||||
core_info_list_t *core_info_list = NULL;
|
||||
const char *current_core_path_data = NULL;
|
||||
const core_info_t *core_info = NULL;
|
||||
|
||||
core_info_get_list(&core_info_list);
|
||||
currentCorePathArray = currentCore["core_path"].toUtf8();
|
||||
current_core_path_data = currentCorePathArray.constData();
|
||||
|
||||
if (!core_info_list || core_info_list->count == 0)
|
||||
return infoList;
|
||||
/* Search for current core */
|
||||
core_info_finder.inf = NULL;
|
||||
core_info_finder.path = current_core_path_data;
|
||||
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
const core_info_t *core = &core_info_list->list[i];
|
||||
|
||||
if (currentCore["core_path"] == core->path)
|
||||
{
|
||||
core_info = core;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (core_info_find(&core_info_finder))
|
||||
core_info = core_info_finder.inf;
|
||||
|
||||
if (currentCore["core_path"].isEmpty() || !core_info || !core_info->config_data)
|
||||
{
|
||||
@ -1865,6 +1861,7 @@ void MainWindow::loadContent(const QHash<QString, QString> &contentHash)
|
||||
const char *contentCrc32 = NULL;
|
||||
QVariantMap coreMap = m_launchWithComboBox->currentData(Qt::UserRole).value<QVariantMap>();
|
||||
core_selection coreSelection = static_cast<core_selection>(coreMap.value("core_selection").toInt());
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
contentDbNameFull[0] = '\0';
|
||||
|
||||
@ -1958,6 +1955,15 @@ void MainWindow::loadContent(const QHash<QString, QString> &contentHash)
|
||||
contentDbName = contentDbNameArray.constData();
|
||||
contentCrc32 = contentCrc32Array.constData();
|
||||
|
||||
/* Search for specified core - ensures path
|
||||
* is 'sanitised' */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = corePath;
|
||||
|
||||
if (core_info_find(&core_info) &&
|
||||
!string_is_empty(core_info.inf->path))
|
||||
corePath = core_info.inf->path;
|
||||
|
||||
/* Add lpl extension to db_name, if required */
|
||||
if (!string_is_empty(contentDbName))
|
||||
{
|
||||
@ -2127,11 +2133,15 @@ void MainWindow::setCoreActions()
|
||||
|
||||
if (!defaultCorePath.isEmpty())
|
||||
{
|
||||
QByteArray defaultCorePathArray;
|
||||
QString currentPlaylistItemDataString;
|
||||
bool allPlaylists = false;
|
||||
int row = 0;
|
||||
core_info_list_t *coreInfoList = NULL;
|
||||
unsigned j = 0;
|
||||
core_info_ctx_find_t core_info_finder;
|
||||
const char *default_core_path_data = NULL;
|
||||
bool allPlaylists = false;
|
||||
int row = 0;
|
||||
|
||||
defaultCorePathArray = defaultCorePath.toUtf8();
|
||||
default_core_path_data = defaultCorePathArray.constData();
|
||||
|
||||
if (currentPlaylistItem)
|
||||
{
|
||||
@ -2153,42 +2163,45 @@ void MainWindow::setCoreActions()
|
||||
continue;
|
||||
}
|
||||
|
||||
core_info_get_list(&coreInfoList);
|
||||
/* Search for default core */
|
||||
core_info_finder.inf = NULL;
|
||||
core_info_finder.path = default_core_path_data;
|
||||
|
||||
if (coreInfoList)
|
||||
if (core_info_find(&core_info_finder))
|
||||
{
|
||||
for (j = 0; j < coreInfoList->count; j++)
|
||||
const core_info_t *info = core_info_finder.inf;
|
||||
|
||||
if (m_launchWithComboBox->findText(info->core_name) == -1)
|
||||
{
|
||||
const core_info_t *info = &coreInfoList->list[j];
|
||||
int i = 0;
|
||||
bool found_existing = false;
|
||||
|
||||
if (defaultCorePath == info->path)
|
||||
for (i = 0; i < m_launchWithComboBox->count(); i++)
|
||||
{
|
||||
if (m_launchWithComboBox->findText(info->core_name) == -1)
|
||||
QByteArray CorePathArray;
|
||||
const char *core_path_data = NULL;
|
||||
QVariantMap map = m_launchWithComboBox->itemData(i, Qt::UserRole).toMap();
|
||||
|
||||
CorePathArray = map.value("core_path").toString().toUtf8();
|
||||
core_path_data = CorePathArray.constData();
|
||||
|
||||
if (string_starts_with(path_basename(core_path_data), info->core_file_id.str) ||
|
||||
map.value("core_name").toString() == info->core_name ||
|
||||
map.value("core_name").toString() == info->display_name)
|
||||
{
|
||||
int i = 0;
|
||||
bool found_existing = false;
|
||||
|
||||
for (i = 0; i < m_launchWithComboBox->count(); i++)
|
||||
{
|
||||
QVariantMap map = m_launchWithComboBox->itemData(i, Qt::UserRole).toMap();
|
||||
|
||||
if (map.value("core_path").toString() == info->path || map.value("core_name").toString() == info->core_name)
|
||||
{
|
||||
found_existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_existing)
|
||||
{
|
||||
QVariantMap comboBoxMap;
|
||||
comboBoxMap["core_name"] = info->core_name;
|
||||
comboBoxMap["core_path"] = info->path;
|
||||
comboBoxMap["core_selection"] = CORE_SELECTION_PLAYLIST_DEFAULT;
|
||||
m_launchWithComboBox->addItem(info->core_name, QVariant::fromValue(comboBoxMap));
|
||||
}
|
||||
found_existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_existing)
|
||||
{
|
||||
QVariantMap comboBoxMap;
|
||||
comboBoxMap["core_name"] = info->core_name;
|
||||
comboBoxMap["core_path"] = info->path;
|
||||
comboBoxMap["core_selection"] = CORE_SELECTION_PLAYLIST_DEFAULT;
|
||||
m_launchWithComboBox->addItem(info->core_name, QVariant::fromValue(comboBoxMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user