Add content import/scan via CLI

This commit is contained in:
sonninnos 2023-05-03 01:54:03 +03:00 committed by LibretroAdmin
parent 15e04b8767
commit f5f1d35370
3 changed files with 115 additions and 28 deletions

View File

@ -1294,8 +1294,9 @@ bool gfx_display_init_first_driver(gfx_display_t *p_disp,
video_is_threaded)) video_is_threaded))
continue; continue;
RARCH_LOG("[Display]: Found display driver: \"%s\".\n", if (video_driver)
gfx_display_ctx_drivers[i]->ident); RARCH_LOG("[Display]: Found display driver: \"%s\".\n",
gfx_display_ctx_drivers[i]->ident);
p_disp->dispctx = gfx_display_ctx_drivers[i]; p_disp->dispctx = gfx_display_ctx_drivers[i];
return true; return true;
} }

View File

@ -286,6 +286,7 @@ enum
RA_OPT_MAX_FRAMES_SCREENSHOT, RA_OPT_MAX_FRAMES_SCREENSHOT,
RA_OPT_MAX_FRAMES_SCREENSHOT_PATH, RA_OPT_MAX_FRAMES_SCREENSHOT_PATH,
RA_OPT_SET_SHADER, RA_OPT_SET_SHADER,
RA_OPT_DATABASE_SCAN,
RA_OPT_ACCESSIBILITY, RA_OPT_ACCESSIBILITY,
RA_OPT_LOAD_MENU_ON_ERROR RA_OPT_LOAD_MENU_ON_ERROR
}; };
@ -4932,8 +4933,7 @@ static void retroarch_print_help(const char *arg0)
"Show version.\n" "Show version.\n"
" --features " " --features "
"Print available features compiled into program.\n" "Print available features compiled into program.\n"
, , sizeof(buf));
sizeof(buf));
#ifdef HAVE_MENU #ifdef HAVE_MENU
strlcat(buf, strlcat(buf,
" --menu " " --menu "
@ -4942,8 +4942,7 @@ static void retroarch_print_help(const char *arg0)
" starts directly in menu. If no arguments are passed to\n" " starts directly in menu. If no arguments are passed to\n"
" " " "
" the program, it is equivalent to using --menu as only argument.\n" " the program, it is equivalent to using --menu as only argument.\n"
, , sizeof(buf));
sizeof(buf));
#endif #endif
#ifdef HAVE_CONFIGFILE #ifdef HAVE_CONFIGFILE
@ -5011,14 +5010,24 @@ static void retroarch_print_help(const char *arg0)
" files are loaded as multiple arguments. If a content\n" " files are loaded as multiple arguments. If a content\n"
" " " "
" file is skipped, use a blank (\"\") command line argument.\n" " file is skipped, use a blank (\"\") command line argument.\n"
, sizeof(buf));
strlcat(buf,
" " " "
" Content must be loaded in an order which depends on the\n" " Content must be loaded in an order which depends on the\n"
" " " "
" particular subsystem used. See verbose log output to learn\n" " particular subsystem used. See verbose log output to learn\n"
" " " "
, sizeof(buf));
strlcat(buf,
" how a particular subsystem wants content to be loaded.\n" " how a particular subsystem wants content to be loaded.\n"
, sizeof(buf));
#ifdef HAVE_LIBRETRODB
strlcat(buf,
" --scan=PATH|FILE "
"Import content from path.\n"
, sizeof(buf));
#endif
strlcat(buf,
" -f, --fullscreen " " -f, --fullscreen "
"Start the program in fullscreen regardless of config setting.\n" "Start the program in fullscreen regardless of config setting.\n"
" --set-shader=PATH " " --set-shader=PATH "
@ -5063,7 +5072,8 @@ static void retroarch_print_help(const char *arg0)
"Check frames when using netplay.\n" "Check frames when using netplay.\n"
, sizeof(buf)); , sizeof(buf));
#ifdef HAVE_NETWORK_CMD #ifdef HAVE_NETWORK_CMD
strlcat(buf, " --command " strlcat(buf,
" --command "
"Sends a command over UDP to an already running program process.\n" "Sends a command over UDP to an already running program process.\n"
" " " "
" Available commands are listed if command is invalid.\n" " Available commands are listed if command is invalid.\n"
@ -5082,24 +5092,27 @@ static void retroarch_print_help(const char *arg0)
, sizeof(buf)); , sizeof(buf));
#endif #endif
strlcat(buf, " -r, --record=FILE " strlcat(buf,
" -r, --record=FILE "
"Path to record video file. Using mkv extension is recommended.\n" "Path to record video file. Using mkv extension is recommended.\n"
" --recordconfig " " --recordconfig "
"Path to settings used during recording.\n" "Path to settings used during recording.\n"
" --size=WIDTHxHEIGHT " " --size=WIDTHxHEIGHT "
"Overrides output video size when recording.\n" "Overrides output video size when recording.\n"
, , sizeof(buf));
sizeof(buf));
fputs(buf, stdout); fputs(buf, stdout);
buf[0] = '\0'; buf[0] = '\0';
strlcat(buf, " -D, --detach " strlcat(buf,
" -D, --detach "
"Detach program from the running console. Not relevant for all platforms.\n" "Detach program from the running console. Not relevant for all platforms.\n"
" --max-frames=NUMBER " " --max-frames=NUMBER "
"Runs for the specified number of frames, then exits.\n" "Runs for the specified number of frames, then exits.\n"
, sizeof(buf)); , sizeof(buf));
#ifdef HAVE_PATCH #ifdef HAVE_PATCH
strlcat(buf, strlcat(buf,
" -U, --ups=FILE " " -U, --ups=FILE "
@ -5123,8 +5136,10 @@ static void retroarch_print_help(const char *arg0)
#endif #endif
#ifdef HAVE_ACCESSIBILITY #ifdef HAVE_ACCESSIBILITY
strlcat(buf, " --accessibility " strlcat(buf,
"Enables accessibilty for blind users using text-to-speech.\n", sizeof(buf)); " --accessibility "
"Enables accessibilty for blind users using text-to-speech.\n"
, sizeof(buf));
#endif #endif
strlcat(buf, strlcat(buf,
@ -5136,8 +5151,7 @@ static void retroarch_print_help(const char *arg0)
"Path for save files (*.srm). (DEPRECATED, use --appendconfig and savefile_directory)\n" "Path for save files (*.srm). (DEPRECATED, use --appendconfig and savefile_directory)\n"
" -S, --savestate=PATH " " -S, --savestate=PATH "
"Path for the save state files (*.state). (DEPRECATED, use --appendconfig and savestate_directory)\n" "Path for the save state files (*.state). (DEPRECATED, use --appendconfig and savestate_directory)\n"
, , sizeof(buf));
sizeof(buf));
fputs(buf, stdout); fputs(buf, stdout);
} }
@ -5280,6 +5294,11 @@ end:
} }
#endif #endif
#ifdef HAVE_LIBRETRODB
void handle_dbscan_finished(retro_task_t *task,
void *task_data, void *user_data, const char *err);
#endif
/** /**
* retroarch_parse_input_and_config: * retroarch_parse_input_and_config:
* @argc : Count of (commandline) arguments. * @argc : Count of (commandline) arguments.
@ -5309,6 +5328,10 @@ static bool retroarch_parse_input_and_config(
#ifdef HAVE_ACCESSIBILITY #ifdef HAVE_ACCESSIBILITY
access_state_t *access_st = access_state_get_ptr(); access_state_t *access_st = access_state_get_ptr();
#endif #endif
#ifdef HAVE_LIBRETRODB
retro_task_callback_t cb_task_dbscan
= NULL;
#endif
const struct option opts[] = { const struct option opts[] = {
#ifdef HAVE_DYNAMIC #ifdef HAVE_DYNAMIC
@ -5364,6 +5387,9 @@ static bool retroarch_parse_input_and_config(
{ "accessibility", 0, NULL, RA_OPT_ACCESSIBILITY}, { "accessibility", 0, NULL, RA_OPT_ACCESSIBILITY},
{ "load-menu-on-error", 0, NULL, RA_OPT_LOAD_MENU_ON_ERROR }, { "load-menu-on-error", 0, NULL, RA_OPT_LOAD_MENU_ON_ERROR },
{ "entryslot", 1, NULL, 'e' }, { "entryslot", 1, NULL, 'e' },
#ifdef HAVE_LIBRETRODB
{ "scan", 1, NULL, RA_OPT_DATABASE_SCAN },
#endif
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -5532,6 +5558,15 @@ static bool retroarch_parse_input_and_config(
rarch_log_file_set_override(optarg); rarch_log_file_set_override(optarg);
break; break;
case RA_OPT_MENU:
explicit_menu = true;
break;
case RA_OPT_DATABASE_SCAN:
#ifdef HAVE_LIBRETRODB
verbosity_enable();
#endif
break;
/* Must handle '?' otherwise you get an infinite loop */ /* Must handle '?' otherwise you get an infinite loop */
case '?': case '?':
frontend_driver_attach_console(); frontend_driver_attach_console();
@ -5915,6 +5950,38 @@ static bool retroarch_parse_input_and_config(
"entry state slot index. Ignoring.\n", optarg); "entry state slot index. Ignoring.\n", optarg);
} }
break; break;
case RA_OPT_DATABASE_SCAN:
#ifdef HAVE_LIBRETRODB
{
settings_t *settings = config_get_ptr();
bool show_hidden_files = settings->bools.show_hidden_files;
const char *directory_playlist = settings->paths.directory_playlist;
const char *path_content_db = settings->paths.path_content_database;
int reinit_flags = DRIVERS_CMD_ALL &
~(DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK | DRIVER_INPUT_MASK | DRIVER_MIDI_MASK);
drivers_init(settings, reinit_flags, false);
retroarch_init_task_queue();
if (explicit_menu)
cb_task_dbscan = handle_dbscan_finished;
task_push_dbscan(
directory_playlist,
path_content_db,
optarg, path_is_directory(optarg),
show_hidden_files,
cb_task_dbscan);
if (!explicit_menu)
{
task_queue_wait(NULL, NULL);
driver_uninit(DRIVERS_CMD_ALL);
exit(0);
}
}
#endif
break;
default: default:
RARCH_ERR("%s\n", msg_hash_to_str(MSG_ERROR_PARSING_ARGUMENTS)); RARCH_ERR("%s\n", msg_hash_to_str(MSG_ERROR_PARSING_ARGUMENTS));
retroarch_fail(1, "retroarch_parse_input()"); retroarch_fail(1, "retroarch_parse_input()");

View File

@ -89,12 +89,19 @@ static const char *database_info_get_current_element_name(
{ {
if (!handle || !handle->list) if (!handle || !handle->list)
return NULL; return NULL;
#if 1
/* Don't skip pruned entries, otherwise iteration
* ends prematurely */
if (!handle->list->elems[handle->list_ptr].data)
return "";
#else
/* Skip pruned entries */ /* Skip pruned entries */
while (!handle->list->elems[handle->list_ptr].data) while (!handle->list->elems[handle->list_ptr].data)
{ {
if (++handle->list_ptr >= handle->list->size) if (++handle->list_ptr >= handle->list->size)
return NULL; return NULL;
} }
#endif
return handle->list->elems[handle->list_ptr].data; return handle->list->elems[handle->list_ptr].data;
} }
@ -103,16 +110,16 @@ static int task_database_iterate_start(retro_task_t *task,
const char *name) const char *name)
{ {
char msg[256]; char msg[256];
const char *basename_path = !string_is_empty(name) ? const char *basename_path = !string_is_empty(name)
path_basename_nocompression(name) : ""; ? path_basename_nocompression(name) : "";
msg[0] = '\0'; msg[0] = '\0';
snprintf(msg, sizeof(msg), if (!string_is_empty(basename_path))
STRING_REP_USIZE "/" STRING_REP_USIZE ": %s %s...\n", snprintf(msg, sizeof(msg),
(size_t)db->list_ptr, STRING_REP_USIZE "/" STRING_REP_USIZE ": %s..\n",
db->list_ptr + 1,
(size_t)db->list->size, (size_t)db->list->size,
msg_hash_to_str(MSG_SCANNING),
basename_path); basename_path);
if (!string_is_empty(msg)) if (!string_is_empty(msg))
@ -124,6 +131,9 @@ static int task_database_iterate_start(retro_task_t *task,
task_set_progress(task, task_set_progress(task,
roundf((float)db->list_ptr / roundf((float)db->list_ptr /
((float)db->list->size / 100.0f))); ((float)db->list->size / 100.0f)));
RARCH_LOG("[Scanner]: %s", msg);
if (verbosity_is_enabled())
printf("%s", msg);
#else #else
fprintf(stderr, "msg: %s\n", msg); fprintf(stderr, "msg: %s\n", msg);
#endif #endif
@ -742,7 +752,7 @@ static int database_info_list_iterate_found_match(
path_basename_nocompression(entry_path), "", str_len); path_basename_nocompression(entry_path), "", str_len);
path_remove_extension(entry_label); path_remove_extension(entry_label);
RARCH_LOG("[Database]: No match for: \"%s\", CRC: 0x%08X\n", entry_path_str, db_state->crc); RARCH_LOG("[Scanner]: No match for: \"%s\", CRC: 0x%08X\n", entry_path_str, db_state->crc);
} }
if (!string_is_empty(archive_name)) if (!string_is_empty(archive_name))
@ -793,6 +803,9 @@ static int database_info_list_iterate_found_match(
entry.last_played_second= 0; entry.last_played_second= 0;
playlist_push(playlist, &entry); playlist_push(playlist, &entry);
RARCH_LOG("[Scanner]: Add \"%s\"\n", entry_label);
if (verbosity_is_enabled())
printf("Add \"%s\"\n", entry.label);
} }
playlist_write_file(playlist); playlist_write_file(playlist);
@ -828,8 +841,7 @@ static int database_info_list_iterate_found_match(
/* End of entries in database info list and didn't find a /* End of entries in database info list and didn't find a
* match, go to the next database. */ * match, go to the next database. */
static int database_info_list_iterate_next( static int database_info_list_iterate_next(
database_state_handle_t *db_state database_state_handle_t *db_state)
)
{ {
db_state->list_index++; db_state->list_index++;
db_state->entry_index = 0; db_state->entry_index = 0;
@ -997,8 +1009,7 @@ static int task_database_iterate_serial_lookup(
db_handle_t *_db, db_handle_t *_db,
database_state_handle_t *db_state, database_state_handle_t *db_state,
database_info_handle_t *db, const char *name, database_info_handle_t *db, const char *name,
bool path_contains_compressed_file bool path_contains_compressed_file)
)
{ {
if ( if (
!db_state->list || !db_state->list ||
@ -1158,6 +1169,10 @@ static void task_database_handler(retro_task_t *task)
db->flags & DB_HANDLE_FLAG_SHOW_HIDDEN_FILES, db->flags & DB_HANDLE_FLAG_SHOW_HIDDEN_FILES,
false, false); false, false);
RARCH_LOG("[Scanner]: %s\"%s\"..\n", msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_START), db->fullpath);
if (verbosity_is_enabled())
printf("%s\"%s\"..\n", msg_hash_to_str(MSG_MANUAL_CONTENT_SCAN_START), db->fullpath);
/* If the scan path matches a database path exactly then /* If the scan path matches a database path exactly then
* save time by only processing that database. */ * save time by only processing that database. */
if (dbstate->list && (db->flags & DB_HANDLE_FLAG_IS_DIRECTORY)) if (dbstate->list && (db->flags & DB_HANDLE_FLAG_IS_DIRECTORY))
@ -1248,6 +1263,9 @@ static void task_database_handler(retro_task_t *task)
task_set_title(task, strdup(msg)); task_set_title(task, strdup(msg));
task_set_progress(task, 100); task_set_progress(task, 100);
ui_companion_driver_notify_refresh(); ui_companion_driver_notify_refresh();
RARCH_LOG("[Scanner]: %s\n", msg);
if (verbosity_is_enabled())
printf("%s\n", msg);
#else #else
fprintf(stderr, "msg: %s\n", msg); fprintf(stderr, "msg: %s\n", msg);
#endif #endif
@ -1261,6 +1279,7 @@ static void task_database_handler(retro_task_t *task)
} }
return; return;
task_finished: task_finished:
if (task) if (task)
task_set_finished(task, true); task_set_finished(task, true);