mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-27 13:15:49 +00:00
Merge branch 'master' into deferred-push-refactor
This commit is contained in:
commit
e57e4dbf57
Makefile.commonfile_path_special.hfile_path_str.cmsg_hash.hplaylist.cplaylist.h
griffin
intl
libretro-common
manual_content_scan.cmanual_content_scan.hmenu
cbs
menu_cbs_deferred_push.cmenu_cbs_get_value.cmenu_cbs_left.cmenu_cbs_ok.cmenu_cbs_right.cmenu_cbs_start.cmenu_cbs_sublabel.cmenu_cbs_title.c
drivers
menu_cbs.hmenu_displaylist.cmenu_displaylist.hmenu_driver.hmenu_setting.cwidgets
tasks
@ -163,6 +163,7 @@ OBJ += frontend/frontend_driver.o \
|
||||
tasks/task_file_transfer.o \
|
||||
tasks/task_image.o \
|
||||
tasks/task_playlist_manager.o \
|
||||
tasks/task_manual_content_scan.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_base64.o \
|
||||
@ -258,8 +259,8 @@ OBJ += \
|
||||
performance_counters.o \
|
||||
verbosity.o \
|
||||
midi/drivers/null_midi.o \
|
||||
$(LIBRETRO_COMM_DIR)/playlists/label_sanitization.o
|
||||
|
||||
$(LIBRETRO_COMM_DIR)/playlists/label_sanitization.o \
|
||||
manual_content_scan.o
|
||||
|
||||
ifeq ($(HAVE_AUDIOMIXER), 1)
|
||||
DEFINES += -DHAVE_AUDIOMIXER
|
||||
|
@ -79,6 +79,7 @@ enum file_path_enum
|
||||
FILE_PATH_LPL_EXTENSION,
|
||||
FILE_PATH_LPL_EXTENSION_NO_DOT,
|
||||
FILE_PATH_RDB_EXTENSION,
|
||||
FILE_PATH_RDB_EXTENSION_NO_DOT,
|
||||
FILE_PATH_BSV_EXTENSION,
|
||||
FILE_PATH_AUTO_EXTENSION,
|
||||
FILE_PATH_ZIP_EXTENSION,
|
||||
|
@ -130,6 +130,9 @@ const char *file_path_str(enum file_path_enum enum_idx)
|
||||
case FILE_PATH_RDB_EXTENSION:
|
||||
str = ".rdb";
|
||||
break;
|
||||
case FILE_PATH_RDB_EXTENSION_NO_DOT:
|
||||
str = "rdb";
|
||||
break;
|
||||
case FILE_PATH_ZIP_EXTENSION:
|
||||
str = ".zip";
|
||||
break;
|
||||
|
@ -1205,6 +1205,7 @@ DATA RUNLOOP
|
||||
#include "../tasks/task_image.c"
|
||||
#include "../tasks/task_file_transfer.c"
|
||||
#include "../tasks/task_playlist_manager.c"
|
||||
#include "../tasks/task_manual_content_scan.c"
|
||||
#ifdef HAVE_ZLIB
|
||||
#include "../tasks/task_decompress.c"
|
||||
#endif
|
||||
@ -1634,3 +1635,8 @@ SSL
|
||||
PLAYLIST NAME SANITIZATION
|
||||
============================================================ */
|
||||
#include "../libretro-common/playlists/label_sanitization.c"
|
||||
|
||||
/*============================================================
|
||||
MANUAL CONTENT SCAN
|
||||
============================================================ */
|
||||
#include "../manual_content_scan.c"
|
||||
|
@ -2105,3 +2105,25 @@ MSG_HASH(MENU_ENUM_LABEL_DRIVER_SWITCH_ENABLE,
|
||||
"driver_switch_enable")
|
||||
MSG_HASH(MENU_ENUM_LABEL_AI_SERVICE_PAUSE,
|
||||
"ai_service_pause")
|
||||
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST,
|
||||
"deferred_manual_content_scan_list")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST,
|
||||
"manual_content_scan_list")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR,
|
||||
"manual_content_scan_dir")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
"manual_content_scan_system_name")
|
||||
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
"deferred_dropdown_box_list_manual_content_scan_system_name")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
"manual_content_scan_system_name_custom")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
"manual_content_scan_core_name")
|
||||
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
"deferred_dropdown_box_list_manual_content_scan_core_name")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS,
|
||||
"manual_content_scan_file_exts")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_OVERWRITE,
|
||||
"manual_content_scan_overwrite")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START,
|
||||
"manual_content_scan_start")
|
||||
|
@ -10040,3 +10040,99 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_AI_SERVICE_PAUSE,
|
||||
"Pauses core while screen is translated."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST,
|
||||
"Manual Scan"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_LIST,
|
||||
"Configurable scan based on content file names. Does not require content to match the database."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_DIR,
|
||||
"Content Directory"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_DIR,
|
||||
"Selects a directory to scan for content."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
"System Name"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
"Specify a 'system name' with which to associate scanned content. Used to name to the generated playlist file and to identify playlist thumbnails."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
"Custom System Name"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
"Manually specify a 'system name' for scanned content. Only used when 'System Name' is set to '<Custom>'."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
"Core"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
"Select a default core to use when launching scanned content."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_FILE_EXTS,
|
||||
"File Extensions"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_FILE_EXTS,
|
||||
"Space-delimited list of file types to include in the scan. If empty, includes all files - or if a core is specified, all files supported by the core."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_OVERWRITE,
|
||||
"Overwrite Existing Playlist"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_OVERWRITE,
|
||||
"When enabled, any existing playlist will be deleted before scanning content. When disabled, existing playlist entries are preserved and only content currently missing from the playlist will be added."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_START,
|
||||
"Start Scan"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_START,
|
||||
"Scan selected content."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CONTENT_DIR,
|
||||
"<Content Directory>"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CUSTOM,
|
||||
"<Custom>"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME_DETECT,
|
||||
"<Unspecified>"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_MANUAL_CONTENT_SCAN_INVALID_CONFIG,
|
||||
"Invalid manual scan configuration"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_MANUAL_CONTENT_SCAN_INVALID_CONTENT,
|
||||
"No valid content detected"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_MANUAL_CONTENT_SCAN_START,
|
||||
"Scanning content: "
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_MANUAL_CONTENT_SCAN_IN_PROGRESS,
|
||||
"Scanning: "
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_MANUAL_CONTENT_SCAN_END,
|
||||
"Scan complete: "
|
||||
)
|
||||
|
@ -133,6 +133,10 @@ char* string_tokenize(char **str, const char *delim);
|
||||
/* Removes every instance of character 'c' from 'str' */
|
||||
void string_remove_all_chars(char *str, char c);
|
||||
|
||||
/* Replaces every instance of character 'find' in 'str'
|
||||
* with character 'replace' */
|
||||
void string_replace_all_chars(char *str, char find, char replace);
|
||||
|
||||
/* Converts string to unsigned integer.
|
||||
* Returns 0 if string is invalid */
|
||||
unsigned string_to_unsigned(const char *str);
|
||||
|
@ -319,6 +319,19 @@ void string_remove_all_chars(char *str, char c)
|
||||
*write_ptr = '\0';
|
||||
}
|
||||
|
||||
/* Replaces every instance of character 'find' in 'str'
|
||||
* with character 'replace' */
|
||||
void string_replace_all_chars(char *str, char find, char replace)
|
||||
{
|
||||
char *str_ptr = str;
|
||||
|
||||
if (string_is_empty(str))
|
||||
return;
|
||||
|
||||
while((str_ptr = strchr(str_ptr, find)) != NULL)
|
||||
*str_ptr++ = replace;
|
||||
}
|
||||
|
||||
/* Converts string to unsigned integer.
|
||||
* Returns 0 if string is invalid */
|
||||
unsigned string_to_unsigned(const char *str)
|
||||
|
875
manual_content_scan.c
Normal file
875
manual_content_scan.c
Normal file
@ -0,0 +1,875 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (manual_content_scan.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <lists/dir_list.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#include "configuration.h"
|
||||
#include "msg_hash.h"
|
||||
#include "list_special.h"
|
||||
#include "core_info.h"
|
||||
#include "file_path_special.h"
|
||||
|
||||
#include "manual_content_scan.h"
|
||||
|
||||
/* Holds all configuration parameters associated
|
||||
* with a manual content scan */
|
||||
typedef struct
|
||||
{
|
||||
char content_dir[PATH_MAX_LENGTH];
|
||||
char system_name_content_dir[PATH_MAX_LENGTH];
|
||||
char system_name_database[PATH_MAX_LENGTH];
|
||||
char system_name_custom[PATH_MAX_LENGTH];
|
||||
char core_name[PATH_MAX_LENGTH];
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char file_exts_core[PATH_MAX_LENGTH];
|
||||
char file_exts_custom[PATH_MAX_LENGTH];
|
||||
enum manual_content_scan_system_name_type system_name_type;
|
||||
enum manual_content_scan_core_type core_type;
|
||||
bool overwrite_playlist;
|
||||
} scan_settings_t;
|
||||
|
||||
/* Static settings object
|
||||
* > Provides easy access to settings parameters
|
||||
* when creating associated menu entries
|
||||
* > We are handling this in almost exactly the same
|
||||
* way as the regular global 'static settings_t *configuration_settings;'
|
||||
* object in retroarch.c. This means it is not inherently thread safe,
|
||||
* but this should not be an issue (i.e. regular configuration_settings
|
||||
* are not thread safe, but we only access them when pushing a
|
||||
* task, not in the task thread itself, so all is well) */
|
||||
static scan_settings_t scan_settings = {
|
||||
"", /* content_dir */
|
||||
"", /* system_name_content_dir */
|
||||
"", /* system_name_database */
|
||||
"", /* system_name_custom */
|
||||
"", /* core_name */
|
||||
"", /* core_path */
|
||||
"", /* file_exts_core */
|
||||
"", /* file_exts_custom */
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR, /* system_name_type */
|
||||
MANUAL_CONTENT_SCAN_CORE_DETECT, /* core_type */
|
||||
false /* overwrite_playlist */
|
||||
};
|
||||
|
||||
/*****************/
|
||||
/* Configuration */
|
||||
/*****************/
|
||||
|
||||
/* Pointer access */
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'system_name_custom' string */
|
||||
char *manual_content_scan_get_system_name_custom_ptr(void)
|
||||
{
|
||||
return scan_settings.system_name_custom;
|
||||
}
|
||||
|
||||
/* Returns size of the internal
|
||||
* 'system_name_custom' string */
|
||||
size_t manual_content_scan_get_system_name_custom_size(void)
|
||||
{
|
||||
return sizeof(scan_settings.system_name_custom);
|
||||
}
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'file_exts_custom' string */
|
||||
char *manual_content_scan_get_file_exts_custom_ptr(void)
|
||||
{
|
||||
return scan_settings.file_exts_custom;
|
||||
}
|
||||
|
||||
/* Returns size of the internal
|
||||
* 'file_exts_custom' string */
|
||||
size_t manual_content_scan_get_file_exts_custom_size(void)
|
||||
{
|
||||
return sizeof(scan_settings.file_exts_custom);
|
||||
}
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'overwrite_playlist' bool */
|
||||
bool *manual_content_scan_get_overwrite_playlist_ptr(void)
|
||||
{
|
||||
return &scan_settings.overwrite_playlist;
|
||||
}
|
||||
|
||||
/* Sanitisation */
|
||||
|
||||
/* Sanitises file extensions list string:
|
||||
* > Removes period (full stop) characters
|
||||
* > Converts to lower case
|
||||
* > Trims leading/trailing whitespace */
|
||||
static void manual_content_scan_scrub_file_exts(char *file_exts)
|
||||
{
|
||||
if (string_is_empty(file_exts))
|
||||
return;
|
||||
|
||||
string_remove_all_chars(file_exts, '.');
|
||||
string_to_lower(file_exts);
|
||||
string_trim_whitespace(file_exts);
|
||||
}
|
||||
|
||||
/* Removes invalid characters from
|
||||
* 'system_name_custom' string */
|
||||
void manual_content_scan_scrub_system_name_custom(void)
|
||||
{
|
||||
char *scrub_char_pointer = NULL;
|
||||
|
||||
if (string_is_empty(scan_settings.system_name_custom))
|
||||
return;
|
||||
|
||||
/* Scrub characters that are not cross-platform
|
||||
* and/or violate the No-Intro filename standard:
|
||||
* http://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).zip
|
||||
* Replace these characters with underscores */
|
||||
while((scrub_char_pointer = strpbrk(scan_settings.system_name_custom, "&*/:`\"<>?\\|")))
|
||||
*scrub_char_pointer = '_';
|
||||
}
|
||||
|
||||
/* Removes period (full stop) characters from
|
||||
* 'file_exts_custom' string and converts to
|
||||
* lower case */
|
||||
void manual_content_scan_scrub_file_exts_custom(void)
|
||||
{
|
||||
manual_content_scan_scrub_file_exts(scan_settings.file_exts_custom);
|
||||
}
|
||||
|
||||
/* Menu setters */
|
||||
|
||||
/* Sets content directory for next manual scan
|
||||
* operation.
|
||||
* Returns true if content directory is valid. */
|
||||
bool manual_content_scan_set_menu_content_dir(const char *content_dir)
|
||||
{
|
||||
const char *dir_name = NULL;
|
||||
size_t len;
|
||||
|
||||
/* Sanity check */
|
||||
if (string_is_empty(content_dir))
|
||||
goto error;
|
||||
|
||||
if (!path_is_directory(content_dir))
|
||||
goto error;
|
||||
|
||||
/* Copy directory path to settings struct */
|
||||
strlcpy(
|
||||
scan_settings.content_dir,
|
||||
content_dir,
|
||||
sizeof(scan_settings.content_dir));
|
||||
|
||||
/* Remove trailing slash, if required */
|
||||
len = strlen(scan_settings.content_dir);
|
||||
if (len > 0)
|
||||
{
|
||||
if (scan_settings.content_dir[len - 1] == path_default_slash_c())
|
||||
scan_settings.content_dir[len - 1] = '\0';
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
|
||||
/* Handle case where path was a single slash... */
|
||||
if (string_is_empty(scan_settings.content_dir))
|
||||
goto error;
|
||||
|
||||
/* Get directory name (used as system name
|
||||
* when scan_settings.system_name_type ==
|
||||
* MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR) */
|
||||
dir_name = path_basename(scan_settings.content_dir);
|
||||
|
||||
if (string_is_empty(dir_name))
|
||||
goto error;
|
||||
|
||||
/* Copy directory name to settings struct */
|
||||
strlcpy(
|
||||
scan_settings.system_name_content_dir,
|
||||
dir_name,
|
||||
sizeof(scan_settings.system_name_content_dir));
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
/* Directory is invalid - reset internal
|
||||
* content directory and associated 'directory'
|
||||
* system name */
|
||||
scan_settings.content_dir[0] = '\0';
|
||||
scan_settings.system_name_content_dir[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sets system name for the next manual scan
|
||||
* operation.
|
||||
* Returns true if system name is valid.
|
||||
* NOTE:
|
||||
* > Only sets 'system_name_type' and 'system_name_database'
|
||||
* > 'system_name_content_dir' and 'system_name_custom' are
|
||||
* (by necessity) handled elsewhere
|
||||
* > This may look fishy, but it's not - it's a menu-specific
|
||||
* function, and this is simply the cleanest way to handle
|
||||
* the setting... */
|
||||
bool manual_content_scan_set_menu_system_name(
|
||||
enum manual_content_scan_system_name_type system_name_type,
|
||||
const char *system_name)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (system_name_type > MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE)
|
||||
goto error;
|
||||
|
||||
/* Cache system name 'type' */
|
||||
scan_settings.system_name_type = system_name_type;
|
||||
|
||||
/* Check if we are using a non-database name */
|
||||
if ((scan_settings.system_name_type == MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR) ||
|
||||
(scan_settings.system_name_type == MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM))
|
||||
scan_settings.system_name_database[0] = '\0';
|
||||
else
|
||||
{
|
||||
/* We are using a database name... */
|
||||
if (string_is_empty(system_name))
|
||||
goto error;
|
||||
|
||||
/* Copy database name to settings struct */
|
||||
strlcpy(
|
||||
scan_settings.system_name_database,
|
||||
system_name,
|
||||
sizeof(scan_settings.system_name_database));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
/* Input parameters are invalid - reset internal
|
||||
* 'system_name_type' and 'system_name_database' */
|
||||
scan_settings.system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR;
|
||||
scan_settings.system_name_database[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sets core name for the next manual scan
|
||||
* operation (+ core path and other associated
|
||||
* parameters).
|
||||
* Returns true if core name is valid. */
|
||||
bool manual_content_scan_set_menu_core_name(
|
||||
enum manual_content_scan_core_type core_type,
|
||||
const char *core_name)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (core_type > MANUAL_CONTENT_SCAN_CORE_SET)
|
||||
goto error;
|
||||
|
||||
/* Cache core 'type' */
|
||||
scan_settings.core_type = core_type;
|
||||
|
||||
/* Check if we are using core autodetection */
|
||||
if (scan_settings.core_type == MANUAL_CONTENT_SCAN_CORE_DETECT)
|
||||
{
|
||||
scan_settings.core_name[0] = '\0';
|
||||
scan_settings.core_path[0] = '\0';
|
||||
scan_settings.file_exts_core[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
core_info_list_t *core_info_list = NULL;
|
||||
core_info_t *core_info = NULL;
|
||||
bool core_found = false;
|
||||
size_t i;
|
||||
|
||||
/* We are using a manually set core... */
|
||||
if (string_is_empty(core_name))
|
||||
goto error;
|
||||
|
||||
/* Get core list */
|
||||
core_info_get_list(&core_info_list);
|
||||
|
||||
if (!core_info_list)
|
||||
goto error;
|
||||
|
||||
/* Search for the specified core name */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
|
||||
if (core_info)
|
||||
{
|
||||
if (string_is_equal(core_info->display_name, core_name))
|
||||
{
|
||||
/* Core has been found */
|
||||
core_found = true;
|
||||
|
||||
/* Copy core path to settings struct */
|
||||
if (string_is_empty(core_info->path))
|
||||
goto error;
|
||||
|
||||
strlcpy(
|
||||
scan_settings.core_path,
|
||||
core_info->path,
|
||||
sizeof(scan_settings.core_path));
|
||||
|
||||
/* Copy core name to settings struct */
|
||||
strlcpy(
|
||||
scan_settings.core_name,
|
||||
core_info->display_name,
|
||||
sizeof(scan_settings.core_name));
|
||||
|
||||
/* Copy supported extensions to settings
|
||||
* struct, if required */
|
||||
if (!string_is_empty(core_info->supported_extensions))
|
||||
{
|
||||
strlcpy(
|
||||
scan_settings.file_exts_core,
|
||||
core_info->supported_extensions,
|
||||
sizeof(scan_settings.file_exts_core));
|
||||
|
||||
/* Core info extensions are delimited by
|
||||
* vertical bars. For internal consistency,
|
||||
* replace them with spaces */
|
||||
string_replace_all_chars(scan_settings.file_exts_core, '|', ' ');
|
||||
|
||||
/* Apply standard scrubbing/clean-up
|
||||
* (should not be required, but must handle the
|
||||
* case where a core info file is incorrectly
|
||||
* formatted) */
|
||||
manual_content_scan_scrub_file_exts(scan_settings.file_exts_core);
|
||||
}
|
||||
else
|
||||
scan_settings.file_exts_core[0] = '\0';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (!core_found)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
/* Input parameters are invalid - reset internal
|
||||
* core values */
|
||||
scan_settings.core_type = MANUAL_CONTENT_SCAN_CORE_DETECT;
|
||||
scan_settings.core_name[0] = '\0';
|
||||
scan_settings.core_path[0] = '\0';
|
||||
scan_settings.file_exts_core[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Menu getters */
|
||||
|
||||
/* Fetches content directory for next manual scan
|
||||
* operation.
|
||||
* Returns true if content directory is valid. */
|
||||
bool manual_content_scan_get_menu_content_dir(const char **content_dir)
|
||||
{
|
||||
if (!content_dir)
|
||||
return false;
|
||||
|
||||
if (string_is_empty(scan_settings.content_dir))
|
||||
return false;
|
||||
|
||||
*content_dir = scan_settings.content_dir;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetches system name for the next manual scan operation.
|
||||
* Returns true if system name is valid.
|
||||
* NOTE: This corresponds to the 'System Name' value
|
||||
* displayed in menus - this is not identical to the
|
||||
* actual system name used when generating the playlist */
|
||||
bool manual_content_scan_get_menu_system_name(const char **system_name)
|
||||
{
|
||||
if (!system_name)
|
||||
return false;
|
||||
|
||||
switch (scan_settings.system_name_type)
|
||||
{
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR:
|
||||
*system_name = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CONTENT_DIR);
|
||||
return true;
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM:
|
||||
*system_name = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CUSTOM);
|
||||
return true;
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE:
|
||||
if (string_is_empty(scan_settings.system_name_database))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
*system_name = scan_settings.system_name_database;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches core name for the next manual scan operation.
|
||||
* Returns true if core name is valid. */
|
||||
bool manual_content_scan_get_menu_core_name(const char **core_name)
|
||||
{
|
||||
if (!core_name)
|
||||
return false;
|
||||
|
||||
switch (scan_settings.core_type)
|
||||
{
|
||||
case MANUAL_CONTENT_SCAN_CORE_DETECT:
|
||||
*core_name = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME_DETECT);
|
||||
return true;
|
||||
case MANUAL_CONTENT_SCAN_CORE_SET:
|
||||
if (string_is_empty(scan_settings.core_name))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
*core_name = scan_settings.core_name;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Menu utility functions */
|
||||
|
||||
/* Creates a list of all possible 'system name' menu
|
||||
* strings, for use in 'menu_displaylist' drop-down
|
||||
* lists and 'menu_cbs_left/right'
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_menu_system_name_list(void)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
struct string_list *name_list = string_list_new();
|
||||
union string_list_elem_attr attr;
|
||||
|
||||
/* Sanity check */
|
||||
if (!name_list)
|
||||
goto error;
|
||||
|
||||
attr.i = 0;
|
||||
|
||||
/* Add 'use content directory' entry */
|
||||
if (!string_list_append(name_list, msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CONTENT_DIR), attr))
|
||||
goto error;
|
||||
|
||||
/* Add 'use custom' entry */
|
||||
if (!string_list_append(name_list, msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CUSTOM), attr))
|
||||
goto error;
|
||||
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
|
||||
/* If platform has database support, get names
|
||||
* of all installed database files */
|
||||
if (settings)
|
||||
{
|
||||
/* Note: dir_list_new_special() is well behaved - the
|
||||
* returned string list will only include database
|
||||
* files (i.e. don't have to check for directories,
|
||||
* or verify file extensions) */
|
||||
struct string_list *rdb_list = dir_list_new_special(
|
||||
settings->paths.path_content_database,
|
||||
DIR_LIST_DATABASES, NULL);
|
||||
|
||||
if (rdb_list && rdb_list->size)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* Ensure database list is in alphabetical order */
|
||||
dir_list_sort(rdb_list, true);
|
||||
|
||||
/* Loop over database files */
|
||||
for (i = 0; i < rdb_list->size; i++)
|
||||
{
|
||||
const char *rdb_path = rdb_list->elems[i].data;
|
||||
const char *rdb_file = NULL;
|
||||
char rdb_name[PATH_MAX_LENGTH];
|
||||
|
||||
rdb_name[0] = '\0';
|
||||
|
||||
/* Sanity check */
|
||||
if (string_is_empty(rdb_path))
|
||||
continue;
|
||||
|
||||
rdb_file = path_basename(rdb_path);
|
||||
|
||||
if (string_is_empty(rdb_file))
|
||||
continue;
|
||||
|
||||
/* Remove file extension */
|
||||
strlcpy(rdb_name, rdb_file, sizeof(rdb_name));
|
||||
path_remove_extension(rdb_name);
|
||||
|
||||
if (string_is_empty(rdb_name))
|
||||
continue;
|
||||
|
||||
/* Add database name to list */
|
||||
if (!string_list_append(name_list, rdb_name, attr))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(rdb_list);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return name_list;
|
||||
|
||||
error:
|
||||
if (name_list)
|
||||
string_list_free(name_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Creates a list of all possible 'core name' menu
|
||||
* strings, for use in 'menu_displaylist' drop-down
|
||||
* lists and 'menu_cbs_left/right'
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_menu_core_name_list(void)
|
||||
{
|
||||
struct string_list *name_list = string_list_new();
|
||||
core_info_list_t *core_info_list = NULL;
|
||||
union string_list_elem_attr attr;
|
||||
|
||||
/* Sanity check */
|
||||
if (!name_list)
|
||||
goto error;
|
||||
|
||||
attr.i = 0;
|
||||
|
||||
/* Add 'DETECT' entry */
|
||||
if (!string_list_append(name_list, msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME_DETECT), attr))
|
||||
goto error;
|
||||
|
||||
/* Get core list */
|
||||
core_info_get_list(&core_info_list);
|
||||
|
||||
if (core_info_list)
|
||||
{
|
||||
core_info_t *core_info = NULL;
|
||||
size_t i;
|
||||
|
||||
/* Sort cores alphabetically */
|
||||
core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME);
|
||||
|
||||
/* Loop through cores */
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
core_info = NULL;
|
||||
core_info = core_info_get(core_info_list, i);
|
||||
|
||||
if (core_info)
|
||||
{
|
||||
if (string_is_empty(core_info->display_name))
|
||||
continue;
|
||||
|
||||
/* Add core name to list */
|
||||
if (!string_list_append(name_list, core_info->display_name, attr))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name_list;
|
||||
|
||||
error:
|
||||
if (name_list)
|
||||
string_list_free(name_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* Task Helpers */
|
||||
/****************/
|
||||
|
||||
/* Parses current manual content scan settings,
|
||||
* and extracts all information required to configure
|
||||
* a manual content scan task.
|
||||
* Returns false if current settings are invalid. */
|
||||
bool manual_content_scan_get_task_config(manual_content_scan_task_config_t *task_config)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (!task_config || !settings)
|
||||
return false;
|
||||
|
||||
/* Ensure all 'task_config' strings are
|
||||
* correctly initialised */
|
||||
task_config->playlist_file[0] = '\0';
|
||||
task_config->content_dir[0] = '\0';
|
||||
task_config->system_name[0] = '\0';
|
||||
task_config->database_name[0] = '\0';
|
||||
task_config->core_name[0] = '\0';
|
||||
task_config->core_path[0] = '\0';
|
||||
task_config->file_exts[0] = '\0';
|
||||
|
||||
/* Get content directory */
|
||||
if (string_is_empty(scan_settings.content_dir))
|
||||
return false;
|
||||
|
||||
if (!path_is_directory(scan_settings.content_dir))
|
||||
return false;
|
||||
|
||||
strlcpy(
|
||||
task_config->content_dir,
|
||||
scan_settings.content_dir,
|
||||
sizeof(task_config->content_dir));
|
||||
|
||||
/* Get system name */
|
||||
switch (scan_settings.system_name_type)
|
||||
{
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR:
|
||||
if (string_is_empty(scan_settings.system_name_content_dir))
|
||||
return false;
|
||||
|
||||
strlcpy(
|
||||
task_config->system_name,
|
||||
scan_settings.system_name_content_dir,
|
||||
sizeof(task_config->system_name));
|
||||
|
||||
break;
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM:
|
||||
if (string_is_empty(scan_settings.system_name_custom))
|
||||
return false;
|
||||
|
||||
strlcpy(
|
||||
task_config->system_name,
|
||||
scan_settings.system_name_custom,
|
||||
sizeof(task_config->system_name));
|
||||
|
||||
break;
|
||||
case MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE:
|
||||
if (string_is_empty(scan_settings.system_name_database))
|
||||
return false;
|
||||
|
||||
strlcpy(
|
||||
task_config->system_name,
|
||||
scan_settings.system_name_database,
|
||||
sizeof(task_config->system_name));
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now we have a valid system name, can generate
|
||||
* a 'database' name... */
|
||||
strlcpy(
|
||||
task_config->database_name,
|
||||
task_config->system_name,
|
||||
sizeof(task_config->database_name));
|
||||
|
||||
strlcat(
|
||||
task_config->database_name,
|
||||
file_path_str(FILE_PATH_LPL_EXTENSION),
|
||||
sizeof(task_config->database_name));
|
||||
|
||||
/* ...which can in turn be used to generate the
|
||||
* playlist path */
|
||||
if (string_is_empty(settings->paths.directory_playlist))
|
||||
return false;
|
||||
|
||||
fill_pathname_join(
|
||||
task_config->playlist_file,
|
||||
settings->paths.directory_playlist,
|
||||
task_config->database_name,
|
||||
sizeof(task_config->playlist_file));
|
||||
|
||||
if (string_is_empty(task_config->playlist_file))
|
||||
return false;
|
||||
|
||||
/* Get core name and path */
|
||||
switch (scan_settings.core_type)
|
||||
{
|
||||
case MANUAL_CONTENT_SCAN_CORE_DETECT:
|
||||
task_config->core_set = false;
|
||||
break;
|
||||
case MANUAL_CONTENT_SCAN_CORE_SET:
|
||||
task_config->core_set = true;
|
||||
|
||||
if (string_is_empty(scan_settings.core_name))
|
||||
return false;
|
||||
if (string_is_empty(scan_settings.core_path))
|
||||
return false;
|
||||
|
||||
strlcpy(
|
||||
task_config->core_name,
|
||||
scan_settings.core_name,
|
||||
sizeof(task_config->core_name));
|
||||
|
||||
strlcpy(
|
||||
task_config->core_path,
|
||||
scan_settings.core_path,
|
||||
sizeof(task_config->core_path));
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get file extensions list
|
||||
* > Note that compressed files are included by
|
||||
* default, regardless of extension filter
|
||||
* (since these can always be handled by the
|
||||
* frontend) */
|
||||
task_config->include_compressed_content = true;
|
||||
|
||||
if (!string_is_empty(scan_settings.file_exts_custom))
|
||||
{
|
||||
strlcpy(
|
||||
task_config->file_exts,
|
||||
scan_settings.file_exts_custom,
|
||||
sizeof(task_config->file_exts));
|
||||
|
||||
/* User has explicitly specified which file
|
||||
* types are allowed - have to exclude compressed
|
||||
* content when calling dir_list_new() */
|
||||
task_config->include_compressed_content = false;
|
||||
}
|
||||
else if (scan_settings.core_type == MANUAL_CONTENT_SCAN_CORE_SET)
|
||||
{
|
||||
if (!string_is_empty(scan_settings.file_exts_core))
|
||||
strlcpy(
|
||||
task_config->file_exts,
|
||||
scan_settings.file_exts_core,
|
||||
sizeof(task_config->file_exts));
|
||||
}
|
||||
|
||||
/* Our extension lists are space delimited
|
||||
* > dir_list_new() expects vertical bar
|
||||
* delimiters, so find and replace */
|
||||
if (!string_is_empty(task_config->file_exts))
|
||||
string_replace_all_chars(task_config->file_exts, ' ', '|');
|
||||
|
||||
/* Copy 'overwrite playlist' setting */
|
||||
task_config->overwrite_playlist = scan_settings.overwrite_playlist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Creates a list of all valid content in the specified
|
||||
* content directory
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_content_list(manual_content_scan_task_config_t *task_config)
|
||||
{
|
||||
struct string_list *dir_list = NULL;
|
||||
bool filter_exts;
|
||||
|
||||
/* Sanity check */
|
||||
if (!task_config)
|
||||
goto error;
|
||||
|
||||
if (string_is_empty(task_config->content_dir))
|
||||
goto error;
|
||||
|
||||
/* Get directory listing
|
||||
* > Exclude directories and hidden files
|
||||
* > Scan recursively */
|
||||
dir_list = dir_list_new(
|
||||
task_config->content_dir,
|
||||
string_is_empty(task_config->file_exts) ? NULL : task_config->file_exts,
|
||||
false, /* include_dirs */
|
||||
false, /* include_hidden */
|
||||
task_config->include_compressed_content,
|
||||
true /* recursive */
|
||||
);
|
||||
|
||||
/* Sanity check */
|
||||
if (!dir_list)
|
||||
goto error;
|
||||
|
||||
if (dir_list->size < 1)
|
||||
goto error;
|
||||
|
||||
/* Ensure list is in alphabetical order
|
||||
* > Not strictly required, but task status
|
||||
* messages will be unintuitive if we leave
|
||||
* the order 'random' */
|
||||
dir_list_sort(dir_list, true);
|
||||
|
||||
return dir_list;
|
||||
|
||||
error:
|
||||
if (dir_list)
|
||||
string_list_free(dir_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Adds specified content to playlist, if not already
|
||||
* present */
|
||||
void manual_content_scan_add_content_to_playlist(
|
||||
manual_content_scan_task_config_t *task_config,
|
||||
playlist_t *playlist, const char *content_path)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (!task_config || !playlist || string_is_empty(content_path))
|
||||
return;
|
||||
|
||||
if (!path_is_valid(content_path))
|
||||
return;
|
||||
|
||||
/* Check whether content is already included
|
||||
* in playlist */
|
||||
if (!playlist_entry_exists(playlist, content_path))
|
||||
{
|
||||
struct playlist_entry entry = {0};
|
||||
char label[PATH_MAX_LENGTH];
|
||||
|
||||
label[0] = '\0';
|
||||
|
||||
/* Get entry label */
|
||||
fill_short_pathname_representation(
|
||||
label, content_path, sizeof(label));
|
||||
|
||||
if (string_is_empty(label))
|
||||
return;
|
||||
|
||||
/* Configure playlist entry
|
||||
* > The push function reads our entry as const,
|
||||
* so these casts are safe */
|
||||
entry.path = (char*)content_path;
|
||||
entry.label = label;
|
||||
entry.core_path = (char*)"DETECT";
|
||||
entry.core_name = (char*)"DETECT";
|
||||
entry.crc32 = (char*)"00000000|crc";
|
||||
entry.db_name = task_config->database_name;
|
||||
|
||||
/* Add entry to playlist */
|
||||
playlist_push(playlist, &entry);
|
||||
}
|
||||
}
|
201
manual_content_scan.h
Normal file
201
manual_content_scan.h
Normal file
@ -0,0 +1,201 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (manual_content_scan.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MANUAL_CONTENT_SCAN_H
|
||||
#define __MANUAL_CONTENT_SCAN_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <lists/string_list.h>
|
||||
|
||||
#include "playlist.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Defines all possible system name types
|
||||
* > Use content directory name
|
||||
* > Use custom name
|
||||
* > Use database name */
|
||||
enum manual_content_scan_system_name_type
|
||||
{
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR = 0,
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE
|
||||
};
|
||||
|
||||
/* Defines all possible core name types
|
||||
* > Autodetect core (DETECT)
|
||||
* > Use manually set core */
|
||||
enum manual_content_scan_core_type
|
||||
{
|
||||
MANUAL_CONTENT_SCAN_CORE_DETECT = 0,
|
||||
MANUAL_CONTENT_SCAN_CORE_SET
|
||||
};
|
||||
|
||||
/* Holds all configuration parameters required
|
||||
* for a manual content scan task */
|
||||
typedef struct
|
||||
{
|
||||
char playlist_file[PATH_MAX_LENGTH];
|
||||
char content_dir[PATH_MAX_LENGTH];
|
||||
char system_name[PATH_MAX_LENGTH];
|
||||
char database_name[PATH_MAX_LENGTH];
|
||||
char core_name[PATH_MAX_LENGTH];
|
||||
char core_path[PATH_MAX_LENGTH];
|
||||
char file_exts[PATH_MAX_LENGTH];
|
||||
bool core_set;
|
||||
bool overwrite_playlist;
|
||||
bool include_compressed_content;
|
||||
} manual_content_scan_task_config_t;
|
||||
|
||||
/*****************/
|
||||
/* Configuration */
|
||||
/*****************/
|
||||
|
||||
/* Pointer access
|
||||
* > This is a little ugly, but it allows us to
|
||||
* make use of standard 'menu_settings' code
|
||||
* for several config parameters (rather than
|
||||
* implementing unnecessary custom menu entries) */
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'system_name_custom' string */
|
||||
char *manual_content_scan_get_system_name_custom_ptr(void);
|
||||
|
||||
/* Returns size of the internal
|
||||
* 'system_name_custom' string */
|
||||
size_t manual_content_scan_get_system_name_custom_size(void);
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'file_exts_custom' string */
|
||||
char *manual_content_scan_get_file_exts_custom_ptr(void);
|
||||
|
||||
/* Returns size of the internal
|
||||
* 'file_exts_custom' string */
|
||||
size_t manual_content_scan_get_file_exts_custom_size(void);
|
||||
|
||||
/* Returns a pointer to the internal
|
||||
* 'overwrite_playlist' bool */
|
||||
bool *manual_content_scan_get_overwrite_playlist_ptr(void);
|
||||
|
||||
/* Sanitisation */
|
||||
|
||||
/* Removes invalid characters from
|
||||
* 'system_name_custom' string */
|
||||
void manual_content_scan_scrub_system_name_custom(void);
|
||||
|
||||
/* Removes period (full stop) characters from
|
||||
* 'file_exts_custom' string and converts to
|
||||
* lower case */
|
||||
void manual_content_scan_scrub_file_exts_custom(void);
|
||||
|
||||
/* Menu setters */
|
||||
|
||||
/* Sets content directory for next manual scan
|
||||
* operation.
|
||||
* Returns true if content directory is valid. */
|
||||
bool manual_content_scan_set_menu_content_dir(const char *content_dir);
|
||||
|
||||
/* Sets system name for the next manual scan
|
||||
* operation.
|
||||
* Returns true if system name is valid.
|
||||
* NOTE:
|
||||
* > Only sets 'system_name_type' and 'system_name_database'
|
||||
* > 'system_name_content_dir' and 'system_name_custom' are
|
||||
* (by necessity) handled elsewhere
|
||||
* > This may look fishy, but it's not - it's a menu-specific
|
||||
* function, and this is simply the cleanest way to handle
|
||||
* the setting... */
|
||||
bool manual_content_scan_set_menu_system_name(
|
||||
enum manual_content_scan_system_name_type system_name_type,
|
||||
const char *system_name);
|
||||
|
||||
/* Sets core name for the next manual scan
|
||||
* operation (+ core path and other associated
|
||||
* parameters).
|
||||
* Returns true if core name is valid. */
|
||||
bool manual_content_scan_set_menu_core_name(
|
||||
enum manual_content_scan_core_type core_type,
|
||||
const char *core_name);
|
||||
|
||||
/* Menu getters */
|
||||
|
||||
/* Fetches content directory for next manual scan
|
||||
* operation.
|
||||
* Returns true if content directory is valid. */
|
||||
bool manual_content_scan_get_menu_content_dir(const char **content_dir);
|
||||
|
||||
/* Fetches system name for the next manual scan operation.
|
||||
* Returns true if system name is valid.
|
||||
* NOTE: This corresponds to the 'System Name' value
|
||||
* displayed in menus - this is not identical to the
|
||||
* actual system name used when generating the playlist */
|
||||
bool manual_content_scan_get_menu_system_name(const char **system_name);
|
||||
|
||||
/* Fetches core name for the next manual scan operation.
|
||||
* Returns true if core name is valid. */
|
||||
bool manual_content_scan_get_menu_core_name(const char **core_name);
|
||||
|
||||
/* Menu utility functions */
|
||||
|
||||
/* Creates a list of all possible 'system name' menu
|
||||
* strings, for use in 'menu_displaylist' drop-down
|
||||
* lists and 'menu_cbs_left/right'
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_menu_system_name_list(void);
|
||||
|
||||
/* Creates a list of all possible 'core name' menu
|
||||
* strings, for use in 'menu_displaylist' drop-down
|
||||
* lists and 'menu_cbs_left/right'
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_menu_core_name_list(void);
|
||||
|
||||
/****************/
|
||||
/* Task Helpers */
|
||||
/****************/
|
||||
|
||||
/* Parses current manual content scan settings,
|
||||
* and extracts all information required to configure
|
||||
* a manual content scan task.
|
||||
* Returns false if current settings are invalid. */
|
||||
bool manual_content_scan_get_task_config(manual_content_scan_task_config_t *task_config);
|
||||
|
||||
/* Creates a list of all valid content in the specified
|
||||
* content directory
|
||||
* > Returns NULL in the event of failure
|
||||
* > Returned string list must be free()'d */
|
||||
struct string_list *manual_content_scan_get_content_list(manual_content_scan_task_config_t *task_config);
|
||||
|
||||
/* Adds specified content to playlist, if not already
|
||||
* present */
|
||||
void manual_content_scan_add_content_to_playlist(
|
||||
manual_content_scan_task_config_t *task_config,
|
||||
playlist_t *playlist, const char *content_path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
@ -217,6 +217,8 @@ generic_deferred_push(deferred_push_switch_gpu_profile, DISPLAYLIST_
|
||||
generic_deferred_push(deferred_push_switch_backlight_control, DISPLAYLIST_SWITCH_BACKLIGHT_CONTROL)
|
||||
#endif
|
||||
|
||||
generic_deferred_push(deferred_push_manual_content_scan_list, DISPLAYLIST_MANUAL_CONTENT_SCAN_LIST)
|
||||
|
||||
static int deferred_push_cursor_manager_list_deferred(
|
||||
menu_displaylist_info_t *info)
|
||||
{
|
||||
@ -636,6 +638,8 @@ generic_deferred_push_clear_general(deferred_push_dropdown_box_list_playlist_def
|
||||
generic_deferred_push_clear_general(deferred_push_dropdown_box_list_playlist_label_display_mode, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE)
|
||||
generic_deferred_push_clear_general(deferred_push_dropdown_box_list_playlist_right_thumbnail_mode, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE)
|
||||
generic_deferred_push_clear_general(deferred_push_dropdown_box_list_playlist_left_thumbnail_mode, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE)
|
||||
generic_deferred_push_clear_general(deferred_push_dropdown_box_list_manual_content_scan_system_name, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME)
|
||||
generic_deferred_push_clear_general(deferred_push_dropdown_box_list_manual_content_scan_core_name, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME)
|
||||
|
||||
static int menu_cbs_init_bind_deferred_push_compare_label(
|
||||
menu_file_list_cbs_t *cbs,
|
||||
@ -745,6 +749,8 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
|
||||
{MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_TWITCH_LIST, deferred_push_accounts_twitch_list},
|
||||
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_SAVE_LIST, deferred_push_video_shader_preset_save},
|
||||
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_REMOVE_LIST, deferred_push_video_shader_preset_remove},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME, deferred_push_dropdown_box_list_manual_content_scan_system_name},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME, deferred_push_dropdown_box_list_manual_content_scan_core_name},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(info_list); i++)
|
||||
@ -1088,6 +1094,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
|
||||
case MENU_ENUM_LABEL_FAVORITES:
|
||||
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_detect_core_list);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_manual_content_scan_list);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -1304,6 +1313,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
|
||||
case MENU_LABEL_FAVORITES:
|
||||
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_detect_core_list);
|
||||
break;
|
||||
case MENU_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_manual_content_scan_list);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -1352,4 +1364,4 @@ int menu_cbs_init_bind_deferred_push(menu_file_list_cbs_t *cbs,
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -43,6 +43,7 @@
|
||||
#include "../../verbosity.h"
|
||||
#include "../../wifi/wifi_driver.h"
|
||||
#include "../../playlist.h"
|
||||
#include "../../manual_content_scan.h"
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "../../network/netplay/netplay.h"
|
||||
@ -1292,6 +1293,66 @@ static void menu_action_setting_disp_set_label_achievement_information(
|
||||
strlcpy(s2, path, len2);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_manual_content_scan_dir(file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
const char *label,
|
||||
char *s, size_t len,
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
const char *content_dir = NULL;
|
||||
|
||||
*s = '\0';
|
||||
*w = 19;
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
|
||||
if (!manual_content_scan_get_menu_content_dir(&content_dir))
|
||||
return;
|
||||
|
||||
strlcpy(s, content_dir, len);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_manual_content_scan_system_name(file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
const char *label,
|
||||
char *s, size_t len,
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
const char *system_name = NULL;
|
||||
|
||||
*s = '\0';
|
||||
*w = 19;
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
|
||||
if (!manual_content_scan_get_menu_system_name(&system_name))
|
||||
return;
|
||||
|
||||
strlcpy(s, system_name, len);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_manual_content_scan_core_name(file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
const char *label,
|
||||
char *s, size_t len,
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
const char *core_name = NULL;
|
||||
|
||||
*s = '\0';
|
||||
*w = 19;
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
|
||||
if (!manual_content_scan_get_menu_core_name(&core_name))
|
||||
return;
|
||||
|
||||
strlcpy(s, core_name, len);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_no_items(
|
||||
file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
@ -1502,6 +1563,18 @@ static int menu_cbs_init_bind_get_string_representation_compare_label(
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_playlist_left_thumbnail_mode);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_manual_content_scan_dir);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_manual_content_scan_core_name);
|
||||
break;
|
||||
default:
|
||||
return - 1;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "../../retroarch.h"
|
||||
#include "../../network/netplay/netplay.h"
|
||||
#include "../../playlist.h"
|
||||
#include "../../manual_content_scan.h"
|
||||
|
||||
#ifndef BIND_ACTION_LEFT
|
||||
#define BIND_ACTION_LEFT(cbs, name) \
|
||||
@ -515,6 +516,116 @@ static int playlist_left_thumbnail_mode_left(unsigned type, const char *label,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manual_content_scan_system_name_left(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
struct string_list *system_name_list =
|
||||
manual_content_scan_get_menu_system_name_list();
|
||||
const char *current_system_name = NULL;
|
||||
enum manual_content_scan_system_name_type next_system_name_type =
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE;
|
||||
const char *next_system_name = NULL;
|
||||
unsigned current_index = 0;
|
||||
unsigned next_index = 0;
|
||||
unsigned i;
|
||||
|
||||
if (!system_name_list)
|
||||
return -1;
|
||||
|
||||
/* Get currently selected system name */
|
||||
if (manual_content_scan_get_menu_system_name(¤t_system_name))
|
||||
{
|
||||
/* Get index of currently selected system name */
|
||||
for (i = 0; i < system_name_list->size; i++)
|
||||
{
|
||||
const char *system_name = system_name_list->elems[i].data;
|
||||
|
||||
if (string_is_equal(current_system_name, system_name))
|
||||
{
|
||||
current_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement index */
|
||||
if (current_index > 0)
|
||||
next_index = current_index - 1;
|
||||
else if (wraparound && (system_name_list->size > 1))
|
||||
next_index = system_name_list->size - 1;
|
||||
}
|
||||
|
||||
/* Get new system name parameters */
|
||||
if (next_index == (unsigned)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR)
|
||||
next_system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR;
|
||||
else if (next_index == (unsigned)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM)
|
||||
next_system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM;
|
||||
|
||||
next_system_name = system_name_list->elems[next_index].data;
|
||||
|
||||
/* Set system name */
|
||||
manual_content_scan_set_menu_system_name(
|
||||
next_system_name_type, next_system_name);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(system_name_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manual_content_scan_core_name_left(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
struct string_list *core_name_list =
|
||||
manual_content_scan_get_menu_core_name_list();
|
||||
const char *current_core_name = NULL;
|
||||
enum manual_content_scan_core_type next_core_type =
|
||||
MANUAL_CONTENT_SCAN_CORE_SET;
|
||||
const char *next_core_name = NULL;
|
||||
unsigned current_index = 0;
|
||||
unsigned next_index = 0;
|
||||
unsigned i;
|
||||
|
||||
if (!core_name_list)
|
||||
return -1;
|
||||
|
||||
/* Get currently selected core name */
|
||||
if (manual_content_scan_get_menu_core_name(¤t_core_name))
|
||||
{
|
||||
/* Get index of currently selected core name */
|
||||
for (i = 0; i < core_name_list->size; i++)
|
||||
{
|
||||
const char *core_name = core_name_list->elems[i].data;
|
||||
|
||||
if (string_is_equal(current_core_name, core_name))
|
||||
{
|
||||
current_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement index */
|
||||
if (current_index > 0)
|
||||
next_index = current_index - 1;
|
||||
else if (wraparound && (core_name_list->size > 1))
|
||||
next_index = core_name_list->size - 1;
|
||||
}
|
||||
|
||||
/* Get new core name parameters */
|
||||
if (next_index == (unsigned)MANUAL_CONTENT_SCAN_CORE_DETECT)
|
||||
next_core_type = MANUAL_CONTENT_SCAN_CORE_DETECT;
|
||||
|
||||
next_core_name = core_name_list->elems[next_index].data;
|
||||
|
||||
/* Set core name */
|
||||
manual_content_scan_set_menu_core_name(
|
||||
next_core_type, next_core_name);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(core_name_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int core_setting_left(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
@ -766,6 +877,12 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE:
|
||||
BIND_ACTION_LEFT(cbs, playlist_left_thumbnail_mode_left);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_LEFT(cbs, manual_content_scan_system_name_left);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_LEFT(cbs, manual_content_scan_core_name_left);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -861,6 +978,7 @@ static int menu_cbs_init_bind_left_compare_type(menu_file_list_cbs_t *cbs,
|
||||
case FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT:
|
||||
case FILE_TYPE_DOWNLOAD_URL:
|
||||
case FILE_TYPE_SCAN_DIRECTORY:
|
||||
case FILE_TYPE_MANUAL_SCAN_DIRECTORY:
|
||||
case FILE_TYPE_FONT:
|
||||
case MENU_SETTING_GROUP:
|
||||
case MENU_SETTINGS_CORE_INFO_NONE:
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include "../../lakka.h"
|
||||
#include "../../wifi/wifi_driver.h"
|
||||
#include "../../gfx/video_display_server.h"
|
||||
#include "../../manual_content_scan.h"
|
||||
|
||||
#include <net/net_http.h>
|
||||
|
||||
@ -182,6 +183,10 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME;
|
||||
case ACTION_OK_DL_MIXER_STREAM_SETTINGS_LIST:
|
||||
return MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST;
|
||||
case ACTION_OK_DL_ACCOUNTS_LIST:
|
||||
@ -306,6 +311,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
|
||||
return MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_SAVE_LIST;
|
||||
case ACTION_OK_DL_SHADER_PRESET_REMOVE:
|
||||
return MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_REMOVE_LIST;
|
||||
case ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST:
|
||||
return MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -440,6 +447,24 @@ int generic_action_ok_displaylist_push(const char *path,
|
||||
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE;
|
||||
dl_type = DISPLAYLIST_GENERIC;
|
||||
break;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
info.type = type;
|
||||
info.directory_ptr = idx;
|
||||
info_path = path;
|
||||
info_label = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME);
|
||||
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME;
|
||||
dl_type = DISPLAYLIST_GENERIC;
|
||||
break;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
info.type = type;
|
||||
info.directory_ptr = idx;
|
||||
info_path = path;
|
||||
info_label = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME);
|
||||
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME;
|
||||
dl_type = DISPLAYLIST_GENERIC;
|
||||
break;
|
||||
case ACTION_OK_DL_USER_BINDS_LIST:
|
||||
info.type = type;
|
||||
info.directory_ptr = idx;
|
||||
@ -600,6 +625,14 @@ int generic_action_ok_displaylist_push(const char *path,
|
||||
info_label = label;
|
||||
dl_type = DISPLAYLIST_FILE_BROWSER_SCAN_DIR;
|
||||
break;
|
||||
case ACTION_OK_DL_MANUAL_SCAN_DIR_LIST:
|
||||
filebrowser_set_type(FILEBROWSER_MANUAL_SCAN_DIR);
|
||||
info.type = FILE_TYPE_DIRECTORY;
|
||||
info.directory_ptr = idx;
|
||||
info_path = new_path;
|
||||
info_label = label;
|
||||
dl_type = DISPLAYLIST_FILE_BROWSER_SELECT_DIR;
|
||||
break;
|
||||
case ACTION_OK_DL_REMAP_FILE:
|
||||
filebrowser_clear_type();
|
||||
info.type = type;
|
||||
@ -1019,6 +1052,7 @@ int generic_action_ok_displaylist_push(const char *path,
|
||||
case ACTION_OK_DL_SHADER_PRESET_REMOVE:
|
||||
case ACTION_OK_DL_SHADER_PRESET_SAVE:
|
||||
case ACTION_OK_DL_CDROM_INFO_LIST:
|
||||
case ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST:
|
||||
action_ok_dl_lbl(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
|
||||
break;
|
||||
case ACTION_OK_DL_CDROM_INFO_DETAIL_LIST:
|
||||
@ -2989,6 +3023,47 @@ static int action_ok_path_scan_directory(const char *path,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int action_ok_path_manual_scan_directory(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
const char *flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST);
|
||||
unsigned flush_type = 0;
|
||||
const char *menu_path = NULL;
|
||||
char content_dir[PATH_MAX_LENGTH];
|
||||
|
||||
content_dir[0] = '\0';
|
||||
|
||||
/* 'Reset' file browser */
|
||||
filebrowser_clear_type();
|
||||
|
||||
/* Get user-selected scan directory */
|
||||
menu_entries_get_last_stack(&menu_path,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!string_is_empty(menu_path))
|
||||
strlcpy(content_dir, menu_path, sizeof(content_dir));
|
||||
|
||||
#ifdef HAVE_COCOATOUCH
|
||||
{
|
||||
/* For iOS, set the path using realpath because the path name
|
||||
* can start with /private and this ensures the path starts with it.
|
||||
* This will allow the path to be properly substituted when
|
||||
* fill_pathname_expand_special() is called. */
|
||||
char real_content_dir[PATH_MAX_LENGTH] = {0};
|
||||
realpath(content_dir, real_content_dir);
|
||||
strlcpy(content_dir, real_content_dir, sizeof(content_dir));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update manual content scan settings */
|
||||
manual_content_scan_set_menu_content_dir(content_dir);
|
||||
|
||||
/* Return to 'manual content scan' menu */
|
||||
menu_entries_flush_stack(flush_char, flush_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_ok_core_deferred_set(const char *new_core_path,
|
||||
const char *content_label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
@ -4671,6 +4746,7 @@ default_action_ok_func(action_ok_push_load_disc_list, ACTION_OK_DL_LOAD_DISC_LIS
|
||||
default_action_ok_func(action_ok_open_archive, ACTION_OK_DL_OPEN_ARCHIVE)
|
||||
default_action_ok_func(action_ok_rgui_menu_theme_preset, ACTION_OK_DL_RGUI_MENU_THEME_PRESET)
|
||||
default_action_ok_func(action_ok_pl_thumbnails_updater_list, ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST)
|
||||
default_action_ok_func(action_ok_push_manual_content_scan_list, ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST)
|
||||
|
||||
static int action_ok_open_uwp_permission_settings(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
@ -5161,6 +5237,17 @@ int action_ok_push_filebrowser_list_file_select(const char *path,
|
||||
entry_idx, ACTION_OK_DL_FILE_BROWSER_SELECT_DIR);
|
||||
}
|
||||
|
||||
int action_ok_push_manual_content_scan_dir_select(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
filebrowser_clear_type();
|
||||
return generic_action_ok_displaylist_push(path,
|
||||
settings->paths.directory_menu_content, label, type, idx,
|
||||
entry_idx, ACTION_OK_DL_MANUAL_SCAN_DIR_LIST);
|
||||
}
|
||||
|
||||
/* TODO/FIXME */
|
||||
static int action_ok_push_dropdown_setting_core_options_item_special(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
@ -5532,6 +5619,54 @@ static int action_ok_push_dropdown_item_playlist_left_thumbnail_mode(const char
|
||||
return action_cancel_pop_default(NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static int action_ok_push_dropdown_item_manual_content_scan_system_name(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
const char* system_name = path;
|
||||
enum manual_content_scan_system_name_type system_name_type =
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE;
|
||||
|
||||
(void)label;
|
||||
(void)type;
|
||||
(void)entry_idx;
|
||||
|
||||
/* Get system name type (i.e. check if setting is
|
||||
* 'use content directory' or 'use custom') */
|
||||
if (idx == (size_t)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR)
|
||||
system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR;
|
||||
else if (idx == (size_t)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM)
|
||||
system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM;
|
||||
|
||||
/* Set system name */
|
||||
manual_content_scan_set_menu_system_name(
|
||||
system_name_type, system_name);
|
||||
|
||||
return action_cancel_pop_default(NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static int action_ok_push_dropdown_item_manual_content_scan_core_name(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
const char* core_name = path;
|
||||
enum manual_content_scan_core_type core_type =
|
||||
MANUAL_CONTENT_SCAN_CORE_SET;
|
||||
|
||||
(void)label;
|
||||
(void)type;
|
||||
(void)entry_idx;
|
||||
|
||||
/* Get core type (i.e. check if setting is
|
||||
* DETECT/Unspecified) */
|
||||
if (idx == (size_t)MANUAL_CONTENT_SCAN_CORE_DETECT)
|
||||
core_type = MANUAL_CONTENT_SCAN_CORE_DETECT;
|
||||
|
||||
/* Set core name */
|
||||
manual_content_scan_set_menu_core_name(
|
||||
core_type, core_name);
|
||||
|
||||
return action_cancel_pop_default(NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static int action_ok_push_default(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
@ -5750,6 +5885,33 @@ static int action_ok_playlist_left_thumbnail_mode(const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_ok_manual_content_scan_system_name(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
generic_action_ok_displaylist_push(
|
||||
NULL,
|
||||
NULL, NULL, 0, idx, 0,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_ok_manual_content_scan_core_name(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
generic_action_ok_displaylist_push(
|
||||
NULL,
|
||||
NULL, NULL, 0, idx, 0,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_ok_manual_content_scan_start(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
task_push_manual_content_scan();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_ok_netplay_enable_host(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
@ -6698,6 +6860,21 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_ACHIEVEMENT_RESUME:
|
||||
BIND_ACTION_OK(cbs, action_ok_cheevos_toggle_hardcore_mode);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_manual_content_scan_list);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_manual_content_scan_dir_select);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_manual_content_scan_core_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START:
|
||||
BIND_ACTION_OK(cbs, action_ok_manual_content_scan_start);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -6826,6 +7003,12 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
|
||||
case MENU_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE:
|
||||
BIND_ACTION_OK(cbs, action_ok_playlist_left_thumbnail_mode);
|
||||
break;
|
||||
case MENU_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_manual_content_scan_core_name);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -6958,6 +7141,12 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
|
||||
case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LEFT_THUMBNAIL_MODE:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_left_thumbnail_mode);
|
||||
break;
|
||||
case MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_manual_content_scan_core_name);
|
||||
break;
|
||||
case MENU_SETTING_ACTION_CORE_DISK_OPTIONS:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_default);
|
||||
break;
|
||||
@ -7043,6 +7232,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_OK(cbs, action_ok_path_scan_directory);
|
||||
break;
|
||||
#endif
|
||||
case FILE_TYPE_MANUAL_SCAN_DIRECTORY:
|
||||
BIND_ACTION_OK(cbs, action_ok_path_manual_scan_directory);
|
||||
break;
|
||||
case FILE_TYPE_CONFIG:
|
||||
BIND_ACTION_OK(cbs, action_ok_config_load);
|
||||
break;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "../../ui/ui_companion_driver.h"
|
||||
#include "../../network/netplay/netplay.h"
|
||||
#include "../../playlist.h"
|
||||
#include "../../manual_content_scan.h"
|
||||
|
||||
#ifndef BIND_ACTION_RIGHT
|
||||
#define BIND_ACTION_RIGHT(cbs, name) \
|
||||
@ -628,6 +629,134 @@ static int playlist_left_thumbnail_mode_right(unsigned type, const char *label,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manual_content_scan_system_name_right(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
struct string_list *system_name_list =
|
||||
manual_content_scan_get_menu_system_name_list();
|
||||
const char *current_system_name = NULL;
|
||||
enum manual_content_scan_system_name_type next_system_name_type =
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE;
|
||||
const char *next_system_name = NULL;
|
||||
unsigned current_index = 0;
|
||||
unsigned next_index = 0;
|
||||
unsigned i;
|
||||
|
||||
if (!system_name_list)
|
||||
return -1;
|
||||
|
||||
/* Get currently selected system name */
|
||||
if (manual_content_scan_get_menu_system_name(¤t_system_name))
|
||||
{
|
||||
/* Get index of currently selected system name */
|
||||
for (i = 0; i < system_name_list->size; i++)
|
||||
{
|
||||
const char *system_name = system_name_list->elems[i].data;
|
||||
|
||||
if (string_is_equal(current_system_name, system_name))
|
||||
{
|
||||
current_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment index */
|
||||
next_index = current_index + 1;
|
||||
if (next_index >= system_name_list->size)
|
||||
{
|
||||
if (wraparound)
|
||||
next_index = 0;
|
||||
else
|
||||
{
|
||||
if (system_name_list->size > 0)
|
||||
next_index = system_name_list->size - 1;
|
||||
else
|
||||
next_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get new system name parameters */
|
||||
if (next_index == (unsigned)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR)
|
||||
next_system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR;
|
||||
else if (next_index == (unsigned)MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM)
|
||||
next_system_name_type = MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM;
|
||||
|
||||
next_system_name = system_name_list->elems[next_index].data;
|
||||
|
||||
/* Set system name */
|
||||
manual_content_scan_set_menu_system_name(
|
||||
next_system_name_type, next_system_name);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(system_name_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manual_content_scan_core_name_right(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
struct string_list *core_name_list =
|
||||
manual_content_scan_get_menu_core_name_list();
|
||||
const char *current_core_name = NULL;
|
||||
enum manual_content_scan_core_type next_core_type =
|
||||
MANUAL_CONTENT_SCAN_CORE_SET;
|
||||
const char *next_core_name = NULL;
|
||||
unsigned current_index = 0;
|
||||
unsigned next_index = 0;
|
||||
unsigned i;
|
||||
|
||||
if (!core_name_list)
|
||||
return -1;
|
||||
|
||||
/* Get currently selected core name */
|
||||
if (manual_content_scan_get_menu_core_name(¤t_core_name))
|
||||
{
|
||||
/* Get index of currently selected core name */
|
||||
for (i = 0; i < core_name_list->size; i++)
|
||||
{
|
||||
const char *core_name = core_name_list->elems[i].data;
|
||||
|
||||
if (string_is_equal(current_core_name, core_name))
|
||||
{
|
||||
current_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment index */
|
||||
next_index = current_index + 1;
|
||||
if (next_index >= core_name_list->size)
|
||||
{
|
||||
if (wraparound)
|
||||
next_index = 0;
|
||||
else
|
||||
{
|
||||
if (core_name_list->size > 0)
|
||||
next_index = core_name_list->size - 1;
|
||||
else
|
||||
next_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get new core name parameters */
|
||||
if (next_index == (unsigned)MANUAL_CONTENT_SCAN_CORE_DETECT)
|
||||
next_core_type = MANUAL_CONTENT_SCAN_CORE_DETECT;
|
||||
|
||||
next_core_name = core_name_list->elems[next_index].data;
|
||||
|
||||
/* Set core name */
|
||||
manual_content_scan_set_menu_core_name(
|
||||
next_core_type, next_core_name);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(core_name_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int core_setting_right(unsigned type, const char *label,
|
||||
bool wraparound)
|
||||
{
|
||||
@ -735,6 +864,7 @@ static int menu_cbs_init_bind_right_compare_type(menu_file_list_cbs_t *cbs,
|
||||
case FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT:
|
||||
case FILE_TYPE_DOWNLOAD_URL:
|
||||
case FILE_TYPE_SCAN_DIRECTORY:
|
||||
case FILE_TYPE_MANUAL_SCAN_DIRECTORY:
|
||||
case FILE_TYPE_FONT:
|
||||
case MENU_SETTING_GROUP:
|
||||
case MENU_SETTINGS_CORE_INFO_NONE:
|
||||
@ -915,6 +1045,12 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE:
|
||||
BIND_ACTION_RIGHT(cbs, playlist_left_thumbnail_mode_right);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_RIGHT(cbs, manual_content_scan_system_name_right);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_RIGHT(cbs, manual_content_scan_core_name_right);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "../../retroarch.h"
|
||||
#include "../../performance_counters.h"
|
||||
#include "../../playlist.h"
|
||||
#include "../../manual_content_scan.h"
|
||||
|
||||
#include "../../input/input_remapping.h"
|
||||
|
||||
@ -302,6 +303,29 @@ static int action_start_playlist_left_thumbnail_mode(unsigned type, const char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_start_manual_content_scan_dir(unsigned type, const char *label)
|
||||
{
|
||||
/* Reset content directory */
|
||||
manual_content_scan_set_menu_content_dir("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_start_manual_content_scan_system_name(unsigned type, const char *label)
|
||||
{
|
||||
/* Reset system name */
|
||||
manual_content_scan_set_menu_system_name(
|
||||
MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_start_manual_content_scan_core_name(unsigned type, const char *label)
|
||||
{
|
||||
/* Reset core name */
|
||||
manual_content_scan_set_menu_core_name(
|
||||
MANUAL_CONTENT_SCAN_CORE_DETECT, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_start_video_resolution(unsigned type, const char *label)
|
||||
{
|
||||
unsigned width = 0, height = 0;
|
||||
@ -405,6 +429,15 @@ static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs)
|
||||
case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE:
|
||||
BIND_ACTION_START(cbs, action_start_playlist_left_thumbnail_mode);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_START(cbs, action_start_manual_content_scan_dir);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_START(cbs, action_start_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_START(cbs, action_start_manual_content_scan_core_name);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -714,6 +714,14 @@ default_sublabel_macro(action_bind_sublabel_thumbnails_updater_list,
|
||||
default_sublabel_macro(action_bind_sublabel_pl_thumbnails_updater_list, MENU_ENUM_SUBLABEL_PL_THUMBNAILS_UPDATER_LIST)
|
||||
default_sublabel_macro(action_bind_sublabel_help_send_debug_info, MENU_ENUM_SUBLABEL_HELP_SEND_DEBUG_INFO)
|
||||
default_sublabel_macro(action_bind_sublabel_rdb_entry_detail, MENU_ENUM_SUBLABEL_RDB_ENTRY_DETAIL)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_list, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_LIST)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_dir, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_DIR)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_system_name, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_system_name_custom, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_core_name, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_CORE_NAME)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_file_exts, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_FILE_EXTS)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_overwrite, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_OVERWRITE)
|
||||
default_sublabel_macro(action_bind_sublabel_manual_content_scan_start, MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_START)
|
||||
|
||||
static int action_bind_sublabel_systeminfo_controller_entry(
|
||||
file_list_t *list,
|
||||
@ -3049,6 +3057,30 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_RDB_ENTRY_DETAIL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_rdb_entry_detail);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_list);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_dir);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_system_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_system_name_custom);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_core_name);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_file_exts);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_OVERWRITE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_overwrite);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_manual_content_scan_start);
|
||||
break;
|
||||
default:
|
||||
case MSG_UNKNOWN:
|
||||
return -1;
|
||||
|
@ -65,6 +65,8 @@ static int action_get_title_action_generic(const char *path, const char *label,
|
||||
const char *title = msg_hash_to_str(lbl); \
|
||||
if (!string_is_empty(path) && !string_is_empty(title)) \
|
||||
fill_pathname_join_delim(s, title, path, ' ', len); \
|
||||
else if (!string_is_empty(title)) \
|
||||
strlcpy(s, title, len); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
@ -396,10 +398,12 @@ default_title_macro(action_get_title_goto_music, MENU_ENUM_LABEL_
|
||||
default_title_macro(action_get_title_goto_video, MENU_ENUM_LABEL_VALUE_GOTO_VIDEO)
|
||||
default_title_macro(action_get_title_collection, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB)
|
||||
default_title_macro(action_get_title_deferred_core_list, MENU_ENUM_LABEL_VALUE_SUPPORTED_CORES)
|
||||
|
||||
default_title_macro(action_get_title_dropdown_resolution_item, MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION)
|
||||
default_title_macro(action_get_title_dropdown_playlist_default_core_item, MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_DEFAULT_CORE)
|
||||
default_title_macro(action_get_title_dropdown_playlist_label_display_mode_item, MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE)
|
||||
default_title_macro(action_get_title_manual_content_scan_list, MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST)
|
||||
default_title_macro(action_get_title_dropdown_manual_content_scan_system_name_item, MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME)
|
||||
default_title_macro(action_get_title_dropdown_manual_content_scan_core_name_item, MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME)
|
||||
|
||||
default_fill_title_macro(action_get_title_disk_image_append, MENU_ENUM_LABEL_VALUE_DISK_IMAGE_APPEND)
|
||||
default_fill_title_macro(action_get_title_cheat_file_load, MENU_ENUM_LABEL_VALUE_CHEAT_FILE)
|
||||
@ -444,6 +448,7 @@ default_fill_title_macro(action_get_title_extraction_directory, MENU_ENUM_LABE
|
||||
default_fill_title_macro(action_get_title_menu, MENU_ENUM_LABEL_VALUE_MENU_SETTINGS)
|
||||
default_fill_title_macro(action_get_title_font_path, MENU_ENUM_LABEL_VALUE_XMB_FONT)
|
||||
default_fill_title_macro(action_get_title_log_dir, MENU_ENUM_LABEL_VALUE_LOG_DIR)
|
||||
default_fill_title_macro(action_get_title_manual_content_scan_dir, MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_DIR)
|
||||
|
||||
default_title_copy_macro(action_get_title_help, MENU_ENUM_LABEL_VALUE_HELP_LIST)
|
||||
default_title_copy_macro(action_get_title_input_settings, MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS)
|
||||
@ -1226,6 +1231,12 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_switch_backlight_control);
|
||||
break;
|
||||
#endif
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_manual_content_scan_list);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_manual_content_scan_dir);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -1363,6 +1374,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
|
||||
case MENU_LABEL_CORE_ASSETS_DIRECTORY:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_core_assets_directory);
|
||||
break;
|
||||
case MENU_LABEL_THUMBNAILS_DIRECTORY:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_thumbnail_directory);
|
||||
break;
|
||||
case MENU_LABEL_RGUI_CONFIG_DIRECTORY:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_config_directory);
|
||||
break;
|
||||
@ -1543,6 +1557,12 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_switch_backlight_control);
|
||||
break;
|
||||
#endif
|
||||
case MENU_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_manual_content_scan_list);
|
||||
break;
|
||||
case MENU_LABEL_MANUAL_CONTENT_SCAN_DIR:
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_manual_content_scan_dir);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -1651,6 +1671,18 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_dropdown_playlist_left_thumbnail_mode_item);
|
||||
return 0;
|
||||
}
|
||||
if (string_is_equal(label,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME)))
|
||||
{
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_dropdown_manual_content_scan_system_name_item);
|
||||
return 0;
|
||||
}
|
||||
if (string_is_equal(label,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME)))
|
||||
{
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_dropdown_manual_content_scan_core_name_item);
|
||||
return 0;
|
||||
}
|
||||
if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)))
|
||||
{
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_quick_menu_views_settings_list);
|
||||
@ -1676,6 +1708,11 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_collection);
|
||||
return 0;
|
||||
}
|
||||
if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST)))
|
||||
{
|
||||
BIND_ACTION_GET_TITLE(cbs, action_get_title_manual_content_scan_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -2552,7 +2552,6 @@ enum materialui_entry_value_type materialui_get_entry_value_type(
|
||||
switch (entry_file_type)
|
||||
{
|
||||
case FILE_TYPE_IN_CARCHIVE:
|
||||
case FILE_TYPE_COMPRESSED:
|
||||
case FILE_TYPE_MORE:
|
||||
case FILE_TYPE_CORE:
|
||||
case FILE_TYPE_DIRECT_LOAD:
|
||||
@ -2564,6 +2563,15 @@ enum materialui_entry_value_type materialui_get_entry_value_type(
|
||||
case FILE_TYPE_IMAGE:
|
||||
case FILE_TYPE_MOVIE:
|
||||
break;
|
||||
case FILE_TYPE_COMPRESSED:
|
||||
/* Note that we have to perform a backup check here,
|
||||
* since the 'manual content scan - file extensions'
|
||||
* setting may have a value of 'zip' or '7z' etc, which
|
||||
* means it would otherwise get incorreclty identified as
|
||||
* an achive file... */
|
||||
if (entry_type != FILE_TYPE_CARCHIVE)
|
||||
value_type = MUI_ENTRY_VALUE_TEXT;
|
||||
break;
|
||||
default:
|
||||
value_type = MUI_ENTRY_VALUE_TEXT;
|
||||
break;
|
||||
@ -2693,7 +2701,13 @@ static void materialui_render_menu_entry_default(
|
||||
switch (entry_file_type)
|
||||
{
|
||||
case FILE_TYPE_COMPRESSED:
|
||||
icon_texture = mui->textures.list[MUI_TEXTURE_ARCHIVE];
|
||||
/* Note that we have to perform a backup check here,
|
||||
* since the 'manual content scan - file extensions'
|
||||
* setting may have a value of 'zip' or '7z' etc, which
|
||||
* means it would otherwise get incorreclty identified as
|
||||
* an achive file... */
|
||||
if (entry_type == FILE_TYPE_CARCHIVE)
|
||||
icon_texture = mui->textures.list[MUI_TEXTURE_ARCHIVE];
|
||||
break;
|
||||
case FILE_TYPE_IMAGE:
|
||||
icon_texture = mui->textures.list[MUI_TEXTURE_IMAGE];
|
||||
@ -7613,7 +7627,8 @@ static void materialui_list_insert(
|
||||
node->has_icon = true;
|
||||
}
|
||||
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_DIRECTORY)) ||
|
||||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE))
|
||||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE)) ||
|
||||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST))
|
||||
)
|
||||
{
|
||||
node->icon_texture_index = MUI_TEXTURE_ADD;
|
||||
|
@ -250,6 +250,7 @@ menu_texture_item ozone_entries_icon_get_texture(ozone_handle_t *ozone,
|
||||
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_USER];
|
||||
case MENU_ENUM_LABEL_DIRECTORY_SETTINGS:
|
||||
case MENU_ENUM_LABEL_SCAN_DIRECTORY:
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST:
|
||||
case MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR:
|
||||
case MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR:
|
||||
case MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_PARENT:
|
||||
|
@ -2379,6 +2379,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
|
||||
return xmb->textures.list[XMB_TEXTURE_RESUME];
|
||||
case MENU_ENUM_LABEL_DIRECTORY_SETTINGS:
|
||||
case MENU_ENUM_LABEL_SCAN_DIRECTORY:
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST:
|
||||
case MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR:
|
||||
case MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR:
|
||||
case MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_PARENT:
|
||||
|
@ -52,11 +52,14 @@ enum
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
ACTION_OK_DL_OPEN_ARCHIVE,
|
||||
ACTION_OK_DL_OPEN_ARCHIVE_DETECT_CORE,
|
||||
ACTION_OK_DL_MUSIC,
|
||||
ACTION_OK_DL_NETPLAY,
|
||||
ACTION_OK_DL_SCAN_DIR_LIST,
|
||||
ACTION_OK_DL_MANUAL_SCAN_DIR_LIST,
|
||||
ACTION_OK_DL_HELP,
|
||||
ACTION_OK_DL_RPL_ENTRY,
|
||||
ACTION_OK_DL_RDB_ENTRY,
|
||||
@ -166,7 +169,8 @@ enum
|
||||
ACTION_OK_DL_BROWSE_URL_START,
|
||||
ACTION_OK_DL_CONTENT_SETTINGS,
|
||||
ACTION_OK_DL_CDROM_INFO_DETAIL_LIST,
|
||||
ACTION_OK_DL_RGUI_MENU_THEME_PRESET
|
||||
ACTION_OK_DL_RGUI_MENU_THEME_PRESET,
|
||||
ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST
|
||||
};
|
||||
|
||||
/* Function callbacks */
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include "../tasks/tasks_internal.h"
|
||||
#include "../dynamic.h"
|
||||
#include "../runtime_file.h"
|
||||
#include "../manual_content_scan.h"
|
||||
|
||||
static char new_path_entry[4096] = {0};
|
||||
static char new_lbl_entry[4096] = {0};
|
||||
@ -2334,9 +2335,9 @@ static unsigned menu_displaylist_parse_playlists(
|
||||
|
||||
if (!horizontal)
|
||||
{
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
if (settings->bools.menu_content_show_add)
|
||||
{
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_SCAN_DIRECTORY),
|
||||
@ -2349,8 +2350,15 @@ static unsigned menu_displaylist_parse_playlists(
|
||||
MENU_ENUM_LABEL_SCAN_FILE,
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST,
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
}
|
||||
|
||||
if (settings->bools.menu_content_show_favorites)
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES),
|
||||
@ -3667,6 +3675,64 @@ static unsigned populate_playlist_thumbnail_mode_dropdown_list(
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool menu_displaylist_parse_manual_content_scan_list(
|
||||
menu_displaylist_info_t *info)
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
/* Content directory */
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_DIR),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR,
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_DIR, 0, 0))
|
||||
count++;
|
||||
|
||||
/* System name */
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_SYSTEM_NAME, 0, 0))
|
||||
count++;
|
||||
|
||||
/* Custom system name */
|
||||
if (menu_displaylist_parse_settings_enum(info->list,
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM, PARSE_ONLY_STRING,
|
||||
false) == 0)
|
||||
count++;
|
||||
|
||||
/* Core name */
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_CORE_NAME, 0, 0))
|
||||
count++;
|
||||
|
||||
/* File extensions */
|
||||
if (menu_displaylist_parse_settings_enum(info->list,
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS, PARSE_ONLY_STRING,
|
||||
false) == 0)
|
||||
count++;
|
||||
|
||||
/* Overwrite playlist */
|
||||
if (menu_displaylist_parse_settings_enum(info->list,
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_OVERWRITE, PARSE_ONLY_BOOL,
|
||||
false) == 0)
|
||||
count++;
|
||||
|
||||
/* Start scan */
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_START),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START,
|
||||
MENU_SETTING_ACTION_MANUAL_CONTENT_SCAN_START, 0, 0))
|
||||
count++;
|
||||
|
||||
return (count > 0);
|
||||
}
|
||||
|
||||
unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ctl_state type)
|
||||
{
|
||||
unsigned i;
|
||||
@ -3863,6 +3929,12 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
#endif
|
||||
if (menu_entries_append_enum(list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST,
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
break;
|
||||
case DISPLAYLIST_NETWORK_INFO:
|
||||
#if defined(HAVE_NETWORKING) && !defined(HAVE_SOCKET_LEGACY) && (!defined(SWITCH) || defined(SWITCH) && defined(HAVE_LIBNX))
|
||||
@ -4125,6 +4197,84 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
|
||||
count = populate_playlist_thumbnail_mode_dropdown_list(list, PLAYLIST_THUMBNAIL_LEFT);
|
||||
break;
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
{
|
||||
/* Get system name list */
|
||||
struct string_list *system_name_list = manual_content_scan_get_menu_system_name_list();
|
||||
|
||||
if (system_name_list)
|
||||
{
|
||||
const char *current_system_name = NULL;
|
||||
unsigned i;
|
||||
|
||||
/* Get currently selected system name */
|
||||
manual_content_scan_get_menu_system_name(¤t_system_name);
|
||||
|
||||
/* Loop through names */
|
||||
for (i = 0; i < system_name_list->size; i++)
|
||||
{
|
||||
/* Note: manual_content_scan_get_system_name_list()
|
||||
* ensures that system_name cannot be empty here */
|
||||
const char *system_name = system_name_list->elems[i].data;
|
||||
|
||||
/* Add menu entry */
|
||||
if (menu_entries_append_enum(list,
|
||||
system_name,
|
||||
"",
|
||||
MENU_ENUM_LABEL_NO_ITEMS,
|
||||
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
i, 0))
|
||||
count++;
|
||||
|
||||
/* Check whether current entry is checked */
|
||||
if (string_is_equal(current_system_name, system_name))
|
||||
menu_entries_set_checked(list, i, true);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(system_name_list);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
{
|
||||
/* Get core name list */
|
||||
struct string_list *core_name_list = manual_content_scan_get_menu_core_name_list();
|
||||
|
||||
if (core_name_list)
|
||||
{
|
||||
const char *current_core_name = NULL;
|
||||
unsigned i;
|
||||
|
||||
/* Get currently selected core name */
|
||||
manual_content_scan_get_menu_core_name(¤t_core_name);
|
||||
|
||||
/* Loop through names */
|
||||
for (i = 0; i < core_name_list->size; i++)
|
||||
{
|
||||
/* Note: manual_content_scan_get_core_name_list()
|
||||
* ensures that core_name cannot be empty here */
|
||||
const char *core_name = core_name_list->elems[i].data;
|
||||
|
||||
/* Add menu entry */
|
||||
if (menu_entries_append_enum(list,
|
||||
core_name,
|
||||
"",
|
||||
MENU_ENUM_LABEL_NO_ITEMS,
|
||||
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
i, 0))
|
||||
count++;
|
||||
|
||||
/* Check whether current entry is checked */
|
||||
if (string_is_equal(current_core_name, core_name))
|
||||
menu_entries_set_checked(list, i, true);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(core_name_list);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DISPLAYLIST_PERFCOUNTERS_CORE:
|
||||
case DISPLAYLIST_PERFCOUNTERS_FRONTEND:
|
||||
{
|
||||
@ -7213,6 +7363,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
case DISPLAYLIST_PERFCOUNTERS_CORE:
|
||||
case DISPLAYLIST_PERFCOUNTERS_FRONTEND:
|
||||
case DISPLAYLIST_MENU_SETTINGS_LIST:
|
||||
@ -7238,6 +7390,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
|
||||
case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
|
||||
@ -7701,6 +7855,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
#endif
|
||||
if (menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST,
|
||||
MENU_SETTING_ACTION, 0, 0))
|
||||
count++;
|
||||
|
||||
if (count == 0)
|
||||
menu_entries_append_enum(info->list,
|
||||
@ -8967,6 +9127,18 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
use_filebrowser = true;
|
||||
break;
|
||||
case DISPLAYLIST_MANUAL_CONTENT_SCAN_LIST:
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
|
||||
if (!menu_displaylist_parse_manual_content_scan_list(info))
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
|
||||
MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
|
||||
info->need_push = true;
|
||||
break;
|
||||
case DISPLAYLIST_DROPDOWN_LIST:
|
||||
{
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
|
@ -60,6 +60,8 @@ enum menu_displaylist_ctl_state
|
||||
DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE,
|
||||
DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE,
|
||||
DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE,
|
||||
DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
DISPLAYLIST_CDROM_DETAIL_INFO,
|
||||
DISPLAYLIST_INFO,
|
||||
DISPLAYLIST_HELP,
|
||||
@ -212,6 +214,7 @@ enum menu_displaylist_ctl_state
|
||||
#if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX)
|
||||
DISPLAYLIST_SWITCH_CPU_PROFILE,
|
||||
#endif
|
||||
DISPLAYLIST_MANUAL_CONTENT_SCAN_LIST,
|
||||
DISPLAYLIST_PENDING_CLEAR
|
||||
};
|
||||
|
||||
|
@ -91,6 +91,8 @@ enum menu_settings_type
|
||||
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LABEL_DISPLAY_MODE,
|
||||
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_RIGHT_THUMBNAIL_MODE,
|
||||
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LEFT_THUMBNAIL_MODE,
|
||||
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM,
|
||||
MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM,
|
||||
MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM,
|
||||
@ -206,6 +208,11 @@ enum menu_settings_type
|
||||
MENU_SET_CDROM_INFO,
|
||||
MENU_SETTING_ACTION_DELETE_PLAYLIST,
|
||||
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_DIR,
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
MENU_SETTING_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
MENU_SETTING_ACTION_MANUAL_CONTENT_SCAN_START,
|
||||
|
||||
MENU_SETTINGS_LAST
|
||||
};
|
||||
|
||||
|
@ -95,6 +95,7 @@
|
||||
#include "../managers/cheat_manager.h"
|
||||
#include "../verbosity.h"
|
||||
#include "../playlist.h"
|
||||
#include "../manual_content_scan.h"
|
||||
|
||||
#include "../tasks/tasks_internal.h"
|
||||
|
||||
@ -157,7 +158,8 @@ enum settings_list_type
|
||||
SETTINGS_LIST_USER_ACCOUNTS_TWITCH,
|
||||
SETTINGS_LIST_DIRECTORY,
|
||||
SETTINGS_LIST_PRIVACY,
|
||||
SETTINGS_LIST_MIDI
|
||||
SETTINGS_LIST_MIDI,
|
||||
SETTINGS_LIST_MANUAL_CONTENT_SCAN
|
||||
};
|
||||
|
||||
struct bool_entry
|
||||
@ -6679,6 +6681,17 @@ void general_write_handler(rarch_setting_t *setting)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM:
|
||||
/* Ensure that custom system name includes no
|
||||
* invalid characters */
|
||||
manual_content_scan_scrub_system_name_custom();
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS:
|
||||
/* Ensure that custom file extension list includes
|
||||
* no period (full stop) characters, and converts
|
||||
* string to lower case */
|
||||
manual_content_scan_scrub_file_exts_custom();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -16430,6 +16443,63 @@ static bool setting_append_list(
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
menu_settings_list_current_add_range(list, list_info, 0.0f, 100.0f, 1.0f, true, true);
|
||||
|
||||
END_SUB_GROUP(list, list_info, parent_group);
|
||||
END_GROUP(list, list_info, parent_group);
|
||||
break;
|
||||
case SETTINGS_LIST_MANUAL_CONTENT_SCAN:
|
||||
START_GROUP(list, list_info, &group_info,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST), parent_group);
|
||||
|
||||
parent_group = msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST);
|
||||
|
||||
START_SUB_GROUP(list, list_info, "State",
|
||||
&group_info, &subgroup_info, parent_group);
|
||||
|
||||
CONFIG_STRING(
|
||||
list, list_info,
|
||||
manual_content_scan_get_system_name_custom_ptr(),
|
||||
manual_content_scan_get_system_name_custom_size(),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM,
|
||||
"",
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT);
|
||||
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_STRING_LINE_EDIT;
|
||||
|
||||
CONFIG_STRING(
|
||||
list, list_info,
|
||||
manual_content_scan_get_file_exts_custom_ptr(),
|
||||
manual_content_scan_get_file_exts_custom_size(),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS,
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_FILE_EXTS,
|
||||
"",
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT);
|
||||
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_STRING_LINE_EDIT;
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
manual_content_scan_get_overwrite_playlist_ptr(),
|
||||
MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_OVERWRITE,
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_OVERWRITE,
|
||||
false,
|
||||
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);
|
||||
break;
|
||||
@ -16566,7 +16636,8 @@ static rarch_setting_t *menu_setting_new_internal(rarch_setting_info_t *list_inf
|
||||
SETTINGS_LIST_USER_ACCOUNTS_TWITCH,
|
||||
SETTINGS_LIST_DIRECTORY,
|
||||
SETTINGS_LIST_PRIVACY,
|
||||
SETTINGS_LIST_MIDI
|
||||
SETTINGS_LIST_MIDI,
|
||||
SETTINGS_LIST_MANUAL_CONTENT_SCAN
|
||||
};
|
||||
const char *root = msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU);
|
||||
rarch_setting_t *list = (rarch_setting_t*)calloc(
|
||||
|
@ -127,6 +127,14 @@ void filebrowser_parse(menu_displaylist_info_t *info, unsigned type_data)
|
||||
FILE_TYPE_SCAN_DIRECTORY, 0 ,0);
|
||||
#endif
|
||||
break;
|
||||
case FILEBROWSER_MANUAL_SCAN_DIR:
|
||||
if (info)
|
||||
menu_entries_prepend(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY),
|
||||
MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY,
|
||||
FILE_TYPE_MANUAL_SCAN_DIRECTORY, 0 ,0);
|
||||
break;
|
||||
case FILEBROWSER_SELECT_DIR:
|
||||
if (info)
|
||||
menu_entries_prepend(info->list,
|
||||
@ -212,6 +220,8 @@ void filebrowser_parse(menu_displaylist_info_t *info, unsigned type_data)
|
||||
continue;
|
||||
if (filebrowser_types == FILEBROWSER_SCAN_DIR)
|
||||
continue;
|
||||
if (filebrowser_types == FILEBROWSER_MANUAL_SCAN_DIR)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Need to preserve slash first time. */
|
||||
|
@ -32,6 +32,7 @@ enum filebrowser_enums
|
||||
FILEBROWSER_SELECT_DIR,
|
||||
FILEBROWSER_SCAN_DIR,
|
||||
FILEBROWSER_SCAN_FILE,
|
||||
FILEBROWSER_MANUAL_SCAN_DIR,
|
||||
FILEBROWSER_SELECT_FILE,
|
||||
FILEBROWSER_SELECT_FILE_SUBSYSTEM,
|
||||
FILEBROWSER_SELECT_IMAGE,
|
||||
|
32
msg_hash.h
32
msg_hash.h
@ -151,6 +151,8 @@ enum msg_file_type
|
||||
* menu_cbs_init_bind_get_string_representation_compare_type() breaks... */
|
||||
FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT,
|
||||
|
||||
FILE_TYPE_MANUAL_SCAN_DIRECTORY,
|
||||
|
||||
FILE_TYPE_LAST
|
||||
};
|
||||
|
||||
@ -1245,6 +1247,8 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME,
|
||||
MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST,
|
||||
MENU_ENUM_LABEL_DEFERRED_CONFIGURATIONS_LIST,
|
||||
MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST,
|
||||
@ -1343,6 +1347,7 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_YOUTUBE_LIST,
|
||||
MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_LIST,
|
||||
MENU_ENUM_LABEL_DEFERRED_INFORMATION,
|
||||
MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST,
|
||||
|
||||
MENU_LABEL(FILE_DETECT_CORE_LIST_PUSH_DIR),
|
||||
MENU_LABEL(DOWNLOADED_FILE_DETECT_CORE_LIST),
|
||||
@ -2658,6 +2663,27 @@ enum msg_hash_enums
|
||||
MSG_NO_DISC_INSERTED,
|
||||
MENU_LABEL(DELETE_PLAYLIST),
|
||||
|
||||
/* Manual content scan */
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_LIST),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_DIR),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_SYSTEM_NAME),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_CORE_NAME),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_FILE_EXTS),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_OVERWRITE),
|
||||
MENU_LABEL(MANUAL_CONTENT_SCAN_START),
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CONTENT_DIR,
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME_USE_CUSTOM,
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME_DETECT,
|
||||
|
||||
MSG_MANUAL_CONTENT_SCAN_INVALID_CONFIG,
|
||||
MSG_MANUAL_CONTENT_SCAN_INVALID_CONTENT,
|
||||
MSG_MANUAL_CONTENT_SCAN_START,
|
||||
MSG_MANUAL_CONTENT_SCAN_IN_PROGRESS,
|
||||
MSG_MANUAL_CONTENT_SCAN_END,
|
||||
|
||||
MSG_LAST
|
||||
};
|
||||
|
||||
@ -2715,6 +2741,7 @@ enum msg_hash_enums
|
||||
#define MENU_LABEL_DEFERRED_CONFIGURATIONS_LIST 0x679a1b0bU
|
||||
#define MENU_LABEL_DEFERRED_BROWSE_URL_START 0xcef58296U
|
||||
#define MENU_LABEL_DEFERRED_INFORMATION 0x3FCC9F2BU
|
||||
#define MENU_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST 0x479546DCU
|
||||
|
||||
/* Cheevos settings */
|
||||
|
||||
@ -2910,6 +2937,11 @@ enum msg_hash_enums
|
||||
#define MENU_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD 0x6e66ef07U
|
||||
#define MENU_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING 0xd44d395cU
|
||||
|
||||
/* Manual content scan */
|
||||
#define MENU_LABEL_MANUAL_CONTENT_SCAN_DIR 0x6674149FU
|
||||
#define MENU_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME 0xA3EC34C5U
|
||||
#define MENU_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME 0xD13B7849U
|
||||
|
||||
/* Main menu */
|
||||
#define MENU_LABEL_LOAD_CONTENT_LIST 0x5745de1fU
|
||||
#define MENU_LABEL_LOAD_CONTENT_HISTORY 0xfe1d79e5U
|
||||
|
@ -368,8 +368,7 @@ void playlist_get_index_by_path(playlist_t *playlist,
|
||||
}
|
||||
|
||||
bool playlist_entry_exists(playlist_t *playlist,
|
||||
const char *path,
|
||||
const char *crc32)
|
||||
const char *path)
|
||||
{
|
||||
size_t i;
|
||||
char real_search_path[PATH_MAX_LENGTH];
|
||||
|
@ -214,8 +214,7 @@ void playlist_get_index_by_path(playlist_t *playlist,
|
||||
const struct playlist_entry **entry);
|
||||
|
||||
bool playlist_entry_exists(playlist_t *playlist,
|
||||
const char *path,
|
||||
const char *crc32);
|
||||
const char *path);
|
||||
|
||||
char *playlist_get_conf_path(playlist_t *playlist);
|
||||
|
||||
|
@ -850,7 +850,7 @@ static int database_info_list_iterate_found_match(
|
||||
fprintf(stderr, "entry path str: %s\n", entry_path_str);
|
||||
#endif
|
||||
|
||||
if (!playlist_entry_exists(playlist, entry_path_str, db_crc))
|
||||
if (!playlist_entry_exists(playlist, entry_path_str))
|
||||
{
|
||||
struct playlist_entry entry;
|
||||
|
||||
@ -1052,8 +1052,7 @@ static int task_database_iterate_playlist_lutro(
|
||||
|
||||
free(db_playlist_path);
|
||||
|
||||
if (!playlist_entry_exists(playlist,
|
||||
path, "DETECT"))
|
||||
if (!playlist_entry_exists(playlist, path))
|
||||
{
|
||||
struct playlist_entry entry;
|
||||
char *game_title = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||
|
354
tasks/task_manual_content_scan.c
Normal file
354
tasks/task_manual_content_scan.c
Normal file
@ -0,0 +1,354 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <file/file_path.h>
|
||||
|
||||
#include "tasks_internal.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../msg_hash.h"
|
||||
#include "../playlist.h"
|
||||
#include "../manual_content_scan.h"
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#ifdef HAVE_MENU
|
||||
#include "../menu/menu_driver.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum manual_scan_status
|
||||
{
|
||||
MANUAL_SCAN_BEGIN = 0,
|
||||
MANUAL_SCAN_ITERATE_CONTENT,
|
||||
MANUAL_SCAN_END
|
||||
};
|
||||
|
||||
typedef struct manual_scan_handle
|
||||
{
|
||||
manual_content_scan_task_config_t *task_config;
|
||||
playlist_t *playlist;
|
||||
struct string_list *content_list;
|
||||
size_t list_size;
|
||||
size_t list_index;
|
||||
enum manual_scan_status status;
|
||||
} manual_scan_handle_t;
|
||||
|
||||
/* Frees task handle + all constituent objects */
|
||||
static void free_manual_content_scan_handle(manual_scan_handle_t *manual_scan)
|
||||
{
|
||||
if (!manual_scan)
|
||||
return;
|
||||
|
||||
if (manual_scan->task_config)
|
||||
{
|
||||
free(manual_scan->task_config);
|
||||
manual_scan->task_config = NULL;
|
||||
}
|
||||
|
||||
if (manual_scan->playlist)
|
||||
{
|
||||
playlist_free(manual_scan->playlist);
|
||||
manual_scan->playlist = NULL;
|
||||
}
|
||||
|
||||
if (manual_scan->content_list)
|
||||
{
|
||||
string_list_free(manual_scan->content_list);
|
||||
manual_scan->content_list = NULL;
|
||||
}
|
||||
|
||||
free(manual_scan);
|
||||
manual_scan = NULL;
|
||||
}
|
||||
|
||||
static void task_manual_content_scan_handler(retro_task_t *task)
|
||||
{
|
||||
manual_scan_handle_t *manual_scan = NULL;
|
||||
|
||||
if (!task)
|
||||
goto task_finished;
|
||||
|
||||
manual_scan = (manual_scan_handle_t*)task->state;
|
||||
|
||||
if (!manual_scan)
|
||||
goto task_finished;
|
||||
|
||||
if (task_get_cancelled(task))
|
||||
goto task_finished;
|
||||
|
||||
switch (manual_scan->status)
|
||||
{
|
||||
case MANUAL_SCAN_BEGIN:
|
||||
{
|
||||
/* Get content list */
|
||||
manual_scan->content_list = manual_content_scan_get_content_list(
|
||||
manual_scan->task_config);
|
||||
|
||||
if (!manual_scan->content_list)
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_INVALID_CONTENT),
|
||||
1, 100, true,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
goto task_finished;
|
||||
}
|
||||
|
||||
manual_scan->list_size = manual_scan->content_list->size;
|
||||
|
||||
/* Open playlist */
|
||||
manual_scan->playlist = playlist_init(
|
||||
manual_scan->task_config->playlist_file, COLLECTION_SIZE);
|
||||
|
||||
if (!manual_scan->playlist)
|
||||
goto task_finished;
|
||||
|
||||
/* Reset playlist, if required */
|
||||
if (manual_scan->task_config->overwrite_playlist)
|
||||
playlist_clear(manual_scan->playlist);
|
||||
|
||||
/* Set default core, if required */
|
||||
if (manual_scan->task_config->core_set)
|
||||
{
|
||||
playlist_set_default_core_path(
|
||||
manual_scan->playlist, manual_scan->task_config->core_path);
|
||||
playlist_set_default_core_name(
|
||||
manual_scan->playlist, manual_scan->task_config->core_name);
|
||||
}
|
||||
|
||||
/* All good - can start iterating */
|
||||
manual_scan->status = MANUAL_SCAN_ITERATE_CONTENT;
|
||||
}
|
||||
break;
|
||||
case MANUAL_SCAN_ITERATE_CONTENT:
|
||||
{
|
||||
const char *content_path =
|
||||
manual_scan->content_list->elems[manual_scan->list_index].data;
|
||||
|
||||
if (!string_is_empty(content_path))
|
||||
{
|
||||
const char *content_file = path_basename(content_path);
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Update progress display */
|
||||
task_free_title(task);
|
||||
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_IN_PROGRESS),
|
||||
sizeof(task_title));
|
||||
|
||||
if (!string_is_empty(content_file))
|
||||
strlcat(task_title, content_file, sizeof(task_title));
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
task_set_progress(task, (manual_scan->list_index * 100) / manual_scan->list_size);
|
||||
|
||||
/* Add content to playlist */
|
||||
manual_content_scan_add_content_to_playlist(
|
||||
manual_scan->task_config, manual_scan->playlist,
|
||||
content_path);
|
||||
}
|
||||
|
||||
/* Increment content index */
|
||||
manual_scan->list_index++;
|
||||
if (manual_scan->list_index >= manual_scan->list_size)
|
||||
manual_scan->status = MANUAL_SCAN_END;
|
||||
}
|
||||
break;
|
||||
case MANUAL_SCAN_END:
|
||||
{
|
||||
playlist_t *cached_playlist = playlist_get_cached();
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Ensure playlist is alphabetically sorted */
|
||||
playlist_qsort(manual_scan->playlist);
|
||||
|
||||
/* Save playlist changes to disk */
|
||||
playlist_write_file(manual_scan->playlist);
|
||||
|
||||
/* If this is the currently cached playlist, then
|
||||
* it must be re-cached (otherwise changes will be
|
||||
* lost if the currently cached playlist is saved
|
||||
* to disk for any reason...) */
|
||||
if (cached_playlist)
|
||||
{
|
||||
if (string_is_equal(
|
||||
manual_scan->task_config->playlist_file,
|
||||
playlist_get_conf_path(cached_playlist)))
|
||||
{
|
||||
playlist_free_cached();
|
||||
playlist_init_cached(
|
||||
manual_scan->task_config->playlist_file, COLLECTION_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update progress display */
|
||||
task_free_title(task);
|
||||
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_END),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, manual_scan->task_config->system_name,
|
||||
sizeof(task_title));
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
}
|
||||
/* fall-through */
|
||||
default:
|
||||
task_set_progress(task, 100);
|
||||
goto task_finished;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
task_finished:
|
||||
|
||||
if (task)
|
||||
task_set_finished(task, true);
|
||||
|
||||
free_manual_content_scan_handle(manual_scan);
|
||||
}
|
||||
|
||||
static bool task_manual_content_scan_finder(retro_task_t *task, void *user_data)
|
||||
{
|
||||
manual_scan_handle_t *manual_scan = NULL;
|
||||
|
||||
if (!task || !user_data)
|
||||
return false;
|
||||
|
||||
if (task->handler != task_manual_content_scan_handler)
|
||||
return false;
|
||||
|
||||
manual_scan = (manual_scan_handle_t*)task->state;
|
||||
if (!manual_scan)
|
||||
return false;
|
||||
|
||||
return string_is_equal(
|
||||
(const char*)user_data, manual_scan->task_config->playlist_file);
|
||||
}
|
||||
|
||||
static void cb_task_manual_content_scan_refresh_menu(
|
||||
retro_task_t *task, void *task_data,
|
||||
void *user_data, const char *err)
|
||||
{
|
||||
#if defined(RARCH_INTERNAL) && defined(HAVE_MENU)
|
||||
menu_ctx_environment_t menu_environ;
|
||||
menu_environ.type = MENU_ENVIRON_RESET_HORIZONTAL_LIST;
|
||||
menu_environ.data = NULL;
|
||||
|
||||
menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool task_push_manual_content_scan(void)
|
||||
{
|
||||
task_finder_data_t find_data;
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
retro_task_t *task = NULL;
|
||||
manual_scan_handle_t *manual_scan = (manual_scan_handle_t*)
|
||||
calloc(1, sizeof(manual_scan_handle_t));
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Sanity check */
|
||||
if (!manual_scan)
|
||||
goto error;
|
||||
|
||||
/* Configure handle */
|
||||
manual_scan->task_config = NULL;
|
||||
manual_scan->playlist = NULL;
|
||||
manual_scan->content_list = NULL;
|
||||
manual_scan->list_size = 0;
|
||||
manual_scan->list_index = 0;
|
||||
manual_scan->status = MANUAL_SCAN_BEGIN;
|
||||
|
||||
/* > Get current manual content scan configuration */
|
||||
manual_scan->task_config = (manual_content_scan_task_config_t*)
|
||||
calloc(1, sizeof(manual_content_scan_task_config_t));
|
||||
|
||||
if (!manual_scan->task_config)
|
||||
goto error;
|
||||
|
||||
if (!manual_content_scan_get_task_config(manual_scan->task_config))
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_INVALID_CONFIG),
|
||||
1, 100, true,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Concurrent scanning of content to the same
|
||||
* playlist is not allowed */
|
||||
find_data.func = task_manual_content_scan_finder;
|
||||
find_data.userdata = (void*)manual_scan->task_config->playlist_file;
|
||||
|
||||
if (task_queue_find(&find_data))
|
||||
goto error;
|
||||
|
||||
/* Create task */
|
||||
task = task_init();
|
||||
|
||||
if (!task)
|
||||
goto error;
|
||||
|
||||
/* > Get task title */
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_START),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, manual_scan->task_config->system_name,
|
||||
sizeof(task_title));
|
||||
|
||||
/* > Configure task */
|
||||
task->handler = task_manual_content_scan_handler;
|
||||
task->state = manual_scan;
|
||||
task->title = strdup(task_title);
|
||||
task->alternative_look = true;
|
||||
task->progress = 0;
|
||||
task->callback = cb_task_manual_content_scan_refresh_menu;
|
||||
|
||||
/* > Push task */
|
||||
task_queue_push(task);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
||||
/* Clean up task */
|
||||
if (task)
|
||||
{
|
||||
free(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
/* Clean up handle */
|
||||
free_manual_content_scan_handle(manual_scan);
|
||||
manual_scan = NULL;
|
||||
|
||||
return false;
|
||||
}
|
@ -98,6 +98,8 @@ bool task_push_dbscan(
|
||||
retro_task_callback_t cb);
|
||||
#endif
|
||||
|
||||
bool task_push_manual_content_scan(void);
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
bool task_push_overlay_load_default(
|
||||
retro_task_callback_t cb,
|
||||
|
Loading…
x
Reference in New Issue
Block a user