Add To Playlist functionality (#16386)

* This PR contains Add To Favorite functionality.  It allows moving content to another playlist or to Create a new playlist with the selected content.

* Update retroarch.c

Fixed ISO C90 variable declaration at top of code.

* Update menu_cbs_ok.c

Fixed variable declaration for ISO requirement.
This commit is contained in:
Jason Breitweiser 2024-03-28 15:58:16 -04:00 committed by GitHub
parent a54811c79b
commit 87b9d0328e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 419 additions and 2 deletions

View file

@ -269,7 +269,9 @@ enum event_command
CMD_EVENT_MICROPHONE_REINIT,
#endif
/* Deprecated */
CMD_EVENT_SEND_DEBUG_INFO
CMD_EVENT_SEND_DEBUG_INFO,
/* Add a playlist entry to another playlist. */
CMD_EVENT_ADD_TO_PLAYLIST
};
enum cmd_source_t

View file

@ -4,6 +4,28 @@ MSG_HASH(
"switch_cpu_profile"
)
#endif
MSG_HASH(
MENU_ENUM_LABEL_ADD_TO_PLAYLIST,
"playlist_add"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_ADD_TO_PLAYLIST_LIST,
"deferred_add_to_playlist_list"
)
MSG_HASH(
MENU_ENUM_LABEL_ADD_ENTRY_TO_PLAYLIST,
"add_entry_to_playlist"
)
MSG_HASH(
MSG_ADDED_TO_PLAYLIST,
"Added to playlist"
)
MSG_HASH(
MSG_ADD_TO_PLAYLIST_FAILED,
"Failed to add to playlist: playlist full"
)
MSG_HASH(
MENU_ENUM_LABEL_ACCOUNTS_CHEEVOS_USERNAME,
"accounts_cheevos_username"

View file

@ -6658,6 +6658,24 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES,
"Show the 'Add to Favorites' option."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_ADD_TO_PLAYLIST,
"Add to Playlist"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_ADD_TO_PLAYLIST,
"Add the content to a playlist."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CREATE_NEW_PLAYLIST,
"Create New Playlist"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CREATE_NEW_PLAYLIST,
"Create a new playlist and add the current entry to it."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SET_CORE_ASSOCIATION,
"Show 'Set Core Association'"

View file

@ -672,6 +672,7 @@ GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_select_physi
#ifdef HAVE_NETWORKING
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_netplay_mitm_server, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_NETPLAY_MITM_SERVER)
#endif
GENERIC_DEFERRED_PUSH(deferred_push_add_to_playlist_list, DISPLAYLIST_ADD_TO_PLAYLIST_LIST)
static int menu_cbs_init_bind_deferred_push_compare_label(
menu_file_list_cbs_t *cbs,
@ -933,6 +934,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
#ifdef HAVE_NETWORKING
{MENU_ENUM_LABEL_DEFERRED_LAKKA_LIST, deferred_push_lakka_list},
#endif
{MENU_ENUM_LABEL_DEFERRED_ADD_TO_PLAYLIST_LIST, deferred_push_add_to_playlist_list},
};
if (!string_is_equal(label, "null"))
@ -1394,6 +1396,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
case MENU_ENUM_LABEL_SIDELOAD_CORE_LIST:
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_file_browser_select_sideload_core);
break;
case MENU_ENUM_LABEL_DEFERRED_ADD_TO_PLAYLIST_LIST:
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_add_to_playlist_list);
break;
default:
return -1;
}

View file

@ -123,6 +123,9 @@ int menu_cbs_init_bind_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS:
BIND_ACTION_LABEL(cbs, action_bind_label_playlist_collection_entry);
break;
case MENU_ENUM_LABEL_CONTENT_SETTINGS:
BIND_ACTION_LABEL(cbs, action_bind_label_playlist_collection_entry);
break;
case MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY:
#ifdef HAVE_CHEATS
BIND_ACTION_LABEL(cbs, action_bind_label_cheat_browse_address);

View file

@ -543,6 +543,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
return MENU_ENUM_LABEL_DEFERRED_CORE_OPTION_OVERRIDE_LIST;
case ACTION_OK_DL_REMAP_FILE_MANAGER_LIST:
return MENU_ENUM_LABEL_DEFERRED_REMAP_FILE_MANAGER_LIST;
case ACTION_OK_DL_ADD_TO_PLAYLIST:
return MENU_ENUM_LABEL_DEFERRED_ADD_TO_PLAYLIST_LIST;
default:
break;
}
@ -1779,6 +1781,7 @@ int generic_action_ok_displaylist_push(
#endif
case ACTION_OK_DL_CORE_OPTION_OVERRIDE_LIST:
case ACTION_OK_DL_REMAP_FILE_MANAGER_LIST:
case ACTION_OK_DL_ADD_TO_PLAYLIST:
ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
break;
case ACTION_OK_DL_CDROM_INFO_DETAIL_LIST:
@ -5769,6 +5772,181 @@ static int action_ok_add_to_favorites(const char *path,
return ret;
}
static int action_ok_add_entry_to_playlist(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
playlist_t *playlist_curr = playlist_get_cached();
const struct playlist_entry *entry = NULL;
menu_handle_t *menu = menu_state_get_ptr()->driver_data;
int ret = 0;
if (!playlist_curr)
return 0;
if (!menu)
return -1;
if(!label)
return 0;
/*
*
* path = menu entry select. use this to identify the menu item to add the content to
* entry->path = The file path of the currently selected content
* [INFO] [playlist] = Add to Favorites
* [INFO] [content_path] = C:\roms\Arcade - Mame 2003 Plus\aburner2.zip
*/
/* Read current playlist parameters */
playlist_get_index(playlist_curr, menu->rpl_entry_selection_ptr, &entry);
/* Error checking
* > If content path is empty, cannot do anything... */
if (!string_is_empty(entry->path))
{
union string_list_elem_attr attr;
char core_display_name[PATH_MAX_LENGTH];
char core_path[PATH_MAX_LENGTH];
char core_name[PATH_MAX_LENGTH];
struct string_list
*str_list = NULL;
core_display_name[0] = '\0';
core_path[0] = '\0';
core_name[0] = '\0';
/* Create string list container for playlist parameters */
attr.i = 0;
if (!(str_list = string_list_new()))
return 0;
/* Copy playlist parameters into string list
* [0]: content_path
* [1]: content_label
* [2]: core_path
* [3]: core_name
* [4]: crc32
* [5]: db_name
* [6]: playlist*/
/* > content_path */
string_list_append(str_list, entry->path, attr);
/* > content_label */
if (!string_is_empty(entry->label))
string_list_append(str_list, entry->label, attr);
else
{
/* Label is empty - use file name instead */
char fallback_content_label[PATH_MAX_LENGTH];
fallback_content_label[0] = '\0';
fill_pathname(fallback_content_label,
path_basename(entry->path), "",
sizeof(fallback_content_label));
string_list_append(str_list, fallback_content_label, attr);
}
/* Replace "DETECT" with default_core_path + name if available */
if ( !string_is_empty(entry->core_path)
&& !string_is_empty(entry->core_name))
{
if ( string_is_equal(entry->core_path, FILE_PATH_DETECT)
&& string_is_equal(entry->core_name, FILE_PATH_DETECT))
{
const char *default_core_path = playlist_get_default_core_path(playlist_curr);
const char *default_core_name = playlist_get_default_core_name(playlist_curr);
if ( !string_is_empty(default_core_path)
&& !string_is_empty(default_core_name))
{
strlcpy(core_path, default_core_path, sizeof(core_path));
strlcpy(core_name, default_core_name, sizeof(core_name));
}
}
else
{
strlcpy(core_path, entry->core_path, sizeof(core_path));
strlcpy(core_name, entry->core_name, sizeof(core_name));
}
}
/* > core_path + core_name */
if ( !string_is_empty(core_path)
&& !string_is_empty(core_name))
{
core_info_t *core_info = NULL;
/* >> core_path */
string_list_append(str_list, core_path, attr);
/* >> core_name
* (always use display name, if available) */
if (core_info_find(core_path, &core_info))
if (!string_is_empty(core_info->display_name))
strlcpy(core_display_name, core_info->display_name, sizeof(core_display_name));
if (!string_is_empty(core_display_name))
string_list_append(str_list, core_display_name, attr);
else
string_list_append(str_list, core_name, attr);
}
else
{
string_list_append(str_list, FILE_PATH_DETECT, attr);
string_list_append(str_list, FILE_PATH_DETECT, attr);
}
/* crc32 */
string_list_append(str_list, !string_is_empty(entry->crc32) ? entry->crc32 : "", attr);
/* db_name */
string_list_append(str_list, !string_is_empty(entry->db_name) ? entry->db_name : "", attr);
/* db_name */
string_list_append(str_list, label, attr);
/* Trigger 'ADD_TO_FAVORITES' event */
if (!command_event(CMD_EVENT_ADD_TO_PLAYLIST, (void*)str_list))
ret = -1;
/* Clean up */
string_list_free(str_list);
str_list = NULL;
}
return ret;
}
static void action_input_add_entry_to_new_playlist(void *userdata, const char *line)
{
settings_t *settings = config_get_ptr();
size_t path_length = 0;
char path[PATH_MAX_LENGTH];
menu_input_dialog_end();
if(!line)
return;
/* Create path for new file */
path_length = fill_pathname_join_special(path, settings->paths.directory_playlist, line, sizeof(path));
strlcat(path, ".lpl", sizeof(path) - path_length);
action_ok_add_entry_to_playlist(NULL, path, 0, 0, 0);
}
static int action_ok_add_entry_to_new_playlist(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
menu_input_ctx_line_t line;
line.label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CREATE_NEW_PLAYLIST);
line.label_setting = NULL;
line.type = 0;
line.idx = 0;
line.cb = action_input_add_entry_to_new_playlist;
menu_input_dialog_start(&line);
return 0;
}
/* This function is called when selecting 'add to favorites'
* while viewing a playlist entry */
static int action_ok_add_to_favorites_playlist(const char *path,
@ -6194,6 +6372,7 @@ STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_push_core_option_override_list, ACTION_O
STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_push_remap_file_manager_list, ACTION_OK_DL_REMAP_FILE_MANAGER_LIST)
STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_push_savestate_list, ACTION_OK_DL_SAVESTATE_LIST)
STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_push_core_options_list, ACTION_OK_DL_CORE_OPTIONS_LIST)
STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_push_add_to_playlist_list, ACTION_OK_DL_ADD_TO_PLAYLIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_playlist_manager_settings, ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS)
#ifdef HAVE_CHEEVOS
DEFAULT_ACTION_OK_FUNC(action_ok_push_achievements_hardcore_pause_list, ACTION_OK_DL_ACHIEVEMENTS_HARDCORE_PAUSE_LIST)
@ -8536,9 +8715,12 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_HALT_REPLAY, action_ok_halt_replay},
{MENU_ENUM_LABEL_RESUME_CONTENT, action_ok_resume_content},
{MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST, action_ok_add_to_favorites_playlist},
{MENU_ENUM_LABEL_ADD_ENTRY_TO_PLAYLIST, action_ok_add_entry_to_playlist},
{MENU_ENUM_LABEL_CREATE_NEW_PLAYLIST, action_ok_add_entry_to_new_playlist},
{MENU_ENUM_LABEL_SET_CORE_ASSOCIATION, action_ok_set_core_association},
{MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION, action_ok_reset_core_association},
{MENU_ENUM_LABEL_ADD_TO_FAVORITES, action_ok_add_to_favorites},
{MENU_ENUM_LABEL_ADD_TO_PLAYLIST, action_ok_push_add_to_playlist_list},
{MENU_ENUM_LABEL_RESTART_CONTENT, action_ok_restart_content},
{MENU_ENUM_LABEL_TAKE_SCREENSHOT, action_ok_screenshot},
{MENU_ENUM_LABEL_RENAME_ENTRY, action_ok_rename_entry},

View file

@ -246,7 +246,8 @@ enum
ACTION_OK_DL_SAVESTATE_LIST,
ACTION_OK_DL_CORE_OPTION_OVERRIDE_LIST,
ACTION_OK_DL_CORE_OPTIONS_LIST,
ACTION_OK_DL_REMAP_FILE_MANAGER_LIST
ACTION_OK_DL_REMAP_FILE_MANAGER_LIST,
ACTION_OK_DL_ADD_TO_PLAYLIST
};
/* Function callbacks */

View file

@ -3720,6 +3720,13 @@ static int menu_displaylist_parse_load_content_settings(
count++;
}
if ( menu_entries_append(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_PLAYLIST),
msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_PLAYLIST),
MENU_ENUM_LABEL_ADD_TO_PLAYLIST,
MENU_SETTING_ACTION, 0, 0, NULL))
count++;
if (!settings->bools.kiosk_mode_enable)
{
if (settings->bools.menu_show_overlays)
@ -3971,6 +3978,12 @@ static int menu_displaylist_parse_horizontal_content_actions(
MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL);
}
/* This is to add to playlist */
menu_entries_append(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_PLAYLIST),
msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_PLAYLIST),
MENU_ENUM_LABEL_ADD_TO_PLAYLIST,
MENU_SETTING_ACTION, 0, 0, NULL);
if (!settings->bools.kiosk_mode_enable)
{
if (settings->bools.quick_menu_show_set_core_association)
@ -4507,6 +4520,77 @@ static unsigned menu_displaylist_parse_cores(
return count;
}
static unsigned menu_displaylist_parse_add_to_playlist_list(
file_list_t *list, settings_t *settings)
{
unsigned count = 0;
const char *dir_playlist = settings->paths.directory_playlist;
bool show_hidden_files = settings->bools.show_hidden_files;
char playlist_display_name[PATH_MAX_LENGTH];
struct string_list *str_list = dir_list_new_special(
dir_playlist, DIR_LIST_COLLECTIONS, NULL, show_hidden_files);
if (str_list && str_list->size)
{
unsigned i;
dir_list_sort(str_list, true);
for (i = 0; i < str_list->size; i++)
{
const char *path = str_list->elems[i].data;
const char *playlist_file = NULL;
if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY)
continue;
if (string_is_empty(path))
continue;
playlist_file = path_basename_nocompression(path);
if (string_is_empty(playlist_file))
continue;
/* Ignore non-playlist files */
if (!string_is_equal_noncase(path_get_extension(playlist_file),
"lpl"))
continue;
/* Ignore history/favourites
* > content_history + favorites are handled separately
* > music/video/image_history are ignored */
if ( string_ends_with_size(path, "_history.lpl", strlen(path), STRLEN_CONST("_history.lpl"))
|| string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES))
continue;
strlcpy(playlist_display_name, playlist_file, sizeof(playlist_display_name));
path_remove_extension(playlist_display_name);
menu_entries_append(list, playlist_display_name, path,
MENU_ENUM_LABEL_ADD_ENTRY_TO_PLAYLIST,
MENU_SETTING_ACTION, 0, 0, NULL);
count++;
}
}
/* Not necessary to check for NULL here */
string_list_free(str_list);
/* Add favourites */
if (
settings->bools.quick_menu_show_add_to_favorites
&& settings->bools.menu_content_show_favorites
&& menu_entries_append(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES),
msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES),
MENU_ENUM_LABEL_ADD_TO_FAVORITES, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL)
)
count++;
return count;
}
static unsigned menu_displaylist_parse_playlist_manager_list(
file_list_t *list, settings_t *settings)
{
@ -13762,6 +13846,27 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
menu_entries_clear(info->list);
count = menu_displaylist_parse_playlist_manager_list(info->list, settings);
if (count == 0)
menu_entries_append(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, NULL);
info->flags |= MD_FLAG_NEED_PUSH;
break;
case DISPLAYLIST_ADD_TO_PLAYLIST_LIST:
menu_entries_clear(info->list);
/* add new list button here */
menu_entries_append(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CREATE_NEW_PLAYLIST),
msg_hash_to_str(MENU_ENUM_LABEL_CREATE_NEW_PLAYLIST),
MENU_ENUM_LABEL_CREATE_NEW_PLAYLIST,
MENU_SETTING_ACTION, 0, 0, NULL);
count = menu_displaylist_parse_add_to_playlist_list(info->list, settings);
if (count == 0)
menu_entries_append(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),

View file

@ -251,6 +251,7 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_RECORDING_SETTINGS_LIST,
DISPLAYLIST_PLAYLIST_SETTINGS_LIST,
DISPLAYLIST_PLAYLIST_MANAGER_LIST,
DISPLAYLIST_ADD_TO_PLAYLIST_LIST,
DISPLAYLIST_PLAYLIST_MANAGER_SETTINGS,
DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST,
DISPLAYLIST_ACCOUNTS_YOUTUBE_LIST,

View file

@ -581,6 +581,14 @@ enum msg_hash_enums
MSG_IOS_TOUCH_MOUSE_ENABLED,
MSG_IOS_TOUCH_MOUSE_DISABLED,
/* Add To Playlist*/
MSG_ADDED_TO_PLAYLIST,
MSG_ADD_TO_PLAYLIST_FAILED,
MENU_ENUM_LABEL_ADD_ENTRY_TO_PLAYLIST,
MENU_ENUM_LABEL_DEFERRED_ADD_TO_PLAYLIST_LIST,
MENU_LABEL(ADD_TO_PLAYLIST),
MENU_LABEL(CREATE_NEW_PLAYLIST),
MENU_LABEL(MENU_XMB_ANIMATION_HORIZONTAL_HIGHLIGHT),
MENU_LABEL(MENU_XMB_ANIMATION_MOVE_UP_DOWN),
MENU_LABEL(MENU_XMB_ANIMATION_OPENING_MAIN_MENU),

View file

@ -4445,6 +4445,76 @@ bool command_event(enum event_command cmd, void *data)
}
break;
}
case CMD_EVENT_ADD_TO_PLAYLIST:
{
struct string_list *str_list = (struct string_list*)data;
struct menu_state *menu_st = menu_state_get_ptr();
settings_t *settings = config_get_ptr();
if (str_list)
{
if (str_list->size >= 7)
{
playlist_config_t playlist_config;
playlist_t * playlist;
struct playlist_entry entry = {0};
bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical;
entry.path = str_list->elems[0].data; /* content_path */
entry.label = str_list->elems[1].data; /* content_label */
entry.core_path = str_list->elems[2].data; /* core_path */
entry.core_name = str_list->elems[3].data; /* core_name */
entry.crc32 = str_list->elems[4].data; /* crc32 */
entry.db_name = str_list->elems[5].data; /* db_name */
/* load the playlist */
playlist_config.capacity = COLLECTION_SIZE;
playlist_config.old_format = settings->bools.playlist_use_old_format;
playlist_config.compress = settings->bools.playlist_compression;
playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match;
playlist_config_set_base_content_directory(&playlist_config,
settings->bools.playlist_portable_paths
? settings->paths.directory_menu_content
: NULL);
playlist_config_set_path(&playlist_config, str_list->elems[6].data);
playlist = playlist_init(&playlist_config);
/* Check whether favourties playlist is at capacity */
if (playlist_size(playlist) >=
playlist_capacity(playlist))
{
runloop_msg_queue_push(
msg_hash_to_str(MSG_ADD_TO_PLAYLIST_FAILED), 1, 180, true, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
return true;
}
/* Write playlist entry */
if (playlist_push(playlist, &entry))
{
enum playlist_sort_mode current_sort_mode =
playlist_get_sort_mode(playlist);
/* New addition - need to resort if option is enabled */
if ( (playlist_sort_alphabetical
&& (current_sort_mode == PLAYLIST_SORT_MODE_DEFAULT))
|| (current_sort_mode == PLAYLIST_SORT_MODE_ALPHABETICAL))
playlist_qsort(playlist);
playlist_write_file(playlist);
runloop_msg_queue_push(
msg_hash_to_str(MSG_ADDED_TO_PLAYLIST), 1, 180, true, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH;
if (menu_st->driver_ctx->environ_cb)
menu_st->driver_ctx->environ_cb(MENU_ENVIRON_RESET_HORIZONTAL_LIST,
NULL, menu_st->userdata);
}
}
break;
}
case CMD_EVENT_RESET_CORE_ASSOCIATION:
{
const char *core_name = "DETECT";