1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2011-2017 - Daniel De Matteis
3  *  Copyright (C) 2016-2019 - Brad Parker
4  *  Copyright (C) 2016-2019 - Andrés Suárez
5  *
6  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
7  *  of the GNU General Public License as published by the Free Software Found-
8  *  ation, either version 3 of the License, or (at your option) any later version.
9  *
10  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  *  PURPOSE.  See the GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along with RetroArch.
15  *  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <compat/strl.h>
19 #include <array/rbuf.h>
20 #include <file/file_path.h>
21 #include <retro_assert.h>
22 #include <string/stdstring.h>
23 #include <streams/file_stream.h>
24 #include <lists/string_list.h>
25 
26 #ifdef HAVE_CONFIG_H
27 #include "../../config.h"
28 #endif
29 
30 #include <vfs/vfs_implementation.h>
31 #ifdef HAVE_CDROM
32 #include <vfs/vfs_implementation_cdrom.h>
33 #endif
34 
35 #ifdef HAVE_DISCORD
36 #include "../../network/discord.h"
37 #endif
38 
39 #include "../../config.def.h"
40 #include "../../config.def.keybinds.h"
41 #include "../../wifi/wifi_driver.h"
42 #include "../../driver.h"
43 
44 #include "../menu_driver.h"
45 #include "../menu_cbs.h"
46 #include "../menu_entries.h"
47 #include "../menu_setting.h"
48 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
49 #include "../menu_shader.h"
50 #endif
51 #include "../menu_dialog.h"
52 #include "../menu_input_bind_dialog.h"
53 #include "../menu_input.h"
54 
55 #include "../../core.h"
56 #include "../../configuration.h"
57 #include "../../core_info.h"
58 #include "../../frontend/frontend_driver.h"
59 #include "../../defaults.h"
60 #include "../../core_option_manager.h"
61 #ifdef HAVE_CHEATS
62 #include "../../cheat_manager.h"
63 #endif
64 #ifdef HAVE_AUDIOMIXER
65 #include "../../tasks/task_audio_mixer.h"
66 #endif
67 #include "../../tasks/task_content.h"
68 #include "../../tasks/task_file_transfer.h"
69 #include "../../tasks/tasks_internal.h"
70 #include "../../input/input_remapping.h"
71 #include "../../paths.h"
72 #include "../../playlist.h"
73 #include "../../retroarch.h"
74 #include "../../verbosity.h"
75 #include "../../lakka.h"
76 #include "../../bluetooth/bluetooth_driver.h"
77 #include "../../gfx/video_display_server.h"
78 #include "../../manual_content_scan.h"
79 
80 #include <net/net_http.h>
81 
82 #ifdef HAVE_NETWORKING
83 #include "../../network/netplay/netplay.h"
84 #include "../../network/netplay/netplay_discovery.h"
85 #include "../../wifi/wifi_driver.h"
86 #endif
87 
88 #ifdef __WINRT__
89 #include "../../uwp/uwp_func.h"
90 #endif
91 
92 #if defined(ANDROID)
93 #include "../../file_path_special.h"
94 #include "../../play_feature_delivery/play_feature_delivery.h"
95 #endif
96 
97 enum
98 {
99    ACTION_OK_LOAD_PRESET = 0,
100    ACTION_OK_LOAD_SHADER_PASS,
101    ACTION_OK_LOAD_STREAM_CONFIGFILE,
102    ACTION_OK_LOAD_RECORD_CONFIGFILE,
103    ACTION_OK_LOAD_REMAPPING_FILE,
104    ACTION_OK_LOAD_CHEAT_FILE,
105    ACTION_OK_SUBSYSTEM_ADD,
106    ACTION_OK_LOAD_CONFIG_FILE,
107    ACTION_OK_LOAD_CORE,
108    ACTION_OK_LOAD_WALLPAPER,
109    ACTION_OK_SET_PATH,
110    ACTION_OK_SET_PATH_AUDIO_FILTER,
111    ACTION_OK_SET_PATH_VIDEO_FILTER,
112    ACTION_OK_SET_PATH_OVERLAY,
113 #ifdef HAVE_VIDEO_LAYOUT
114    ACTION_OK_SET_PATH_VIDEO_LAYOUT,
115 #endif
116    ACTION_OK_SET_PATH_VIDEO_FONT,
117    ACTION_OK_SET_DIRECTORY,
118    ACTION_OK_SHOW_WIMP,
119    ACTION_OK_LOAD_CHEAT_FILE_APPEND,
120    ACTION_OK_LOAD_RGUI_MENU_THEME_PRESET,
121    ACTION_OK_SET_MANUAL_CONTENT_SCAN_DAT_FILE
122 };
123 
124 enum
125 {
126    ACTION_OK_REMAP_FILE_SAVE_CORE = 0,
127    ACTION_OK_REMAP_FILE_SAVE_CONTENT_DIR,
128    ACTION_OK_REMAP_FILE_SAVE_GAME,
129    ACTION_OK_REMAP_FILE_REMOVE_CORE,
130    ACTION_OK_REMAP_FILE_REMOVE_CONTENT_DIR,
131    ACTION_OK_REMAP_FILE_REMOVE_GAME
132 };
133 
134 #ifndef BIND_ACTION_OK
135 #define BIND_ACTION_OK(cbs, name) (cbs)->action_ok = (name)
136 #endif
137 
138 #ifdef HAVE_NETWORKING
139 
140 #ifndef INET6_ADDRSTRLEN
141 #define INET6_ADDRSTRLEN 46
142 #endif
143 
144 #endif
145 
146 #define ACTION_OK_DL_LBL(a, b) \
147    info.directory_ptr = idx; \
148    info.type          = type; \
149    info_path          = path; \
150    info_label         = msg_hash_to_str(a); \
151    info.enum_idx      = a; \
152    dl_type            = b;
153 
154 
155 #define DEFAULT_ACTION_OK_SET(funcname, _id, _flush) \
156 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
157 { \
158    return generic_action_ok(path, label, type, idx, entry_idx, _id, _flush); \
159 }
160 
161 
162 #define DEFAULT_ACTION_DIALOG_START(funcname, _label, _idx, _cb) \
163 static int (funcname)(const char *path, const char *label_setting, unsigned type, size_t idx, size_t entry_idx) \
164 { \
165    menu_input_ctx_line_t line; \
166    line.label         = _label; \
167    line.label_setting = label_setting; \
168    line.type          = type; \
169    line.idx           = (_idx); \
170    line.cb            = _cb; \
171    if (!menu_input_dialog_start(&line)) \
172       return -1; \
173    return 0; \
174 }
175 
176 
177 #define DEFAULT_ACTION_OK_START_BUILTIN_CORE(funcname, _id) \
178 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
179 { \
180    content_ctx_info_t content_info; \
181    content_info.argc                   = 0; \
182    content_info.argv                   = NULL; \
183    content_info.args                   = NULL; \
184    content_info.environ_get            = NULL; \
185    if (!task_push_start_builtin_core(&content_info, _id, NULL, NULL)) \
186       return -1; \
187    return 0; \
188 }
189 
190 #define DEFAULT_ACTION_OK_LIST(funcname, _id) \
191 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
192 { \
193    return generic_action_ok_network(path, label, type, idx, entry_idx, _id); \
194 }
195 
196 #define DEFAULT_ACTION_OK_DOWNLOAD(funcname, _id) \
197 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
198 { \
199    return action_ok_download_generic(path, label, NULL, type, idx, entry_idx,_id); \
200 }
201 
202 #define DEFAULT_ACTION_OK_CMD_FUNC(func_name, cmd) \
203 int (func_name)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
204 { \
205    return generic_action_ok_command(cmd); \
206 }
207 
208 #define DEFAULT_ACTION_OK_FUNC(func_name, lbl) \
209 int (func_name)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
210 { \
211    return generic_action_ok_displaylist_push(path, NULL, label, type, idx, entry_idx, lbl); \
212 }
213 
214 #define DEFAULT_ACTION_OK_DL_PUSH(funcname, _fbid, _id, _path) \
215 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
216 { \
217    settings_t            *settings   = config_get_ptr(); \
218    (void)settings; \
219    filebrowser_set_type(_fbid); \
220    return generic_action_ok_displaylist_push(path, _path, label, type, idx, entry_idx, _id); \
221 }
222 
223 #define DEFAULT_ACTION_OK_HELP(funcname, _id, _id2) \
224 static int (funcname)(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) \
225 { \
226    return generic_action_ok_help(path, label, type, idx, entry_idx, _id, _id2); \
227 }
228 
229 #ifdef HAVE_NETWORKING
230 #ifdef HAVE_LAKKA
lakka_get_project(void)231 static char *lakka_get_project(void)
232 {
233    size_t len;
234    static char lakka_project[128];
235    FILE *command_file = popen("cat /etc/release | cut -d - -f 1", "r");
236 
237    fgets(lakka_project, sizeof(lakka_project), command_file);
238    len = strlen(lakka_project);
239 
240    if (len > 0 && lakka_project[len-1] == '\n')
241       lakka_project[--len] = '\0';
242 
243    pclose(command_file);
244    return lakka_project;
245 }
246 #endif
247 #endif
248 
action_ok_dl_to_enum(unsigned lbl)249 static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
250 {
251    switch (lbl)
252    {
253       case ACTION_OK_DL_REMAPPINGS_PORT_LIST:
254          return MENU_ENUM_LABEL_DEFERRED_REMAPPINGS_PORT_LIST;
255       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PARAMETER:
256          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PARAMETER;
257       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PRESET_PARAMETER:
258          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PRESET_PARAMETER;
259       case ACTION_OK_DL_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES:
260          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES;
261       case ACTION_OK_DL_DROPDOWN_BOX_LIST:
262          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST;
263       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SPECIAL:
264          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL;
265       case ACTION_OK_DL_DROPDOWN_BOX_LIST_RESOLUTION:
266          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION;
267       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE:
268          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE;
269       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE:
270          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE;
271       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE:
272          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE;
273       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
274          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE;
275       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE:
276          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE;
277       case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
278          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME;
279       case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
280          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME;
281       case ACTION_OK_DL_DROPDOWN_BOX_LIST_DISK_INDEX:
282          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_DISK_INDEX;
283       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE:
284          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE;
285       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_INDEX:
286          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_INDEX;
287       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION:
288          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION;
289       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD:
290          return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD;
291       case ACTION_OK_DL_MIXER_STREAM_SETTINGS_LIST:
292          return MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST;
293       case ACTION_OK_DL_ACCOUNTS_LIST:
294          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_LIST;
295       case ACTION_OK_DL_ACHIEVEMENTS_HARDCORE_PAUSE_LIST:
296          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_LIST;
297       case ACTION_OK_DL_INPUT_SETTINGS_LIST:
298          return MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST;
299       case ACTION_OK_DL_INPUT_MENU_SETTINGS_LIST:
300          return MENU_ENUM_LABEL_DEFERRED_INPUT_MENU_SETTINGS_LIST;
301       case ACTION_OK_DL_INPUT_TURBO_FIRE_SETTINGS_LIST:
302          return MENU_ENUM_LABEL_DEFERRED_INPUT_TURBO_FIRE_SETTINGS_LIST;
303       case ACTION_OK_DL_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST:
304          return MENU_ENUM_LABEL_DEFERRED_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST;
305       case ACTION_OK_DL_LATENCY_SETTINGS_LIST:
306          return MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST;
307       case ACTION_OK_DL_DRIVER_SETTINGS_LIST:
308          return MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST;
309       case ACTION_OK_DL_CORE_SETTINGS_LIST:
310          return MENU_ENUM_LABEL_DEFERRED_CORE_SETTINGS_LIST;
311       case ACTION_OK_DL_CORE_INFORMATION_LIST:
312          return MENU_ENUM_LABEL_DEFERRED_CORE_INFORMATION_LIST;
313       case ACTION_OK_DL_CORE_RESTORE_BACKUP_LIST:
314          return MENU_ENUM_LABEL_DEFERRED_CORE_RESTORE_BACKUP_LIST;
315       case ACTION_OK_DL_CORE_DELETE_BACKUP_LIST:
316          return MENU_ENUM_LABEL_DEFERRED_CORE_DELETE_BACKUP_LIST;
317       case ACTION_OK_DL_VIDEO_SETTINGS_LIST:
318          return MENU_ENUM_LABEL_DEFERRED_VIDEO_SETTINGS_LIST;
319       case ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST:
320          return MENU_ENUM_LABEL_DEFERRED_VIDEO_SYNCHRONIZATION_SETTINGS_LIST;
321       case ACTION_OK_DL_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST:
322          return MENU_ENUM_LABEL_DEFERRED_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST;
323       case ACTION_OK_DL_VIDEO_WINDOWED_MODE_SETTINGS_LIST:
324          return MENU_ENUM_LABEL_DEFERRED_VIDEO_WINDOWED_MODE_SETTINGS_LIST;
325       case ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST:
326          return MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST;
327       case ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST:
328          return MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST;
329       case ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST:
330          return MENU_ENUM_LABEL_DEFERRED_CRT_SWITCHRES_SETTINGS_LIST;
331       case ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST:
332          return MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST;
333       case ACTION_OK_DL_SAVING_SETTINGS_LIST:
334          return MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST;
335       case ACTION_OK_DL_LOGGING_SETTINGS_LIST:
336          return MENU_ENUM_LABEL_DEFERRED_LOGGING_SETTINGS_LIST;
337       case ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST:
338          return MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST;
339       case ACTION_OK_DL_FRAME_TIME_COUNTER_SETTINGS_LIST:
340          return MENU_ENUM_LABEL_DEFERRED_FRAME_TIME_COUNTER_SETTINGS_LIST;
341       case ACTION_OK_DL_REWIND_SETTINGS_LIST:
342          return MENU_ENUM_LABEL_DEFERRED_REWIND_SETTINGS_LIST;
343       case ACTION_OK_DL_CHEAT_DETAILS_SETTINGS_LIST:
344          return MENU_ENUM_LABEL_DEFERRED_CHEAT_DETAILS_SETTINGS_LIST;
345       case ACTION_OK_DL_CHEAT_SEARCH_SETTINGS_LIST:
346          return MENU_ENUM_LABEL_DEFERRED_CHEAT_SEARCH_SETTINGS_LIST;
347       case ACTION_OK_DL_ONSCREEN_DISPLAY_SETTINGS_LIST:
348          return MENU_ENUM_LABEL_DEFERRED_ONSCREEN_DISPLAY_SETTINGS_LIST;
349       case ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST:
350          return MENU_ENUM_LABEL_DEFERRED_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST;
351       case ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST:
352          return MENU_ENUM_LABEL_DEFERRED_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST;
353       case ACTION_OK_DL_ONSCREEN_OVERLAY_SETTINGS_LIST:
354          return MENU_ENUM_LABEL_DEFERRED_ONSCREEN_OVERLAY_SETTINGS_LIST;
355 #ifdef HAVE_VIDEO_LAYOUT
356       case ACTION_OK_DL_ONSCREEN_VIDEO_LAYOUT_SETTINGS_LIST:
357          return MENU_ENUM_LABEL_DEFERRED_ONSCREEN_VIDEO_LAYOUT_SETTINGS_LIST;
358 #endif
359       case ACTION_OK_DL_MENU_SETTINGS_LIST:
360          return MENU_ENUM_LABEL_DEFERRED_MENU_SETTINGS_LIST;
361       case ACTION_OK_DL_MENU_VIEWS_SETTINGS_LIST:
362          return MENU_ENUM_LABEL_DEFERRED_MENU_VIEWS_SETTINGS_LIST;
363       case ACTION_OK_DL_SETTINGS_VIEWS_SETTINGS_LIST:
364          return MENU_ENUM_LABEL_DEFERRED_SETTINGS_VIEWS_SETTINGS_LIST;
365       case ACTION_OK_DL_QUICK_MENU_VIEWS_SETTINGS_LIST:
366          return MENU_ENUM_LABEL_DEFERRED_QUICK_MENU_VIEWS_SETTINGS_LIST;
367       case ACTION_OK_DL_QUICK_MENU_OVERRIDE_OPTIONS_LIST:
368          return MENU_ENUM_LABEL_DEFERRED_QUICK_MENU_OVERRIDE_OPTIONS;
369       case ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST:
370          return MENU_ENUM_LABEL_DEFERRED_USER_INTERFACE_SETTINGS_LIST;
371       case ACTION_OK_DL_AI_SERVICE_SETTINGS_LIST:
372          return MENU_ENUM_LABEL_DEFERRED_AI_SERVICE_SETTINGS_LIST;
373       case ACTION_OK_DL_ACCESSIBILITY_SETTINGS_LIST:
374          return MENU_ENUM_LABEL_DEFERRED_ACCESSIBILITY_SETTINGS_LIST;
375       case ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST:
376          return MENU_ENUM_LABEL_DEFERRED_POWER_MANAGEMENT_SETTINGS_LIST;
377       case ACTION_OK_DL_CPU_PERFPOWER_SETTINGS_LIST:
378          return MENU_ENUM_LABEL_DEFERRED_CPU_PERFPOWER_LIST;
379       case ACTION_OK_DL_CPU_POLICY_SETTINGS_LIST:
380          return MENU_ENUM_LABEL_DEFERRED_CPU_POLICY_ENTRY;
381       case ACTION_OK_DL_MENU_SOUNDS_LIST:
382          return MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST;
383       case ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST:
384          return MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST;
385       case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST:
386          return MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST;
387       case ACTION_OK_DL_UPDATER_SETTINGS_LIST:
388          return MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST;
389       case ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST:
390          return MENU_ENUM_LABEL_DEFERRED_NETWORK_HOSTING_SETTINGS_LIST;
391       case ACTION_OK_DL_SUBSYSTEM_SETTINGS_LIST:
392          return MENU_ENUM_LABEL_DEFERRED_SUBSYSTEM_SETTINGS_LIST;
393       case ACTION_OK_DL_NETWORK_SETTINGS_LIST:
394          return MENU_ENUM_LABEL_DEFERRED_NETWORK_SETTINGS_LIST;
395       case ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST:
396          return MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST;
397       case ACTION_OK_DL_WIFI_SETTINGS_LIST:
398          return MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST;
399       case ACTION_OK_DL_WIFI_NETWORKS_LIST:
400          return MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST;
401       case ACTION_OK_DL_NETPLAY:
402          return MENU_ENUM_LABEL_DEFERRED_NETPLAY;
403       case ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST:
404          return MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST;
405       case ACTION_OK_DL_LAKKA_SERVICES_LIST:
406          return MENU_ENUM_LABEL_DEFERRED_LAKKA_SERVICES_LIST;
407       case ACTION_OK_DL_USER_SETTINGS_LIST:
408          return MENU_ENUM_LABEL_DEFERRED_USER_SETTINGS_LIST;
409       case ACTION_OK_DL_DIRECTORY_SETTINGS_LIST:
410          return MENU_ENUM_LABEL_DEFERRED_DIRECTORY_SETTINGS_LIST;
411       case ACTION_OK_DL_PRIVACY_SETTINGS_LIST:
412          return MENU_ENUM_LABEL_DEFERRED_PRIVACY_SETTINGS_LIST;
413       case ACTION_OK_DL_MIDI_SETTINGS_LIST:
414          return MENU_ENUM_LABEL_DEFERRED_MIDI_SETTINGS_LIST;
415       case ACTION_OK_DL_AUDIO_SETTINGS_LIST:
416          return MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST;
417       case ACTION_OK_DL_AUDIO_OUTPUT_SETTINGS_LIST:
418          return MENU_ENUM_LABEL_DEFERRED_AUDIO_OUTPUT_SETTINGS_LIST;
419       case ACTION_OK_DL_AUDIO_RESAMPLER_SETTINGS_LIST:
420          return MENU_ENUM_LABEL_DEFERRED_AUDIO_RESAMPLER_SETTINGS_LIST;
421       case ACTION_OK_DL_AUDIO_SYNCHRONIZATION_SETTINGS_LIST:
422          return MENU_ENUM_LABEL_DEFERRED_AUDIO_SYNCHRONIZATION_SETTINGS_LIST;
423       case ACTION_OK_DL_AUDIO_MIXER_SETTINGS_LIST:
424          return MENU_ENUM_LABEL_DEFERRED_AUDIO_MIXER_SETTINGS_LIST;
425       case ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST:
426          return MENU_ENUM_LABEL_DEFERRED_INPUT_HOTKEY_BINDS_LIST;
427       case ACTION_OK_DL_RECORDING_SETTINGS_LIST:
428          return MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST;
429       case ACTION_OK_DL_PLAYLIST_SETTINGS_LIST:
430          return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST;
431       case ACTION_OK_DL_PLAYLIST_MANAGER_LIST:
432          return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST;
433       case ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS:
434          return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS;
435       case ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST:
436          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_CHEEVOS_LIST;
437       case ACTION_OK_DL_ACCOUNTS_TWITCH_LIST:
438          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_TWITCH_LIST;
439       case ACTION_OK_DL_ACCOUNTS_FACEBOOK_LIST:
440          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_FACEBOOK_LIST;
441       case ACTION_OK_DL_DUMP_DISC_LIST:
442          return MENU_ENUM_LABEL_DEFERRED_DUMP_DISC_LIST;
443       case ACTION_OK_DL_LOAD_DISC_LIST:
444          return MENU_ENUM_LABEL_DEFERRED_LOAD_DISC_LIST;
445       case ACTION_OK_DL_ACCOUNTS_YOUTUBE_LIST:
446          return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_YOUTUBE_LIST;
447       case ACTION_OK_DL_PLAYLIST_COLLECTION:
448          return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_LIST;
449       case ACTION_OK_DL_FAVORITES_LIST:
450          return MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST;
451       case ACTION_OK_DL_BROWSE_URL_LIST:
452          return MENU_ENUM_LABEL_DEFERRED_BROWSE_URL_LIST;
453       case ACTION_OK_DL_MUSIC_LIST:
454          return MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST;
455       case ACTION_OK_DL_IMAGES_LIST:
456          return MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST;
457       case ACTION_OK_DL_CDROM_INFO_DETAIL_LIST:
458          return MENU_ENUM_LABEL_DEFERRED_CDROM_INFO_LIST;
459       case ACTION_OK_DL_SHADER_PRESET_SAVE:
460          return MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_SAVE_LIST;
461       case ACTION_OK_DL_SHADER_PRESET_REMOVE:
462          return MENU_ENUM_LABEL_DEFERRED_VIDEO_SHADER_PRESET_REMOVE_LIST;
463       case ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST:
464          return MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST;
465       case ACTION_OK_DL_CORE_MANAGER_LIST:
466          return MENU_ENUM_LABEL_DEFERRED_CORE_MANAGER_LIST;
467       case ACTION_OK_DL_CORE_OPTION_OVERRIDE_LIST:
468          return MENU_ENUM_LABEL_DEFERRED_CORE_OPTION_OVERRIDE_LIST;
469       default:
470          break;
471    }
472 
473    return MSG_UNKNOWN;
474 }
475 
action_ok_get_file_browser_start_path(const char * current_path,const char * default_path,char * start_path,size_t start_path_len,bool set_pending)476 static void action_ok_get_file_browser_start_path(
477       const char *current_path, const char *default_path,
478       char *start_path, size_t start_path_len,
479       bool set_pending)
480 {
481    const char *pending_selection = NULL;
482    bool current_path_valid       = false;
483 
484    if (!start_path || (start_path_len < 1))
485       return;
486 
487    /* Parse current path */
488    if (!string_is_empty(current_path))
489    {
490       /* Start path is the parent directory of
491        * the current path */
492       fill_pathname_parent_dir(start_path, current_path,
493             start_path_len);
494 
495       /* 'Pending selection' is the basename of
496        * the current path - either a file name
497        * or a directory name */
498       pending_selection = path_basename(current_path);
499 
500       /* Check if current path is valid */
501       if (path_is_directory(start_path) &&
502           !string_is_empty(pending_selection))
503          current_path_valid = true;
504    }
505 
506    /* If current path is invalid, use default path */
507    if (!current_path_valid)
508    {
509       if (string_is_empty(default_path) ||
510           !path_is_directory(default_path))
511       {
512          start_path[0] = '\0';
513          return;
514       }
515 
516       strlcpy(start_path, default_path, start_path_len);
517       return;
518    }
519    /* Current path is valid - set pending selection,
520     * if required */
521    else if (set_pending)
522       menu_driver_set_pending_selection(pending_selection);
523 }
524 
generic_action_ok_displaylist_push(const char * path,const char * new_path,const char * label,unsigned type,size_t idx,size_t entry_idx,unsigned action_type)525 int generic_action_ok_displaylist_push(const char *path,
526       const char *new_path,
527       const char *label, unsigned type, size_t idx, size_t entry_idx,
528       unsigned action_type)
529 {
530    menu_displaylist_info_t info;
531    char tmp[PATH_MAX_LENGTH];
532    char parent_dir[PATH_MAX_LENGTH];
533    enum menu_displaylist_ctl_state dl_type = DISPLAYLIST_NONE;
534    const char           *menu_label        = NULL;
535    const char            *menu_path        = NULL;
536    const char          *content_path       = NULL;
537    const char          *info_label         = NULL;
538    const char          *info_path          = NULL;
539    menu_handle_t *menu                     = menu_driver_get_ptr();
540    settings_t            *settings         = config_get_ptr();
541    const char *menu_ident                  = menu_driver_ident();
542    file_list_t           *menu_stack       = menu_entries_get_menu_stack_ptr(0);
543 #ifdef HAVE_AUDIOMIXER
544    bool audio_enable_menu                  = settings->bools.audio_enable_menu;
545    bool audio_enable_menu_ok               = settings->bools.audio_enable_menu_ok;
546 #endif
547    const char *dir_menu_content            = settings->paths.directory_menu_content;
548    const char *dir_libretro                = settings->paths.directory_libretro;
549 
550    if (!menu || string_is_equal(menu_ident, "null"))
551    {
552       menu_displaylist_info_free(&info);
553       return menu_cbs_exit();
554    }
555 
556 #ifdef HAVE_AUDIOMIXER
557    if (audio_enable_menu && audio_enable_menu_ok)
558       audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
559 #endif
560 
561    menu_displaylist_info_init(&info);
562 
563    info.list                               = menu_stack;
564 
565    tmp[0] = parent_dir[0] = '\0';
566 
567    menu_entries_get_last_stack(&menu_path, &menu_label, NULL, NULL, NULL);
568 
569    switch (action_type)
570    {
571       case ACTION_OK_DL_BROWSE_URL_START:
572          info.type          = type;
573          info.directory_ptr = idx;
574          info_path          = NULL;
575          info_label         = msg_hash_to_str(
576                MENU_ENUM_LABEL_DEFERRED_BROWSE_URL_START);
577          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_BROWSE_URL_START;
578          dl_type            = DISPLAYLIST_GENERIC;
579          break;
580       case ACTION_OK_DL_VIDEO_LIST:
581          info.type          = type;
582          info.directory_ptr = idx;
583          info_path          = label;
584          info_label         = msg_hash_to_str(
585                MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST);
586          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST;
587          dl_type            = DISPLAYLIST_GENERIC;
588          break;
589       case ACTION_OK_DL_EXPLORE_LIST:
590          info.type          = type;
591          info.directory_ptr = idx;
592          info_path          = label;
593          info_label         = msg_hash_to_str(
594                MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST);
595          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST;
596          dl_type            = DISPLAYLIST_GENERIC;
597          break;
598       case ACTION_OK_DL_REMAPPINGS_PORT_LIST:
599          info.type          = type;
600          info.directory_ptr = idx;
601          info.path          = strdup(label);
602          info_label         = msg_hash_to_str(
603                MENU_ENUM_LABEL_DEFERRED_REMAPPINGS_PORT_LIST);
604          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_REMAPPINGS_PORT_LIST;
605          dl_type            = DISPLAYLIST_GENERIC;
606          break;
607       case ACTION_OK_DL_DROPDOWN_BOX_LIST:
608          info.type          = type;
609          info.directory_ptr = idx;
610          info_path          = path;
611          info_label         = msg_hash_to_str(
612                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST);
613          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST;
614          dl_type            = DISPLAYLIST_GENERIC;
615          break;
616       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SPECIAL:
617          info.type          = type;
618          info.directory_ptr = idx;
619          info_path          = path;
620          info_label         = msg_hash_to_str(
621                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL);
622          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL;
623          dl_type            = DISPLAYLIST_GENERIC;
624          break;
625       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PARAMETER:
626          info.type          = (unsigned)(MENU_SETTINGS_SHADER_PARAMETER_0 + idx);
627          info.directory_ptr = idx;
628          info_path          = path;
629          info_label         = msg_hash_to_str(
630                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PARAMETER);
631          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PARAMETER;
632          dl_type            = DISPLAYLIST_GENERIC;
633          break;
634       case ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PRESET_PARAMETER:
635          info.type          = type;
636          info.directory_ptr = idx;
637          info_path          = path;
638          info_label         = msg_hash_to_str(
639                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PRESET_PARAMETER);
640          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_PRESET_PARAMETER;
641          dl_type            = DISPLAYLIST_GENERIC;
642          break;
643       case ACTION_OK_DL_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES:
644          info.type          = type;
645          info.directory_ptr = idx;
646          info_path          = path;
647          info_label         = msg_hash_to_str(
648                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES);
649          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES;
650          dl_type            = DISPLAYLIST_GENERIC;
651          break;
652       case ACTION_OK_DL_DROPDOWN_BOX_LIST_RESOLUTION:
653          info.type          = type;
654          info.directory_ptr = idx;
655          info_path          = path;
656          info_label         = msg_hash_to_str(
657                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION);
658          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION;
659          dl_type            = DISPLAYLIST_GENERIC;
660          break;
661       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE:
662          info.type          = type;
663          info.directory_ptr = idx;
664          info_path          = path;
665          info_label         = msg_hash_to_str(
666                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE);
667          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE;
668          dl_type            = DISPLAYLIST_GENERIC;
669          break;
670       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE:
671          info.type          = type;
672          info.directory_ptr = idx;
673          info_path          = path;
674          info_label         = msg_hash_to_str(
675                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE);
676          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE;
677          dl_type            = DISPLAYLIST_GENERIC;
678          break;
679       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE:
680          info.type          = type;
681          info.directory_ptr = idx;
682          info_path          = path;
683          info_label         = msg_hash_to_str(
684                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE);
685          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE;
686          dl_type            = DISPLAYLIST_GENERIC;
687          break;
688       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE:
689          info.type          = type;
690          info.directory_ptr = idx;
691          info_path          = path;
692          info_label         = msg_hash_to_str(
693                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE);
694          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE;
695          dl_type            = DISPLAYLIST_GENERIC;
696          break;
697       case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE:
698          info.type          = type;
699          info.directory_ptr = idx;
700          info_path          = path;
701          info_label         = msg_hash_to_str(
702                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE);
703          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE;
704          dl_type            = DISPLAYLIST_GENERIC;
705          break;
706       case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
707          info.type          = type;
708          info.directory_ptr = idx;
709          info_path          = path;
710          info_label         = msg_hash_to_str(
711                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME);
712          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME;
713          dl_type            = DISPLAYLIST_GENERIC;
714          break;
715       case ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME:
716          info.type          = type;
717          info.directory_ptr = idx;
718          info_path          = path;
719          info_label         = msg_hash_to_str(
720                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME);
721          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME;
722          dl_type            = DISPLAYLIST_GENERIC;
723          break;
724       case ACTION_OK_DL_DROPDOWN_BOX_LIST_DISK_INDEX:
725          info.type          = type;
726          info.directory_ptr = idx;
727          info_path          = path;
728          info_label         = msg_hash_to_str(
729                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_DISK_INDEX);
730          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_DISK_INDEX;
731          dl_type            = DISPLAYLIST_GENERIC;
732          break;
733       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE:
734          info.type          = type;
735          info.directory_ptr = idx;
736          info_path          = path;
737          info_label         = msg_hash_to_str(
738                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE);
739          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE;
740          dl_type            = DISPLAYLIST_GENERIC;
741          break;
742       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_INDEX:
743          info.type          = type;
744          info.directory_ptr = idx;
745          info_path          = path;
746          info_label         = msg_hash_to_str(
747                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_INDEX);
748          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_INDEX;
749          dl_type            = DISPLAYLIST_GENERIC;
750          break;
751       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION:
752          info.type          = type;
753          info.directory_ptr = idx;
754          info_path          = path;
755          info_label         = msg_hash_to_str(
756                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION);
757          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION;
758          dl_type            = DISPLAYLIST_GENERIC;
759          break;
760       case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD:
761          info.type          = type;
762          info.directory_ptr = idx;
763          info_path          = path;
764          info_label         = msg_hash_to_str(
765                MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD);
766          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD;
767          dl_type            = DISPLAYLIST_GENERIC;
768          break;
769       case ACTION_OK_DL_USER_BINDS_LIST:
770          info.type          = type;
771          info.directory_ptr = idx;
772          info_path          = label;
773          info_label         = msg_hash_to_str(
774                MENU_ENUM_LABEL_DEFERRED_USER_BINDS_LIST);
775          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_USER_BINDS_LIST;
776          dl_type            = DISPLAYLIST_GENERIC;
777          break;
778       case ACTION_OK_DL_MUSIC:
779          if (!string_is_empty(path))
780             strlcpy(menu->scratch_buf, path, sizeof(menu->scratch_buf));
781          if (!string_is_empty(menu_path))
782             strlcpy(menu->scratch2_buf, menu_path, sizeof(menu->scratch2_buf));
783 
784          info_label         = msg_hash_to_str(
785                MENU_ENUM_LABEL_DEFERRED_MUSIC);
786          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_MUSIC;
787          info_path          = path;
788          info.type          = type;
789          info.directory_ptr = idx;
790          dl_type            = DISPLAYLIST_GENERIC;
791          break;
792       case ACTION_OK_DL_OPEN_ARCHIVE_DETECT_CORE:
793          if (menu)
794          {
795             menu_path    = menu->scratch2_buf;
796             content_path = menu->scratch_buf;
797          }
798          if (content_path)
799             fill_pathname_join(menu->detect_content_path,
800                   menu_path, content_path,
801                   sizeof(menu->detect_content_path));
802 
803          info_label         = msg_hash_to_str(
804                MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN_DETECT_CORE);
805          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN_DETECT_CORE;
806          info_path          = path;
807          info.type          = type;
808          info.directory_ptr = idx;
809          dl_type            = DISPLAYLIST_GENERIC;
810          break;
811       case ACTION_OK_DL_OPEN_ARCHIVE:
812          if (menu)
813          {
814             menu_path    = menu->scratch2_buf;
815             content_path = menu->scratch_buf;
816          }
817          if (content_path)
818             fill_pathname_join(menu->detect_content_path,
819                   menu_path, content_path,
820                   sizeof(menu->detect_content_path));
821 
822          info_label         = msg_hash_to_str(
823                MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN);
824          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN;
825          info_path          = path;
826          info.type          = type;
827          info.directory_ptr = idx;
828          dl_type            = DISPLAYLIST_GENERIC;
829          break;
830       case ACTION_OK_DL_HELP:
831          info_label             = label;
832          dl_type                = DISPLAYLIST_HELP;
833          menu_dialog_push_pending((enum menu_dialog_type)type);
834          break;
835       case ACTION_OK_DL_RPL_ENTRY:
836          strlcpy(menu->deferred_path, label, sizeof(menu->deferred_path));
837          info_label = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS);
838          info.enum_idx                 = MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS;
839          info.directory_ptr            = idx;
840          menu->rpl_entry_selection_ptr = (unsigned)entry_idx;
841          dl_type                       = DISPLAYLIST_GENERIC;
842          break;
843       case ACTION_OK_DL_AUDIO_DSP_PLUGIN:
844          filebrowser_clear_type();
845          info.directory_ptr = idx;
846          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN);
847          info.enum_idx      = MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN;
848          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
849 
850          action_ok_get_file_browser_start_path(
851                settings->paths.path_audio_dsp_plugin,
852                settings->paths.directory_audio_filter,
853                parent_dir, sizeof(parent_dir), true);
854 
855          info_path          = parent_dir;
856          break;
857       case ACTION_OK_DL_VIDEO_FILTER:
858          filebrowser_clear_type();
859          info.directory_ptr = idx;
860          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FILTER);
861          info.enum_idx      = MENU_ENUM_LABEL_VIDEO_FILTER;
862          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
863 
864          action_ok_get_file_browser_start_path(
865                settings->paths.path_softfilter_plugin,
866                settings->paths.directory_video_filter,
867                parent_dir, sizeof(parent_dir), true);
868 
869          info_path          = parent_dir;
870          break;
871       case ACTION_OK_DL_OVERLAY_PRESET:
872          filebrowser_clear_type();
873          info.directory_ptr = idx;
874          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_OVERLAY_PRESET);
875          info.enum_idx      = MENU_ENUM_LABEL_OVERLAY_PRESET;
876          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
877 
878          action_ok_get_file_browser_start_path(
879                settings->paths.path_overlay,
880                settings->paths.directory_overlay,
881                parent_dir, sizeof(parent_dir), true);
882 
883          info_path          = parent_dir;
884          break;
885 #if defined(HAVE_VIDEO_LAYOUT)
886       case ACTION_OK_DL_VIDEO_LAYOUT:
887          filebrowser_clear_type();
888          info.directory_ptr = idx;
889          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_LAYOUT_PATH);
890          info.enum_idx      = MENU_ENUM_LABEL_VIDEO_LAYOUT_PATH;
891          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
892 
893          action_ok_get_file_browser_start_path(
894                settings->paths.path_video_layout,
895                settings->paths.directory_video_layout,
896                parent_dir, sizeof(parent_dir), true);
897 
898          info_path          = parent_dir;
899          break;
900 #endif
901       case ACTION_OK_DL_VIDEO_FONT:
902          filebrowser_set_type(FILEBROWSER_SELECT_VIDEO_FONT);
903          info.directory_ptr = idx;
904          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FONT_PATH);
905          info.enum_idx      = MENU_ENUM_LABEL_VIDEO_FONT_PATH;
906          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
907 
908          action_ok_get_file_browser_start_path(
909                settings->paths.path_font,
910                NULL,
911                parent_dir, sizeof(parent_dir), true);
912 
913          info_path          = parent_dir;
914          break;
915       case ACTION_OK_DL_SHADER_PARAMETERS:
916          info.type          = MENU_SETTING_ACTION;
917          info.directory_ptr = idx;
918          info_label         = label;
919          dl_type            = DISPLAYLIST_GENERIC;
920          break;
921       case ACTION_OK_DL_GENERIC:
922          if (path)
923             strlcpy(menu->deferred_path, path,
924                   sizeof(menu->deferred_path));
925 
926          info.type          = type;
927          info.directory_ptr = idx;
928          info_label         = label;
929          dl_type            = DISPLAYLIST_GENERIC;
930          break;
931       case ACTION_OK_DL_FILE_BROWSER_SELECT_FILE:
932          if (path)
933             strlcpy(menu->deferred_path, path,
934                   sizeof(menu->deferred_path));
935 
936          info.type          = type;
937          info.directory_ptr = idx;
938          info_label         = label;
939          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
940          break;
941       case ACTION_OK_DL_FILE_BROWSER_SELECT_DIR:
942          if (path)
943             strlcpy(menu->deferred_path, path,
944                   sizeof(menu->deferred_path));
945 
946          info.type          = type;
947          info.directory_ptr = idx;
948          info_label         = label;
949          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_DIR;
950          break;
951       case ACTION_OK_DL_PUSH_DEFAULT:
952          info.type          = type;
953          info.directory_ptr = idx;
954          info_path          = label;
955          info_label         = label;
956          dl_type            = DISPLAYLIST_GENERIC;
957          break;
958       case ACTION_OK_DL_SHADER_PASS:
959 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
960          {
961             const char *shader_file_name = NULL;
962 
963             filebrowser_clear_type();
964             info.type          = type;
965             info.directory_ptr = idx;
966             info_label         = label;
967             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
968 
969             menu_driver_get_last_shader_pass_path(&info_path, &shader_file_name);
970             menu_driver_set_pending_selection(shader_file_name);
971          }
972 #endif
973          break;
974       case ACTION_OK_DL_SHADER_PRESET:
975 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
976          {
977             const char *shader_file_name = NULL;
978 
979             filebrowser_clear_type();
980             info.type          = type;
981             info.directory_ptr = idx;
982             info_label         = label;
983             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
984 
985             menu_driver_get_last_shader_preset_path(&info_path, &shader_file_name);
986             menu_driver_set_pending_selection(shader_file_name);
987          }
988 #endif
989          break;
990       case ACTION_OK_DL_CONTENT_LIST:
991          info.type          = FILE_TYPE_DIRECTORY;
992          info.directory_ptr = idx;
993          info_path          = new_path;
994          info_label         = label;
995          dl_type            = DISPLAYLIST_GENERIC;
996 
997          /* If this is the 'Start Directory' content
998           * list, use last selected directory/file */
999          if ((type == MENU_SETTING_ACTION_FAVORITES_DIR) &&
1000              settings->bools.use_last_start_directory)
1001          {
1002             info_path       = menu_driver_get_last_start_directory();
1003             menu_driver_set_pending_selection(menu_driver_get_last_start_file_name());
1004          }
1005 
1006          break;
1007       case ACTION_OK_DL_SCAN_DIR_LIST:
1008          filebrowser_set_type(FILEBROWSER_SCAN_DIR);
1009          info.type          = FILE_TYPE_DIRECTORY;
1010          info.directory_ptr = idx;
1011          info_path          = new_path;
1012          info_label         = label;
1013          dl_type            = DISPLAYLIST_FILE_BROWSER_SCAN_DIR;
1014          break;
1015       case ACTION_OK_DL_MANUAL_SCAN_DIR_LIST:
1016          filebrowser_set_type(FILEBROWSER_MANUAL_SCAN_DIR);
1017          info.type          = FILE_TYPE_DIRECTORY;
1018          info.directory_ptr = idx;
1019          info_label         = label;
1020          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_DIR;
1021 
1022          action_ok_get_file_browser_start_path(
1023                manual_content_scan_get_content_dir_ptr(),
1024                new_path, parent_dir, sizeof(parent_dir), true);
1025 
1026          info_path          = parent_dir;
1027          break;
1028       case ACTION_OK_DL_MANUAL_CONTENT_SCAN_DAT_FILE:
1029          filebrowser_clear_type();
1030          info.type          = type;
1031          info.directory_ptr = idx;
1032          info_label         = label;
1033          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1034 
1035          action_ok_get_file_browser_start_path(
1036                manual_content_scan_get_dat_file_path_ptr(),
1037                dir_menu_content, parent_dir, sizeof(parent_dir), true);
1038 
1039          info_path          = parent_dir;
1040          break;
1041       case ACTION_OK_DL_REMAP_FILE:
1042          {
1043             struct retro_system_info *system     = runloop_get_libretro_system_info();
1044             const char *core_name                = system ? system->library_name : NULL;
1045 
1046             if (!string_is_empty(core_name) && !string_is_empty(settings->paths.directory_input_remapping))
1047             {
1048                fill_pathname_join(tmp,
1049                      settings->paths.directory_input_remapping, core_name, sizeof(tmp));
1050                if (!path_is_directory(tmp))
1051                   tmp[0] = '\0';
1052             }
1053 
1054             filebrowser_clear_type();
1055             info.type          = type;
1056             info.directory_ptr = idx;
1057             info_path          = !string_is_empty(tmp) ? tmp : settings->paths.directory_input_remapping;
1058             info_label         = label;
1059             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1060          }
1061          break;
1062       case ACTION_OK_DL_STREAM_CONFIGFILE:
1063          {
1064             global_t  *global  = global_get_ptr();
1065             info.type          = type;
1066             info.directory_ptr = idx;
1067             info_path          = global->record.config_dir;
1068             info_label         = label;
1069             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1070          }
1071          break;
1072       case ACTION_OK_DL_RECORD_CONFIGFILE:
1073          filebrowser_clear_type();
1074          {
1075             global_t  *global  = global_get_ptr();
1076             info.type          = type;
1077             info.directory_ptr = idx;
1078             info_path          = global->record.config_dir;
1079             info_label         = label;
1080             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1081          }
1082          break;
1083       case ACTION_OK_DL_DISK_IMAGE_APPEND_LIST:
1084          {
1085             filebrowser_clear_type();
1086             strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp));
1087             path_basedir(tmp);
1088 
1089             info.type          = type;
1090             info.directory_ptr = idx;
1091             info_path          = !string_is_empty(tmp) ? tmp : dir_menu_content;
1092             info_label         = label;
1093             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1094          }
1095          break;
1096       case ACTION_OK_DL_SUBSYSTEM_ADD_LIST:
1097          {
1098             filebrowser_clear_type();
1099             if (content_get_subsystem_rom_id() > 0)
1100                strlcpy(tmp, content_get_subsystem_rom(content_get_subsystem_rom_id() - 1), sizeof(tmp));
1101             else
1102                strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp));
1103             path_basedir(tmp);
1104 
1105             if (content_get_subsystem() != type - MENU_SETTINGS_SUBSYSTEM_ADD)
1106                content_clear_subsystem();
1107             content_set_subsystem(type - MENU_SETTINGS_SUBSYSTEM_ADD);
1108             filebrowser_set_type(FILEBROWSER_SELECT_FILE_SUBSYSTEM);
1109             info.type          = type;
1110             info.directory_ptr = idx;
1111             info_path          = !string_is_empty(tmp) ? tmp : dir_menu_content;
1112             info_label         = label;
1113             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1114          }
1115          break;
1116       case ACTION_OK_DL_SUBSYSTEM_LOAD:
1117          {
1118             content_ctx_info_t content_info = {0};
1119             filebrowser_clear_type();
1120             task_push_load_subsystem_with_core_from_menu(
1121                   NULL, &content_info,
1122                   CORE_TYPE_PLAIN, NULL, NULL);
1123          }
1124          break;
1125       case ACTION_OK_DL_CHEAT_FILE:
1126       case ACTION_OK_DL_CHEAT_FILE_APPEND:
1127 #ifdef HAVE_CHEATS
1128          filebrowser_clear_type();
1129          info.type          = type;
1130          info.directory_ptr = idx;
1131          info_path          = settings->paths.path_cheat_database;
1132          info_label         = label;
1133          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1134 #endif
1135          break;
1136       case ACTION_OK_DL_RGUI_MENU_THEME_PRESET:
1137          {
1138             char rgui_assets_dir[PATH_MAX_LENGTH];
1139             rgui_assets_dir[0] = '\0';
1140 
1141             filebrowser_clear_type();
1142             info.type          = type;
1143             info.directory_ptr = idx;
1144             info_label         = label;
1145             dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1146 
1147             fill_pathname_join(rgui_assets_dir,
1148                   settings->paths.directory_assets, "rgui",
1149                   sizeof(rgui_assets_dir));
1150 
1151             action_ok_get_file_browser_start_path(
1152                   settings->paths.path_rgui_theme_preset,
1153                   rgui_assets_dir,
1154                   parent_dir, sizeof(parent_dir), true);
1155 
1156             info_path          = parent_dir;
1157          }
1158          break;
1159       case ACTION_OK_DL_CORE_LIST:
1160          filebrowser_clear_type();
1161          info.type          = type;
1162          info.directory_ptr = idx;
1163          info_path          = dir_libretro;
1164          info_label         = label;
1165          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_CORE;
1166          break;
1167       case ACTION_OK_DL_SIDELOAD_CORE_LIST:
1168          filebrowser_clear_type();
1169          info.type          = type;
1170          info.directory_ptr = idx;
1171          info_path          = settings->paths.directory_core_assets;
1172          info_label         = label;
1173          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_FILE;
1174          break;
1175       case ACTION_OK_DL_CONTENT_COLLECTION_LIST:
1176          info.type          = type;
1177          info.directory_ptr = idx;
1178          info_path          = settings->paths.directory_playlist;
1179          info_label         = label;
1180          dl_type            = DISPLAYLIST_FILE_BROWSER_SELECT_COLLECTION;
1181          break;
1182       case ACTION_OK_DL_RDB_ENTRY:
1183          filebrowser_clear_type();
1184          fill_pathname_join_delim(tmp,
1185                msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RDB_ENTRY_DETAIL),
1186                path, '|', sizeof(tmp));
1187 
1188          info.directory_ptr = idx;
1189          info_path          = label;
1190          info_label         = tmp;
1191          dl_type            = DISPLAYLIST_GENERIC;
1192          break;
1193       case ACTION_OK_DL_RDB_ENTRY_SUBMENU:
1194          info.directory_ptr = idx;
1195          info_label         = label;
1196          info_path          = path;
1197          dl_type            = DISPLAYLIST_GENERIC;
1198          break;
1199       case ACTION_OK_DL_CONFIGURATIONS_LIST:
1200          info.type          = type;
1201          info.directory_ptr = idx;
1202          if (string_is_empty(settings->paths.directory_menu_config))
1203             info_path        = label;
1204          else
1205             info_path        = settings->paths.directory_menu_config;
1206          info_label          = label;
1207          dl_type             = DISPLAYLIST_GENERIC;
1208          break;
1209       case ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH_DETECT_CORE:
1210          info.type          = type;
1211          info.directory_ptr = idx;
1212          info_path          = path;
1213          info_label         = msg_hash_to_str(
1214                MENU_ENUM_LABEL_DEFERRED_ARCHIVE_ACTION_DETECT_CORE);
1215          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_ARCHIVE_ACTION_DETECT_CORE;
1216 
1217          if (!string_is_empty(path))
1218             strlcpy(menu->scratch_buf, path, sizeof(menu->scratch_buf));
1219          if (!string_is_empty(menu_path))
1220             strlcpy(menu->scratch2_buf, menu_path, sizeof(menu->scratch2_buf));
1221          dl_type            = DISPLAYLIST_GENERIC;
1222          break;
1223       case ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH:
1224          info.type          = type;
1225          info.directory_ptr = idx;
1226          info_path          = path;
1227          info_label         = msg_hash_to_str(
1228                MENU_ENUM_LABEL_DEFERRED_ARCHIVE_ACTION);
1229          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_ARCHIVE_ACTION;
1230 
1231          if (!string_is_empty(path))
1232             strlcpy(menu->scratch_buf, path, sizeof(menu->scratch_buf));
1233          if (!string_is_empty(menu_path))
1234             strlcpy(menu->scratch2_buf, menu_path, sizeof(menu->scratch2_buf));
1235          dl_type                 = DISPLAYLIST_GENERIC;
1236          break;
1237       case ACTION_OK_DL_PARENT_DIRECTORY_PUSH:
1238          parent_dir[0]  = '\0';
1239 
1240          if (path && menu_path)
1241             fill_pathname_join(tmp,
1242                   menu_path, path, sizeof(tmp));
1243 
1244          fill_pathname_parent_dir(parent_dir,
1245                tmp, sizeof(parent_dir));
1246          fill_pathname_parent_dir(parent_dir,
1247                parent_dir, sizeof(parent_dir));
1248 
1249          info.type          = type;
1250          info.directory_ptr = idx;
1251          info_path          = parent_dir;
1252          info_label         = menu_label;
1253          dl_type            = DISPLAYLIST_GENERIC;
1254          break;
1255       case ACTION_OK_DL_DIRECTORY_PUSH:
1256          if (!string_is_empty(path))
1257          {
1258             if (!string_is_empty(menu_path))
1259                fill_pathname_join(
1260                      tmp, menu_path, path, sizeof(tmp));
1261             else
1262                strlcpy(tmp, path, sizeof(tmp));
1263          }
1264 
1265          info.type          = type;
1266          info.directory_ptr = idx;
1267          info_path          = tmp;
1268          info_label         = menu_label;
1269          dl_type            = DISPLAYLIST_GENERIC;
1270          break;
1271       case ACTION_OK_DL_DATABASE_MANAGER_LIST:
1272          {
1273             char lpl_basename[PATH_MAX_LENGTH];
1274             lpl_basename[0] = '\0';
1275             filebrowser_clear_type();
1276             fill_pathname_join(tmp,
1277                   settings->paths.path_content_database,
1278                   path, sizeof(tmp));
1279 
1280             fill_pathname_base_noext(lpl_basename, path, sizeof(lpl_basename));
1281             menu_driver_set_thumbnail_system(lpl_basename, sizeof(lpl_basename));
1282 
1283             info.directory_ptr = idx;
1284             info_path          = tmp;
1285             info_label         = msg_hash_to_str(
1286                   MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST);
1287             info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST;
1288             dl_type            = DISPLAYLIST_GENERIC;
1289          }
1290          break;
1291       case ACTION_OK_DL_CURSOR_MANAGER_LIST:
1292          filebrowser_clear_type();
1293          fill_pathname_join(tmp, settings->paths.directory_cursor,
1294                path, sizeof(tmp));
1295 
1296          info.directory_ptr = idx;
1297          info_path          = tmp;
1298          info_label         = msg_hash_to_str(
1299                MENU_ENUM_LABEL_DEFERRED_CURSOR_MANAGER_LIST);
1300          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CURSOR_MANAGER_LIST;
1301          dl_type            = DISPLAYLIST_GENERIC;
1302          break;
1303          /* Pending clear */
1304       case ACTION_OK_DL_CORE_UPDATER_LIST:
1305          info.type          = type;
1306          info.directory_ptr = idx;
1307          info_path          = path;
1308          info_label         = msg_hash_to_str(
1309                MENU_ENUM_LABEL_DEFERRED_CORE_UPDATER_LIST);
1310          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CORE_UPDATER_LIST;
1311          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1312          break;
1313       case ACTION_OK_DL_THUMBNAILS_UPDATER_LIST:
1314          info.type          = type;
1315          info.directory_ptr = idx;
1316          info_path          = path;
1317          info_label         = msg_hash_to_str(
1318                MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST);
1319          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST;
1320          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1321          break;
1322       case ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST:
1323          info.type          = type;
1324          info.directory_ptr = idx;
1325          info_path          = path;
1326          info_label         = msg_hash_to_str(
1327                MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST);
1328          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST;
1329          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1330          break;
1331       case ACTION_OK_DL_CORE_CONTENT_DIRS_LIST:
1332          info.type          = type;
1333          info.directory_ptr = idx;
1334          info_path          = path;
1335          info_label         = msg_hash_to_str(
1336                MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_LIST);
1337          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_LIST;
1338          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1339          break;
1340       case ACTION_OK_DL_CORE_CONTENT_LIST:
1341          info.type          = type;
1342          info.directory_ptr = idx;
1343          info_path          = path;
1344          info_label         = msg_hash_to_str(
1345                MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_LIST);
1346          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_LIST;
1347          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1348          break;
1349       case ACTION_OK_DL_LAKKA_LIST:
1350          info.type          = type;
1351          info.directory_ptr = idx;
1352          info_path          = path;
1353          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_LAKKA_LIST);
1354          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_LAKKA_LIST;
1355          dl_type            = DISPLAYLIST_PENDING_CLEAR;
1356          break;
1357 
1358       case ACTION_OK_DL_CORE_CONTENT_DIRS_SUBDIR_LIST:
1359          fill_pathname_join_delim(tmp, path, label, ';',
1360                sizeof(tmp));
1361          info.type          = type;
1362          info.directory_ptr = idx;
1363          info_path          = tmp;
1364          info_label         = msg_hash_to_str(
1365                MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_SUBDIR_LIST);
1366          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_SUBDIR_LIST;
1367          dl_type            = DISPLAYLIST_GENERIC;
1368          break;
1369       case ACTION_OK_DL_DEFERRED_CORE_LIST:
1370          info.directory_ptr = idx;
1371          info_path          = dir_libretro;
1372          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CORE_LIST);
1373          info.enum_idx      = MENU_ENUM_LABEL_DEFERRED_CORE_LIST;
1374          dl_type            = DISPLAYLIST_GENERIC;
1375          break;
1376       case ACTION_OK_DL_DEFERRED_CORE_LIST_SET:
1377          info.directory_ptr                       = idx;
1378          menu->scratchpad.unsigned_var            = (unsigned)idx;
1379          info_path                                = dir_libretro;
1380          info_label                               = msg_hash_to_str(
1381                MENU_ENUM_LABEL_DEFERRED_CORE_LIST_SET);
1382          info.enum_idx                            =
1383             MENU_ENUM_LABEL_DEFERRED_CORE_LIST_SET;
1384          dl_type                                  = DISPLAYLIST_GENERIC;
1385          break;
1386       case ACTION_OK_DL_CHEAT_DETAILS_SETTINGS_LIST:
1387 #ifdef HAVE_CHEATS
1388          {
1389             rarch_setting_t *setting = NULL;
1390 
1391             cheat_manager_copy_idx_to_working(type-MENU_SETTINGS_CHEAT_BEGIN);
1392             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_IDX);
1393             if (setting)
1394                setting->max = cheat_manager_get_size()-1;
1395             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_VALUE);
1396             if (setting)
1397                setting->max = cheat_manager_get_state_search_size(cheat_manager_state.working_cheat.memory_search_size);
1398             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_RUMBLE_VALUE);
1399             if (setting)
1400                setting->max = cheat_manager_get_state_search_size(cheat_manager_state.working_cheat.memory_search_size);
1401             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_ADDRESS_BIT_POSITION);
1402             if (setting)
1403             {
1404                int max_bit_position = cheat_manager_state.working_cheat.memory_search_size<3 ? 7 : 0;
1405                setting->max = max_bit_position;
1406             }
1407             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_ADDRESS);
1408             if (setting)
1409                cheat_manager_state.browse_address = *setting->value.target.unsigned_integer;
1410             ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
1411          }
1412 #endif
1413          break;
1414       case ACTION_OK_DL_CHEAT_SEARCH_SETTINGS_LIST:
1415 #ifdef HAVE_CHEATS
1416          {
1417             rarch_setting_t *setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_SEARCH_EXACT);
1418             if (setting)
1419                setting->max = cheat_manager_get_state_search_size(cheat_manager_state.search_bit_size);
1420             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_SEARCH_EQPLUS);
1421             if (setting)
1422                setting->max = cheat_manager_get_state_search_size(cheat_manager_state.search_bit_size);
1423             setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_SEARCH_EQMINUS);
1424             if (setting)
1425                setting->max = cheat_manager_get_state_search_size(cheat_manager_state.search_bit_size);
1426             ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
1427          }
1428 #endif
1429          break;
1430       case ACTION_OK_DL_MIXER_STREAM_SETTINGS_LIST:
1431       {
1432          unsigned player_no = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_BEGIN;
1433          ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
1434          info.type          = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN + player_no;
1435       }
1436          break;
1437       case ACTION_OK_DL_ACCOUNTS_LIST:
1438       case ACTION_OK_DL_ACHIEVEMENTS_HARDCORE_PAUSE_LIST:
1439       case ACTION_OK_DL_INPUT_SETTINGS_LIST:
1440       case ACTION_OK_DL_INPUT_MENU_SETTINGS_LIST:
1441       case ACTION_OK_DL_INPUT_TURBO_FIRE_SETTINGS_LIST:
1442       case ACTION_OK_DL_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST:
1443       case ACTION_OK_DL_LATENCY_SETTINGS_LIST:
1444       case ACTION_OK_DL_DRIVER_SETTINGS_LIST:
1445       case ACTION_OK_DL_CORE_SETTINGS_LIST:
1446       case ACTION_OK_DL_CORE_INFORMATION_LIST:
1447       case ACTION_OK_DL_VIDEO_SETTINGS_LIST:
1448       case ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST:
1449       case ACTION_OK_DL_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST:
1450       case ACTION_OK_DL_VIDEO_WINDOWED_MODE_SETTINGS_LIST:
1451       case ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST:
1452       case ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST:
1453       case ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST:
1454       case ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST:
1455       case ACTION_OK_DL_SAVING_SETTINGS_LIST:
1456       case ACTION_OK_DL_LOGGING_SETTINGS_LIST:
1457       case ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST:
1458       case ACTION_OK_DL_FRAME_TIME_COUNTER_SETTINGS_LIST:
1459       case ACTION_OK_DL_REWIND_SETTINGS_LIST:
1460       case ACTION_OK_DL_ONSCREEN_DISPLAY_SETTINGS_LIST:
1461       case ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST:
1462       case ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST:
1463       case ACTION_OK_DL_ONSCREEN_OVERLAY_SETTINGS_LIST:
1464 #ifdef HAVE_VIDEO_LAYOUT
1465       case ACTION_OK_DL_ONSCREEN_VIDEO_LAYOUT_SETTINGS_LIST:
1466 #endif
1467       case ACTION_OK_DL_MENU_SETTINGS_LIST:
1468       case ACTION_OK_DL_MENU_VIEWS_SETTINGS_LIST:
1469       case ACTION_OK_DL_SETTINGS_VIEWS_SETTINGS_LIST:
1470       case ACTION_OK_DL_QUICK_MENU_VIEWS_SETTINGS_LIST:
1471       case ACTION_OK_DL_QUICK_MENU_OVERRIDE_OPTIONS_LIST:
1472       case ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST:
1473       case ACTION_OK_DL_AI_SERVICE_SETTINGS_LIST:
1474       case ACTION_OK_DL_ACCESSIBILITY_SETTINGS_LIST:
1475       case ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST:
1476       case ACTION_OK_DL_CPU_PERFPOWER_SETTINGS_LIST:
1477       case ACTION_OK_DL_CPU_POLICY_SETTINGS_LIST:
1478       case ACTION_OK_DL_MENU_SOUNDS_LIST:
1479       case ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST:
1480       case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST:
1481       case ACTION_OK_DL_UPDATER_SETTINGS_LIST:
1482       case ACTION_OK_DL_NETWORK_SETTINGS_LIST:
1483       case ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST:
1484       case ACTION_OK_DL_SUBSYSTEM_SETTINGS_LIST:
1485       case ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST:
1486       case ACTION_OK_DL_WIFI_SETTINGS_LIST:
1487       case ACTION_OK_DL_WIFI_NETWORKS_LIST:
1488       case ACTION_OK_DL_NETPLAY:
1489       case ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST:
1490       case ACTION_OK_DL_LAKKA_SERVICES_LIST:
1491       case ACTION_OK_DL_USER_SETTINGS_LIST:
1492       case ACTION_OK_DL_DIRECTORY_SETTINGS_LIST:
1493       case ACTION_OK_DL_PRIVACY_SETTINGS_LIST:
1494       case ACTION_OK_DL_MIDI_SETTINGS_LIST:
1495       case ACTION_OK_DL_AUDIO_SETTINGS_LIST:
1496       case ACTION_OK_DL_AUDIO_SYNCHRONIZATION_SETTINGS_LIST:
1497       case ACTION_OK_DL_AUDIO_OUTPUT_SETTINGS_LIST:
1498       case ACTION_OK_DL_AUDIO_RESAMPLER_SETTINGS_LIST:
1499       case ACTION_OK_DL_AUDIO_MIXER_SETTINGS_LIST:
1500       case ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST:
1501       case ACTION_OK_DL_RECORDING_SETTINGS_LIST:
1502       case ACTION_OK_DL_PLAYLIST_SETTINGS_LIST:
1503       case ACTION_OK_DL_PLAYLIST_MANAGER_LIST:
1504       case ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS:
1505       case ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST:
1506       case ACTION_OK_DL_ACCOUNTS_YOUTUBE_LIST:
1507       case ACTION_OK_DL_ACCOUNTS_TWITCH_LIST:
1508       case ACTION_OK_DL_ACCOUNTS_FACEBOOK_LIST:
1509       case ACTION_OK_DL_PLAYLIST_COLLECTION:
1510       case ACTION_OK_DL_FAVORITES_LIST:
1511       case ACTION_OK_DL_BROWSE_URL_LIST:
1512       case ACTION_OK_DL_MUSIC_LIST:
1513       case ACTION_OK_DL_IMAGES_LIST:
1514       case ACTION_OK_DL_LOAD_DISC_LIST:
1515       case ACTION_OK_DL_DUMP_DISC_LIST:
1516       case ACTION_OK_DL_SHADER_PRESET_REMOVE:
1517       case ACTION_OK_DL_SHADER_PRESET_SAVE:
1518       case ACTION_OK_DL_CDROM_INFO_LIST:
1519       case ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST:
1520       case ACTION_OK_DL_CORE_MANAGER_LIST:
1521       case ACTION_OK_DL_CORE_OPTION_OVERRIDE_LIST:
1522          ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
1523          break;
1524       case ACTION_OK_DL_CDROM_INFO_DETAIL_LIST:
1525       case ACTION_OK_DL_CORE_RESTORE_BACKUP_LIST:
1526       case ACTION_OK_DL_CORE_DELETE_BACKUP_LIST:
1527          ACTION_OK_DL_LBL(action_ok_dl_to_enum(action_type), DISPLAYLIST_GENERIC);
1528          info_path          = label;
1529          break;
1530       case ACTION_OK_DL_CONTENT_SETTINGS:
1531          info.list          = menu_entries_get_selection_buf_ptr(0);
1532          info_path          = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS);
1533          info_label         = msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_SETTINGS);
1534          info.enum_idx      = MENU_ENUM_LABEL_CONTENT_SETTINGS;
1535          menu_entries_append_enum(menu_stack, info_path, info_label,
1536                MENU_ENUM_LABEL_CONTENT_SETTINGS,
1537                0, 0, 0);
1538          dl_type            = DISPLAYLIST_CONTENT_SETTINGS;
1539          break;
1540    }
1541 
1542    if (info_label)
1543       info.label = strdup(info_label);
1544    if (info_path)
1545       info.path  = strdup(info_path);
1546 
1547    if (menu_displaylist_ctl(dl_type, &info, settings))
1548    {
1549       if (menu_displaylist_process(&info))
1550       {
1551          menu_displaylist_info_free(&info);
1552          return 0;
1553       }
1554    }
1555 
1556    menu_displaylist_info_free(&info);
1557    return menu_cbs_exit();
1558 }
1559 
1560 /**
1561  * menu_content_find_first_core:
1562  * @core_info            : Core info list handle.
1563  * @dir                  : Directory. Gets joined with @path.
1564  * @path                 : Path. Gets joined with @dir.
1565  * @menu_label           : Label identifier of menu setting.
1566  * @s                    : Deferred core path. Will be filled in
1567  *                         by function.
1568  * @len                  : Size of @s.
1569  *
1570  * Gets deferred core.
1571  *
1572  * Returns: false if there are multiple deferred cores and a
1573  * selection needs to be made from a list, otherwise
1574  * returns true and fills in @s with path to core.
1575  **/
menu_content_find_first_core(menu_content_ctx_defer_info_t * def_info,bool load_content_with_current_core,char * new_core_path,size_t len)1576 static bool menu_content_find_first_core(menu_content_ctx_defer_info_t *def_info,
1577       bool load_content_with_current_core,
1578       char *new_core_path, size_t len)
1579 {
1580    const core_info_t *info                 = NULL;
1581    size_t supported                        = 0;
1582    core_info_list_t *core_info             = (core_info_list_t*)def_info->data;
1583    const char *default_info_dir            = def_info->dir;
1584 
1585    if (!string_is_empty(default_info_dir))
1586    {
1587       const char *default_info_path = def_info->path;
1588       size_t default_info_length    = def_info->len;
1589 
1590       if (!string_is_empty(default_info_path))
1591          fill_pathname_join(def_info->s,
1592                default_info_dir, default_info_path,
1593                default_info_length);
1594 
1595 #ifdef HAVE_COMPRESSION
1596       if (path_is_compressed_file(default_info_dir))
1597       {
1598          size_t _len = strlen(default_info_dir);
1599          /* In case of a compressed archive, we have to join with a hash */
1600          /* We are going to write at the position of dir: */
1601          def_info->s[_len] = '#';
1602       }
1603 #endif
1604    }
1605 
1606    if (core_info)
1607       core_info_list_get_supported_cores(core_info,
1608             def_info->s, &info,
1609             &supported);
1610 
1611    /* We started the menu with 'Load Content', we are
1612     * going to use the current core to load this. */
1613    if (load_content_with_current_core)
1614    {
1615       core_info_get_current_core((core_info_t**)&info);
1616       if (info)
1617       {
1618 #if 0
1619          RARCH_LOG("[lobby] use the current core (%s) to load this content...\n",
1620                info->path);
1621 #endif
1622          supported = 1;
1623       }
1624    }
1625 
1626    /* There are multiple deferred cores and a
1627     * selection needs to be made from a list, return 0. */
1628    if (supported != 1)
1629       return false;
1630 
1631     if (info)
1632       strlcpy(new_core_path, info->path, len);
1633 
1634    return true;
1635 }
1636 
1637 #ifdef HAVE_LIBRETRODB
1638 void handle_dbscan_finished(retro_task_t *task,
1639       void *task_data, void *user_data, const char *err);
1640 #endif
1641 
content_add_to_playlist(const char * path)1642 static void content_add_to_playlist(const char *path)
1643 {
1644 #if 0
1645 #ifdef HAVE_LIBRETRODB
1646    settings_t *settings = config_get_ptr();
1647    if (!settings || !settings->bools.automatically_add_content_to_playlist)
1648       return;
1649    task_push_dbscan(
1650          settings->paths.directory_playlist,
1651          settings->paths.path_content_database,
1652          path, false,
1653          settings->bools.show_hidden_files,
1654          handle_dbscan_finished);
1655 #endif
1656 #endif
1657 }
1658 
file_load_with_detect_core_wrapper(enum msg_hash_enums enum_label_idx,size_t idx,size_t entry_idx,const char * path,const char * label,unsigned type,bool is_carchive)1659 static int file_load_with_detect_core_wrapper(
1660       enum msg_hash_enums enum_label_idx,
1661       size_t idx, size_t entry_idx,
1662       const char *path, const char *label,
1663       unsigned type, bool is_carchive)
1664 {
1665    int ret                             = 0;
1666    menu_handle_t *menu                 = menu_driver_get_ptr();
1667 
1668    if (!menu)
1669       return menu_cbs_exit();
1670 
1671    {
1672       menu_content_ctx_defer_info_t def_info;
1673       char menu_path_new[PATH_MAX_LENGTH];
1674       char new_core_path[PATH_MAX_LENGTH];
1675       const char *menu_path                  = NULL;
1676       const char *menu_label                 = NULL;
1677       core_info_list_t *list                 = NULL;
1678       new_core_path[0]    = menu_path_new[0] = '\0';
1679 
1680       menu_entries_get_last_stack(&menu_path, &menu_label, NULL, NULL, NULL);
1681 
1682       if (!string_is_empty(menu_path))
1683          strlcpy(menu_path_new, menu_path, sizeof(menu_path_new));
1684 
1685       if (string_is_equal(menu_label,
1686                msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN_DETECT_CORE)))
1687          fill_pathname_join(menu_path_new,
1688                menu->scratch2_buf, menu->scratch_buf, sizeof(menu_path_new));
1689       else if (string_is_equal(menu_label,
1690                msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN)))
1691          fill_pathname_join(menu_path_new,
1692                menu->scratch2_buf, menu->scratch_buf, sizeof(menu_path_new));
1693 
1694       core_info_get_list(&list);
1695 
1696       def_info.data       = list;
1697       def_info.dir        = menu_path_new;
1698       def_info.path       = path;
1699       def_info.menu_label = menu_label;
1700       def_info.s          = menu->deferred_path;
1701       def_info.len        = sizeof(menu->deferred_path);
1702 
1703       if (menu_content_find_first_core(&def_info, false, new_core_path,
1704                sizeof(new_core_path)))
1705          ret = -1;
1706 
1707       if (     !is_carchive && !string_is_empty(path)
1708             && !string_is_empty(menu_path_new))
1709          fill_pathname_join(menu->detect_content_path,
1710                menu_path_new, path,
1711                sizeof(menu->detect_content_path));
1712 
1713       if (enum_label_idx == MENU_ENUM_LABEL_COLLECTION)
1714          return generic_action_ok_displaylist_push(path, NULL,
1715                NULL, 0, idx, entry_idx, ACTION_OK_DL_DEFERRED_CORE_LIST_SET);
1716 
1717       switch (ret)
1718       {
1719          case -1:
1720             {
1721                content_ctx_info_t content_info;
1722 
1723                content_info.argc        = 0;
1724                content_info.argv        = NULL;
1725                content_info.args        = NULL;
1726                content_info.environ_get = NULL;
1727 
1728                if (!task_push_load_content_with_new_core_from_menu(
1729                         new_core_path, def_info.s,
1730                         &content_info,
1731                         CORE_TYPE_PLAIN,
1732                         NULL, NULL))
1733                   return -1;
1734 
1735                content_add_to_playlist(def_info.s);
1736                menu_driver_set_last_start_content(def_info.s);
1737 
1738                ret = 0;
1739                break;
1740             }
1741          case 0:
1742             ret = generic_action_ok_displaylist_push(path, NULL, label, type,
1743                   idx, entry_idx, ACTION_OK_DL_DEFERRED_CORE_LIST);
1744             break;
1745          default:
1746             break;
1747       }
1748    }
1749 
1750    return ret;
1751 }
1752 
action_ok_file_load_with_detect_core_carchive(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)1753 static int action_ok_file_load_with_detect_core_carchive(
1754       const char *path,
1755       const char *label, unsigned type, size_t idx, size_t entry_idx)
1756 {
1757    menu_handle_t *menu                 = menu_driver_get_ptr();
1758 
1759    if (!menu)
1760       return menu_cbs_exit();
1761 
1762    fill_pathname_join_delim(menu->detect_content_path,
1763          menu->detect_content_path, path,
1764          '#', sizeof(menu->detect_content_path));
1765 
1766    type = 0;
1767    label = NULL;
1768 
1769    return file_load_with_detect_core_wrapper(
1770          MSG_UNKNOWN, idx, entry_idx,
1771          path, label, type, true);
1772 }
1773 
action_ok_file_load_with_detect_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)1774 static int action_ok_file_load_with_detect_core(const char *path,
1775       const char *label, unsigned type, size_t idx, size_t entry_idx)
1776 {
1777 
1778    type  = 0;
1779    label = NULL;
1780 
1781    return file_load_with_detect_core_wrapper(
1782          MSG_UNKNOWN, idx, entry_idx,
1783          path, label, type, false);
1784 }
1785 
action_ok_file_load_with_detect_core_collection(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)1786 static int action_ok_file_load_with_detect_core_collection(const char *path,
1787       const char *label, unsigned type, size_t idx, size_t entry_idx)
1788 {
1789    type  = 0;
1790    label = NULL;
1791 
1792    return file_load_with_detect_core_wrapper(
1793          MENU_ENUM_LABEL_COLLECTION,
1794          idx, entry_idx,
1795          path, label, type, false);
1796 }
1797 
set_path_generic(const char * label,const char * action_path)1798 static int set_path_generic(const char *label, const char *action_path)
1799 {
1800    rarch_setting_t *setting = menu_setting_find(label);
1801 
1802    if (setting)
1803    {
1804       setting_set_with_string_representation(
1805             setting, action_path);
1806       return menu_setting_generic(setting, 0, false);
1807    }
1808 
1809    return 0;
1810 }
1811 
generic_action_ok_command(enum event_command cmd)1812 int generic_action_ok_command(enum event_command cmd)
1813 {
1814 #ifdef HAVE_AUDIOMIXER
1815    settings_t *settings      = config_get_ptr();
1816    bool audio_enable_menu    = settings->bools.audio_enable_menu;
1817    bool audio_enable_menu_ok = settings->bools.audio_enable_menu_ok;
1818 
1819    if (audio_enable_menu && audio_enable_menu_ok)
1820       audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
1821 #endif
1822 
1823    if (!command_event(cmd, NULL))
1824       return menu_cbs_exit();
1825    return 0;
1826 }
1827 
generic_action_ok(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,unsigned id,enum msg_hash_enums flush_id)1828 static int generic_action_ok(const char *path,
1829       const char *label, unsigned type, size_t idx, size_t entry_idx,
1830       unsigned id, enum msg_hash_enums flush_id)
1831 {
1832    char action_path[PATH_MAX_LENGTH];
1833    unsigned flush_type               = 0;
1834    int ret                           = 0;
1835    enum msg_hash_enums enum_idx      = MSG_UNKNOWN;
1836    const char             *menu_path = NULL;
1837    const char            *menu_label = NULL;
1838    const char *flush_char            = NULL;
1839    menu_handle_t               *menu = menu_driver_get_ptr();
1840 #ifdef HAVE_AUDIOMIXER
1841    settings_t              *settings = config_get_ptr();
1842    bool audio_enable_menu            = settings->bools.audio_enable_menu;
1843    bool audio_enable_menu_ok         = settings->bools.audio_enable_menu_ok;
1844 
1845    if (audio_enable_menu && audio_enable_menu_ok)
1846       audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
1847 #endif
1848 
1849    if (!menu)
1850       goto error;
1851 
1852    menu_entries_get_last_stack(&menu_path,
1853          &menu_label, NULL, &enum_idx, NULL);
1854 
1855    action_path[0] = '\0';
1856 
1857    if (!string_is_empty(path))
1858       fill_pathname_join(action_path,
1859             menu_path, path, sizeof(action_path));
1860    else
1861       strlcpy(action_path, menu_path, sizeof(action_path));
1862 
1863    switch (id)
1864    {
1865       case ACTION_OK_LOAD_WALLPAPER:
1866          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MENU_SETTINGS_LIST);
1867          if (filestream_exists(action_path))
1868          {
1869             settings_t            *settings = config_get_ptr();
1870 
1871             configuration_set_string(settings,
1872                   settings->paths.path_menu_wallpaper,
1873                   action_path);
1874 
1875             task_push_image_load(action_path,
1876                   video_driver_supports_rgba(), 0,
1877                   menu_display_handle_wallpaper_upload, NULL);
1878          }
1879          break;
1880       case ACTION_OK_LOAD_CORE:
1881          {
1882             content_ctx_info_t content_info;
1883 
1884             content_info.argc        = 0;
1885             content_info.argv        = NULL;
1886             content_info.args        = NULL;
1887             content_info.environ_get = NULL;
1888 
1889             flush_type = MENU_SETTINGS;
1890 
1891             if (!task_push_load_new_core(
1892                      action_path, NULL,
1893                      &content_info,
1894                      CORE_TYPE_PLAIN,
1895                      NULL, NULL))
1896             {
1897 #ifndef HAVE_DYNAMIC
1898                ret = -1;
1899 #endif
1900             }
1901          }
1902          break;
1903       case ACTION_OK_LOAD_CONFIG_FILE:
1904 #ifdef HAVE_CONFIGFILE
1905          {
1906             settings_t            *settings = config_get_ptr();
1907             bool config_save_on_exit        = settings->bools.config_save_on_exit;
1908             flush_type                      = MENU_SETTINGS;
1909 
1910             gfx_display_set_msg_force(true);
1911 
1912             if (config_replace(config_save_on_exit, action_path))
1913             {
1914                bool pending_push = false;
1915                menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push);
1916                ret = -1;
1917             }
1918          }
1919 #endif
1920          break;
1921       case ACTION_OK_LOAD_PRESET:
1922 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
1923          {
1924             struct video_shader      *shader  = menu_shader_get();
1925             flush_char = msg_hash_to_str(flush_id);
1926 
1927             /* Cache selected shader parent directory/file name */
1928             menu_driver_set_last_shader_preset_path(action_path);
1929 
1930             menu_shader_manager_set_preset(shader,
1931                   menu_driver_get_last_shader_preset_type(),
1932                   action_path,
1933                   true);
1934          }
1935 #endif
1936          break;
1937       case ACTION_OK_LOAD_SHADER_PASS:
1938 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
1939          {
1940             struct video_shader *shader           = menu_shader_get();
1941             struct video_shader_pass *shader_pass = shader ? &shader->pass[menu->scratchpad.unsigned_var] : NULL;
1942             flush_char                            = msg_hash_to_str((enum msg_hash_enums)flush_id);
1943 
1944             if (shader_pass)
1945             {
1946                /* Cache selected shader parent directory/file name */
1947                menu_driver_set_last_shader_pass_path(action_path);
1948 
1949                strlcpy(
1950                      shader_pass->source.path,
1951                      action_path,
1952                      sizeof(shader_pass->source.path));
1953                video_shader_resolve_parameters(shader);
1954 
1955                shader->modified         = true;
1956             }
1957          }
1958 #endif
1959          break;
1960       case ACTION_OK_LOAD_STREAM_CONFIGFILE:
1961          {
1962             settings_t *settings = config_get_ptr();
1963             flush_char       = msg_hash_to_str(flush_id);
1964 
1965             if (settings)
1966             {
1967                configuration_set_string(settings,
1968                      settings->paths.path_stream_config, action_path);
1969             }
1970          }
1971          break;
1972       case ACTION_OK_LOAD_RECORD_CONFIGFILE:
1973          {
1974             settings_t *settings = config_get_ptr();
1975             flush_char           = msg_hash_to_str(flush_id);
1976 
1977             if (settings)
1978             {
1979                configuration_set_string(settings,
1980                      settings->paths.path_record_config, action_path);
1981             }
1982          }
1983          break;
1984       case ACTION_OK_LOAD_REMAPPING_FILE:
1985 #ifdef HAVE_CONFIGFILE
1986          {
1987             config_file_t     *conf = config_file_new_from_path_to_string(
1988                   action_path);
1989             retro_ctx_controller_info_t pad;
1990             unsigned current_device = 0;
1991             unsigned port           = 0;
1992             int conf_val            = 0;
1993             char conf_key[64];
1994             flush_char              = msg_hash_to_str(flush_id);
1995 
1996             conf_key[0]             = '\0';
1997 
1998             if (conf)
1999             {
2000                if (input_remapping_load_file(conf, action_path))
2001                {
2002                   for (port = 0; port < MAX_USERS; port++)
2003                   {
2004                      snprintf(conf_key, sizeof(conf_key), "input_libretro_device_p%u", port + 1);
2005                      if (!config_get_int(conf, conf_key, &conf_val))
2006                         continue;
2007 
2008                      current_device = input_config_get_device(port);
2009                      input_config_set_device(port, current_device);
2010                      pad.port   = port;
2011                      pad.device = current_device;
2012                      core_set_controller_port_device(&pad);
2013                   }
2014                }
2015                config_file_free(conf);
2016                conf = NULL;
2017             }
2018          }
2019 #endif
2020          break;
2021       case ACTION_OK_LOAD_CHEAT_FILE:
2022 #ifdef HAVE_CHEATS
2023          flush_char = msg_hash_to_str(flush_id);
2024          cheat_manager_state_free();
2025 
2026          if (!cheat_manager_load(action_path,false))
2027             goto error;
2028 #endif
2029          break;
2030       case ACTION_OK_LOAD_CHEAT_FILE_APPEND:
2031 #ifdef HAVE_CHEATS
2032          flush_char = msg_hash_to_str(flush_id);
2033 
2034          if (!cheat_manager_load(action_path,true))
2035             goto error;
2036 #endif
2037          break;
2038       case ACTION_OK_LOAD_RGUI_MENU_THEME_PRESET:
2039          {
2040             settings_t *settings = config_get_ptr();
2041             flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MENU_SETTINGS_LIST);
2042 
2043             if (settings)
2044             {
2045                configuration_set_string(settings,
2046                      settings->paths.path_rgui_theme_preset, action_path);
2047             }
2048          }
2049          break;
2050       case ACTION_OK_SUBSYSTEM_ADD:
2051          flush_type = MENU_SETTINGS;
2052          content_add_subsystem(action_path);
2053          break;
2054       case ACTION_OK_SET_DIRECTORY:
2055          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DIRECTORY_SETTINGS_LIST);
2056 #ifdef HAVE_COCOATOUCH
2057          /* For iOS, set the path using realpath because the
2058           * path name can start with /private and this ensures
2059           * the path starts with it.
2060           *
2061           * This will allow the path to be properly substituted
2062           * when fill_pathname_expand_special
2063           * is called.
2064           */
2065          {
2066             char real_action_path[PATH_MAX_LENGTH];
2067             real_action_path[0] = '\0';
2068             realpath(action_path, real_action_path);
2069             strlcpy(action_path, real_action_path, sizeof(action_path));
2070          }
2071 #endif
2072          ret        = set_path_generic(menu->filebrowser_label, action_path);
2073          break;
2074       case ACTION_OK_SET_PATH_VIDEO_FILTER:
2075          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_VIDEO_SETTINGS_LIST);
2076          ret        = set_path_generic(menu_label, action_path);
2077          break;
2078       case ACTION_OK_SET_PATH_AUDIO_FILTER:
2079          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST);
2080          ret        = set_path_generic(menu_label, action_path);
2081          break;
2082       case ACTION_OK_SET_PATH_OVERLAY:
2083          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ONSCREEN_OVERLAY_SETTINGS_LIST);
2084          ret        = set_path_generic(menu_label, action_path);
2085          break;
2086 #ifdef HAVE_VIDEO_LAYOUT
2087       case ACTION_OK_SET_PATH_VIDEO_LAYOUT:
2088          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ONSCREEN_VIDEO_LAYOUT_SETTINGS_LIST);
2089          ret        = set_path_generic(menu_label, action_path);
2090          break;
2091 #endif
2092       case ACTION_OK_SET_PATH_VIDEO_FONT:
2093          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST);
2094          ret        = set_path_generic(menu_label, action_path);
2095          break;
2096       case ACTION_OK_SET_MANUAL_CONTENT_SCAN_DAT_FILE:
2097          flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST);
2098          ret        = set_path_generic(menu_label, action_path);
2099          break;
2100       case ACTION_OK_SET_PATH:
2101          flush_type = MENU_SETTINGS;
2102          ret        = set_path_generic(menu_label, action_path);
2103          break;
2104       default:
2105          flush_char = msg_hash_to_str(flush_id);
2106          break;
2107    }
2108 
2109    menu_entries_flush_stack(flush_char, flush_type);
2110 
2111    return ret;
2112 
2113 error:
2114    return menu_cbs_exit();
2115 }
2116 
default_action_ok_load_content_with_core_from_menu(const char * _path,unsigned _type)2117 static int default_action_ok_load_content_with_core_from_menu(const char *_path, unsigned _type)
2118 {
2119    content_ctx_info_t content_info;
2120    content_info.argc                   = 0;
2121    content_info.argv                   = NULL;
2122    content_info.args                   = NULL;
2123    content_info.environ_get            = NULL;
2124    if (!task_push_load_content_with_core_from_menu(
2125             _path, &content_info,
2126             (enum rarch_core_type)_type, NULL, NULL))
2127       return -1;
2128    content_add_to_playlist(_path);
2129    menu_driver_set_last_start_content(_path);
2130    return 0;
2131 }
2132 
default_action_ok_load_content_from_playlist_from_menu(const char * _path,const char * path,const char * entry_label)2133 static int default_action_ok_load_content_from_playlist_from_menu(const char *_path,
2134       const char *path, const char *entry_label)
2135 {
2136    content_ctx_info_t content_info;
2137    content_info.argc                   = 0;
2138    content_info.argv                   = NULL;
2139    content_info.args                   = NULL;
2140    content_info.environ_get            = NULL;
2141    if (!task_push_load_content_from_playlist_from_menu(
2142             _path, path, entry_label,
2143             &content_info,
2144             NULL, NULL))
2145       return -1;
2146    return 0;
2147 }
2148 
DEFAULT_ACTION_OK_SET(action_ok_set_path_audiofilter,ACTION_OK_SET_PATH_AUDIO_FILTER,MSG_UNKNOWN)2149 DEFAULT_ACTION_OK_SET(action_ok_set_path_audiofilter, ACTION_OK_SET_PATH_AUDIO_FILTER, MSG_UNKNOWN)
2150 DEFAULT_ACTION_OK_SET(action_ok_set_path_videofilter, ACTION_OK_SET_PATH_VIDEO_FILTER, MSG_UNKNOWN)
2151 DEFAULT_ACTION_OK_SET(action_ok_set_path_overlay,     ACTION_OK_SET_PATH_OVERLAY,      MSG_UNKNOWN)
2152 #ifdef HAVE_VIDEO_LAYOUT
2153 DEFAULT_ACTION_OK_SET(action_ok_set_path_video_layout,ACTION_OK_SET_PATH_VIDEO_LAYOUT, MSG_UNKNOWN)
2154 #endif
2155 DEFAULT_ACTION_OK_SET(action_ok_set_path_video_font,  ACTION_OK_SET_PATH_VIDEO_FONT,   MSG_UNKNOWN)
2156 DEFAULT_ACTION_OK_SET(action_ok_set_path,             ACTION_OK_SET_PATH,              MSG_UNKNOWN)
2157 DEFAULT_ACTION_OK_SET(action_ok_load_core,            ACTION_OK_LOAD_CORE,             MSG_UNKNOWN)
2158 DEFAULT_ACTION_OK_SET(action_ok_config_load,          ACTION_OK_LOAD_CONFIG_FILE,      MSG_UNKNOWN)
2159 DEFAULT_ACTION_OK_SET(action_ok_subsystem_add,        ACTION_OK_SUBSYSTEM_ADD,         MSG_UNKNOWN)
2160 DEFAULT_ACTION_OK_SET(action_ok_cheat_file_load,      ACTION_OK_LOAD_CHEAT_FILE,       MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS)
2161 DEFAULT_ACTION_OK_SET(action_ok_cheat_file_load_append,      ACTION_OK_LOAD_CHEAT_FILE_APPEND,       MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS)
2162 DEFAULT_ACTION_OK_SET(action_ok_record_configfile_load,      ACTION_OK_LOAD_RECORD_CONFIGFILE,       MENU_ENUM_LABEL_RECORDING_SETTINGS)
2163 DEFAULT_ACTION_OK_SET(action_ok_stream_configfile_load,      ACTION_OK_LOAD_STREAM_CONFIGFILE,       MENU_ENUM_LABEL_RECORDING_SETTINGS)
2164 DEFAULT_ACTION_OK_SET(action_ok_remap_file_load,      ACTION_OK_LOAD_REMAPPING_FILE,   MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS    )
2165 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
2166 DEFAULT_ACTION_OK_SET(action_ok_shader_preset_load,   ACTION_OK_LOAD_PRESET   ,        MENU_ENUM_LABEL_SHADER_OPTIONS)
2167 DEFAULT_ACTION_OK_SET(action_ok_shader_pass_load,     ACTION_OK_LOAD_SHADER_PASS,      MENU_ENUM_LABEL_SHADER_OPTIONS)
2168 #endif
2169 DEFAULT_ACTION_OK_SET(action_ok_rgui_menu_theme_preset_load,  ACTION_OK_LOAD_RGUI_MENU_THEME_PRESET,  MENU_ENUM_LABEL_MENU_SETTINGS)
2170 DEFAULT_ACTION_OK_SET(action_ok_set_manual_content_scan_dat_file, ACTION_OK_SET_MANUAL_CONTENT_SCAN_DAT_FILE, MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST)
2171 
2172 static int action_ok_file_load(const char *path,
2173       const char *label, unsigned type, size_t idx, size_t entry_idx)
2174 {
2175    char menu_path_new[PATH_MAX_LENGTH];
2176    char full_path_new[PATH_MAX_LENGTH];
2177    const char *menu_label              = NULL;
2178    const char *menu_path               = NULL;
2179    rarch_setting_t *setting            = NULL;
2180    file_list_t  *menu_stack            = menu_entries_get_menu_stack_ptr(0);
2181 
2182    menu_path_new[0] = full_path_new[0] = '\0';
2183 
2184    if (filebrowser_get_type() == FILEBROWSER_SELECT_FILE_SUBSYSTEM)
2185    {
2186       /* TODO/FIXME - this path is triggered when we try to load a
2187        * file from an archive while inside the load subsystem
2188        * action */
2189       menu_handle_t *menu                 = menu_driver_get_ptr();
2190       if (!menu)
2191          return menu_cbs_exit();
2192 
2193       fill_pathname_join(menu_path_new,
2194             menu->scratch2_buf, menu->scratch_buf,
2195             sizeof(menu_path_new));
2196       switch (type)
2197       {
2198          case FILE_TYPE_IN_CARCHIVE:
2199             fill_pathname_join_delim(full_path_new, menu_path_new, path,
2200                   '#',sizeof(full_path_new));
2201             break;
2202          default:
2203             fill_pathname_join(full_path_new, menu_path_new, path,
2204                   sizeof(full_path_new));
2205             break;
2206       }
2207 
2208       content_add_subsystem(full_path_new);
2209       menu_entries_flush_stack(NULL, MENU_SETTINGS);
2210       return 0;
2211    }
2212 
2213    file_list_get_last(menu_stack, &menu_path, &menu_label, NULL, NULL);
2214 
2215    if (!string_is_empty(menu_label))
2216       setting = menu_setting_find(menu_label);
2217 
2218    if (setting && setting->type == ST_PATH)
2219       return action_ok_set_path(path, label, type, idx, entry_idx);
2220 
2221    if (!string_is_empty(menu_path))
2222       strlcpy(menu_path_new, menu_path, sizeof(menu_path_new));
2223 
2224    if (!string_is_empty(menu_label))
2225    {
2226       if (
2227             string_is_equal(menu_label,
2228                msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN_DETECT_CORE)) ||
2229             string_is_equal(menu_label,
2230                msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN))
2231          )
2232       {
2233          menu_handle_t *menu                 = menu_driver_get_ptr();
2234          if (!menu)
2235             return menu_cbs_exit();
2236 
2237          fill_pathname_join(menu_path_new,
2238                menu->scratch2_buf, menu->scratch_buf,
2239                sizeof(menu_path_new));
2240       }
2241    }
2242 
2243    switch (type)
2244    {
2245       case FILE_TYPE_IN_CARCHIVE:
2246          fill_pathname_join_delim(full_path_new, menu_path_new, path,
2247                '#',sizeof(full_path_new));
2248          break;
2249       default:
2250          fill_pathname_join(full_path_new, menu_path_new, path,
2251                sizeof(full_path_new));
2252          break;
2253    }
2254 
2255    return default_action_ok_load_content_with_core_from_menu(full_path_new,
2256          CORE_TYPE_PLAIN);
2257 }
2258 
playlist_entry_path_is_valid(const char * entry_path)2259 static bool playlist_entry_path_is_valid(const char *entry_path)
2260 {
2261    char *archive_delim = NULL;
2262    char *file_path     = NULL;
2263 
2264    if (string_is_empty(entry_path))
2265       goto error;
2266 
2267    file_path = strdup(entry_path);
2268 
2269    /* We need to check whether the file referenced by the
2270     * entry path actually exists. If it is a normal file,
2271     * we can do this directly. If the path contains an
2272     * archive delimiter, then we have to trim everything
2273     * after the archive extension
2274     * > Note: Have to do a nasty cast here, since
2275     *   path_get_archive_delim() returns a const char *
2276     *   (this cast is safe, though, and is done in many
2277     *   places throughout the codebase...) */
2278    archive_delim = (char *)path_get_archive_delim(file_path);
2279 
2280    if (archive_delim)
2281    {
2282       *archive_delim = '\0';
2283       if (string_is_empty(file_path))
2284          goto error;
2285    }
2286 
2287    /* Path is 'sanitised' - can now check if it exists */
2288    if (!path_is_valid(file_path))
2289       goto error;
2290 
2291    /* File is valid */
2292    free(file_path);
2293    file_path = NULL;
2294 
2295    return true;
2296 
2297 error:
2298    if (file_path)
2299    {
2300       free(file_path);
2301       file_path = NULL;
2302    }
2303 
2304    return false;
2305 }
2306 
action_ok_playlist_entry_collection(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2307 static int action_ok_playlist_entry_collection(const char *path,
2308       const char *label, unsigned type, size_t idx, size_t entry_idx)
2309 {
2310    playlist_config_t playlist_config;
2311    char content_path[PATH_MAX_LENGTH];
2312    char content_label[PATH_MAX_LENGTH];
2313    char core_path[PATH_MAX_LENGTH];
2314    size_t selection_ptr                   = entry_idx;
2315    bool playlist_initialized              = false;
2316    playlist_t *playlist                   = NULL;
2317    playlist_t *tmp_playlist               = NULL;
2318    const struct playlist_entry *entry     = NULL;
2319    core_info_t* core_info                 = NULL;
2320    bool core_is_builtin                   = false;
2321    menu_handle_t *menu                    = menu_driver_get_ptr();
2322    settings_t *settings                   = config_get_ptr();
2323    bool playlist_sort_alphabetical        = settings->bools.playlist_sort_alphabetical;
2324    const char *path_content_history       = settings->paths.path_content_history;
2325    const char *path_content_image_history = settings->paths.path_content_image_history;
2326    const char *path_content_music_history = settings->paths.path_content_music_history;
2327    const char *path_content_video_history = settings->paths.path_content_video_history;
2328 
2329    playlist_config.capacity               = COLLECTION_SIZE;
2330    playlist_config.old_format             = settings->bools.playlist_use_old_format;
2331    playlist_config.compress               = settings->bools.playlist_compression;
2332    playlist_config.fuzzy_archive_match    = settings->bools.playlist_fuzzy_archive_match;
2333    playlist_config_set_base_content_directory(&playlist_config, settings->bools.playlist_portable_paths ? settings->paths.directory_menu_content : NULL);
2334 
2335    content_path[0]  = '\0';
2336    content_label[0] = '\0';
2337    core_path[0]     = '\0';
2338 
2339    if (!menu)
2340       goto error;
2341 
2342    /* Get playlist */
2343    tmp_playlist = playlist_get_cached();
2344 
2345    if (!tmp_playlist)
2346    {
2347       /* If playlist is not cached, have to load
2348        * it here
2349        * > Since the menu will always sort playlists
2350        *   based on current user config, have to do
2351        *   the same here - otherwise entry_idx may
2352        *   go out of sync... */
2353       bool is_content_history = string_is_equal(menu->db_playlist_file, path_content_history) ||
2354                                 string_is_equal(menu->db_playlist_file, path_content_image_history) ||
2355                                 string_is_equal(menu->db_playlist_file, path_content_music_history) ||
2356                                 string_is_equal(menu->db_playlist_file, path_content_video_history);
2357 
2358       enum playlist_sort_mode current_sort_mode;
2359 
2360       playlist_config_set_path(&playlist_config, menu->db_playlist_file);
2361       tmp_playlist = playlist_init(&playlist_config);
2362 
2363       if (!tmp_playlist)
2364          goto error;
2365 
2366       current_sort_mode = playlist_get_sort_mode(tmp_playlist);
2367 
2368       if (!is_content_history &&
2369           ((playlist_sort_alphabetical && (current_sort_mode == PLAYLIST_SORT_MODE_DEFAULT)) ||
2370            (current_sort_mode == PLAYLIST_SORT_MODE_ALPHABETICAL)))
2371          playlist_qsort(tmp_playlist);
2372 
2373       playlist_initialized = true;
2374    }
2375 
2376    playlist = tmp_playlist;
2377 
2378    /* Get playlist entry */
2379    playlist_get_index(playlist, selection_ptr, &entry);
2380    if (!entry)
2381       goto error;
2382 
2383    /* Cache entry path */
2384    if (!string_is_empty(entry->path))
2385    {
2386       strlcpy(content_path, entry->path, sizeof(content_path));
2387       playlist_resolve_path(PLAYLIST_LOAD, false, content_path, sizeof(content_path));
2388    }
2389 
2390    /* Cache entry label */
2391    if (!string_is_empty(entry->label))
2392       strlcpy(content_label, entry->label, sizeof(content_label));
2393 
2394    /* Get core path */
2395    if (!playlist_entry_has_core(entry))
2396    {
2397       struct playlist_entry update_entry = {0};
2398 
2399       /* Entry core is not set - attempt to use
2400        * playlist default */
2401       core_info = playlist_get_default_core_info(playlist);
2402 
2403       /* If default core is not set, prompt user
2404        * to select one */
2405       if (!core_info)
2406       {
2407          /* TODO: figure out if this should refer to the inner or outer content_path */
2408          int ret = action_ok_file_load_with_detect_core_collection(content_path,
2409                label, type, selection_ptr, entry_idx);
2410 
2411          if (playlist_initialized && tmp_playlist)
2412          {
2413             playlist_free(tmp_playlist);
2414             tmp_playlist = NULL;
2415             playlist     = NULL;
2416          }
2417 
2418          return ret;
2419       }
2420 
2421       /* Cache core path */
2422       strlcpy(core_path, core_info->path, sizeof(core_path));
2423 
2424       /* Update playlist entry */
2425       update_entry.core_path = core_info->path;
2426       update_entry.core_name = core_info->display_name;
2427 
2428       command_playlist_update_write(
2429             playlist,
2430             selection_ptr,
2431             &update_entry);
2432    }
2433    else
2434    {
2435       /* Entry does have a core assignment
2436        * > If core is 'built-in' (imageviewer, etc.),
2437        *   then copy the path without modification
2438        * > If this is a standard core, ensure
2439        *   it has a corresponding core info entry */
2440       if (string_ends_with_size(entry->core_path, "builtin",
2441                strlen(entry->core_path),
2442                STRLEN_CONST("builtin")))
2443       {
2444          strlcpy(core_path, entry->core_path, sizeof(core_path));
2445          core_is_builtin = true;
2446       }
2447       else
2448       {
2449          core_info = playlist_entry_get_core_info(entry);
2450 
2451          if (core_info && !string_is_empty(core_info->path))
2452             strlcpy(core_path, core_info->path, sizeof(core_path));
2453          else
2454          {
2455             /* Core path is invalid - just copy what we have
2456              * and hope for the best... */
2457             strlcpy(core_path, entry->core_path, sizeof(core_path));
2458             playlist_resolve_path(PLAYLIST_LOAD, true, core_path, sizeof(core_path));
2459          }
2460       }
2461    }
2462 
2463    /* Ensure core path is valid */
2464    if (string_is_empty(core_path) ||
2465        (!core_is_builtin && !path_is_valid(core_path)))
2466       goto error;
2467 
2468    /* Subsystem codepath */
2469    if (!string_is_empty(entry->subsystem_ident))
2470    {
2471       content_ctx_info_t content_info = {0};
2472       size_t i;
2473 
2474       task_push_load_new_core(core_path, NULL,
2475             &content_info, CORE_TYPE_PLAIN, NULL, NULL);
2476 
2477       content_clear_subsystem();
2478 
2479       if (!content_set_subsystem_by_name(entry->subsystem_ident))
2480       {
2481          RARCH_LOG("[playlist] subsystem not found in implementation\n");
2482          goto error;
2483       }
2484 
2485       for (i = 0; i < entry->subsystem_roms->size; i++)
2486          content_add_subsystem(entry->subsystem_roms->elems[i].data);
2487 
2488       task_push_load_subsystem_with_core_from_menu(
2489             NULL, &content_info,
2490             CORE_TYPE_PLAIN, NULL, NULL);
2491 
2492       /* TODO: update playlist entry? move to first position I guess? */
2493       if (playlist_initialized && tmp_playlist)
2494       {
2495          playlist_free(tmp_playlist);
2496          tmp_playlist = NULL;
2497          playlist     = NULL;
2498       }
2499       return 1;
2500    }
2501 
2502    /* Ensure entry path is valid */
2503    if (!playlist_entry_path_is_valid(content_path))
2504       goto error;
2505 
2506    /* Free temporary playlist, if required */
2507    if (playlist_initialized && tmp_playlist)
2508    {
2509       playlist_free(tmp_playlist);
2510       tmp_playlist = NULL;
2511       playlist     = NULL;
2512    }
2513 
2514    /* Note: Have to use cached entry label, since entry
2515     * may be free()'d by above playlist_free() - but need
2516     * to pass NULL explicitly if label is empty */
2517    return default_action_ok_load_content_from_playlist_from_menu(
2518          core_path, content_path, string_is_empty(content_label) ? NULL : content_label);
2519 
2520 error:
2521    runloop_msg_queue_push(
2522          "File could not be loaded from playlist.\n",
2523          1, 100, true,
2524          NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2525 
2526    if (playlist_initialized && tmp_playlist)
2527    {
2528       playlist_free(tmp_playlist);
2529       tmp_playlist = NULL;
2530       playlist     = NULL;
2531    }
2532 
2533    return menu_cbs_exit();
2534 }
2535 
2536 #ifdef HAVE_AUDIOMIXER
action_ok_mixer_stream_action_play(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2537 static int action_ok_mixer_stream_action_play(const char *path,
2538       const char *label, unsigned type, size_t idx, size_t entry_idx)
2539 {
2540    unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN;
2541    enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
2542 
2543    switch (state)
2544    {
2545       case AUDIO_STREAM_STATE_STOPPED:
2546          audio_driver_mixer_play_stream(stream_id);
2547          break;
2548       case AUDIO_STREAM_STATE_PLAYING:
2549       case AUDIO_STREAM_STATE_PLAYING_LOOPED:
2550       case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
2551       case AUDIO_STREAM_STATE_NONE:
2552          break;
2553    }
2554    return 0;
2555 }
2556 
action_ok_mixer_stream_action_play_looped(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2557 static int action_ok_mixer_stream_action_play_looped(const char *path,
2558       const char *label, unsigned type, size_t idx, size_t entry_idx)
2559 {
2560    unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN;
2561    enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
2562 
2563    switch (state)
2564    {
2565       case AUDIO_STREAM_STATE_STOPPED:
2566          audio_driver_mixer_play_stream_looped(stream_id);
2567          break;
2568       case AUDIO_STREAM_STATE_PLAYING:
2569       case AUDIO_STREAM_STATE_PLAYING_LOOPED:
2570       case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
2571       case AUDIO_STREAM_STATE_NONE:
2572          break;
2573    }
2574    return 0;
2575 }
2576 
action_ok_mixer_stream_action_play_sequential(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2577 static int action_ok_mixer_stream_action_play_sequential(const char *path,
2578       const char *label, unsigned type, size_t idx, size_t entry_idx)
2579 {
2580    unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN;
2581    enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
2582 
2583    switch (state)
2584    {
2585       case AUDIO_STREAM_STATE_STOPPED:
2586          audio_driver_mixer_play_stream_sequential(stream_id);
2587          break;
2588       case AUDIO_STREAM_STATE_PLAYING:
2589       case AUDIO_STREAM_STATE_PLAYING_LOOPED:
2590       case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
2591       case AUDIO_STREAM_STATE_NONE:
2592          break;
2593    }
2594    return 0;
2595 }
2596 
action_ok_mixer_stream_action_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2597 static int action_ok_mixer_stream_action_remove(const char *path,
2598       const char *label, unsigned type, size_t idx, size_t entry_idx)
2599 {
2600    unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN;
2601    enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
2602 
2603    switch (state)
2604    {
2605       case AUDIO_STREAM_STATE_PLAYING:
2606       case AUDIO_STREAM_STATE_PLAYING_LOOPED:
2607       case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
2608       case AUDIO_STREAM_STATE_STOPPED:
2609          audio_driver_mixer_remove_stream(stream_id);
2610          break;
2611       case AUDIO_STREAM_STATE_NONE:
2612          break;
2613    }
2614    return 0;
2615 }
2616 
action_ok_mixer_stream_action_stop(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2617 static int action_ok_mixer_stream_action_stop(const char *path,
2618       const char *label, unsigned type, size_t idx, size_t entry_idx)
2619 {
2620    unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_BEGIN;
2621    enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
2622 
2623    switch (state)
2624    {
2625       case AUDIO_STREAM_STATE_PLAYING:
2626       case AUDIO_STREAM_STATE_PLAYING_LOOPED:
2627       case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
2628          audio_driver_mixer_stop_stream(stream_id);
2629          break;
2630       case AUDIO_STREAM_STATE_STOPPED:
2631       case AUDIO_STREAM_STATE_NONE:
2632          break;
2633    }
2634    return 0;
2635 }
2636 #endif
2637 
action_ok_load_cdrom(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2638 static int action_ok_load_cdrom(const char *path,
2639       const char *label, unsigned type, size_t idx, size_t entry_idx)
2640 {
2641 #ifdef HAVE_CDROM
2642    struct retro_system_info *system;
2643 
2644    if (!cdrom_drive_has_media(label[0]))
2645    {
2646       RARCH_LOG("[CDROM]: No media is inserted or drive is not ready.\n");
2647 
2648       runloop_msg_queue_push(
2649             msg_hash_to_str(MSG_NO_DISC_INSERTED),
2650             1, 100, true,
2651             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2652 
2653       return -1;
2654    }
2655 
2656    system = runloop_get_libretro_system_info();
2657 
2658    if (system && !string_is_empty(system->library_name))
2659    {
2660       char cdrom_path[256] = {0};
2661 
2662       cdrom_device_fillpath(cdrom_path, sizeof(cdrom_path), label[0], 0, true);
2663 
2664       RARCH_LOG("[CDROM]: Loading disc from path: %s\n", cdrom_path);
2665 
2666       path_clear(RARCH_PATH_CONTENT);
2667       path_set(RARCH_PATH_CONTENT, cdrom_path);
2668 
2669 #if defined(HAVE_DYNAMIC)
2670       {
2671          content_ctx_info_t content_info;
2672 
2673          content_info.argc        = 0;
2674          content_info.argv        = NULL;
2675          content_info.args        = NULL;
2676          content_info.environ_get = NULL;
2677 
2678          task_push_load_content_with_core_from_menu(cdrom_path, &content_info, CORE_TYPE_PLAIN, NULL, NULL);
2679       }
2680 #else
2681       frontend_driver_set_fork(FRONTEND_FORK_CORE_WITH_ARGS);
2682 #endif
2683    }
2684    else
2685    {
2686       RARCH_LOG("[CDROM]: Cannot load disc without a core.\n");
2687 
2688       runloop_msg_queue_push(
2689          msg_hash_to_str(MSG_LOAD_CORE_FIRST),
2690          1, 100, true,
2691          NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2692 
2693       return -1;
2694    }
2695 #endif
2696    return 0;
2697 }
2698 
action_ok_dump_cdrom(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2699 static int action_ok_dump_cdrom(const char *path,
2700       const char *label, unsigned type, size_t idx, size_t entry_idx)
2701 {
2702    if (string_is_empty(label))
2703       return -1;
2704 #ifdef HAVE_CDROM
2705    if (!cdrom_drive_has_media(label[0]))
2706    {
2707       RARCH_LOG("[CDROM]: No media is inserted or drive is not ready.\n");
2708 
2709       runloop_msg_queue_push(
2710             msg_hash_to_str(MSG_NO_DISC_INSERTED),
2711             1, 100, true,
2712             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2713 
2714       return -1;
2715    }
2716 
2717    task_push_cdrom_dump(label);
2718 #endif
2719    return 0;
2720 }
2721 
action_ok_lookup_setting(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2722 static int action_ok_lookup_setting(const char *path,
2723       const char *label, unsigned type, size_t idx, size_t entry_idx)
2724 {
2725    return menu_setting_set(type, MENU_ACTION_OK, false);
2726 }
2727 
2728 #ifdef HAVE_AUDIOMIXER
action_ok_audio_add_to_mixer(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2729 static int action_ok_audio_add_to_mixer(const char *path,
2730       const char *label, unsigned type, size_t idx, size_t entry_idx)
2731 {
2732    playlist_t *tmp_playlist            = playlist_get_cached();
2733    const struct playlist_entry *entry  = NULL;
2734 
2735    if (!tmp_playlist)
2736       return -1;
2737 
2738    playlist_get_index(tmp_playlist, entry_idx, &entry);
2739 
2740    if (filestream_exists(entry->path))
2741       task_push_audio_mixer_load(entry->path,
2742             NULL, NULL, false,
2743             AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC,
2744             0
2745             );
2746 
2747    return 0;
2748 }
2749 
action_ok_audio_add_to_mixer_and_play(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2750 static int action_ok_audio_add_to_mixer_and_play(const char *path,
2751       const char *label, unsigned type, size_t idx, size_t entry_idx)
2752 {
2753    playlist_t *tmp_playlist            = playlist_get_cached();
2754    const struct playlist_entry *entry  = NULL;
2755 
2756    if (!tmp_playlist)
2757       return -1;
2758 
2759    playlist_get_index(tmp_playlist, entry_idx, &entry);
2760 
2761    if (filestream_exists(entry->path))
2762       task_push_audio_mixer_load_and_play(entry->path,
2763             NULL, NULL, false,
2764             AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC,
2765             0);
2766 
2767    return 0;
2768 }
2769 
action_ok_audio_add_to_mixer_and_collection(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2770 static int action_ok_audio_add_to_mixer_and_collection(const char *path,
2771       const char *label, unsigned type, size_t idx, size_t entry_idx)
2772 {
2773    char combined_path[PATH_MAX_LENGTH];
2774    struct playlist_entry entry = {0};
2775    menu_handle_t *menu         = menu_driver_get_ptr();
2776 
2777    combined_path[0]            = '\0';
2778 
2779    if (!menu)
2780       return menu_cbs_exit();
2781 
2782    fill_pathname_join(combined_path, menu->scratch2_buf,
2783          menu->scratch_buf, sizeof(combined_path));
2784 
2785    /* the push function reads our entry as const, so these casts are safe */
2786    entry.path = combined_path;
2787    entry.core_path = (char*)"builtin";
2788    entry.core_name = (char*)"musicplayer";
2789 
2790    command_playlist_push_write(g_defaults.music_history, &entry);
2791 
2792    if (filestream_exists(combined_path))
2793       task_push_audio_mixer_load(combined_path,
2794             NULL, NULL, false,
2795             AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC,
2796             0);
2797 
2798    return 0;
2799 }
2800 
action_ok_audio_add_to_mixer_and_collection_and_play(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2801 static int action_ok_audio_add_to_mixer_and_collection_and_play(const char *path,
2802       const char *label, unsigned type, size_t idx, size_t entry_idx)
2803 {
2804    char combined_path[PATH_MAX_LENGTH];
2805    struct playlist_entry entry = {0};
2806    menu_handle_t *menu         = menu_driver_get_ptr();
2807 
2808    combined_path[0]            = '\0';
2809 
2810    if (!menu)
2811       return menu_cbs_exit();
2812 
2813    fill_pathname_join(combined_path, menu->scratch2_buf,
2814          menu->scratch_buf, sizeof(combined_path));
2815 
2816    /* the push function reads our entry as const, so these casts are safe */
2817    entry.path = combined_path;
2818    entry.core_path = (char*)"builtin";
2819    entry.core_name = (char*)"musicplayer";
2820 
2821    command_playlist_push_write(g_defaults.music_history, &entry);
2822 
2823    if (filestream_exists(combined_path))
2824       task_push_audio_mixer_load_and_play(combined_path,
2825             NULL, NULL, false,
2826             AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC,
2827             0);
2828 
2829    return 0;
2830 }
2831 #endif
2832 
action_ok_menu_wallpaper(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2833 static int action_ok_menu_wallpaper(const char *path,
2834       const char *label, unsigned type, size_t idx, size_t entry_idx)
2835 {
2836    filebrowser_set_type(FILEBROWSER_SELECT_IMAGE);
2837    return action_ok_lookup_setting(path, label, type, idx, entry_idx);
2838 }
2839 
action_ok_menu_wallpaper_load(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2840 static int action_ok_menu_wallpaper_load(const char *path,
2841       const char *label, unsigned type, size_t idx, size_t entry_idx)
2842 {
2843    settings_t *settings            = config_get_ptr();
2844 
2845    filebrowser_clear_type();
2846 
2847    settings->uints.menu_xmb_shader_pipeline = XMB_SHADER_PIPELINE_WALLPAPER;
2848    return generic_action_ok(path, label, type, idx, entry_idx,
2849          ACTION_OK_LOAD_WALLPAPER, MSG_UNKNOWN);
2850 }
2851 
generic_action_ok_help(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,enum msg_hash_enums id,enum menu_dialog_type id2)2852 int  generic_action_ok_help(const char *path,
2853       const char *label, unsigned type, size_t idx, size_t entry_idx,
2854       enum msg_hash_enums id, enum menu_dialog_type id2)
2855 {
2856    const char               *lbl  = msg_hash_to_str(id);
2857 
2858    return generic_action_ok_displaylist_push(path, NULL, lbl, id2, idx,
2859          entry_idx, ACTION_OK_DL_HELP);
2860 }
2861 
action_ok_bluetooth(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2862 static int action_ok_bluetooth(const char *path, const char *label,
2863          unsigned type, size_t idx, size_t entry_idx)
2864 {
2865    driver_bluetooth_connect_device((unsigned)idx);
2866 
2867    return 0;
2868 }
2869 
2870 #ifdef HAVE_NETWORKING
menu_input_wifi_cb(void * userdata,const char * passphrase)2871 static void menu_input_wifi_cb(void *userdata, const char *passphrase)
2872 {
2873    unsigned idx = menu_input_dialog_get_kb_idx();
2874    wifi_network_scan_t *scan = driver_wifi_get_ssids();
2875    wifi_network_info_t *netinfo = &scan->net_list[idx];
2876 
2877    if (idx < RBUF_LEN(scan->net_list) && passphrase)
2878    {
2879       /* Need to fill in the passphrase that we got from the user! */
2880       strlcpy(netinfo->passphrase, passphrase, sizeof(netinfo->passphrase));
2881       task_push_wifi_connect(NULL, netinfo);
2882    }
2883 
2884    menu_input_dialog_end();
2885 }
2886 #endif
2887 
menu_input_st_string_cb_rename_entry(void * userdata,const char * str)2888 static void menu_input_st_string_cb_rename_entry(void *userdata,
2889       const char *str)
2890 {
2891    if (str && *str)
2892    {
2893       const char        *label    = menu_input_dialog_get_buffer();
2894 
2895       if (!string_is_empty(label))
2896       {
2897          struct playlist_entry entry = {0};
2898 
2899          /* the update function reads our entry as const,
2900           * so these casts are safe */
2901          entry.label = (char*)label;
2902 
2903          command_playlist_update_write(NULL,
2904                menu_input_dialog_get_kb_idx(),
2905                &entry);
2906       }
2907    }
2908 
2909    menu_input_dialog_end();
2910 }
2911 
menu_input_st_string_cb_disable_kiosk_mode(void * userdata,const char * str)2912 static void menu_input_st_string_cb_disable_kiosk_mode(void *userdata,
2913       const char *str)
2914 {
2915    if (str && *str)
2916    {
2917       const char                    *label = menu_input_dialog_get_buffer();
2918       settings_t                 *settings = config_get_ptr();
2919       const char *path_kiosk_mode_password =
2920          settings->paths.kiosk_mode_password;
2921 
2922       if (string_is_equal(label, path_kiosk_mode_password))
2923       {
2924          settings->bools.kiosk_mode_enable = false;
2925 
2926          runloop_msg_queue_push(
2927             msg_hash_to_str(MSG_INPUT_KIOSK_MODE_PASSWORD_OK),
2928             1, 100, true,
2929             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2930       }
2931       else
2932       {
2933          runloop_msg_queue_push(
2934             msg_hash_to_str(MSG_INPUT_KIOSK_MODE_PASSWORD_NOK),
2935             1, 100, true,
2936             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2937       }
2938    }
2939 
2940    menu_input_dialog_end();
2941 }
2942 
menu_input_st_string_cb_enable_settings(void * userdata,const char * str)2943 static void menu_input_st_string_cb_enable_settings(void *userdata,
2944       const char *str)
2945 {
2946    if (str && *str)
2947    {
2948       const char                                 *label    =
2949          menu_input_dialog_get_buffer();
2950       settings_t                                 *settings = config_get_ptr();
2951       const char *menu_content_show_settings_password      = settings->paths.menu_content_show_settings_password;
2952 
2953       if (string_is_equal(label, menu_content_show_settings_password))
2954       {
2955          settings->bools.menu_content_show_settings = true;
2956 
2957          runloop_msg_queue_push(
2958             msg_hash_to_str(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_OK),
2959             1, 100, true,
2960             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2961       }
2962       else
2963       {
2964          runloop_msg_queue_push(
2965             msg_hash_to_str(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_NOK),
2966             1, 100, true,
2967             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
2968       }
2969    }
2970 
2971    menu_input_dialog_end();
2972 }
2973 
2974 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
action_ok_shader_pass(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)2975 static int action_ok_shader_pass(const char *path,
2976       const char *label, unsigned type, size_t idx, size_t entry_idx)
2977 {
2978    menu_handle_t *menu       = menu_driver_get_ptr();
2979 
2980    if (!menu)
2981       return menu_cbs_exit();
2982 
2983    menu->scratchpad.unsigned_var = type - MENU_SETTINGS_SHADER_PASS_0;
2984    return generic_action_ok_displaylist_push(path, NULL, label, type, idx,
2985          entry_idx, ACTION_OK_DL_SHADER_PASS);
2986 }
2987 
menu_input_st_string_cb_save_preset(void * userdata,const char * str)2988 static void menu_input_st_string_cb_save_preset(void *userdata,
2989       const char *str)
2990 {
2991    if (!string_is_empty(str))
2992    {
2993       rarch_setting_t *setting     = NULL;
2994       bool                 ret     = false;
2995       const char        *label     = menu_input_dialog_get_label_buffer();
2996       settings_t *settings         = config_get_ptr();
2997       const char *dir_video_shader = settings->paths.directory_video_shader;
2998       const char *dir_menu_config  = settings->paths.directory_menu_config;
2999 
3000       if (!string_is_empty(label))
3001          setting = menu_setting_find(label);
3002 
3003       if (setting)
3004       {
3005          setting_set_with_string_representation(setting, str);
3006          menu_setting_generic(setting, 0, false);
3007       }
3008       else if (!string_is_empty(label))
3009          ret = menu_shader_manager_save_preset(
3010                menu_shader_get(),
3011                str,
3012                dir_video_shader,
3013                dir_menu_config,
3014                true);
3015 
3016       if (ret)
3017          runloop_msg_queue_push(
3018                msg_hash_to_str(MSG_SHADER_PRESET_SAVED_SUCCESSFULLY),
3019                1, 100, true,
3020                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3021       else
3022          runloop_msg_queue_push(
3023                msg_hash_to_str(MSG_ERROR_SAVING_SHADER_PRESET),
3024                1, 100, true,
3025                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3026    }
3027 
3028    menu_input_dialog_end();
3029 }
3030 
3031 DEFAULT_ACTION_DIALOG_START(action_ok_shader_preset_save_as,
3032    msg_hash_to_str(MSG_INPUT_PRESET_FILENAME),
3033    (unsigned)idx,
3034    menu_input_st_string_cb_save_preset)
3035 
3036 enum
3037 {
3038    ACTION_OK_SHADER_PRESET_SAVE_GLOBAL = 0,
3039    ACTION_OK_SHADER_PRESET_SAVE_CORE,
3040    ACTION_OK_SHADER_PRESET_SAVE_PARENT,
3041    ACTION_OK_SHADER_PRESET_SAVE_GAME
3042 };
3043 
3044 enum
3045 {
3046    ACTION_OK_SHADER_PRESET_REMOVE_GLOBAL = 0,
3047    ACTION_OK_SHADER_PRESET_REMOVE_CORE,
3048    ACTION_OK_SHADER_PRESET_REMOVE_PARENT,
3049    ACTION_OK_SHADER_PRESET_REMOVE_GAME
3050 };
3051 
generic_action_ok_shader_preset_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,unsigned action_type)3052 static int generic_action_ok_shader_preset_remove(const char *path,
3053       const char *label, unsigned type, size_t idx, size_t entry_idx,
3054       unsigned action_type)
3055 {
3056    enum auto_shader_type preset_type;
3057    settings_t         *settings = config_get_ptr();
3058    const char *dir_video_shader = settings->paths.directory_video_shader;
3059    const char *dir_menu_config  = settings->paths.directory_menu_config;
3060 
3061    switch (action_type)
3062    {
3063       case ACTION_OK_SHADER_PRESET_REMOVE_GLOBAL:
3064          preset_type = SHADER_PRESET_GLOBAL;
3065          break;
3066       case ACTION_OK_SHADER_PRESET_REMOVE_CORE:
3067          preset_type = SHADER_PRESET_CORE;
3068          break;
3069       case ACTION_OK_SHADER_PRESET_REMOVE_PARENT:
3070          preset_type = SHADER_PRESET_PARENT;
3071          break;
3072       case ACTION_OK_SHADER_PRESET_REMOVE_GAME:
3073          preset_type = SHADER_PRESET_GAME;
3074          break;
3075       default:
3076          return 0;
3077    }
3078 
3079    if (menu_shader_manager_remove_auto_preset(preset_type,
3080          dir_video_shader, dir_menu_config))
3081    {
3082       bool refresh = false;
3083 
3084       runloop_msg_queue_push(
3085             msg_hash_to_str(MSG_SHADER_PRESET_REMOVED_SUCCESSFULLY),
3086             1, 100, true,
3087             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3088 
3089       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3090    }
3091    else
3092       runloop_msg_queue_push(
3093             msg_hash_to_str(MSG_ERROR_REMOVING_SHADER_PRESET),
3094             1, 100, true,
3095             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3096 
3097    return 0;
3098 }
3099 
generic_action_ok_shader_preset_save(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,unsigned action_type)3100 static int generic_action_ok_shader_preset_save(const char *path,
3101       const char *label, unsigned type, size_t idx, size_t entry_idx,
3102       unsigned action_type)
3103 {
3104    enum auto_shader_type preset_type;
3105    settings_t      *settings     = config_get_ptr();
3106    const char *dir_video_shader  = settings->paths.directory_video_shader;
3107    const char *dir_menu_config   = settings->paths.directory_menu_config;
3108 
3109    switch (action_type)
3110    {
3111       case ACTION_OK_SHADER_PRESET_SAVE_GLOBAL:
3112          preset_type = SHADER_PRESET_GLOBAL;
3113          break;
3114       case ACTION_OK_SHADER_PRESET_SAVE_CORE:
3115          preset_type = SHADER_PRESET_CORE;
3116          break;
3117       case ACTION_OK_SHADER_PRESET_SAVE_PARENT:
3118          preset_type = SHADER_PRESET_PARENT;
3119          break;
3120       case ACTION_OK_SHADER_PRESET_SAVE_GAME:
3121          preset_type = SHADER_PRESET_GAME;
3122          break;
3123       default:
3124          return 0;
3125    }
3126 
3127    /* Save Auto Preset and have it immediately reapply the preset
3128     * TODO: This seems necessary so that the loaded shader gains a link to the file saved
3129     * But this is slow and seems like a redundant way to do this
3130     * It seems like it would be better to just set the path and shader_preset_loaded
3131     * on the current shader */
3132    if (menu_shader_manager_save_auto_preset(menu_shader_get(), preset_type,
3133             dir_video_shader, dir_menu_config,
3134             true))
3135       runloop_msg_queue_push(
3136             msg_hash_to_str(MSG_SHADER_PRESET_SAVED_SUCCESSFULLY),
3137             1, 100, true,
3138             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3139    else
3140       runloop_msg_queue_push(
3141             msg_hash_to_str(MSG_ERROR_SAVING_SHADER_PRESET),
3142             1, 100, true,
3143             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3144 
3145    return 0;
3146 }
3147 
action_ok_shader_preset_save_global(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3148 static int action_ok_shader_preset_save_global(const char *path,
3149       const char *label, unsigned type, size_t idx, size_t entry_idx)
3150 {
3151    return generic_action_ok_shader_preset_save(path, label, type,
3152          idx, entry_idx, ACTION_OK_SHADER_PRESET_SAVE_GLOBAL);
3153 }
3154 
action_ok_shader_preset_save_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3155 static int action_ok_shader_preset_save_core(const char *path,
3156       const char *label, unsigned type, size_t idx, size_t entry_idx)
3157 {
3158    return generic_action_ok_shader_preset_save(path, label, type,
3159          idx, entry_idx, ACTION_OK_SHADER_PRESET_SAVE_CORE);
3160 }
3161 
action_ok_shader_preset_save_parent(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3162 static int action_ok_shader_preset_save_parent(const char *path,
3163       const char *label, unsigned type, size_t idx, size_t entry_idx)
3164 {
3165    return generic_action_ok_shader_preset_save(path, label, type,
3166          idx, entry_idx, ACTION_OK_SHADER_PRESET_SAVE_PARENT);
3167 }
3168 
action_ok_shader_preset_save_game(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3169 static int action_ok_shader_preset_save_game(const char *path,
3170       const char *label, unsigned type, size_t idx, size_t entry_idx)
3171 {
3172    return generic_action_ok_shader_preset_save(path, label, type,
3173          idx, entry_idx, ACTION_OK_SHADER_PRESET_SAVE_GAME);
3174 }
3175 
action_ok_shader_preset_remove_global(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3176 static int action_ok_shader_preset_remove_global(const char *path,
3177       const char *label, unsigned type, size_t idx, size_t entry_idx)
3178 {
3179    return generic_action_ok_shader_preset_remove(path, label, type,
3180          idx, entry_idx, ACTION_OK_SHADER_PRESET_REMOVE_GLOBAL);
3181 }
3182 
action_ok_shader_preset_remove_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3183 static int action_ok_shader_preset_remove_core(const char *path,
3184       const char *label, unsigned type, size_t idx, size_t entry_idx)
3185 {
3186    return generic_action_ok_shader_preset_remove(path, label, type,
3187          idx, entry_idx, ACTION_OK_SHADER_PRESET_REMOVE_CORE);
3188 }
3189 
action_ok_shader_preset_remove_parent(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3190 static int action_ok_shader_preset_remove_parent(const char *path,
3191       const char *label, unsigned type, size_t idx, size_t entry_idx)
3192 {
3193    return generic_action_ok_shader_preset_remove(path, label, type,
3194          idx, entry_idx, ACTION_OK_SHADER_PRESET_REMOVE_PARENT);
3195 }
3196 
action_ok_shader_preset_remove_game(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3197 static int action_ok_shader_preset_remove_game(const char *path,
3198       const char *label, unsigned type, size_t idx, size_t entry_idx)
3199 {
3200    return generic_action_ok_shader_preset_remove(path, label, type,
3201          idx, entry_idx, ACTION_OK_SHADER_PRESET_REMOVE_GAME);
3202 }
3203 #endif
3204 
3205 #ifdef HAVE_NETWORKING
action_ok_wifi(const char * path,const char * label_setting,unsigned type,size_t idx,size_t entry_idx)3206 static int action_ok_wifi(const char *path, const char *label_setting,
3207       unsigned type, size_t idx, size_t entry_idx)
3208 {
3209    wifi_network_scan_t* scan = driver_wifi_get_ssids();
3210    if (idx >= RBUF_LEN(scan->net_list))
3211       return -1;
3212 
3213    if (scan->net_list[idx].saved_password)
3214    {
3215       /* No need to ask for a password, should be stored */
3216       task_push_wifi_connect(NULL, &scan->net_list[idx]);
3217       return 0;
3218    }
3219    else
3220    {
3221       /* Show password input dialog */
3222       menu_input_ctx_line_t line;
3223       line.label         = "Passphrase";
3224       line.label_setting = label_setting;
3225       line.type          = type;
3226       line.idx           = (unsigned)idx;
3227       line.cb            = menu_input_wifi_cb;
3228       if (!menu_input_dialog_start(&line))
3229          return -1;
3230       return 0;
3231    }
3232 }
3233 #endif
3234 
action_ok_video_filter_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3235 static int action_ok_video_filter_remove(const char *path,
3236       const char *label, unsigned type, size_t idx, size_t entry_idx)
3237 {
3238    settings_t *settings = config_get_ptr();
3239 
3240    if (!settings)
3241       return menu_cbs_exit();
3242 
3243    if (!string_is_empty(settings->paths.path_softfilter_plugin))
3244    {
3245       bool refresh = false;
3246 
3247       /* Unload video filter */
3248       settings->paths.path_softfilter_plugin[0] = '\0';
3249       command_event(CMD_EVENT_REINIT, NULL);
3250 
3251       /* Refresh menu */
3252       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3253       menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3254    }
3255 
3256    return 0;
3257 }
3258 
action_ok_audio_dsp_plugin_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3259 static int action_ok_audio_dsp_plugin_remove(const char *path,
3260       const char *label, unsigned type, size_t idx, size_t entry_idx)
3261 {
3262    settings_t *settings = config_get_ptr();
3263 
3264    if (!settings)
3265       return menu_cbs_exit();
3266 
3267    if (!string_is_empty(settings->paths.path_audio_dsp_plugin))
3268    {
3269       bool refresh = false;
3270 
3271       /* Unload dsp plugin filter */
3272       settings->paths.path_audio_dsp_plugin[0] = '\0';
3273       command_event(CMD_EVENT_DSP_FILTER_INIT, NULL);
3274 
3275       /* Refresh menu */
3276       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3277       menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3278    }
3279 
3280    return 0;
3281 }
3282 
3283 #ifdef HAVE_CHEATS
menu_input_st_string_cb_cheat_file_save_as(void * userdata,const char * str)3284 static void menu_input_st_string_cb_cheat_file_save_as(
3285       void *userdata, const char *str)
3286 {
3287    if (str && *str)
3288    {
3289       rarch_setting_t *setting        = NULL;
3290       const char        *label        = menu_input_dialog_get_label_buffer();
3291       settings_t *settings            = config_get_ptr();
3292       const char *path_cheat_database = settings->paths.path_cheat_database;
3293 
3294       if (!string_is_empty(label))
3295          setting = menu_setting_find(label);
3296 
3297       if (setting)
3298       {
3299          setting_set_with_string_representation(setting, str);
3300          menu_setting_generic(setting, 0, false);
3301       }
3302       else if (!string_is_empty(label))
3303          cheat_manager_save(str, path_cheat_database,
3304                false);
3305    }
3306 
3307    menu_input_dialog_end();
3308 }
3309 #endif
3310 
3311 DEFAULT_ACTION_DIALOG_START(action_ok_enable_settings,
3312    msg_hash_to_str(MSG_INPUT_ENABLE_SETTINGS_PASSWORD),
3313    (unsigned)entry_idx,
3314    menu_input_st_string_cb_enable_settings)
3315 #ifdef HAVE_CHEATS
3316 DEFAULT_ACTION_DIALOG_START(action_ok_cheat_file_save_as,
3317    msg_hash_to_str(MSG_INPUT_CHEAT_FILENAME),
3318    (unsigned)idx,
3319    menu_input_st_string_cb_cheat_file_save_as)
3320 #endif
3321 DEFAULT_ACTION_DIALOG_START(action_ok_disable_kiosk_mode,
3322    msg_hash_to_str(MSG_INPUT_KIOSK_MODE_PASSWORD),
3323    (unsigned)entry_idx,
3324    menu_input_st_string_cb_disable_kiosk_mode)
3325 DEFAULT_ACTION_DIALOG_START(action_ok_rename_entry,
3326    msg_hash_to_str(MSG_INPUT_RENAME_ENTRY),
3327    (unsigned)entry_idx,
3328    menu_input_st_string_cb_rename_entry)
3329 
3330 
generic_action_ok_remap_file_operation(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,unsigned action_type)3331 static int generic_action_ok_remap_file_operation(const char *path,
3332       const char *label, unsigned type, size_t idx, size_t entry_idx,
3333       unsigned action_type)
3334 {
3335 #ifdef HAVE_CONFIGFILE
3336    char directory[PATH_MAX_LENGTH];
3337    char file[PATH_MAX_LENGTH];
3338    char content_dir[PATH_MAX_LENGTH];
3339    struct retro_system_info *system     = runloop_get_libretro_system_info();
3340    const char *core_name                = system ? system->library_name : NULL;
3341    settings_t *settings                 = config_get_ptr();
3342    const char *path_dir_input_remapping = settings->paths.directory_input_remapping;
3343 
3344    directory[0] = file[0]          = '\0';
3345 
3346    if (!string_is_empty(core_name))
3347       fill_pathname_join(
3348             directory,
3349             path_dir_input_remapping,
3350             core_name,
3351             sizeof(directory));
3352 
3353    switch (action_type)
3354    {
3355       case ACTION_OK_REMAP_FILE_SAVE_CORE:
3356       case ACTION_OK_REMAP_FILE_REMOVE_CORE:
3357          if (!string_is_empty(core_name))
3358             fill_pathname_join(file, core_name, core_name, sizeof(file));
3359          break;
3360       case ACTION_OK_REMAP_FILE_SAVE_GAME:
3361       case ACTION_OK_REMAP_FILE_REMOVE_GAME:
3362          if (!string_is_empty(core_name))
3363             fill_pathname_join(file, core_name,
3364                   path_basename(path_get(RARCH_PATH_BASENAME)), sizeof(file));
3365          break;
3366       case ACTION_OK_REMAP_FILE_SAVE_CONTENT_DIR:
3367       case ACTION_OK_REMAP_FILE_REMOVE_CONTENT_DIR:
3368          if (!string_is_empty(core_name))
3369          {
3370             fill_pathname_parent_dir_name(content_dir, path_get(RARCH_PATH_BASENAME), sizeof(content_dir));
3371             fill_pathname_join(file, core_name,
3372                   content_dir, sizeof(file));
3373          }
3374          break;
3375    }
3376 
3377    if (!path_is_directory(directory))
3378        path_mkdir(directory);
3379 
3380    if (action_type < ACTION_OK_REMAP_FILE_REMOVE_CORE)
3381    {
3382       if (input_remapping_save_file(file))
3383       {
3384 #ifdef HAVE_CONFIGFILE
3385          switch (action_type)
3386          {
3387             case ACTION_OK_REMAP_FILE_SAVE_CORE:
3388                rarch_ctl(RARCH_CTL_SET_REMAPS_CORE_ACTIVE, NULL);
3389                break;
3390             case ACTION_OK_REMAP_FILE_SAVE_GAME:
3391                rarch_ctl(RARCH_CTL_SET_REMAPS_GAME_ACTIVE, NULL);
3392                break;
3393             case ACTION_OK_REMAP_FILE_SAVE_CONTENT_DIR:
3394                rarch_ctl(RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE, NULL);
3395                break;
3396          }
3397 #endif
3398 
3399          runloop_msg_queue_push(
3400                msg_hash_to_str(MSG_REMAP_FILE_SAVED_SUCCESSFULLY),
3401                1, 100, true,
3402                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3403       }
3404       else
3405          runloop_msg_queue_push(
3406                msg_hash_to_str(MSG_ERROR_SAVING_REMAP_FILE),
3407                1, 100, true,
3408                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3409    }
3410    else
3411    {
3412       if (input_remapping_remove_file(file, path_dir_input_remapping))
3413       {
3414          switch (action_type)
3415          {
3416             case ACTION_OK_REMAP_FILE_REMOVE_CORE:
3417                if (rarch_ctl(RARCH_CTL_IS_REMAPS_CORE_ACTIVE, NULL))
3418                {
3419                   input_remapping_deinit();
3420                   input_remapping_set_defaults(false);
3421                }
3422                break;
3423             case ACTION_OK_REMAP_FILE_REMOVE_GAME:
3424                if (rarch_ctl(RARCH_CTL_IS_REMAPS_GAME_ACTIVE, NULL))
3425                {
3426                   input_remapping_deinit();
3427                   input_remapping_set_defaults(false);
3428                }
3429                break;
3430             case ACTION_OK_REMAP_FILE_REMOVE_CONTENT_DIR:
3431                if (rarch_ctl(RARCH_CTL_IS_REMAPS_CONTENT_DIR_ACTIVE, NULL))
3432                {
3433                   input_remapping_deinit();
3434                   input_remapping_set_defaults(false);
3435                }
3436                break;
3437          }
3438 
3439          runloop_msg_queue_push(
3440                msg_hash_to_str(MSG_REMAP_FILE_REMOVED_SUCCESSFULLY),
3441                1, 100, true,
3442                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3443       }
3444       else
3445          runloop_msg_queue_push(
3446                msg_hash_to_str(MSG_ERROR_REMOVING_REMAP_FILE),
3447                1, 100, true,
3448                NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3449    }
3450 #endif
3451    return 0;
3452 }
3453 
action_ok_remap_file_save_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3454 static int action_ok_remap_file_save_core(const char *path,
3455       const char *label, unsigned type, size_t idx, size_t entry_idx)
3456 {
3457    return generic_action_ok_remap_file_operation(path, label, type,
3458          idx, entry_idx, ACTION_OK_REMAP_FILE_SAVE_CORE);
3459 }
3460 
action_ok_remap_file_save_content_dir(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3461 static int action_ok_remap_file_save_content_dir(const char *path,
3462       const char *label, unsigned type, size_t idx, size_t entry_idx)
3463 {
3464    return generic_action_ok_remap_file_operation(path, label, type,
3465          idx, entry_idx, ACTION_OK_REMAP_FILE_SAVE_CONTENT_DIR);
3466 }
3467 
action_ok_remap_file_save_game(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3468 static int action_ok_remap_file_save_game(const char *path,
3469       const char *label, unsigned type, size_t idx, size_t entry_idx)
3470 {
3471    return generic_action_ok_remap_file_operation(path, label, type,
3472          idx, entry_idx, ACTION_OK_REMAP_FILE_SAVE_GAME);
3473 }
3474 
action_ok_remap_file_remove_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3475 static int action_ok_remap_file_remove_core(const char *path,
3476       const char *label, unsigned type, size_t idx, size_t entry_idx)
3477 {
3478    return generic_action_ok_remap_file_operation(path, label, type,
3479          idx, entry_idx, ACTION_OK_REMAP_FILE_REMOVE_CORE);
3480 }
3481 
action_ok_remap_file_remove_content_dir(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3482 static int action_ok_remap_file_remove_content_dir(const char *path,
3483       const char *label, unsigned type, size_t idx, size_t entry_idx)
3484 {
3485    return generic_action_ok_remap_file_operation(path, label, type,
3486          idx, entry_idx, ACTION_OK_REMAP_FILE_REMOVE_CONTENT_DIR);
3487 }
3488 
action_ok_remap_file_remove_game(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3489 static int action_ok_remap_file_remove_game(const char *path,
3490       const char *label, unsigned type, size_t idx, size_t entry_idx)
3491 {
3492    return generic_action_ok_remap_file_operation(path, label, type,
3493          idx, entry_idx, ACTION_OK_REMAP_FILE_REMOVE_GAME);
3494 }
3495 
action_ok_path_use_directory(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3496 int action_ok_path_use_directory(const char *path,
3497       const char *label, unsigned type, size_t idx, size_t entry_idx)
3498 {
3499    filebrowser_clear_type();
3500    return generic_action_ok(NULL, label, type, idx, entry_idx,
3501          ACTION_OK_SET_DIRECTORY, MSG_UNKNOWN);
3502 }
3503 
3504 #ifdef HAVE_LIBRETRODB
action_ok_scan_file(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3505 static int action_ok_scan_file(const char *path,
3506       const char *label, unsigned type, size_t idx, size_t entry_idx)
3507 {
3508    return action_scan_file(path, label, type, idx);
3509 }
3510 
action_ok_path_scan_directory(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3511 static int action_ok_path_scan_directory(const char *path,
3512       const char *label, unsigned type, size_t idx, size_t entry_idx)
3513 {
3514    return action_scan_directory(NULL, label, type, idx);
3515 }
3516 #endif
3517 
action_ok_path_manual_scan_directory(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3518 static int action_ok_path_manual_scan_directory(const char *path,
3519       const char *label, unsigned type, size_t idx, size_t entry_idx)
3520 {
3521    char content_dir[PATH_MAX_LENGTH];
3522    const char *flush_char = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MANUAL_CONTENT_SCAN_LIST);
3523    unsigned flush_type    = 0;
3524    const char *menu_path  = NULL;
3525 
3526    content_dir[0]         = '\0';
3527 
3528    /* 'Reset' file browser */
3529    filebrowser_clear_type();
3530 
3531    /* Get user-selected scan directory */
3532    menu_entries_get_last_stack(&menu_path,
3533          NULL, NULL, NULL, NULL);
3534 
3535    if (!string_is_empty(menu_path))
3536       strlcpy(content_dir, menu_path, sizeof(content_dir));
3537 
3538 #ifdef HAVE_COCOATOUCH
3539    {
3540       /* For iOS, set the path using realpath because the path name
3541        * can start with /private and this ensures the path starts with it.
3542        * This will allow the path to be properly substituted when
3543        * fill_pathname_expand_special() is called. */
3544       char real_content_dir[PATH_MAX_LENGTH];
3545       real_content_dir[0] = '\0';
3546       realpath(content_dir, real_content_dir);
3547       strlcpy(content_dir, real_content_dir, sizeof(content_dir));
3548    }
3549 #endif
3550 
3551    /* Update manual content scan settings */
3552    manual_content_scan_set_menu_content_dir(content_dir);
3553 
3554    /* Return to 'manual content scan' menu */
3555    menu_entries_flush_stack(flush_char, flush_type);
3556 
3557    return 0;
3558 }
3559 
action_ok_core_deferred_set(const char * new_core_path,const char * content_label,unsigned type,size_t idx,size_t entry_idx)3560 static int action_ok_core_deferred_set(const char *new_core_path,
3561       const char *content_label, unsigned type, size_t idx, size_t entry_idx)
3562 {
3563    size_t selection              = menu_navigation_get_selection();
3564    struct playlist_entry entry   = {0};
3565    menu_handle_t *menu           = menu_driver_get_ptr();
3566    core_info_t *core_info        = NULL;
3567    const char *core_display_name = NULL;
3568    char resolved_core_path[PATH_MAX_LENGTH];
3569    char msg[PATH_MAX_LENGTH];
3570 
3571    resolved_core_path[0] = '\0';
3572    msg[0]                = '\0';
3573 
3574    if (!menu ||
3575        string_is_empty(new_core_path))
3576       return menu_cbs_exit();
3577 
3578    /* Get core display name */
3579    if (core_info_find(new_core_path, &core_info))
3580       core_display_name = core_info->display_name;
3581 
3582    if (string_is_empty(core_display_name))
3583       core_display_name = path_basename_nocompression(new_core_path);
3584 
3585    /* Get 'real' core path */
3586    strlcpy(resolved_core_path, new_core_path, sizeof(resolved_core_path));
3587    playlist_resolve_path(PLAYLIST_SAVE, true, resolved_core_path, sizeof(resolved_core_path));
3588 
3589    /* the update function reads our entry
3590     * as const, so these casts are safe */
3591    entry.core_path = (char*)resolved_core_path;
3592    entry.core_name = (char*)core_display_name;
3593 
3594    command_playlist_update_write(
3595          NULL,
3596          menu->scratchpad.unsigned_var,
3597          &entry);
3598 
3599    /* Provide visual feedback */
3600    strlcpy(msg, msg_hash_to_str(MSG_SET_CORE_ASSOCIATION), sizeof(msg));
3601    strlcat(msg, core_display_name, sizeof(msg));
3602    runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3603 
3604    menu_entries_pop_stack(&selection, 0, 1);
3605    menu_navigation_set_selection(selection);
3606 
3607    return 0;
3608 }
3609 
action_ok_deferred_list_stub(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3610 static int action_ok_deferred_list_stub(const char *path,
3611       const char *label, unsigned type, size_t idx, size_t entry_idx)
3612 {
3613    return 0;
3614 }
3615 
3616 #if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX)
action_ok_set_switch_cpu_profile(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3617 static int action_ok_set_switch_cpu_profile(const char *path,
3618       const char *label, unsigned type, size_t idx, size_t entry_idx)
3619 {
3620    char command[PATH_MAX_LENGTH] = {0};
3621 #ifdef HAVE_LAKKA_SWITCH
3622    char* profile_name            = SWITCH_CPU_PROFILES[entry_idx];
3623 
3624    snprintf(command, sizeof(command), "cpu-profile set '%s'", profile_name);
3625 
3626    system(command);
3627    snprintf(command, sizeof(command), "Current profile set to %s", profile_name);
3628 #else
3629    unsigned profile_clock          = SWITCH_CPU_SPEEDS_VALUES[entry_idx];
3630    settings_t *settings            = config_get_ptr();
3631 
3632    settings->uints.libnx_overclock = entry_idx;
3633 
3634    if (hosversionBefore(8, 0, 0))
3635       pcvSetClockRate(PcvModule_CpuBus, (u32)profile_clock);
3636    else
3637    {
3638       ClkrstSession session = {0};
3639       clkrstOpenSession(&session, PcvModuleId_CpuBus, 3);
3640       clkrstSetClockRate(&session, profile_clock);
3641       clkrstCloseSession(&session);
3642    }
3643    snprintf(command, sizeof(command),
3644          "Current Clock set to %i", profile_clock);
3645 #endif
3646 
3647    runloop_msg_queue_push(command, 1, 90, true, NULL,
3648          MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3649 
3650    return menu_cbs_exit();
3651 }
3652 #endif
3653 
3654 #ifdef HAVE_LAKKA_SWITCH
3655 
action_ok_set_switch_gpu_profile(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3656 static int action_ok_set_switch_gpu_profile(const char *path,
3657       const char *label, unsigned type, size_t idx, size_t entry_idx)
3658 {
3659    char command[PATH_MAX_LENGTH];
3660    char            *profile_name  = SWITCH_GPU_PROFILES[entry_idx];
3661 
3662    command[0]                     = '\0';
3663 
3664    snprintf(command, sizeof(command),
3665          "gpu-profile set '%s'",
3666          profile_name);
3667 
3668    system(command);
3669 
3670    snprintf(command, sizeof(command),
3671          "Current profile set to %s",
3672          profile_name);
3673 
3674    runloop_msg_queue_push(command, 1, 90, true, NULL,
3675          MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3676 
3677    return menu_cbs_exit();
3678 }
3679 
3680 #endif
3681 
action_ok_load_core_deferred(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3682 static int action_ok_load_core_deferred(const char *path,
3683       const char *label, unsigned type, size_t idx, size_t entry_idx)
3684 {
3685    content_ctx_info_t content_info;
3686    menu_handle_t *menu                 = menu_driver_get_ptr();
3687 
3688    content_info.argc                   = 0;
3689    content_info.argv                   = NULL;
3690    content_info.args                   = NULL;
3691    content_info.environ_get            = NULL;
3692 
3693    if (!menu)
3694       return menu_cbs_exit();
3695 
3696    if (!task_push_load_content_with_new_core_from_menu(
3697             path, menu->deferred_path,
3698             &content_info,
3699             CORE_TYPE_PLAIN,
3700             NULL, NULL))
3701       return -1;
3702    content_add_to_playlist(path);
3703    menu_driver_set_last_start_content(path);
3704 
3705    return 0;
3706 }
3707 
DEFAULT_ACTION_OK_START_BUILTIN_CORE(action_ok_start_net_retropad_core,CORE_TYPE_NETRETROPAD)3708 DEFAULT_ACTION_OK_START_BUILTIN_CORE(action_ok_start_net_retropad_core, CORE_TYPE_NETRETROPAD)
3709 DEFAULT_ACTION_OK_START_BUILTIN_CORE(action_ok_start_gong_core, CORE_TYPE_GONG)
3710 DEFAULT_ACTION_OK_START_BUILTIN_CORE(action_ok_start_video_processor_core, CORE_TYPE_VIDEO_PROCESSOR)
3711 
3712 #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
3713 static int action_ok_file_load_ffmpeg(const char *path,
3714       const char *label, unsigned type, size_t idx, size_t entry_idx)
3715 {
3716    char new_path[PATH_MAX_LENGTH];
3717    const char *menu_path           = NULL;
3718    file_list_t *menu_stack         = menu_entries_get_menu_stack_ptr(0);
3719 
3720    file_list_get_last(menu_stack, &menu_path, NULL, NULL, NULL);
3721 
3722    new_path[0] = '\0';
3723 
3724    if (!string_is_empty(menu_path))
3725       fill_pathname_join(new_path, menu_path, path,
3726             sizeof(new_path));
3727 
3728    /* TODO/FIXME - should become runtime optional */
3729 #ifdef HAVE_MPV
3730    return default_action_ok_load_content_with_core_from_menu(
3731          new_path, CORE_TYPE_MPV);
3732 #else
3733    return default_action_ok_load_content_with_core_from_menu(
3734          new_path, CORE_TYPE_FFMPEG);
3735 #endif
3736 }
3737 #endif
3738 
action_ok_audio_run(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3739 static int action_ok_audio_run(const char *path,
3740       const char *label, unsigned type, size_t idx, size_t entry_idx)
3741 {
3742    char combined_path[PATH_MAX_LENGTH];
3743    menu_handle_t *menu                 = menu_driver_get_ptr();
3744 
3745    combined_path[0] = '\0';
3746 
3747    if (!menu)
3748       return menu_cbs_exit();
3749 
3750    fill_pathname_join(combined_path, menu->scratch2_buf,
3751          menu->scratch_buf, sizeof(combined_path));
3752 
3753    /* TODO/FIXME - should become runtime optional */
3754 #ifdef HAVE_MPV
3755    return default_action_ok_load_content_with_core_from_menu(
3756          combined_path, CORE_TYPE_MPV);
3757 #else
3758    return default_action_ok_load_content_with_core_from_menu(
3759          combined_path, CORE_TYPE_FFMPEG);
3760 #endif
3761 }
3762 
action_ok_core_option_dropdown_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3763 int action_ok_core_option_dropdown_list(const char *path,
3764       const char *label, unsigned type, size_t idx, size_t entry_idx)
3765 {
3766    core_option_manager_t *coreopts = NULL;
3767    struct core_option *option      = NULL;
3768    const char *value_label_0       = NULL;
3769    const char *value_label_1       = NULL;
3770    size_t option_index;
3771    char option_path_str[256];
3772    char option_lbl_str[256];
3773 
3774    option_path_str[0] = '\0';
3775    option_lbl_str[0]  = '\0';
3776 
3777    /* Boolean options are toggled directly,
3778     * without the use of a drop-down list */
3779 
3780    /* > Get current option index */
3781    if (type < MENU_SETTINGS_CORE_OPTION_START)
3782       goto push_dropdown_list;
3783 
3784    option_index = type - MENU_SETTINGS_CORE_OPTION_START;
3785 
3786    /* > Get core options struct */
3787    if (!rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts) ||
3788        (option_index >= coreopts->size))
3789       goto push_dropdown_list;
3790 
3791    /* > Get current option, and check whether
3792     *   it has exactly 2 values (i.e. on/off) */
3793    option = (struct core_option*)&coreopts->opts[option_index];
3794 
3795    if (!option ||
3796        (option->vals->size != 2) ||
3797        ((option->index != 0) &&
3798             (option->index != 1)))
3799       goto push_dropdown_list;
3800 
3801    /* > Check whether option values correspond
3802     *   to a boolean toggle */
3803    value_label_0 = option->val_labels->elems[0].data;
3804    value_label_1 = option->val_labels->elems[1].data;
3805 
3806    if (string_is_empty(value_label_0) ||
3807        string_is_empty(value_label_1) ||
3808        !((string_is_equal(value_label_0,   msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON))   &&
3809             string_is_equal(value_label_1, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) ||
3810          (string_is_equal(value_label_0,   msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))  &&
3811             string_is_equal(value_label_1, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))))
3812       goto push_dropdown_list;
3813 
3814    /* > Update value and return */
3815    core_option_manager_set_val(coreopts, option_index,
3816          (option->index == 0) ? 1 : 0);
3817 
3818    return 0;
3819 
3820 push_dropdown_list:
3821 
3822    /* If this option is not a boolean toggle,
3823     * push drop-down list */
3824    snprintf(option_path_str, sizeof(option_path_str),
3825          "core_option_%d", (int)idx);
3826    snprintf(option_lbl_str, sizeof(option_lbl_str),
3827          "%d", type);
3828 
3829    /* TODO/FIXME: This should be refactored to make
3830     * use of a core-option-specific drop-down list,
3831     * rather than hijacking the generic one... */
3832    generic_action_ok_displaylist_push(
3833          option_path_str, NULL,
3834          option_lbl_str, 0, idx, 0,
3835          ACTION_OK_DL_DROPDOWN_BOX_LIST);
3836 
3837    return 0;
3838 }
3839 
3840 #ifdef HAVE_CHEATS
action_ok_cheat_reload_cheats(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3841 static int action_ok_cheat_reload_cheats(const char *path,
3842       const char *label, unsigned type, size_t idx, size_t entry_idx)
3843 {
3844    bool                    refresh = false;
3845    settings_t           *settings  = config_get_ptr();
3846    const char *path_cheat_database = settings->paths.path_cheat_database;
3847 
3848    cheat_manager_realloc(0, CHEAT_HANDLER_TYPE_EMU);
3849 
3850    cheat_manager_load_game_specific_cheats(
3851          path_cheat_database);
3852 
3853    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3854    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3855    return 0;
3856 }
3857 #endif
3858 
action_ok_start_recording(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3859 static int action_ok_start_recording(const char *path,
3860       const char *label, unsigned type, size_t idx, size_t entry_idx)
3861 {
3862    streaming_set_state(false);
3863    command_event(CMD_EVENT_RECORD_INIT, NULL);
3864    return generic_action_ok_command(CMD_EVENT_RESUME);
3865 }
3866 
action_ok_start_streaming(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3867 static int action_ok_start_streaming(const char *path,
3868       const char *label, unsigned type, size_t idx, size_t entry_idx)
3869 {
3870    streaming_set_state(true);
3871    command_event(CMD_EVENT_RECORD_INIT, NULL);
3872    return generic_action_ok_command(CMD_EVENT_RESUME);
3873 }
3874 
action_ok_stop_recording(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3875 static int action_ok_stop_recording(const char *path,
3876       const char *label, unsigned type, size_t idx, size_t entry_idx)
3877 {
3878    command_event(CMD_EVENT_RECORD_DEINIT, NULL);
3879    return generic_action_ok_command(CMD_EVENT_RESUME);
3880 }
3881 
action_ok_stop_streaming(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3882 static int action_ok_stop_streaming(const char *path,
3883       const char *label, unsigned type, size_t idx, size_t entry_idx)
3884 {
3885    command_event(CMD_EVENT_RECORD_DEINIT, NULL);
3886    return generic_action_ok_command(CMD_EVENT_RESUME);
3887 }
3888 
3889 #ifdef HAVE_CHEATS
action_ok_cheat_add_top(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3890 static int action_ok_cheat_add_top(const char *path,
3891       const char *label, unsigned type, size_t idx, size_t entry_idx)
3892 {
3893    int i;
3894    struct item_cheat tmp;
3895    char msg[256];
3896    bool          refresh = false;
3897    unsigned int new_size = cheat_manager_get_size() + 1;
3898 
3899    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3900    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3901    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_EMU);
3902 
3903    memcpy(&tmp, &cheat_manager_state.cheats[cheat_manager_state.size-1],
3904          sizeof(struct item_cheat));
3905    tmp.idx = 0;
3906 
3907    for (i = cheat_manager_state.size-2; i >=0; i--)
3908    {
3909       memcpy(&cheat_manager_state.cheats[i+1],
3910             &cheat_manager_state.cheats[i], sizeof(struct item_cheat));
3911       cheat_manager_state.cheats[i+1].idx++;
3912    }
3913 
3914    memcpy(&cheat_manager_state.cheats[0], &tmp, sizeof(struct item_cheat));
3915 
3916    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_ADD_TOP_SUCCESS), sizeof(msg));
3917    msg[sizeof(msg) - 1] = 0;
3918 
3919    runloop_msg_queue_push(msg, 1, 180, true, NULL,
3920          MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3921 
3922    return 0;
3923 }
3924 
action_ok_cheat_add_bottom(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3925 static int action_ok_cheat_add_bottom(const char *path,
3926       const char *label, unsigned type, size_t idx, size_t entry_idx)
3927 {
3928    char msg[256];
3929    bool          refresh = false;
3930    unsigned int new_size = cheat_manager_get_size() + 1;
3931 
3932    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3933    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3934    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_EMU);
3935 
3936    msg[0] = '\0';
3937    strlcpy(msg,
3938          msg_hash_to_str(MSG_CHEAT_ADD_BOTTOM_SUCCESS), sizeof(msg));
3939    msg[sizeof(msg) - 1] = 0;
3940 
3941    runloop_msg_queue_push(msg, 1, 180, true, NULL,
3942          MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3943 
3944    return 0;
3945 }
3946 
action_ok_cheat_delete_all(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3947 static int action_ok_cheat_delete_all(const char *path,
3948       const char *label, unsigned type, size_t idx, size_t entry_idx)
3949 {
3950    char msg[256];
3951    bool refresh = false;
3952 
3953    msg[0]       = '\0';
3954    cheat_manager_state.delete_state = 0;
3955    cheat_manager_realloc(0, CHEAT_HANDLER_TYPE_EMU);
3956    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3957    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3958 
3959    strlcpy(msg,
3960          msg_hash_to_str(MSG_CHEAT_DELETE_ALL_SUCCESS), sizeof(msg));
3961    msg[sizeof(msg) - 1] = 0;
3962 
3963    runloop_msg_queue_push(msg, 1, 180, true, NULL,
3964          MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3965 
3966    return 0;
3967 }
3968 
action_ok_cheat_add_new_after(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)3969 static int action_ok_cheat_add_new_after(const char *path,
3970       const char *label, unsigned type, size_t idx, size_t entry_idx)
3971 {
3972    int i;
3973    char msg[256];
3974    struct item_cheat tmp;
3975    bool          refresh = false;
3976    unsigned int new_size = cheat_manager_get_size() + 1;
3977 
3978    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_EMU);
3979 
3980    memcpy(&tmp, &cheat_manager_state.cheats[cheat_manager_state.size-1],
3981          sizeof(struct item_cheat));
3982    tmp.idx = cheat_manager_state.working_cheat.idx+1;
3983 
3984    for (i = cheat_manager_state.size-2; i >= (int)(cheat_manager_state.working_cheat.idx+1); i--)
3985    {
3986       memcpy(&cheat_manager_state.cheats[i+1], &cheat_manager_state.cheats[i], sizeof(struct item_cheat));
3987       cheat_manager_state.cheats[i+1].idx++;
3988    }
3989 
3990    memcpy(&cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx+1], &tmp, sizeof(struct item_cheat));
3991 
3992    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
3993    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
3994 
3995    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_ADD_AFTER_SUCCESS), sizeof(msg));
3996    msg[sizeof(msg) - 1] = 0;
3997 
3998    runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
3999 
4000    return 0;
4001 }
4002 
action_ok_cheat_add_new_before(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4003 static int action_ok_cheat_add_new_before(const char *path,
4004       const char *label, unsigned type, size_t idx, size_t entry_idx)
4005 {
4006    int i;
4007    char msg[256];
4008    struct item_cheat tmp;
4009    bool          refresh = false;
4010    unsigned int new_size = cheat_manager_get_size() + 1;
4011 
4012    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_EMU);
4013 
4014    memcpy(&tmp, &cheat_manager_state.cheats[cheat_manager_state.size-1], sizeof(struct item_cheat));
4015    tmp.idx = cheat_manager_state.working_cheat.idx;
4016 
4017    for (i = cheat_manager_state.size-2; i >=(int)tmp.idx; i--)
4018    {
4019       memcpy(&cheat_manager_state.cheats[i+1], &cheat_manager_state.cheats[i], sizeof(struct item_cheat));
4020       cheat_manager_state.cheats[i+1].idx++;
4021    }
4022 
4023    memcpy(&cheat_manager_state.cheats[tmp.idx],
4024          &tmp, sizeof(struct item_cheat));
4025    memcpy(&cheat_manager_state.working_cheat,
4026          &tmp, sizeof(struct item_cheat));
4027 
4028    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
4029    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
4030 
4031    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_ADD_BEFORE_SUCCESS), sizeof(msg));
4032    msg[sizeof(msg) - 1] = 0;
4033 
4034    runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
4035 
4036    return 0;
4037 }
4038 
action_ok_cheat_copy_before(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4039 static int action_ok_cheat_copy_before(const char *path,
4040       const char *label, unsigned type, size_t idx, size_t entry_idx)
4041 {
4042    int i;
4043    struct item_cheat tmp;
4044    char msg[256];
4045    bool          refresh = false;
4046    unsigned int new_size = cheat_manager_get_size() + 1;
4047    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_RETRO);
4048 
4049    memcpy(&tmp, &cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx], sizeof(struct item_cheat));
4050    tmp.idx = cheat_manager_state.working_cheat.idx;
4051    if (tmp.code)
4052       tmp.code = strdup(tmp.code);
4053    if (tmp.desc)
4054       tmp.desc = strdup(tmp.desc);
4055 
4056    for (i = cheat_manager_state.size-2; i >=(int)tmp.idx; i--)
4057    {
4058       memcpy(&cheat_manager_state.cheats[i+1], &cheat_manager_state.cheats[i], sizeof(struct item_cheat));
4059       cheat_manager_state.cheats[i+1].idx++;
4060    }
4061 
4062    memcpy(&cheat_manager_state.cheats[tmp.idx], &tmp, sizeof(struct item_cheat));
4063    memcpy(&cheat_manager_state.working_cheat, &tmp, sizeof(struct item_cheat));
4064 
4065    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
4066    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
4067 
4068    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_COPY_BEFORE_SUCCESS), sizeof(msg));
4069    msg[sizeof(msg) - 1] = 0;
4070 
4071    runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
4072 
4073    return 0;
4074 }
4075 
action_ok_cheat_copy_after(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4076 static int action_ok_cheat_copy_after(const char *path,
4077       const char *label, unsigned type, size_t idx, size_t entry_idx)
4078 {
4079    int i;
4080    struct item_cheat tmp;
4081    char msg[256];
4082    bool          refresh = false;
4083    unsigned int new_size = cheat_manager_get_size() + 1;
4084 
4085    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_RETRO);
4086 
4087    memcpy(&tmp, &cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx], sizeof(struct item_cheat));
4088    tmp.idx = cheat_manager_state.working_cheat.idx+1;
4089    if (tmp.code)
4090       tmp.code = strdup(tmp.code);
4091    if (tmp.desc)
4092       tmp.desc = strdup(tmp.desc);
4093 
4094    for (i = cheat_manager_state.size-2; i >= (int)(cheat_manager_state.working_cheat.idx+1); i--)
4095    {
4096       memcpy(&cheat_manager_state.cheats[i+1], &cheat_manager_state.cheats[i], sizeof(struct item_cheat));
4097       cheat_manager_state.cheats[i+1].idx++;
4098    }
4099 
4100    memcpy(&cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx+1], &tmp, sizeof(struct item_cheat ));
4101 
4102    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
4103    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
4104 
4105    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_COPY_AFTER_SUCCESS), sizeof(msg));
4106    msg[sizeof(msg) - 1] = 0;
4107 
4108    runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
4109 
4110    return 0;
4111 }
4112 
action_ok_cheat_delete(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4113 static int action_ok_cheat_delete(const char *path,
4114       const char *label, unsigned type, size_t idx, size_t entry_idx)
4115 {
4116    char msg[256];
4117    size_t new_selection_ptr = 0;
4118    unsigned int new_size    = cheat_manager_get_size() - 1;
4119 
4120    if (new_size >0)
4121    {
4122       unsigned i;
4123 
4124       if (cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].code)
4125          free(cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].code);
4126       if (cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].desc)
4127          free(cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].desc);
4128 
4129       for (i = cheat_manager_state.working_cheat.idx; i <cheat_manager_state.size-1; i++)
4130       {
4131          memcpy(&cheat_manager_state.cheats[i], &cheat_manager_state.cheats[i+1], sizeof(struct item_cheat ));
4132          cheat_manager_state.cheats[i].idx--;
4133       }
4134 
4135       cheat_manager_state.cheats[cheat_manager_state.size-1].code            = NULL;
4136       cheat_manager_state.cheats[cheat_manager_state.size-1].desc            = NULL;
4137       cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].desc = NULL;
4138       cheat_manager_state.cheats[cheat_manager_state.working_cheat.idx].code = NULL;
4139 
4140    }
4141 
4142    cheat_manager_realloc(new_size, CHEAT_HANDLER_TYPE_RETRO);
4143 
4144    strlcpy(msg, msg_hash_to_str(MSG_CHEAT_DELETE_SUCCESS), sizeof(msg));
4145    msg[sizeof(msg) - 1] = 0;
4146 
4147    runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
4148 
4149    new_selection_ptr = menu_navigation_get_selection();
4150    menu_entries_pop_stack(&new_selection_ptr, 0, 1);
4151    menu_navigation_set_selection(new_selection_ptr);
4152 
4153    menu_driver_ctl(RARCH_MENU_CTL_UPDATE_SAVESTATE_THUMBNAIL_PATH, NULL);
4154    menu_driver_ctl(RARCH_MENU_CTL_UPDATE_SAVESTATE_THUMBNAIL_IMAGE, NULL);
4155 
4156    return 0;
4157 }
4158 #endif
4159 
action_ok_file_load_imageviewer(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4160 static int action_ok_file_load_imageviewer(const char *path,
4161       const char *label, unsigned type, size_t idx, size_t entry_idx)
4162 {
4163    char fullpath[PATH_MAX_LENGTH];
4164    const char *menu_path           = NULL;
4165    file_list_t *menu_stack         = menu_entries_get_menu_stack_ptr(0);
4166 
4167    file_list_get_last(menu_stack, &menu_path, NULL, NULL, NULL);
4168 
4169    fullpath[0] = '\0';
4170 
4171    if (!string_is_empty(menu_path))
4172       fill_pathname_join(fullpath, menu_path, path,
4173             sizeof(fullpath));
4174 
4175    return default_action_ok_load_content_with_core_from_menu(fullpath, CORE_TYPE_IMAGEVIEWER);
4176 }
4177 
action_ok_file_load_current_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4178 static int action_ok_file_load_current_core(const char *path,
4179       const char *label, unsigned type, size_t idx, size_t entry_idx)
4180 {
4181    menu_handle_t *menu                 = menu_driver_get_ptr();
4182 
4183    if (!menu)
4184       return menu_cbs_exit();
4185 
4186    return default_action_ok_load_content_with_core_from_menu(
4187          menu->detect_content_path, CORE_TYPE_PLAIN);
4188 }
4189 
action_ok_file_load_detect_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4190 static int action_ok_file_load_detect_core(const char *path,
4191       const char *label, unsigned type, size_t idx, size_t entry_idx)
4192 {
4193    content_ctx_info_t content_info;
4194    menu_handle_t *menu                 = menu_driver_get_ptr();
4195 
4196    if (!menu)
4197       return menu_cbs_exit();
4198 
4199    content_info.argc                   = 0;
4200    content_info.argv                   = NULL;
4201    content_info.args                   = NULL;
4202    content_info.environ_get            = NULL;
4203 
4204    if (!task_push_load_content_with_new_core_from_menu(
4205             path, menu->detect_content_path,
4206             &content_info,
4207             CORE_TYPE_PLAIN,
4208             NULL, NULL))
4209       return -1;
4210    content_add_to_playlist(menu->detect_content_path);
4211    menu_driver_set_last_start_content(menu->detect_content_path);
4212 
4213    return 0;
4214 }
4215 
action_ok_load_state(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4216 static int action_ok_load_state(const char *path,
4217       const char *label, unsigned type, size_t idx, size_t entry_idx)
4218 {
4219    settings_t *settings = config_get_ptr();
4220    bool resume          = settings->bools.menu_savestate_resume;
4221 
4222    if (generic_action_ok_command(CMD_EVENT_LOAD_STATE) == -1)
4223       return menu_cbs_exit();
4224 
4225    if (resume)
4226       return generic_action_ok_command(CMD_EVENT_RESUME);
4227 
4228    return 0;
4229 }
4230 
action_ok_save_state(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4231 static int action_ok_save_state(const char *path,
4232       const char *label, unsigned type, size_t idx, size_t entry_idx)
4233 {
4234    settings_t *settings = config_get_ptr();
4235    bool resume          = settings->bools.menu_savestate_resume;
4236 
4237    if (generic_action_ok_command(CMD_EVENT_SAVE_STATE) == -1)
4238       return menu_cbs_exit();
4239 
4240    if (resume)
4241       return generic_action_ok_command(CMD_EVENT_RESUME);
4242 
4243    return 0;
4244 }
4245 
action_ok_close_submenu(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4246 static int action_ok_close_submenu(const char* path,
4247    const char* label, unsigned type, size_t idx, size_t entry_idx)
4248 {
4249    return action_cancel_pop_default(path, label, type, idx);
4250 }
4251 
action_ok_cheevos_toggle_hardcore_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4252 static int action_ok_cheevos_toggle_hardcore_mode(const char *path,
4253       const char *label, unsigned type, size_t idx, size_t entry_idx)
4254 {
4255    generic_action_ok_command(CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE);
4256    action_cancel_pop_default(path, label, type, idx);
4257    return generic_action_ok_command(CMD_EVENT_RESUME);
4258 }
4259 
action_ok_undo_load_state(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4260 static int action_ok_undo_load_state(const char *path,
4261       const char *label, unsigned type, size_t idx, size_t entry_idx)
4262 {
4263    if (generic_action_ok_command(CMD_EVENT_UNDO_LOAD_STATE) == -1)
4264       return menu_cbs_exit();
4265    return generic_action_ok_command(CMD_EVENT_RESUME);
4266 }
4267 
action_ok_undo_save_state(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4268 static int action_ok_undo_save_state(const char *path,
4269       const char *label, unsigned type, size_t idx, size_t entry_idx)
4270 {
4271    if (generic_action_ok_command(CMD_EVENT_UNDO_SAVE_STATE) == -1)
4272       return menu_cbs_exit();
4273    return generic_action_ok_command(CMD_EVENT_RESUME);
4274 }
4275 
4276 #ifdef HAVE_NETWORKING
4277 
4278 #ifdef HAVE_ZLIB
cb_decompressed(retro_task_t * task,void * task_data,void * user_data,const char * err)4279 static void cb_decompressed(retro_task_t *task,
4280       void *task_data, void *user_data, const char *err)
4281 {
4282    decompress_task_data_t *dec = (decompress_task_data_t*)task_data;
4283 
4284    if (dec && !err)
4285    {
4286       unsigned enum_idx = (unsigned)(uintptr_t)user_data;
4287 
4288       switch (enum_idx)
4289       {
4290          case MENU_ENUM_LABEL_CB_UPDATE_ASSETS:
4291             generic_action_ok_command(CMD_EVENT_REINIT);
4292             break;
4293          default:
4294             break;
4295       }
4296    }
4297 
4298    if (err)
4299       RARCH_ERR("%s", err);
4300 
4301    if (dec)
4302    {
4303       if (filestream_exists(dec->source_file))
4304          filestream_delete(dec->source_file);
4305 
4306       free(dec->source_file);
4307       free(dec);
4308    }
4309 }
4310 #endif
4311 
action_ok_core_updater_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4312 static int action_ok_core_updater_list(const char *path,
4313       const char *label, unsigned type, size_t idx, size_t entry_idx)
4314 {
4315    /* Get cached core updater list, initialising
4316     * it if required */
4317    core_updater_list_t *core_list = core_updater_list_get_cached();
4318 
4319    if (!core_list)
4320    {
4321       core_updater_list_init_cached();
4322       core_list = core_updater_list_get_cached();
4323 
4324       if (!core_list)
4325          return menu_cbs_exit();
4326    }
4327 
4328 #if defined(ANDROID)
4329    if (play_feature_delivery_enabled())
4330    {
4331       settings_t *settings                = config_get_ptr();
4332       const char *path_dir_libretro       = settings->paths.directory_libretro;
4333       const char *path_libretro_info      = settings->paths.path_libretro_info;
4334       /* Core downloads are handled via play
4335        * feature delivery
4336        * > Core list can be populated directly
4337        *   using the play feature delivery
4338        *   interface */
4339       struct string_list *available_cores =
4340          play_feature_delivery_available_cores();
4341       bool success                        = false;
4342 
4343       if (!available_cores)
4344          return menu_cbs_exit();
4345 
4346       core_updater_list_reset(core_list);
4347 
4348       success = core_updater_list_parse_pfd_data(
4349             core_list,
4350             path_dir_libretro,
4351             path_libretro_info,
4352             available_cores);
4353 
4354       string_list_free(available_cores);
4355 
4356       if (!success)
4357          return menu_cbs_exit();
4358 
4359       /* Ensure network is initialised */
4360       generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
4361    }
4362    else
4363 #endif
4364    {
4365       bool refresh = true;
4366 
4367       /* Initial setup... */
4368       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
4369       generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
4370 
4371       /* Push core list update task */
4372       task_push_get_core_updater_list(core_list, false, true);
4373    }
4374 
4375    return generic_action_ok_displaylist_push(
4376          path, NULL, label, type, idx, entry_idx,
4377          ACTION_OK_DL_CORE_UPDATER_LIST);
4378 }
4379 
cb_net_generic_subdir(retro_task_t * task,void * task_data,void * user_data,const char * err)4380 static void cb_net_generic_subdir(retro_task_t *task,
4381       void *task_data, void *user_data, const char *err)
4382 {
4383    char subdir_path[PATH_MAX_LENGTH];
4384    http_transfer_data_t *data   = (http_transfer_data_t*)task_data;
4385    file_transfer_t *state       = (file_transfer_t*)user_data;
4386 
4387    subdir_path[0]               = '\0';
4388 
4389    if (!data || err)
4390       goto finish;
4391 
4392    if (!string_is_empty(data->data))
4393       memcpy(subdir_path, data->data, data->len * sizeof(char));
4394    subdir_path[data->len] = '\0';
4395 
4396 finish:
4397    if (!err && !string_ends_with_size(subdir_path,
4398             FILE_PATH_INDEX_DIRS_URL,
4399             strlen(subdir_path),
4400             STRLEN_CONST(FILE_PATH_INDEX_DIRS_URL)
4401             ))
4402    {
4403       char parent_dir[PATH_MAX_LENGTH];
4404 
4405       parent_dir[0] = '\0';
4406 
4407       fill_pathname_parent_dir(parent_dir,
4408             state->path, sizeof(parent_dir));
4409 
4410       /*generic_action_ok_displaylist_push(parent_dir, NULL,
4411             subdir_path, 0, 0, 0, ACTION_OK_DL_CORE_CONTENT_DIRS_SUBDIR_LIST);*/
4412    }
4413 
4414    if (user_data)
4415       free(user_data);
4416 }
4417 
cb_net_generic(retro_task_t * task,void * task_data,void * user_data,const char * err)4418 static void cb_net_generic(retro_task_t *task,
4419       void *task_data, void *user_data, const char *err)
4420 {
4421    bool refresh                   = false;
4422    http_transfer_data_t *data     = (http_transfer_data_t*)task_data;
4423    file_transfer_t *state         = (file_transfer_t*)user_data;
4424    menu_handle_t            *menu = menu_driver_get_ptr();
4425 
4426    if (!menu)
4427       goto finish;
4428 
4429    if (menu->core_buf)
4430       free(menu->core_buf);
4431 
4432    menu->core_buf = NULL;
4433    menu->core_len = 0;
4434 
4435    if (!data || err || !data->data)
4436       goto finish;
4437 
4438    menu->core_buf = (char*)malloc((data->len+1) * sizeof(char));
4439 
4440    if (!menu->core_buf)
4441       goto finish;
4442 
4443    if (!string_is_empty(data->data))
4444       memcpy(menu->core_buf, data->data, data->len * sizeof(char));
4445    menu->core_buf[data->len] = '\0';
4446    menu->core_len            = data->len;
4447 
4448 finish:
4449    refresh = true;
4450    menu_entries_ctl(MENU_ENTRIES_CTL_UNSET_REFRESH, &refresh);
4451 
4452    if (!err &&
4453          !string_ends_with_size(state->path,
4454             FILE_PATH_INDEX_DIRS_URL,
4455             strlen(state->path),
4456             STRLEN_CONST(FILE_PATH_INDEX_DIRS_URL)
4457             ))
4458    {
4459       char parent_dir[PATH_MAX_LENGTH];
4460       char parent_dir_encoded[PATH_MAX_LENGTH];
4461       file_transfer_t *transf     = NULL;
4462 
4463       parent_dir[0]               = '\0';
4464       parent_dir_encoded[0]       = '\0';
4465 
4466       fill_pathname_parent_dir(parent_dir,
4467             state->path, sizeof(parent_dir));
4468       strlcat(parent_dir, FILE_PATH_INDEX_DIRS_URL,
4469             sizeof(parent_dir));
4470 
4471       transf           = (file_transfer_t*)malloc(sizeof(*transf));
4472 
4473       transf->enum_idx = MSG_UNKNOWN;
4474       strlcpy(transf->path, parent_dir, sizeof(transf->path));
4475 
4476       net_http_urlencode_full(parent_dir_encoded, parent_dir,
4477             sizeof(parent_dir_encoded));
4478       task_push_http_transfer_file(parent_dir_encoded, true,
4479             "index_dirs", cb_net_generic_subdir, transf);
4480    }
4481 
4482    if (state)
4483       free(state);
4484 }
4485 
generic_action_ok_network(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,enum msg_hash_enums enum_idx)4486 static int generic_action_ok_network(const char *path,
4487       const char *label, unsigned type, size_t idx, size_t entry_idx,
4488       enum msg_hash_enums enum_idx)
4489 {
4490    char url_path[PATH_MAX_LENGTH];
4491    char url_path_encoded[PATH_MAX_LENGTH];
4492    unsigned type_id2                       = 0;
4493    file_transfer_t *transf                 = NULL;
4494    const char *url_label                   = NULL;
4495    retro_task_callback_t callback          = NULL;
4496    bool refresh                            = true;
4497    bool suppress_msg                       = false;
4498    settings_t *settings                    = config_get_ptr();
4499    const char *network_buildbot_assets_url =
4500       settings->paths.network_buildbot_assets_url;
4501 
4502    url_path[0]         = '\0';
4503    url_path_encoded[0] = '\0';
4504 
4505    switch (enum_idx)
4506    {
4507       case MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST:
4508 
4509          if (string_is_empty(network_buildbot_assets_url))
4510             return menu_cbs_exit();
4511 
4512          fill_pathname_join(url_path,
4513                network_buildbot_assets_url,
4514                "cores/" FILE_PATH_INDEX_DIRS_URL,
4515                sizeof(url_path));
4516          url_label    = msg_hash_to_str(enum_idx);
4517          type_id2     = ACTION_OK_DL_CORE_CONTENT_DIRS_LIST;
4518          callback     = cb_net_generic;
4519          suppress_msg = true;
4520          break;
4521       case MENU_ENUM_LABEL_CB_CORE_CONTENT_LIST:
4522          fill_pathname_join(url_path, path,
4523                FILE_PATH_INDEX_URL, sizeof(url_path));
4524          url_label    = msg_hash_to_str(enum_idx);
4525          type_id2     = ACTION_OK_DL_CORE_CONTENT_LIST;
4526          callback     = cb_net_generic;
4527          suppress_msg = true;
4528          break;
4529       case MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_LIST:
4530          fill_pathname_join(url_path,
4531                FILE_PATH_CORE_THUMBNAILPACKS_URL,
4532                FILE_PATH_INDEX_URL, sizeof(url_path));
4533          url_label    = msg_hash_to_str(enum_idx);
4534          type_id2     = ACTION_OK_DL_THUMBNAILS_UPDATER_LIST;
4535          callback     = cb_net_generic;
4536          break;
4537 #ifdef HAVE_LAKKA
4538       case MENU_ENUM_LABEL_CB_LAKKA_LIST:
4539          /* TODO unhardcode this path */
4540          fill_pathname_join(url_path,
4541                FILE_PATH_LAKKA_URL,
4542                lakka_get_project(), sizeof(url_path));
4543          fill_pathname_join(url_path, url_path,
4544                FILE_PATH_INDEX_URL,
4545                sizeof(url_path));
4546          url_label    = msg_hash_to_str(enum_idx);
4547          type_id2     = ACTION_OK_DL_LAKKA_LIST;
4548          callback     = cb_net_generic;
4549          break;
4550 #endif
4551       default:
4552          break;
4553    }
4554 
4555    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
4556 
4557    generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
4558 
4559    transf           = (file_transfer_t*)calloc(1, sizeof(*transf));
4560    strlcpy(transf->path, url_path, sizeof(transf->path));
4561 
4562    net_http_urlencode_full(url_path_encoded, url_path, sizeof(url_path_encoded));
4563    task_push_http_transfer_file(url_path_encoded, suppress_msg, url_label, callback, transf);
4564 
4565    return generic_action_ok_displaylist_push(path, NULL,
4566          label, type, idx, entry_idx, type_id2);
4567 }
4568 
DEFAULT_ACTION_OK_LIST(action_ok_core_content_list,MENU_ENUM_LABEL_CB_CORE_CONTENT_LIST)4569 DEFAULT_ACTION_OK_LIST(action_ok_core_content_list, MENU_ENUM_LABEL_CB_CORE_CONTENT_LIST)
4570 DEFAULT_ACTION_OK_LIST(action_ok_core_content_dirs_list, MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST)
4571 DEFAULT_ACTION_OK_LIST(action_ok_thumbnails_updater_list, MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_LIST)
4572 DEFAULT_ACTION_OK_LIST(action_ok_lakka_list, MENU_ENUM_LABEL_CB_LAKKA_LIST)
4573 
4574 static void cb_generic_dir_download(retro_task_t *task,
4575       void *task_data,
4576       void *user_data, const char *err)
4577 {
4578    file_transfer_t     *transf      = (file_transfer_t*)user_data;
4579    if (transf)
4580    {
4581       generic_action_ok_network(transf->path, transf->path, 0, 0, 0,
4582             MENU_ENUM_LABEL_CB_CORE_CONTENT_LIST);
4583 
4584       free(transf);
4585    }
4586 }
4587 
4588 /* expects http_transfer_t*, file_transfer_t* */
cb_generic_download(retro_task_t * task,void * task_data,void * user_data,const char * err)4589 void cb_generic_download(retro_task_t *task,
4590       void *task_data,
4591       void *user_data, const char *err)
4592 {
4593    char output_path[PATH_MAX_LENGTH];
4594    char buf[PATH_MAX_LENGTH];
4595 #if defined(HAVE_COMPRESSION) && defined(HAVE_ZLIB)
4596    bool extract                          = true;
4597 #endif
4598    const char             *dir_path      = NULL;
4599    file_transfer_t     *transf           = (file_transfer_t*)user_data;
4600    settings_t              *settings     = config_get_ptr();
4601    http_transfer_data_t        *data     = (http_transfer_data_t*)task_data;
4602 
4603    if (!data || !data->data || !transf)
4604       goto finish;
4605 
4606    output_path[0] = '\0';
4607 
4608    /* we have to determine dir_path at the time of writting or else
4609     * we'd run into races when the user changes the setting during an
4610     * http transfer. */
4611    switch (transf->enum_idx)
4612    {
4613       case MENU_ENUM_LABEL_CB_CORE_THUMBNAILS_DOWNLOAD:
4614          dir_path = settings->paths.directory_thumbnails;
4615          break;
4616       case MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD:
4617          dir_path = settings->paths.directory_core_assets;
4618 #if defined(HAVE_COMPRESSION) && defined(HAVE_ZLIB)
4619          extract  = settings->bools.network_buildbot_auto_extract_archive;
4620 #endif
4621          break;
4622       case MENU_ENUM_LABEL_CB_UPDATE_CORE_INFO_FILES:
4623          dir_path = settings->paths.path_libretro_info;
4624          break;
4625       case MENU_ENUM_LABEL_CB_UPDATE_ASSETS:
4626          dir_path = settings->paths.directory_assets;
4627          break;
4628       case MENU_ENUM_LABEL_CB_UPDATE_AUTOCONFIG_PROFILES:
4629          dir_path = settings->paths.directory_autoconfig;
4630          break;
4631       case MENU_ENUM_LABEL_CB_UPDATE_DATABASES:
4632          dir_path = settings->paths.path_content_database;
4633          break;
4634       case MENU_ENUM_LABEL_CB_UPDATE_OVERLAYS:
4635          dir_path = settings->paths.directory_overlay;
4636          break;
4637       case MENU_ENUM_LABEL_CB_UPDATE_CHEATS:
4638          dir_path = settings->paths.path_cheat_database;
4639          break;
4640       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_CG:
4641       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL:
4642       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG:
4643 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
4644          {
4645             static char shaderdir[PATH_MAX_LENGTH] = {0};
4646             const char *dirname                    = NULL;
4647             const char *dir_video_shader           = settings->paths.directory_video_shader;
4648 
4649             switch (transf->enum_idx)
4650             {
4651                case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_CG:
4652                   dirname                                   = "shaders_cg";
4653                   break;
4654                case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL:
4655                   dirname                                   = "shaders_glsl";
4656                   break;
4657                case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG:
4658                   dirname                                   = "shaders_slang";
4659                   break;
4660                default:
4661                   break;
4662             }
4663 
4664             fill_pathname_join(shaderdir, dir_video_shader,
4665                   dirname, sizeof(shaderdir));
4666 
4667             if (!path_is_directory(shaderdir) && !path_mkdir(shaderdir))
4668                goto finish;
4669 
4670             dir_path = shaderdir;
4671          }
4672 #endif
4673          break;
4674       case MENU_ENUM_LABEL_CB_LAKKA_DOWNLOAD:
4675          dir_path = LAKKA_UPDATE_DIR;
4676          break;
4677       case MENU_ENUM_LABEL_CB_DISCORD_AVATAR:
4678          fill_pathname_application_special(buf, sizeof(buf),
4679                APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS);
4680          dir_path = buf;
4681          break;
4682       default:
4683          RARCH_WARN("Unknown transfer type '%s' bailing out.\n",
4684                msg_hash_to_str(transf->enum_idx));
4685          break;
4686    }
4687 
4688    if (!string_is_empty(dir_path))
4689       fill_pathname_join(output_path, dir_path,
4690             transf->path, sizeof(output_path));
4691 
4692    /* Make sure the directory exists
4693     * This function is horrible. It mutates the original path
4694     * so after operating we'll have to set the path to the intended
4695     * location again...
4696     */
4697    path_basedir_wrapper(output_path);
4698 
4699    if (!path_mkdir(output_path))
4700    {
4701       err = msg_hash_to_str(MSG_FAILED_TO_CREATE_THE_DIRECTORY);
4702       goto finish;
4703    }
4704 
4705    if (!string_is_empty(dir_path))
4706       fill_pathname_join(output_path, dir_path,
4707             transf->path, sizeof(output_path));
4708 
4709 #ifdef HAVE_COMPRESSION
4710    if (path_is_compressed_file(output_path))
4711    {
4712       if (task_check_decompress(output_path))
4713       {
4714          err = msg_hash_to_str(MSG_DECOMPRESSION_ALREADY_IN_PROGRESS);
4715          goto finish;
4716       }
4717    }
4718 #endif
4719 
4720    if (!filestream_write_file(output_path, data->data, data->len))
4721    {
4722       err = "Write failed.";
4723       goto finish;
4724    }
4725 
4726 #if defined(HAVE_COMPRESSION) && defined(HAVE_ZLIB)
4727    if (!extract)
4728       goto finish;
4729 
4730    if (path_is_compressed_file(output_path))
4731    {
4732       retro_task_t *decompress_task = NULL;
4733       void *frontend_userdata       = task->frontend_userdata;
4734       task->frontend_userdata       = NULL;
4735 
4736       decompress_task = (retro_task_t*)task_push_decompress(
4737             output_path, dir_path,
4738             NULL, NULL, NULL,
4739             cb_decompressed,
4740             (void*)(uintptr_t)transf->enum_idx,
4741             frontend_userdata, false);
4742 
4743       if (!decompress_task)
4744       {
4745          err = msg_hash_to_str(MSG_DECOMPRESSION_FAILED);
4746          goto finish;
4747       }
4748    }
4749 #endif
4750 
4751 finish:
4752    if (err)
4753    {
4754       RARCH_ERR("Download of '%s' failed: %s\n",
4755             (transf ? transf->path: msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNKNOWN)), err);
4756    }
4757 #ifdef HAVE_DISCORD
4758    else if (transf && transf->enum_idx == MENU_ENUM_LABEL_CB_DISCORD_AVATAR)
4759       discord_avatar_set_ready(true);
4760 #endif
4761 
4762    if (transf)
4763       free(transf);
4764 }
4765 #endif
4766 
action_ok_download_generic(const char * path,const char * label,const char * menu_label,unsigned type,size_t idx,size_t entry_idx,enum msg_hash_enums enum_idx)4767 static int action_ok_download_generic(const char *path,
4768       const char *label, const char *menu_label,
4769       unsigned type, size_t idx, size_t entry_idx,
4770       enum msg_hash_enums enum_idx)
4771 {
4772 #ifdef HAVE_NETWORKING
4773    char s[PATH_MAX_LENGTH];
4774    char s2[PATH_MAX_LENGTH];
4775    char s3[PATH_MAX_LENGTH];
4776    file_transfer_t *transf      = NULL;
4777    bool suppress_msg            = false;
4778    retro_task_callback_t cb     = cb_generic_download;
4779    settings_t *settings         = config_get_ptr();
4780    const char *network_buildbot_assets_url =
4781       settings->paths.network_buildbot_assets_url;
4782    const char *network_buildbot_url = settings->paths.network_buildbot_url;
4783 
4784    s[0] = s2[0] = s3[0] = '\0';
4785 
4786    fill_pathname_join(s,
4787          network_buildbot_assets_url,
4788          "frontend", sizeof(s));
4789 
4790    switch (enum_idx)
4791    {
4792       case MENU_ENUM_LABEL_CB_DOWNLOAD_URL:
4793          suppress_msg = true;
4794          fill_pathname_join(s, label,
4795                path, sizeof(s));
4796          path = s;
4797          cb = cb_generic_dir_download;
4798          break;
4799       case MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD:
4800          {
4801             struct string_list str_list  = {0};
4802 
4803             string_list_initialize(&str_list);
4804             if (string_split_noalloc(&str_list, menu_label, ";"))
4805                strlcpy(s, str_list.elems[0].data, sizeof(s));
4806             string_list_deinitialize(&str_list);
4807          }
4808          break;
4809       case MENU_ENUM_LABEL_CB_LAKKA_DOWNLOAD:
4810 #ifdef HAVE_LAKKA
4811          /* TODO unhardcode this path*/
4812          fill_pathname_join(s, FILE_PATH_LAKKA_URL,
4813                lakka_get_project(), sizeof(s));
4814 #endif
4815          break;
4816       case MENU_ENUM_LABEL_CB_UPDATE_ASSETS:
4817          path = "assets.zip";
4818          break;
4819       case MENU_ENUM_LABEL_CB_UPDATE_AUTOCONFIG_PROFILES:
4820          path = "autoconfig.zip";
4821          break;
4822       case MENU_ENUM_LABEL_CB_UPDATE_CORE_INFO_FILES:
4823          path = "info.zip";
4824          break;
4825       case MENU_ENUM_LABEL_CB_UPDATE_CHEATS:
4826          path = "cheats.zip";
4827          break;
4828       case MENU_ENUM_LABEL_CB_UPDATE_OVERLAYS:
4829          path = "overlays.zip";
4830          break;
4831       case MENU_ENUM_LABEL_CB_UPDATE_DATABASES:
4832          path = "database-rdb.zip";
4833          break;
4834       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL:
4835          path = "shaders_glsl.zip";
4836          break;
4837       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG:
4838          path = "shaders_slang.zip";
4839          break;
4840       case MENU_ENUM_LABEL_CB_UPDATE_SHADERS_CG:
4841          path = "shaders_cg.zip";
4842          break;
4843       case MENU_ENUM_LABEL_CB_CORE_THUMBNAILS_DOWNLOAD:
4844          strcpy_literal(s, "http://thumbnailpacks.libretro.com");
4845          break;
4846       default:
4847          strlcpy(s, network_buildbot_url, sizeof(s));
4848          break;
4849    }
4850 
4851    fill_pathname_join(s2, s, path, sizeof(s2));
4852 
4853    transf           = (file_transfer_t*)calloc(1, sizeof(*transf));
4854    transf->enum_idx = enum_idx;
4855    strlcpy(transf->path, path, sizeof(transf->path));
4856 
4857    if (string_is_equal(path, s))
4858       net_http_urlencode_full(s3, s, sizeof(s3));
4859    else
4860       net_http_urlencode_full(s3, s2, sizeof(s3));
4861 
4862    task_push_http_transfer_file(s3, suppress_msg,
4863          msg_hash_to_str(enum_idx), cb, transf);
4864 #endif
4865    return 0;
4866 }
4867 
action_ok_core_content_download(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4868 static int action_ok_core_content_download(const char *path,
4869       const char *label, unsigned type, size_t idx, size_t entry_idx)
4870 {
4871    const char *menu_path   = NULL;
4872    const char *menu_label  = NULL;
4873    enum msg_hash_enums enum_idx = MSG_UNKNOWN;
4874 
4875    menu_entries_get_last_stack(&menu_path, &menu_label,
4876          NULL, &enum_idx, NULL);
4877 
4878    return action_ok_download_generic(path, label,
4879          menu_path, type, idx, entry_idx,
4880          MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD);
4881 }
4882 
action_ok_core_updater_download(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4883 static int action_ok_core_updater_download(const char *path,
4884       const char *label, unsigned type, size_t idx, size_t entry_idx)
4885 {
4886 #ifdef HAVE_NETWORKING
4887    core_updater_list_t *core_list    = core_updater_list_get_cached();
4888    settings_t          *settings     = config_get_ptr();
4889    bool auto_backup                  = settings->bools.core_updater_auto_backup;
4890    unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
4891    const char *path_dir_libretro     = settings->paths.directory_libretro;
4892    const char *path_dir_core_assets  = settings->paths.directory_core_assets;
4893 
4894    if (!core_list)
4895       return menu_cbs_exit();
4896 
4897 #if defined(ANDROID)
4898    /* Play Store builds install cores via
4899     * the play feature delivery interface */
4900    if (play_feature_delivery_enabled())
4901       task_push_play_feature_delivery_core_install(
4902             core_list, path, false);
4903    else
4904 #endif
4905       task_push_core_updater_download(
4906             core_list, path, 0, false,
4907             auto_backup, (size_t)auto_backup_history_size,
4908             path_dir_libretro, path_dir_core_assets);
4909 
4910 #endif
4911    return 0;
4912 }
4913 
4914 #ifdef HAVE_NETWORKING
action_ok_update_installed_cores(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4915 static int action_ok_update_installed_cores(const char *path,
4916       const char *label, unsigned type, size_t idx, size_t entry_idx)
4917 {
4918    settings_t          *settings     = config_get_ptr();
4919    bool auto_backup                  = settings->bools.core_updater_auto_backup;
4920    unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
4921    const char *path_dir_libretro     = settings->paths.directory_libretro;
4922    const char *path_dir_core_assets  = settings->paths.directory_core_assets;
4923 
4924    /* Ensure networking is initialised */
4925    generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
4926 
4927    /* Push update task */
4928    task_push_update_installed_cores(
4929          auto_backup, auto_backup_history_size,
4930          path_dir_libretro, path_dir_core_assets);
4931 
4932    return 0;
4933 }
4934 
4935 #if defined(ANDROID)
action_ok_switch_installed_cores_pfd(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4936 static int action_ok_switch_installed_cores_pfd(const char *path,
4937       const char *label, unsigned type, size_t idx, size_t entry_idx)
4938 {
4939    settings_t          *settings     = config_get_ptr();
4940    const char *path_dir_libretro     = settings->paths.directory_libretro;
4941    const char *path_libretro_info    = settings->paths.path_libretro_info;
4942 
4943    /* Ensure networking is initialised */
4944    generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
4945 
4946    /* Push core switch/update task */
4947    task_push_play_feature_delivery_switch_installed_cores(
4948          path_dir_libretro, path_libretro_info);
4949 
4950    return 0;
4951 }
4952 #endif
4953 #endif
4954 
action_ok_sideload_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)4955 static int action_ok_sideload_core(const char *path,
4956       const char *label, unsigned type, size_t idx, size_t entry_idx)
4957 {
4958    char backup_path[PATH_MAX_LENGTH];
4959    const char *menu_path    = NULL;
4960    const char *core_file    = path;
4961    bool core_loaded         = false;
4962    menu_handle_t *menu      = menu_driver_get_ptr();
4963    settings_t *settings     = config_get_ptr();
4964    const char *dir_libretro = settings->paths.directory_libretro;
4965 
4966    backup_path[0] = '\0';
4967 
4968    if (string_is_empty(core_file) || !menu)
4969       return menu_cbs_exit();
4970 
4971    /* Get path of source (core 'backup') file */
4972    menu_entries_get_last_stack(
4973          &menu_path, NULL, NULL, NULL, NULL);
4974 
4975    if (!string_is_empty(menu_path))
4976       fill_pathname_join(
4977             backup_path, menu_path, core_file, sizeof(backup_path));
4978    else
4979       strlcpy(backup_path, core_file, sizeof(backup_path));
4980 
4981    /* Push core 'restore' task */
4982    task_push_core_restore(backup_path, dir_libretro, &core_loaded);
4983 
4984    /* Flush stack
4985     * > Since the 'sideload core' option is present
4986     *   in several locations, can't flush to a predefined
4987     *   level - just go to the top */
4988    menu_entries_flush_stack(NULL, 0);
4989 
4990    return 0;
4991 }
4992 
DEFAULT_ACTION_OK_DOWNLOAD(action_ok_core_content_thumbnails,MENU_ENUM_LABEL_CB_CORE_THUMBNAILS_DOWNLOAD)4993 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_core_content_thumbnails, MENU_ENUM_LABEL_CB_CORE_THUMBNAILS_DOWNLOAD)
4994 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_thumbnails_updater_download, MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_DOWNLOAD)
4995 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_download_url, MENU_ENUM_LABEL_CB_DOWNLOAD_URL)
4996 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_lakka_download, MENU_ENUM_LABEL_CB_LAKKA_DOWNLOAD)
4997 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_assets, MENU_ENUM_LABEL_CB_UPDATE_ASSETS)
4998 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_core_info_files, MENU_ENUM_LABEL_CB_UPDATE_CORE_INFO_FILES)
4999 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_overlays, MENU_ENUM_LABEL_CB_UPDATE_OVERLAYS)
5000 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
5001 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_shaders_cg, MENU_ENUM_LABEL_CB_UPDATE_SHADERS_CG)
5002 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_shaders_glsl, MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL)
5003 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_shaders_slang, MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG)
5004 #endif
5005 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_databases, MENU_ENUM_LABEL_CB_UPDATE_DATABASES)
5006 #ifdef HAVE_CHEATS
5007 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_cheats, MENU_ENUM_LABEL_CB_UPDATE_CHEATS)
5008 #endif
5009 DEFAULT_ACTION_OK_DOWNLOAD(action_ok_update_autoconfig_profiles, MENU_ENUM_LABEL_CB_UPDATE_AUTOCONFIG_PROFILES)
5010 
5011 static int action_ok_game_specific_core_options_create(const char *path,
5012       const char *label, unsigned type, size_t idx, size_t entry_idx)
5013 {
5014    bool refresh = false;
5015 
5016    core_options_create_override(true);
5017 
5018    /* Refresh menu */
5019    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5020    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5021 
5022    return 0;
5023 }
5024 
action_ok_folder_specific_core_options_create(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5025 static int action_ok_folder_specific_core_options_create(const char *path,
5026       const char *label, unsigned type, size_t idx, size_t entry_idx)
5027 {
5028    bool refresh = false;
5029 
5030    core_options_create_override(false);
5031 
5032    /* Refresh menu */
5033    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5034    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5035 
5036    return 0;
5037 }
5038 
action_ok_game_specific_core_options_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5039 static int action_ok_game_specific_core_options_remove(const char *path,
5040       const char *label, unsigned type, size_t idx, size_t entry_idx)
5041 {
5042    bool refresh = false;
5043 
5044    core_options_remove_override(true);
5045 
5046    /* Refresh menu */
5047    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5048    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5049 
5050    return 0;
5051 }
5052 
action_ok_folder_specific_core_options_remove(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5053 static int action_ok_folder_specific_core_options_remove(const char *path,
5054       const char *label, unsigned type, size_t idx, size_t entry_idx)
5055 {
5056    bool refresh = false;
5057 
5058    core_options_remove_override(false);
5059 
5060    /* Refresh menu */
5061    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5062    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5063 
5064    return 0;
5065 }
5066 
action_ok_core_options_reset(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5067 static int action_ok_core_options_reset(const char *path,
5068       const char *label, unsigned type, size_t idx, size_t entry_idx)
5069 {
5070    core_options_reset();
5071    return 0;
5072 }
5073 
action_ok_close_content(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5074 int action_ok_close_content(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx)
5075 {
5076    int ret;
5077 
5078    /* Reset navigation pointer
5079     * > If we are returning to the quick menu, want
5080     *   the active entry to be 'Run' (first item in
5081     *   menu list) */
5082    menu_navigation_set_selection(0);
5083 
5084    /* Unload core */
5085    ret = generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
5086 
5087    /* If close content was selected via 'Main Menu > Quick Menu',
5088     * have to flush the menu stack back to 'Main Menu'
5089     * (otherwise users will be presented with an empty
5090     * 'No items' quick menu, requiring needless backwards
5091     * navigation) */
5092    if (type == MENU_SETTING_ACTION_CLOSE)
5093    {
5094       menu_entries_flush_stack(msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU), 0);
5095       /* An annoyance - some menu drivers (Ozone...) call
5096        * RARCH_MENU_CTL_SET_PREVENT_POPULATE in awkward
5097        * places, which can cause breakage here when flushing
5098        * the menu stack. We therefore have to force a
5099        * RARCH_MENU_CTL_UNSET_PREVENT_POPULATE */
5100       menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
5101    }
5102 
5103    return ret;
5104 }
5105 
DEFAULT_ACTION_OK_CMD_FUNC(action_ok_cheat_apply_changes,CMD_EVENT_CHEATS_APPLY)5106 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_cheat_apply_changes,      CMD_EVENT_CHEATS_APPLY)
5107 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_quit,                     CMD_EVENT_QUIT)
5108 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_save_new_config,          CMD_EVENT_MENU_SAVE_CONFIG)
5109 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_resume_content,           CMD_EVENT_RESUME)
5110 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_restart_content,          CMD_EVENT_RESET)
5111 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_screenshot,               CMD_EVENT_TAKE_SCREENSHOT)
5112 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
5113 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_shader_apply_changes,     CMD_EVENT_SHADERS_APPLY_CHANGES)
5114 #endif
5115 DEFAULT_ACTION_OK_CMD_FUNC(action_ok_show_wimp,                CMD_EVENT_UI_COMPANION_TOGGLE)
5116 
5117 static int action_ok_set_core_association(const char *path,
5118       const char *label, unsigned type, size_t idx, size_t entry_idx)
5119 {
5120    menu_handle_t *menu                 = menu_driver_get_ptr();
5121 
5122    if (!menu)
5123       return menu_cbs_exit();
5124 
5125    /* TODO/FIXME - menu->rpl_entry_selection_ptr - find
5126     * a way so that we can remove this temporary state */
5127    return generic_action_ok_displaylist_push(path, NULL,
5128          NULL, 0, menu->rpl_entry_selection_ptr, entry_idx,
5129          ACTION_OK_DL_DEFERRED_CORE_LIST_SET);
5130 }
5131 
action_ok_reset_core_association(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5132 static int action_ok_reset_core_association(const char *path,
5133       const char *label, unsigned type, size_t idx, size_t entry_idx)
5134 {
5135    menu_handle_t *menu                 = menu_driver_get_ptr();
5136    size_t playlist_index;
5137 
5138    if (!menu)
5139       return menu_cbs_exit();
5140 
5141    playlist_index = (size_t)menu->rpl_entry_selection_ptr;
5142 
5143    if (!command_event(CMD_EVENT_RESET_CORE_ASSOCIATION,
5144             (void *)&playlist_index))
5145       return menu_cbs_exit();
5146    return 0;
5147 }
5148 
5149 /* This function is called when selecting 'add to favorites'
5150  * while viewing the quick menu (i.e. content is running) */
action_ok_add_to_favorites(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5151 static int action_ok_add_to_favorites(const char *path,
5152       const char *label, unsigned type, size_t idx, size_t entry_idx)
5153 {
5154    const char *content_path = path_get(RARCH_PATH_CONTENT);
5155    int ret = 0;
5156 
5157    /* Error checking
5158     * > If content path is empty, cannot do anything... */
5159    if (!string_is_empty(content_path))
5160    {
5161       global_t *global                 = global_get_ptr();
5162       struct retro_system_info *system = runloop_get_libretro_system_info();
5163       struct string_list *str_list     = NULL;
5164       const char *crc32                = NULL;
5165       const char *db_name              = NULL;
5166 
5167       union string_list_elem_attr attr;
5168       char content_label[PATH_MAX_LENGTH];
5169       char core_path[PATH_MAX_LENGTH];
5170       char core_name[PATH_MAX_LENGTH];
5171 
5172       content_label[0] = '\0';
5173       core_path[0]     = '\0';
5174       core_name[0]     = '\0';
5175 
5176       /* Create string list container for playlist parameters */
5177       attr.i           = 0;
5178       str_list         = string_list_new();
5179       if (!str_list)
5180          return 0;
5181 
5182       /* Determine playlist parameters */
5183 
5184       /* > content_label */
5185       if (global)
5186          if (!string_is_empty(global->name.label))
5187             strlcpy(content_label, global->name.label, sizeof(content_label));
5188 
5189       /* Label is empty - use file name instead */
5190       if (string_is_empty(content_label))
5191          fill_short_pathname_representation(content_label,
5192                content_path, sizeof(content_label));
5193 
5194       /* > core_path + core_name */
5195       if (system)
5196       {
5197          if (!string_is_empty(path_get(RARCH_PATH_CORE)))
5198          {
5199             core_info_t *core_info = NULL;
5200 
5201             /* >> core_path */
5202             strlcpy(core_path, path_get(RARCH_PATH_CORE), sizeof(core_path));
5203 
5204             /* >> core_name
5205              * (always use display name, if available) */
5206             if (core_info_find(core_path, &core_info))
5207                if (!string_is_empty(core_info->display_name))
5208                   strlcpy(core_name, core_info->display_name,
5209                         sizeof(core_name));
5210          }
5211 
5212          /* >> core_name (continued) */
5213          if (   string_is_empty(core_name) &&
5214                !string_is_empty(system->library_name))
5215             strlcpy(core_name, system->library_name, sizeof(core_name));
5216       }
5217 
5218       if (string_is_empty(core_path) || string_is_empty(core_name))
5219       {
5220          strcpy_literal(core_path, "DETECT");
5221          strcpy_literal(core_name, "DETECT");
5222       }
5223 
5224       /* > crc32 + db_name */
5225       {
5226          menu_handle_t *menu                 = menu_driver_get_ptr();
5227          if (menu)
5228          {
5229             playlist_t *playlist_curr = playlist_get_cached();
5230 
5231             if (playlist_index_is_valid(playlist_curr,
5232                      menu->rpl_entry_selection_ptr,
5233                      content_path, core_path))
5234             {
5235                playlist_get_crc32(playlist_curr,
5236                      menu->rpl_entry_selection_ptr, &crc32);
5237                playlist_get_db_name(playlist_curr,
5238                      menu->rpl_entry_selection_ptr, &db_name);
5239             }
5240          }
5241       }
5242 
5243       /* Copy playlist parameters into string list
5244        *   [0]: content_path
5245        *   [1]: content_label
5246        *   [2]: core_path
5247        *   [3]: core_name
5248        *   [4]: crc32
5249        *   [5]: db_name */
5250       string_list_append(str_list, content_path, attr);
5251       string_list_append(str_list, content_label, attr);
5252       string_list_append(str_list, core_path, attr);
5253       string_list_append(str_list, core_name, attr);
5254       string_list_append(str_list, !string_is_empty(crc32)
5255             ? crc32 : "", attr);
5256       string_list_append(str_list, !string_is_empty(db_name)
5257             ? db_name : "", attr);
5258 
5259       /* Trigger 'ADD_TO_FAVORITES' event */
5260       if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
5261          ret = menu_cbs_exit();
5262 
5263       /* Clean up */
5264       string_list_free(str_list);
5265       str_list = NULL;
5266    }
5267 
5268    return ret;
5269 }
5270 
5271 /* This function is called when selecting 'add to favorites'
5272  * while viewing a playlist entry */
action_ok_add_to_favorites_playlist(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5273 static int action_ok_add_to_favorites_playlist(const char *path,
5274       const char *label, unsigned type, size_t idx, size_t entry_idx)
5275 {
5276    playlist_t *playlist_curr           = playlist_get_cached();
5277    const struct playlist_entry *entry  = NULL;
5278    menu_handle_t *menu                 = menu_driver_get_ptr();
5279    int ret                             = 0;
5280 
5281    if (!playlist_curr)
5282       return 0;
5283    if (!menu)
5284       return menu_cbs_exit();
5285 
5286    /* Read current playlist parameters */
5287    playlist_get_index(playlist_curr, menu->rpl_entry_selection_ptr, &entry);
5288 
5289    /* Error checking
5290     * > If content path is empty, cannot do anything... */
5291    if (!string_is_empty(entry->path))
5292    {
5293       union string_list_elem_attr attr;
5294       char core_display_name[PATH_MAX_LENGTH];
5295       struct string_list
5296          *str_list         = NULL;
5297 
5298       core_display_name[0] = '\0';
5299 
5300       /* Create string list container for playlist parameters */
5301       attr.i               = 0;
5302       str_list             = string_list_new();
5303       if (!str_list)
5304          return 0;
5305 
5306       /* Copy playlist parameters into string list
5307        *   [0]: content_path
5308        *   [1]: content_label
5309        *   [2]: core_path
5310        *   [3]: core_name
5311        *   [4]: crc32
5312        *   [5]: db_name */
5313 
5314       /* > content_path */
5315       string_list_append(str_list, entry->path, attr);
5316 
5317       /* > content_label */
5318       if (!string_is_empty(entry->label))
5319          string_list_append(str_list, entry->label, attr);
5320       else
5321       {
5322          /* Label is empty - use file name instead */
5323          char fallback_content_label[PATH_MAX_LENGTH];
5324          fallback_content_label[0] = '\0';
5325          fill_short_pathname_representation(fallback_content_label, entry->path, sizeof(fallback_content_label));
5326          string_list_append(str_list, fallback_content_label, attr);
5327       }
5328 
5329       /* > core_path + core_name */
5330       if (!string_is_empty(entry->core_path) && !string_is_empty(entry->core_name))
5331       {
5332          core_info_t *core_info = NULL;
5333 
5334          /* >> core_path */
5335          string_list_append(str_list, entry->core_path, attr);
5336 
5337          /* >> core_name
5338           * (always use display name, if available) */
5339          if (core_info_find(entry->core_path, &core_info))
5340             if (!string_is_empty(core_info->display_name))
5341                strlcpy(core_display_name, core_info->display_name, sizeof(core_display_name));
5342 
5343          if (!string_is_empty(core_display_name))
5344             string_list_append(str_list, core_display_name, attr);
5345          else
5346             string_list_append(str_list, entry->core_name, attr);
5347       }
5348       else
5349       {
5350          string_list_append(str_list, "DETECT", attr);
5351          string_list_append(str_list, "DETECT", attr);
5352       }
5353 
5354       /* crc32 */
5355       string_list_append(str_list, !string_is_empty(entry->crc32) ? entry->crc32 : "", attr);
5356 
5357       /* db_name */
5358       string_list_append(str_list, !string_is_empty(entry->db_name) ? entry->db_name : "", attr);
5359 
5360       /* Trigger 'ADD_TO_FAVORITES' event */
5361       if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
5362          ret = menu_cbs_exit();
5363 
5364       /* Clean up */
5365       string_list_free(str_list);
5366       str_list = NULL;
5367    }
5368 
5369    return ret;
5370 }
5371 
action_ok_delete_entry(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5372 static int action_ok_delete_entry(const char *path,
5373       const char *label, unsigned type, size_t idx, size_t entry_idx)
5374 {
5375    size_t new_selection_ptr;
5376    char *conf_path              = NULL;
5377    char *def_conf_path          = NULL;
5378    char *def_conf_music_path    = NULL;
5379 #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
5380    char *def_conf_video_path    = NULL;
5381 #endif
5382 #ifdef HAVE_IMAGEVIEWER
5383    char *def_conf_img_path      = NULL;
5384 #endif
5385    char *def_conf_fav_path      = NULL;
5386    playlist_t *playlist         = playlist_get_cached();
5387    menu_handle_t *menu          = menu_driver_get_ptr();
5388 
5389    if (!menu)
5390       return menu_cbs_exit();
5391 
5392    conf_path                 = playlist_get_conf_path(playlist);
5393    def_conf_path             = playlist_get_conf_path(g_defaults.content_history);
5394    def_conf_music_path       = playlist_get_conf_path(g_defaults.music_history);
5395 #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
5396    def_conf_video_path       = playlist_get_conf_path(g_defaults.video_history);
5397 #endif
5398 #ifdef HAVE_IMAGEVIEWER
5399    def_conf_img_path         = playlist_get_conf_path(g_defaults.image_history);
5400 #endif
5401    def_conf_fav_path         = playlist_get_conf_path(g_defaults.content_favorites);
5402 
5403    if (string_is_equal(conf_path, def_conf_path))
5404       playlist = g_defaults.content_history;
5405    else if (string_is_equal(conf_path, def_conf_music_path))
5406       playlist = g_defaults.music_history;
5407 #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
5408    else if (string_is_equal(conf_path, def_conf_video_path))
5409       playlist = g_defaults.video_history;
5410 #endif
5411 #ifdef HAVE_IMAGEVIEWER
5412    else if (string_is_equal(conf_path, def_conf_img_path))
5413       playlist = g_defaults.image_history;
5414 #endif
5415    else if (string_is_equal(conf_path, def_conf_fav_path))
5416       playlist = g_defaults.content_favorites;
5417 
5418    if (playlist)
5419    {
5420       playlist_delete_index(playlist, menu->rpl_entry_selection_ptr);
5421       playlist_write_file(playlist);
5422    }
5423 
5424    new_selection_ptr = menu_navigation_get_selection();
5425    menu_entries_pop_stack(&new_selection_ptr, 0, 1);
5426    menu_navigation_set_selection(new_selection_ptr);
5427 
5428    return 0;
5429 }
5430 
action_ok_rdb_entry_submenu(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5431 static int action_ok_rdb_entry_submenu(const char *path,
5432       const char *label, unsigned type, size_t idx, size_t entry_idx)
5433 {
5434    union string_list_elem_attr attr;
5435    char new_label[PATH_MAX_LENGTH];
5436    char new_path[PATH_MAX_LENGTH];
5437    int ret                         = -1;
5438    char *rdb                       = NULL;
5439    int len                         = 0;
5440    struct string_list str_list     = {0};
5441    struct string_list str_list2    = {0};
5442 
5443    if (!label)
5444       return menu_cbs_exit();
5445 
5446    new_label[0] = new_path[0]      = '\0';
5447 
5448    string_list_initialize(&str_list);
5449    if (!string_split_noalloc(&str_list, label, "|"))
5450       goto end;
5451 
5452    string_list_initialize(&str_list2);
5453 
5454    /* element 0 : label
5455     * element 1 : value
5456     * element 2 : database path
5457     */
5458 
5459    attr.i = 0;
5460 
5461    len += strlen(str_list.elems[1].data) + 1;
5462    string_list_append(&str_list2, str_list.elems[1].data, attr);
5463 
5464    len += strlen(str_list.elems[2].data) + 1;
5465    string_list_append(&str_list2, str_list.elems[2].data, attr);
5466 
5467    rdb = (char*)calloc(len, sizeof(char));
5468 
5469    if (!rdb)
5470       goto end;
5471 
5472    string_list_join_concat(rdb, len, &str_list2, "|");
5473    strlcpy(new_path, rdb, sizeof(new_path));
5474 
5475    fill_pathname_join_delim(new_label,
5476          msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CURSOR_MANAGER_LIST),
5477          str_list.elems[0].data, '_',
5478          sizeof(new_label));
5479 
5480    ret = generic_action_ok_displaylist_push(new_path, NULL,
5481          new_label, type, idx, entry_idx,
5482          ACTION_OK_DL_RDB_ENTRY_SUBMENU);
5483 
5484 end:
5485    if (rdb)
5486       free(rdb);
5487    string_list_deinitialize(&str_list);
5488    string_list_deinitialize(&str_list2);
5489 
5490    return ret;
5491 }
5492 
DEFAULT_ACTION_OK_FUNC(action_ok_browse_url_start,ACTION_OK_DL_BROWSE_URL_START)5493 DEFAULT_ACTION_OK_FUNC(action_ok_browse_url_start, ACTION_OK_DL_BROWSE_URL_START)
5494 DEFAULT_ACTION_OK_FUNC(action_ok_goto_favorites, ACTION_OK_DL_FAVORITES_LIST)
5495 DEFAULT_ACTION_OK_FUNC(action_ok_goto_images, ACTION_OK_DL_IMAGES_LIST)
5496 DEFAULT_ACTION_OK_FUNC(action_ok_cdrom_info_list, ACTION_OK_DL_CDROM_INFO_DETAIL_LIST)
5497 DEFAULT_ACTION_OK_FUNC(action_ok_goto_video, ACTION_OK_DL_VIDEO_LIST)
5498 DEFAULT_ACTION_OK_FUNC(action_ok_goto_music, ACTION_OK_DL_MUSIC_LIST)
5499 DEFAULT_ACTION_OK_FUNC(action_ok_goto_explore, ACTION_OK_DL_EXPLORE_LIST)
5500 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
5501 DEFAULT_ACTION_OK_FUNC(action_ok_shader_preset_save, ACTION_OK_DL_SHADER_PRESET_SAVE)
5502 DEFAULT_ACTION_OK_FUNC(action_ok_shader_preset_remove, ACTION_OK_DL_SHADER_PRESET_REMOVE)
5503 DEFAULT_ACTION_OK_FUNC(action_ok_shader_parameters, ACTION_OK_DL_SHADER_PARAMETERS)
5504 #endif
5505 DEFAULT_ACTION_OK_FUNC(action_ok_parent_directory_push, ACTION_OK_DL_PARENT_DIRECTORY_PUSH)
5506 DEFAULT_ACTION_OK_FUNC(action_ok_directory_push, ACTION_OK_DL_DIRECTORY_PUSH)
5507 DEFAULT_ACTION_OK_FUNC(action_ok_configurations_list, ACTION_OK_DL_CONFIGURATIONS_LIST)
5508 DEFAULT_ACTION_OK_FUNC(action_ok_saving_list, ACTION_OK_DL_SAVING_SETTINGS_LIST)
5509 DEFAULT_ACTION_OK_FUNC(action_ok_network_list, ACTION_OK_DL_NETWORK_SETTINGS_LIST)
5510 DEFAULT_ACTION_OK_FUNC(action_ok_network_hosting_list, ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST)
5511 DEFAULT_ACTION_OK_FUNC(action_ok_subsystem_list, ACTION_OK_DL_SUBSYSTEM_SETTINGS_LIST)
5512 DEFAULT_ACTION_OK_FUNC(action_ok_database_manager_list, ACTION_OK_DL_DATABASE_MANAGER_LIST)
5513 DEFAULT_ACTION_OK_FUNC(action_ok_bluetooth_list, ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST)
5514 #ifdef HAVE_NETWORKING
5515 DEFAULT_ACTION_OK_FUNC(action_ok_wifi_list, ACTION_OK_DL_WIFI_SETTINGS_LIST)
5516 DEFAULT_ACTION_OK_FUNC(action_ok_wifi_networks_list, ACTION_OK_DL_WIFI_NETWORKS_LIST)
5517 #endif
5518 DEFAULT_ACTION_OK_FUNC(action_ok_cursor_manager_list, ACTION_OK_DL_CURSOR_MANAGER_LIST)
5519 DEFAULT_ACTION_OK_FUNC(action_ok_compressed_archive_push, ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH)
5520 DEFAULT_ACTION_OK_FUNC(action_ok_compressed_archive_push_detect_core, ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH_DETECT_CORE)
5521 DEFAULT_ACTION_OK_FUNC(action_ok_logging_list, ACTION_OK_DL_LOGGING_SETTINGS_LIST)
5522 DEFAULT_ACTION_OK_FUNC(action_ok_frame_throttle_list, ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST)
5523 DEFAULT_ACTION_OK_FUNC(action_ok_frame_time_counter_list, ACTION_OK_DL_FRAME_TIME_COUNTER_SETTINGS_LIST)
5524 DEFAULT_ACTION_OK_FUNC(action_ok_rewind_list, ACTION_OK_DL_REWIND_SETTINGS_LIST)
5525 DEFAULT_ACTION_OK_FUNC(action_ok_cheat, ACTION_OK_DL_CHEAT_DETAILS_SETTINGS_LIST)
5526 DEFAULT_ACTION_OK_FUNC(action_ok_cheat_start_or_cont, ACTION_OK_DL_CHEAT_SEARCH_SETTINGS_LIST)
5527 DEFAULT_ACTION_OK_FUNC(action_ok_onscreen_display_list, ACTION_OK_DL_ONSCREEN_DISPLAY_SETTINGS_LIST)
5528 DEFAULT_ACTION_OK_FUNC(action_ok_onscreen_notifications_list, ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST)
5529 DEFAULT_ACTION_OK_FUNC(action_ok_onscreen_notifications_views_list, ACTION_OK_DL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST)
5530 DEFAULT_ACTION_OK_FUNC(action_ok_onscreen_overlay_list, ACTION_OK_DL_ONSCREEN_OVERLAY_SETTINGS_LIST)
5531 #ifdef HAVE_VIDEO_LAYOUT
5532 DEFAULT_ACTION_OK_FUNC(action_ok_onscreen_video_layout_list, ACTION_OK_DL_ONSCREEN_VIDEO_LAYOUT_SETTINGS_LIST)
5533 #endif
5534 DEFAULT_ACTION_OK_FUNC(action_ok_menu_list, ACTION_OK_DL_MENU_SETTINGS_LIST)
5535 DEFAULT_ACTION_OK_FUNC(action_ok_quick_menu_override_options, ACTION_OK_DL_QUICK_MENU_OVERRIDE_OPTIONS_LIST)
5536 DEFAULT_ACTION_OK_FUNC(action_ok_menu_views_list, ACTION_OK_DL_MENU_VIEWS_SETTINGS_LIST)
5537 DEFAULT_ACTION_OK_FUNC(action_ok_settings_views_list, ACTION_OK_DL_SETTINGS_VIEWS_SETTINGS_LIST)
5538 DEFAULT_ACTION_OK_FUNC(action_ok_quick_menu_views_list, ACTION_OK_DL_QUICK_MENU_VIEWS_SETTINGS_LIST)
5539 DEFAULT_ACTION_OK_FUNC(action_ok_power_management_list, ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST)
5540 DEFAULT_ACTION_OK_FUNC(action_ok_cpu_perfpower_list, ACTION_OK_DL_CPU_PERFPOWER_SETTINGS_LIST)
5541 DEFAULT_ACTION_OK_FUNC(action_ok_cpu_policy_entry, ACTION_OK_DL_CPU_POLICY_SETTINGS_LIST)
5542 DEFAULT_ACTION_OK_FUNC(action_ok_menu_sounds_list, ACTION_OK_DL_MENU_SOUNDS_LIST)
5543 DEFAULT_ACTION_OK_FUNC(action_ok_user_interface_list, ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST)
5544 DEFAULT_ACTION_OK_FUNC(action_ok_menu_file_browser_list, ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST)
5545 DEFAULT_ACTION_OK_FUNC(action_ok_retro_achievements_list, ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST)
5546 DEFAULT_ACTION_OK_FUNC(action_ok_updater_list, ACTION_OK_DL_UPDATER_SETTINGS_LIST)
5547 DEFAULT_ACTION_OK_FUNC(action_ok_lakka_services, ACTION_OK_DL_LAKKA_SERVICES_LIST)
5548 DEFAULT_ACTION_OK_FUNC(action_ok_user_list, ACTION_OK_DL_USER_SETTINGS_LIST)
5549 DEFAULT_ACTION_OK_FUNC(action_ok_netplay_sublist, ACTION_OK_DL_NETPLAY)
5550 DEFAULT_ACTION_OK_FUNC(action_ok_directory_list, ACTION_OK_DL_DIRECTORY_SETTINGS_LIST)
5551 DEFAULT_ACTION_OK_FUNC(action_ok_privacy_list, ACTION_OK_DL_PRIVACY_SETTINGS_LIST)
5552 DEFAULT_ACTION_OK_FUNC(action_ok_midi_list, ACTION_OK_DL_MIDI_SETTINGS_LIST)
5553 DEFAULT_ACTION_OK_FUNC(action_ok_rdb_entry, ACTION_OK_DL_RDB_ENTRY)
5554 #ifdef HAVE_AUDIOMIXER
5555 DEFAULT_ACTION_OK_FUNC(action_ok_mixer_stream_actions, ACTION_OK_DL_MIXER_STREAM_SETTINGS_LIST)
5556 #endif
5557 DEFAULT_ACTION_OK_FUNC(action_ok_browse_url_list, ACTION_OK_DL_BROWSE_URL_LIST)
5558 DEFAULT_ACTION_OK_FUNC(action_ok_core_list, ACTION_OK_DL_CORE_LIST)
5559 DEFAULT_ACTION_OK_FUNC(action_ok_sideload_core_list, ACTION_OK_DL_SIDELOAD_CORE_LIST)
5560 DEFAULT_ACTION_OK_FUNC(action_ok_cheat_file, ACTION_OK_DL_CHEAT_FILE)
5561 DEFAULT_ACTION_OK_FUNC(action_ok_cheat_file_append, ACTION_OK_DL_CHEAT_FILE_APPEND)
5562 DEFAULT_ACTION_OK_FUNC(action_ok_playlist_collection, ACTION_OK_DL_PLAYLIST_COLLECTION)
5563 DEFAULT_ACTION_OK_FUNC(action_ok_disk_image_append_list, ACTION_OK_DL_DISK_IMAGE_APPEND_LIST)
5564 DEFAULT_ACTION_OK_FUNC(action_ok_subsystem_add_list, ACTION_OK_DL_SUBSYSTEM_ADD_LIST)
5565 DEFAULT_ACTION_OK_FUNC(action_ok_subsystem_add_load, ACTION_OK_DL_SUBSYSTEM_LOAD)
5566 DEFAULT_ACTION_OK_FUNC(action_ok_record_configfile, ACTION_OK_DL_RECORD_CONFIGFILE)
5567 DEFAULT_ACTION_OK_FUNC(action_ok_stream_configfile, ACTION_OK_DL_STREAM_CONFIGFILE)
5568 DEFAULT_ACTION_OK_FUNC(action_ok_remap_file, ACTION_OK_DL_REMAP_FILE)
5569 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
5570 DEFAULT_ACTION_OK_FUNC(action_ok_shader_preset, ACTION_OK_DL_SHADER_PRESET)
5571 #endif
5572 DEFAULT_ACTION_OK_FUNC(action_ok_push_generic_list, ACTION_OK_DL_GENERIC)
5573 DEFAULT_ACTION_OK_FUNC(action_ok_audio_dsp_plugin, ACTION_OK_DL_AUDIO_DSP_PLUGIN)
5574 DEFAULT_ACTION_OK_FUNC(action_ok_video_filter, ACTION_OK_DL_VIDEO_FILTER)
5575 DEFAULT_ACTION_OK_FUNC(action_ok_overlay_preset, ACTION_OK_DL_OVERLAY_PRESET)
5576 #if defined(HAVE_VIDEO_LAYOUT)
5577 DEFAULT_ACTION_OK_FUNC(action_ok_video_layout, ACTION_OK_DL_VIDEO_LAYOUT)
5578 #endif
5579 DEFAULT_ACTION_OK_FUNC(action_ok_video_font, ACTION_OK_DL_VIDEO_FONT)
5580 DEFAULT_ACTION_OK_FUNC(action_ok_rpl_entry, ACTION_OK_DL_RPL_ENTRY)
5581 DEFAULT_ACTION_OK_FUNC(action_ok_open_archive_detect_core, ACTION_OK_DL_OPEN_ARCHIVE_DETECT_CORE)
5582 DEFAULT_ACTION_OK_FUNC(action_ok_file_load_music, ACTION_OK_DL_MUSIC)
5583 DEFAULT_ACTION_OK_FUNC(action_ok_push_accounts_list, ACTION_OK_DL_ACCOUNTS_LIST)
5584 DEFAULT_ACTION_OK_FUNC(action_ok_push_achievements_hardcore_pause_list, ACTION_OK_DL_ACHIEVEMENTS_HARDCORE_PAUSE_LIST)
5585 DEFAULT_ACTION_OK_FUNC(action_ok_push_driver_settings_list, ACTION_OK_DL_DRIVER_SETTINGS_LIST)
5586 DEFAULT_ACTION_OK_FUNC(action_ok_push_crt_switchres_settings_list, ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST)
5587 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_settings_list, ACTION_OK_DL_VIDEO_SETTINGS_LIST)
5588 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_fullscreen_mode_settings_list, ACTION_OK_DL_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST)
5589 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_synchronization_settings_list, ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST)
5590 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_windowed_mode_settings_list, ACTION_OK_DL_VIDEO_WINDOWED_MODE_SETTINGS_LIST)
5591 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_scaling_settings_list, ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST)
5592 DEFAULT_ACTION_OK_FUNC(action_ok_push_video_output_settings_list, ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST)
5593 DEFAULT_ACTION_OK_FUNC(action_ok_push_configuration_settings_list, ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST)
5594 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_settings_list, ACTION_OK_DL_CORE_SETTINGS_LIST)
5595 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_information_list, ACTION_OK_DL_CORE_INFORMATION_LIST)
5596 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_restore_backup_list, ACTION_OK_DL_CORE_RESTORE_BACKUP_LIST)
5597 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_delete_backup_list, ACTION_OK_DL_CORE_DELETE_BACKUP_LIST)
5598 DEFAULT_ACTION_OK_FUNC(action_ok_push_audio_settings_list, ACTION_OK_DL_AUDIO_SETTINGS_LIST)
5599 DEFAULT_ACTION_OK_FUNC(action_ok_push_audio_output_settings_list, ACTION_OK_DL_AUDIO_OUTPUT_SETTINGS_LIST)
5600 DEFAULT_ACTION_OK_FUNC(action_ok_push_audio_resampler_settings_list, ACTION_OK_DL_AUDIO_RESAMPLER_SETTINGS_LIST)
5601 DEFAULT_ACTION_OK_FUNC(action_ok_push_audio_synchronization_settings_list, ACTION_OK_DL_AUDIO_SYNCHRONIZATION_SETTINGS_LIST)
5602 #ifdef HAVE_AUDIOMIXER
5603 DEFAULT_ACTION_OK_FUNC(action_ok_push_audio_mixer_settings_list, ACTION_OK_DL_AUDIO_MIXER_SETTINGS_LIST)
5604 #endif
5605 DEFAULT_ACTION_OK_FUNC(action_ok_push_ai_service_settings_list, ACTION_OK_DL_AI_SERVICE_SETTINGS_LIST)
5606 DEFAULT_ACTION_OK_FUNC(action_ok_push_accessibility_settings_list, ACTION_OK_DL_ACCESSIBILITY_SETTINGS_LIST)
5607 DEFAULT_ACTION_OK_FUNC(action_ok_push_input_settings_list, ACTION_OK_DL_INPUT_SETTINGS_LIST)
5608 DEFAULT_ACTION_OK_FUNC(action_ok_push_input_menu_settings_list, ACTION_OK_DL_INPUT_MENU_SETTINGS_LIST)
5609 DEFAULT_ACTION_OK_FUNC(action_ok_push_input_turbo_fire_settings_list, ACTION_OK_DL_INPUT_TURBO_FIRE_SETTINGS_LIST)
5610 DEFAULT_ACTION_OK_FUNC(action_ok_push_input_haptic_feedback_settings_list, ACTION_OK_DL_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST)
5611 DEFAULT_ACTION_OK_FUNC(action_ok_push_latency_settings_list, ACTION_OK_DL_LATENCY_SETTINGS_LIST)
5612 DEFAULT_ACTION_OK_FUNC(action_ok_push_recording_settings_list, ACTION_OK_DL_RECORDING_SETTINGS_LIST)
5613 DEFAULT_ACTION_OK_FUNC(action_ok_push_playlist_settings_list, ACTION_OK_DL_PLAYLIST_SETTINGS_LIST)
5614 DEFAULT_ACTION_OK_FUNC(action_ok_push_playlist_manager_list, ACTION_OK_DL_PLAYLIST_MANAGER_LIST)
5615 DEFAULT_ACTION_OK_FUNC(action_ok_push_playlist_manager_settings, ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS)
5616 DEFAULT_ACTION_OK_FUNC(action_ok_push_input_hotkey_binds_list, ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST)
5617 DEFAULT_ACTION_OK_FUNC(action_ok_push_user_binds_list, ACTION_OK_DL_USER_BINDS_LIST)
5618 DEFAULT_ACTION_OK_FUNC(action_ok_push_accounts_cheevos_list, ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST)
5619 DEFAULT_ACTION_OK_FUNC(action_ok_push_accounts_youtube_list, ACTION_OK_DL_ACCOUNTS_YOUTUBE_LIST)
5620 DEFAULT_ACTION_OK_FUNC(action_ok_push_accounts_twitch_list, ACTION_OK_DL_ACCOUNTS_TWITCH_LIST)
5621 DEFAULT_ACTION_OK_FUNC(action_ok_push_accounts_facebook_list, ACTION_OK_DL_ACCOUNTS_FACEBOOK_LIST)
5622 DEFAULT_ACTION_OK_FUNC(action_ok_push_dump_disc_list, ACTION_OK_DL_DUMP_DISC_LIST)
5623 DEFAULT_ACTION_OK_FUNC(action_ok_push_load_disc_list, ACTION_OK_DL_LOAD_DISC_LIST)
5624 DEFAULT_ACTION_OK_FUNC(action_ok_open_archive, ACTION_OK_DL_OPEN_ARCHIVE)
5625 DEFAULT_ACTION_OK_FUNC(action_ok_rgui_menu_theme_preset, ACTION_OK_DL_RGUI_MENU_THEME_PRESET)
5626 DEFAULT_ACTION_OK_FUNC(action_ok_pl_thumbnails_updater_list, ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST)
5627 DEFAULT_ACTION_OK_FUNC(action_ok_push_manual_content_scan_list, ACTION_OK_DL_MANUAL_CONTENT_SCAN_LIST)
5628 DEFAULT_ACTION_OK_FUNC(action_ok_manual_content_scan_dat_file, ACTION_OK_DL_MANUAL_CONTENT_SCAN_DAT_FILE)
5629 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_manager_list, ACTION_OK_DL_CORE_MANAGER_LIST)
5630 DEFAULT_ACTION_OK_FUNC(action_ok_push_core_option_override_list, ACTION_OK_DL_CORE_OPTION_OVERRIDE_LIST)
5631 
5632 static int action_ok_open_uwp_permission_settings(const char *path,
5633    const char *label, unsigned type, size_t idx, size_t entry_idx)
5634 {
5635 #ifdef __WINRT__
5636    uwp_open_broadfilesystemaccess_settings();
5637 #else
5638    retro_assert(false);
5639 #endif
5640    return 0;
5641 }
5642 
action_ok_open_picker(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5643 static int action_ok_open_picker(const char *path,
5644    const char *label, unsigned type, size_t idx, size_t entry_idx)
5645 {
5646    int ret;
5647 #ifdef __WINRT__
5648    char *new_path = uwp_trigger_picker();
5649    if (!new_path)
5650       return 0; /* User aborted */
5651 #else
5652    char *new_path = NULL;
5653    retro_assert(false);
5654 #endif
5655 
5656    ret = generic_action_ok_displaylist_push(path, new_path,
5657       msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES),
5658       MENU_SETTING_ACTION_FAVORITES_DIR, idx,
5659       entry_idx, ACTION_OK_DL_CONTENT_LIST);
5660 
5661    free(new_path);
5662    return ret;
5663 }
5664 
5665 #ifdef HAVE_NETWORKING
wifi_menu_refresh_callback(retro_task_t * task,void * task_data,void * user_data,const char * error)5666 static void wifi_menu_refresh_callback(retro_task_t *task,
5667       void *task_data,
5668       void *user_data, const char *error)
5669 {
5670    bool refresh = false;
5671    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5672    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5673 }
5674 
action_ok_wifi_disconnect(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5675 static int action_ok_wifi_disconnect(const char *path,
5676       const char *label, unsigned type, size_t idx, size_t entry_idx)
5677 {
5678    task_push_wifi_disconnect(wifi_menu_refresh_callback);
5679    return true;
5680 }
5681 #endif
5682 
action_ok_netplay_connect_room(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5683 static int action_ok_netplay_connect_room(const char *path,
5684       const char *label, unsigned type, size_t idx, size_t entry_idx)
5685 {
5686 #ifdef HAVE_NETWORKING
5687    char tmp_hostname[4115];
5688    unsigned room_index = type - MENU_SETTINGS_NETPLAY_ROOMS_START;
5689 
5690    tmp_hostname[0] = '\0';
5691 
5692    if (room_index >= (unsigned)netplay_room_count)
5693       return menu_cbs_exit();
5694 
5695    if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
5696       generic_action_ok_command(CMD_EVENT_NETPLAY_DEINIT);
5697    netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL);
5698 
5699    if (netplay_room_list[room_index].host_method == NETPLAY_HOST_METHOD_MITM)
5700       snprintf(tmp_hostname,
5701             sizeof(tmp_hostname),
5702             "%s|%d",
5703          netplay_room_list[room_index].mitm_address,
5704          netplay_room_list[room_index].mitm_port);
5705    else
5706       snprintf(tmp_hostname,
5707             sizeof(tmp_hostname),
5708             "%s|%d",
5709          netplay_room_list[room_index].address,
5710          netplay_room_list[room_index].port);
5711 
5712 #if 0
5713    RARCH_LOG("[lobby] connecting to: %s with game: %s/%08x\n",
5714          tmp_hostname,
5715          netplay_room_list[room_index].gamename,
5716          netplay_room_list[room_index].gamecrc);
5717 #endif
5718 
5719    task_push_netplay_crc_scan(
5720          netplay_room_list[room_index].gamecrc,
5721          netplay_room_list[room_index].gamename,
5722          tmp_hostname,
5723          netplay_room_list[room_index].corename,
5724          netplay_room_list[room_index].subsystem_name);
5725 
5726 #else
5727    return -1;
5728 
5729 #endif
5730    return 0;
5731 }
5732 
action_ok_netplay_lan_scan(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5733 static int action_ok_netplay_lan_scan(const char *path,
5734       const char *label, unsigned type, size_t idx, size_t entry_idx)
5735 {
5736 #ifdef HAVE_NETWORKING
5737    struct netplay_host_list *hosts = NULL;
5738    struct netplay_host *host       = NULL;
5739 
5740    /* Figure out what host we're connecting to */
5741    if (!netplay_discovery_driver_ctl(RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, &hosts))
5742       return -1;
5743    if (entry_idx >= hosts->size)
5744       return -1;
5745    host = &hosts->hosts[entry_idx];
5746 
5747    /* Enable Netplay client mode */
5748    if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
5749       generic_action_ok_command(CMD_EVENT_NETPLAY_DEINIT);
5750    netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL);
5751 
5752    /* Enable Netplay */
5753    if (command_event(CMD_EVENT_NETPLAY_INIT_DIRECT, (void *) host))
5754       return generic_action_ok_command(CMD_EVENT_RESUME);
5755 #endif
5756    return -1;
5757 }
5758 
DEFAULT_ACTION_OK_DL_PUSH(action_ok_content_collection_list,FILEBROWSER_SELECT_COLLECTION,ACTION_OK_DL_CONTENT_COLLECTION_LIST,NULL)5759 DEFAULT_ACTION_OK_DL_PUSH(action_ok_content_collection_list, FILEBROWSER_SELECT_COLLECTION, ACTION_OK_DL_CONTENT_COLLECTION_LIST, NULL)
5760 DEFAULT_ACTION_OK_DL_PUSH(action_ok_push_content_list, FILEBROWSER_SELECT_FILE, ACTION_OK_DL_CONTENT_LIST, settings->paths.directory_menu_content)
5761 DEFAULT_ACTION_OK_DL_PUSH(action_ok_push_scan_file, FILEBROWSER_SCAN_FILE, ACTION_OK_DL_CONTENT_LIST, settings->paths.directory_menu_content)
5762 
5763 #ifdef HAVE_NETWORKING
5764 static void netplay_refresh_rooms_cb(retro_task_t *task,
5765       void *task_data, void *user_data, const char *err)
5766 {
5767    char *new_data                = NULL;
5768    const char *path              = NULL;
5769    const char *label             = NULL;
5770    unsigned menu_type            = 0;
5771    enum msg_hash_enums enum_idx  = MSG_UNKNOWN;
5772 
5773    http_transfer_data_t *data    = (http_transfer_data_t*)task_data;
5774 
5775    menu_entries_get_last_stack(&path, &label, &menu_type, &enum_idx, NULL);
5776 
5777    /* Don't push the results if we left the netplay menu */
5778    if (!string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_TAB))
5779     && !string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY)))
5780       return;
5781 
5782    if (!data || err)
5783       goto finish;
5784 
5785    new_data = (char*)realloc(data->data, data->len + 1);
5786 
5787    if (!new_data)
5788       goto finish;
5789 
5790    data->data            = new_data;
5791    data->data[data->len] = '\0';
5792 
5793    if (!string_ends_with_size(data->data, "registry.lpl",
5794             strlen(data->data),
5795             STRLEN_CONST("registry.lpl")))
5796    {
5797       if (string_is_empty(data->data))
5798          netplay_room_count = 0;
5799       else
5800       {
5801          char s[PATH_MAX_LENGTH];
5802          unsigned i                           = 0;
5803          unsigned j                           = 0;
5804          struct netplay_host_list *lan_hosts  = NULL;
5805          int lan_room_count                   = 0;
5806          bool refresh                         = false;
5807 
5808 #ifndef RARCH_CONSOLE
5809          netplay_discovery_driver_ctl(RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, &lan_hosts);
5810          if (lan_hosts)
5811             lan_room_count                    = (int)lan_hosts->size;
5812 #endif
5813 
5814          netplay_rooms_parse(data->data);
5815 
5816          if (netplay_room_list)
5817             free(netplay_room_list);
5818 
5819          /* TODO/FIXME - right now, a LAN and non-LAN netplay session might appear
5820           * in the same list. If both entries are available, we want to show only
5821           * the LAN one. */
5822 
5823          netplay_room_count                   = netplay_rooms_get_count();
5824          netplay_room_list                    = (struct netplay_room*)
5825             calloc(netplay_room_count + lan_room_count,
5826                   sizeof(struct netplay_room));
5827 
5828          for (i = 0; i < (unsigned)netplay_room_count; i++)
5829             memcpy(&netplay_room_list[i], netplay_room_get(i), sizeof(netplay_room_list[i]));
5830 
5831          if (lan_room_count != 0)
5832          {
5833             for (i = netplay_room_count; i < (unsigned)(netplay_room_count + lan_room_count); i++)
5834             {
5835                struct netplay_host *host = &lan_hosts->hosts[j++];
5836 
5837                strlcpy(netplay_room_list[i].nickname,
5838                      host->nick,
5839                      sizeof(netplay_room_list[i].nickname));
5840 
5841                strlcpy(netplay_room_list[i].address,
5842                      host->address,
5843                      INET6_ADDRSTRLEN);
5844                strlcpy(netplay_room_list[i].corename,
5845                      host->core,
5846                      sizeof(netplay_room_list[i].corename));
5847                strlcpy(netplay_room_list[i].retroarch_version,
5848                      host->retroarch_version,
5849                      sizeof(netplay_room_list[i].retroarch_version));
5850                strlcpy(netplay_room_list[i].coreversion,
5851                      host->core_version,
5852                      sizeof(netplay_room_list[i].coreversion));
5853                strlcpy(netplay_room_list[i].gamename,
5854                      host->content,
5855                      sizeof(netplay_room_list[i].gamename));
5856                strlcpy(netplay_room_list[i].frontend,
5857                      host->frontend,
5858                      sizeof(netplay_room_list[i].frontend));
5859                strlcpy(netplay_room_list[i].subsystem_name,
5860                      host->subsystem_name,
5861                      sizeof(netplay_room_list[i].subsystem_name));
5862 
5863                netplay_room_list[i].port      = host->port;
5864                netplay_room_list[i].gamecrc   = host->content_crc;
5865                netplay_room_list[i].timestamp = 0;
5866                netplay_room_list[i].lan       = true;
5867 
5868                snprintf(s, sizeof(s),
5869                      msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_ROOM_NICKNAME),
5870                      netplay_room_list[i].nickname);
5871             }
5872             netplay_room_count += lan_room_count;
5873          }
5874 
5875          menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
5876          menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
5877       }
5878    }
5879 
5880 finish:
5881 
5882    if (err)
5883       RARCH_ERR("%s: %s\n", msg_hash_to_str(MSG_DOWNLOAD_FAILED), err);
5884 
5885    if (user_data)
5886       free(user_data);
5887 }
5888 
5889 #ifndef RARCH_CONSOLE
netplay_lan_scan_callback(retro_task_t * task,void * task_data,void * user_data,const char * error)5890 static void netplay_lan_scan_callback(retro_task_t *task,
5891       void *task_data,
5892       void *user_data, const char *error)
5893 {
5894    struct netplay_host_list *netplay_hosts = NULL;
5895    enum msg_hash_enums enum_idx            = MSG_UNKNOWN;
5896    unsigned menu_type                      = 0;
5897    const char *label                       = NULL;
5898    const char *path                        = NULL;
5899 
5900    /* TODO/FIXME: I have no idea what this is supposed to be
5901     * doing...
5902     * As it stands, this function will never get past the
5903     * following sanity check (i.e. netplay_lan_scan_callback()
5904     * will never be called when we are viewing the 'lan scan
5905     * settings' list, since this list doesn't even exist...).
5906     * Moreover, any menu entries that get added here
5907     * (menu_entries_append_enum()) will be erased by the
5908     * subsequent netplay_refresh_rooms_cb() callback - and
5909     * menu entries should never be added outside of
5910     * menu_displaylist.c anyway.
5911     * This is some legacy garbage, and someone who understands
5912     * netplay needs to rip it all out. */
5913 
5914    menu_entries_get_last_stack(&path, &label, &menu_type, &enum_idx, NULL);
5915 
5916    /* Don't push the results if we left the LAN scan menu */
5917    if (!string_is_equal(label,
5918          msg_hash_to_str(
5919             MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST)))
5920       return;
5921 
5922    if (!netplay_discovery_driver_ctl(
5923             RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES,
5924             (void *) &netplay_hosts))
5925       return;
5926 
5927    if (netplay_hosts->size > 0)
5928    {
5929       unsigned i;
5930       file_list_t *file_list = menu_entries_get_selection_buf_ptr(0);
5931 
5932       menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list);
5933 
5934       for (i = 0; i < netplay_hosts->size; i++)
5935       {
5936          struct netplay_host *host = &netplay_hosts->hosts[i];
5937          menu_entries_append_enum(file_list,
5938                host->nick,
5939                msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_CONNECT_TO),
5940                MENU_ENUM_LABEL_NETPLAY_CONNECT_TO,
5941                MENU_NETPLAY_LAN_SCAN, 0, 0);
5942       }
5943    }
5944 }
5945 #endif
5946 
action_ok_push_netplay_refresh_rooms(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5947 static int action_ok_push_netplay_refresh_rooms(const char *path,
5948       const char *label, unsigned type, size_t idx, size_t entry_idx)
5949 {
5950    char url [2048] = "http://lobby.libretro.com/list/";
5951 #ifndef RARCH_CONSOLE
5952    task_push_netplay_lan_scan(netplay_lan_scan_callback);
5953 #endif
5954    task_push_http_transfer(url, true, NULL, netplay_refresh_rooms_cb, NULL);
5955    return 0;
5956 }
5957 #endif
5958 
action_ok_scan_directory_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5959 static int action_ok_scan_directory_list(const char *path,
5960       const char *label, unsigned type, size_t idx, size_t entry_idx)
5961 {
5962    settings_t            *settings   = config_get_ptr();
5963    const char *dir_menu_content      = settings->paths.directory_menu_content;
5964 
5965    filebrowser_clear_type();
5966    return generic_action_ok_displaylist_push(path,
5967          dir_menu_content, label, type, idx,
5968          entry_idx, ACTION_OK_DL_SCAN_DIR_LIST);
5969 }
5970 
action_ok_push_random_dir(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5971 static int action_ok_push_random_dir(const char *path,
5972       const char *label, unsigned type, size_t idx, size_t entry_idx)
5973 {
5974    return generic_action_ok_displaylist_push(path, path,
5975          msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES),
5976          type, idx,
5977          entry_idx, ACTION_OK_DL_CONTENT_LIST);
5978 }
5979 
action_ok_push_downloads_dir(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5980 static int action_ok_push_downloads_dir(const char *path,
5981       const char *label, unsigned type, size_t idx, size_t entry_idx)
5982 {
5983    settings_t            *settings   = config_get_ptr();
5984    const char *dir_core_assets       = settings->paths.directory_core_assets;
5985 
5986    filebrowser_set_type(FILEBROWSER_SELECT_FILE);
5987    return generic_action_ok_displaylist_push(path,
5988          dir_core_assets,
5989          msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES),
5990          type, idx,
5991          entry_idx, ACTION_OK_DL_CONTENT_LIST);
5992 }
5993 
action_ok_push_filebrowser_list_dir_select(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)5994 int action_ok_push_filebrowser_list_dir_select(const char *path,
5995       const char *label, unsigned type, size_t idx, size_t entry_idx)
5996 {
5997    menu_handle_t *menu       = menu_driver_get_ptr();
5998 
5999    if (!menu)
6000       return menu_cbs_exit();
6001 
6002    filebrowser_set_type(FILEBROWSER_SELECT_DIR);
6003    strlcpy(menu->filebrowser_label, label, sizeof(menu->filebrowser_label));
6004    return generic_action_ok_displaylist_push(path, NULL, label, type, idx,
6005          entry_idx, ACTION_OK_DL_FILE_BROWSER_SELECT_DIR);
6006 }
6007 
action_ok_push_filebrowser_list_file_select(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6008 int action_ok_push_filebrowser_list_file_select(const char *path,
6009       const char *label, unsigned type, size_t idx, size_t entry_idx)
6010 {
6011    menu_handle_t *menu       = menu_driver_get_ptr();
6012 
6013    if (!menu)
6014       return menu_cbs_exit();
6015 
6016    filebrowser_set_type(FILEBROWSER_SELECT_FILE);
6017    strlcpy(menu->filebrowser_label, label, sizeof(menu->filebrowser_label));
6018    return generic_action_ok_displaylist_push(path, NULL, label, type, idx,
6019          entry_idx, ACTION_OK_DL_FILE_BROWSER_SELECT_DIR);
6020 }
6021 
action_ok_push_manual_content_scan_dir_select(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6022 int action_ok_push_manual_content_scan_dir_select(const char *path,
6023       const char *label, unsigned type, size_t idx, size_t entry_idx)
6024 {
6025    settings_t            *settings   = config_get_ptr();
6026    const char *dir_menu_content      = settings->paths.directory_menu_content;
6027 
6028    filebrowser_clear_type();
6029    return generic_action_ok_displaylist_push(path,
6030          dir_menu_content, label, type, idx,
6031          entry_idx, ACTION_OK_DL_MANUAL_SCAN_DIR_LIST);
6032 }
6033 
6034 /* TODO/FIXME */
action_ok_push_dropdown_setting_core_options_item_special(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6035 static int action_ok_push_dropdown_setting_core_options_item_special(
6036       const char *path,
6037       const char *label, unsigned type, size_t idx, size_t entry_idx)
6038 {
6039    core_option_manager_t *coreopts = NULL;
6040    int core_option_idx             = (int)atoi(label);
6041 
6042    rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts);
6043 
6044    if (!coreopts)
6045       return -1;
6046 
6047    core_option_manager_set_val(coreopts, core_option_idx, idx);
6048    return action_cancel_pop_default(NULL, NULL, 0, 0);
6049 }
6050 
action_ok_push_dropdown_setting_core_options_item(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6051 static int action_ok_push_dropdown_setting_core_options_item(const char *path,
6052       const char *label, unsigned type, size_t idx, size_t entry_idx)
6053 {
6054    core_option_manager_t *coreopts = NULL;
6055    int core_option_idx             = (int)atoi(label);
6056 
6057    rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts);
6058 
6059    if (!coreopts)
6060       return -1;
6061 
6062    core_option_manager_set_val(coreopts, core_option_idx, idx);
6063    return action_cancel_pop_default(NULL, NULL, 0, 0);
6064 }
6065 
6066 /* TODO/FIXME */
6067 
action_ok_push_dropdown_setting_uint_item_special(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6068 static int action_ok_push_dropdown_setting_uint_item_special(const char *path,
6069       const char *label, unsigned type, size_t idx, size_t entry_idx)
6070 {
6071    unsigned value;
6072    enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(label);
6073    rarch_setting_t     *setting = menu_setting_find_enum(enum_idx);
6074 
6075    if (!setting)
6076       return -1;
6077 
6078    value = (unsigned)(idx + setting->offset_by);
6079 
6080    if (!string_is_empty(path))
6081    {
6082       unsigned path_value = atoi(path);
6083       if (path_value != value)
6084          value = path_value;
6085    }
6086 
6087    *setting->value.target.unsigned_integer = value;
6088 
6089    if (setting->change_handler)
6090       setting->change_handler(setting);
6091 
6092    return action_cancel_pop_default(NULL, NULL, 0, 0);
6093 }
6094 
6095 
generic_action_ok_dropdown_setting(const char * path,const char * label,unsigned type,size_t idx)6096 static int generic_action_ok_dropdown_setting(const char *path, const char *label,
6097       unsigned type, size_t idx)
6098 {
6099    enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(label);
6100    rarch_setting_t     *setting = menu_setting_find_enum(enum_idx);
6101 
6102    if (!setting)
6103       return -1;
6104 
6105    switch (setting->type)
6106    {
6107       case ST_INT:
6108          *setting->value.target.integer = (int32_t)(idx + setting->offset_by);
6109          break;
6110       case ST_UINT:
6111          {
6112             unsigned value = (unsigned)(idx + setting->offset_by);
6113             *setting->value.target.unsigned_integer = value;
6114          }
6115          break;
6116       case ST_FLOAT:
6117          {
6118             float val                    = (float)atof(path);
6119             *setting->value.target.fraction = (float)val;
6120          }
6121          break;
6122       case ST_STRING_OPTIONS:
6123          if (setting->get_string_representation)
6124          {
6125             struct string_list tmp_str_list = { 0 };
6126             string_list_initialize(&tmp_str_list);
6127             string_split_noalloc(&tmp_str_list,
6128                setting->values, "|");
6129 
6130             if (idx < tmp_str_list.size)
6131             {
6132                strlcpy(setting->value.target.string,
6133                   tmp_str_list.elems[idx].data, setting->size);
6134             }
6135 
6136             string_list_deinitialize(&tmp_str_list);
6137             break;
6138          }
6139          /* fallthrough */
6140       case ST_STRING:
6141       case ST_PATH:
6142       case ST_DIR:
6143          strlcpy(setting->value.target.string, path,
6144                setting->size);
6145          break;
6146       default:
6147          break;
6148    }
6149 
6150    if (setting->change_handler)
6151       setting->change_handler(setting);
6152 
6153    return action_cancel_pop_default(NULL, NULL, 0, 0);
6154 }
6155 
action_ok_push_dropdown_setting(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6156 static int action_ok_push_dropdown_setting(const char *path,
6157       const char *label, unsigned type, size_t idx, size_t entry_idx)
6158 {
6159    return generic_action_ok_dropdown_setting(path, label, type, idx);
6160 }
6161 
action_ok_push_dropdown_item(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6162 static int action_ok_push_dropdown_item(const char *path,
6163       const char *label, unsigned type, size_t idx, size_t entry_idx)
6164 {
6165 #if 0
6166    RARCH_LOG("dropdown: \n");
6167    RARCH_LOG("path: %s \n", path);
6168    RARCH_LOG("label: %s \n", label);
6169    RARCH_LOG("type: %d \n", type);
6170    RARCH_LOG("idx: %d \n", idx);
6171    RARCH_LOG("entry_idx: %d \n", entry_idx);
6172 #endif
6173    return 0;
6174 }
6175 
action_cb_push_dropdown_item_resolution(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6176 int action_cb_push_dropdown_item_resolution(const char *path,
6177       const char *label, unsigned type, size_t idx, size_t entry_idx)
6178 {
6179    char str[100];
6180    char *pch            = NULL;
6181    unsigned width       = 0;
6182    unsigned height      = 0;
6183    unsigned refreshrate = 0;
6184 
6185    strlcpy(str, path, sizeof(str));
6186    pch            = strtok(str, "x");
6187    if (pch)
6188       width       = (unsigned)strtoul(pch, NULL, 0);
6189    pch            = strtok(NULL, " ");
6190    if (pch)
6191       height      = (unsigned)strtoul(pch, NULL, 0);
6192    pch            = strtok(NULL, "(");
6193    if (pch)
6194       refreshrate = (unsigned)strtoul(pch, NULL, 0);
6195 
6196    if (video_display_server_set_resolution(width, height,
6197          refreshrate, (float)refreshrate, 0, 0, 0, 0))
6198    {
6199       settings_t *settings = config_get_ptr();
6200 
6201       video_monitor_set_refresh_rate((float)refreshrate);
6202 
6203       settings->uints.video_fullscreen_x = width;
6204       settings->uints.video_fullscreen_y = height;
6205 
6206       return 1;
6207    }
6208 
6209    return 0;
6210 }
6211 
action_ok_push_dropdown_item_video_shader_num_pass(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6212 static int action_ok_push_dropdown_item_video_shader_num_pass(const char *path,
6213       const char *label, unsigned type, size_t idx, size_t entry_idx)
6214 {
6215 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
6216    struct video_shader *shader = menu_shader_get();
6217 
6218    if (!shader)
6219       return menu_cbs_exit();
6220 
6221    shader->passes              = (unsigned)idx;
6222 
6223    video_shader_resolve_parameters(shader);
6224 
6225    shader->modified            = true;
6226 
6227    return action_cancel_pop_default(NULL, NULL, 0, 0);
6228 #else
6229    return 0;
6230 #endif
6231 }
6232 
action_ok_push_dropdown_item_video_shader_param_generic(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx,size_t setting_offset)6233 static int action_ok_push_dropdown_item_video_shader_param_generic(const char *path,
6234       const char *label, unsigned type, size_t idx, size_t entry_idx,
6235       size_t setting_offset)
6236 {
6237 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
6238    video_shader_ctx_t shader_info;
6239    unsigned offset                           = (unsigned)setting_offset;
6240    float val                                 = atof(path);
6241    struct video_shader *shader               = menu_shader_get();
6242    struct video_shader_parameter *param_menu = NULL;
6243    struct video_shader_parameter *param_prev = NULL;
6244 
6245    video_shader_driver_get_current_shader(&shader_info);
6246 
6247    param_prev    = &shader_info.data->parameters[entry_idx - offset];
6248    if (shader)
6249       param_menu = &shader->parameters [entry_idx - offset];
6250 
6251    if (!param_prev || !param_menu)
6252       return menu_cbs_exit();
6253 
6254    param_prev->current  = val;
6255    param_menu->current  = param_prev->current;
6256 
6257    shader->modified     = true;
6258 
6259    return action_cancel_pop_default(NULL, NULL, 0, 0);
6260 #else
6261    return 0;
6262 #endif
6263 }
6264 
action_ok_push_dropdown_item_video_shader_param(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6265 static int action_ok_push_dropdown_item_video_shader_param(const char *path,
6266       const char *label, unsigned type, size_t idx, size_t entry_idx)
6267 {
6268    return action_ok_push_dropdown_item_video_shader_param_generic(
6269          path, label, type,
6270          idx, entry_idx, MENU_SETTINGS_SHADER_PARAMETER_0);
6271 }
6272 
action_ok_push_dropdown_item_video_shader_preset_param(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6273 static int action_ok_push_dropdown_item_video_shader_preset_param(
6274       const char *path,
6275       const char *label, unsigned type, size_t idx, size_t entry_idx)
6276 {
6277    return action_ok_push_dropdown_item_video_shader_param_generic(
6278          path, label, type,
6279          idx, entry_idx, MENU_SETTINGS_SHADER_PRESET_PARAMETER_0);
6280 }
6281 
action_ok_push_dropdown_item_resolution(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6282 static int action_ok_push_dropdown_item_resolution(const char *path,
6283       const char *label, unsigned type, size_t idx, size_t entry_idx)
6284 {
6285    if (action_cb_push_dropdown_item_resolution(path,
6286             label, type, idx, entry_idx) == 1)
6287    {
6288       /* TODO/FIXME - menu drivers like XMB don't rescale
6289        * automatically */
6290       return menu_cbs_exit();
6291    }
6292    return 0;
6293 }
6294 
action_ok_push_dropdown_item_playlist_default_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6295 static int action_ok_push_dropdown_item_playlist_default_core(
6296       const char *path,
6297       const char *label, unsigned type, size_t idx, size_t entry_idx)
6298 {
6299    core_info_list_t *core_info_list = NULL;
6300    playlist_t *playlist             = playlist_get_cached();
6301    const char* core_name            = path;
6302 
6303    /* Get core list */
6304    core_info_get_list(&core_info_list);
6305 
6306    if (!core_info_list || !playlist)
6307       return -1;
6308 
6309    /* Handle N/A or empty path input */
6310    if (string_is_empty(core_name) ||
6311        string_is_equal(core_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)))
6312    {
6313       playlist_set_default_core_path(playlist, "DETECT");
6314       playlist_set_default_core_name(playlist, "DETECT");
6315    }
6316    else
6317    {
6318       core_info_t *core_info = NULL;
6319       bool found             = false;
6320       size_t i;
6321 
6322       /* Loop through cores until we find a match */
6323       for (i = 0; i < core_info_list->count; i++)
6324       {
6325          core_info = NULL;
6326          core_info = core_info_get(core_info_list, i);
6327 
6328          if (core_info)
6329          {
6330             if (string_is_equal(core_name, core_info->display_name))
6331             {
6332                /* Update playlist */
6333                playlist_set_default_core_path(playlist, core_info->path);
6334                playlist_set_default_core_name(playlist, core_info->display_name);
6335 
6336                found = true;
6337                break;
6338             }
6339          }
6340       }
6341 
6342       /* Fallback... */
6343       if (!found)
6344       {
6345          playlist_set_default_core_path(playlist, "DETECT");
6346          playlist_set_default_core_name(playlist, "DETECT");
6347       }
6348    }
6349 
6350    /* In all cases, update file on disk */
6351    playlist_write_file(playlist);
6352 
6353    return action_cancel_pop_default(NULL, NULL, 0, 0);
6354 }
6355 
6356 
action_ok_push_dropdown_item_playlist_label_display_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6357 static int action_ok_push_dropdown_item_playlist_label_display_mode(
6358       const char *path,
6359       const char *label, unsigned type, size_t idx, size_t entry_idx)
6360 {
6361    playlist_t *playlist = playlist_get_cached();
6362 
6363    playlist_set_label_display_mode(playlist,
6364          (enum playlist_label_display_mode)idx);
6365 
6366    /* In all cases, update file on disk */
6367    playlist_write_file(playlist);
6368 
6369    return action_cancel_pop_default(NULL, NULL, 0, 0);
6370 }
6371 
generic_set_thumbnail_mode(enum playlist_thumbnail_id thumbnail_id,size_t idx)6372 static int generic_set_thumbnail_mode(
6373       enum playlist_thumbnail_id thumbnail_id, size_t idx)
6374 {
6375    playlist_t *playlist = playlist_get_cached();
6376 
6377    if (!playlist)
6378       return -1;
6379 
6380    playlist_set_thumbnail_mode(playlist, thumbnail_id,
6381          (enum playlist_thumbnail_mode)idx);
6382    playlist_write_file(playlist);
6383 
6384    return action_cancel_pop_default(NULL, NULL, 0, 0);
6385 }
6386 
action_ok_push_dropdown_item_playlist_right_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6387 static int action_ok_push_dropdown_item_playlist_right_thumbnail_mode(
6388       const char *path,
6389       const char *label, unsigned type, size_t idx, size_t entry_idx)
6390 {
6391    return generic_set_thumbnail_mode(PLAYLIST_THUMBNAIL_RIGHT, idx);
6392 }
6393 
action_ok_push_dropdown_item_playlist_left_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6394 static int action_ok_push_dropdown_item_playlist_left_thumbnail_mode(
6395       const char *path,
6396       const char *label, unsigned type, size_t idx, size_t entry_idx)
6397 {
6398    return generic_set_thumbnail_mode(PLAYLIST_THUMBNAIL_LEFT, idx);
6399 }
6400 
action_ok_push_dropdown_item_playlist_sort_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6401 static int action_ok_push_dropdown_item_playlist_sort_mode(
6402       const char *path,
6403       const char *label, unsigned type, size_t idx, size_t entry_idx)
6404 {
6405    playlist_t *playlist = playlist_get_cached();
6406 
6407    playlist_set_sort_mode(playlist, (enum playlist_sort_mode)idx);
6408    playlist_write_file(playlist);
6409 
6410    return action_cancel_pop_default(NULL, NULL, 0, 0);
6411 }
6412 
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)6413 static int action_ok_push_dropdown_item_manual_content_scan_system_name(
6414       const char *path,
6415       const char *label, unsigned type, size_t idx, size_t entry_idx)
6416 {
6417    const char* system_name                                    = path;
6418    enum manual_content_scan_system_name_type system_name_type =
6419          MANUAL_CONTENT_SCAN_SYSTEM_NAME_DATABASE;
6420 
6421    /* Get system name type (i.e. check if setting is
6422     * 'use content directory' or 'use custom') */
6423    switch (idx)
6424    {
6425       case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR:
6426       case MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM:
6427          system_name_type = (enum manual_content_scan_system_name_type)idx;
6428          break;
6429       default:
6430          break;
6431    }
6432 
6433    /* Set system name */
6434    manual_content_scan_set_menu_system_name(
6435       system_name_type, system_name);
6436 
6437    return action_cancel_pop_default(NULL, NULL, 0, 0);
6438 }
6439 
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)6440 static int action_ok_push_dropdown_item_manual_content_scan_core_name(
6441       const char *path,
6442       const char *label, unsigned type, size_t idx, size_t entry_idx)
6443 {
6444    const char* core_name                        = path;
6445    enum manual_content_scan_core_type core_type =
6446          MANUAL_CONTENT_SCAN_CORE_SET;
6447 
6448    /* Get core type (i.e. check if setting is
6449     * DETECT/Unspecified) */
6450    if (idx == (size_t)MANUAL_CONTENT_SCAN_CORE_DETECT)
6451       core_type = MANUAL_CONTENT_SCAN_CORE_DETECT;
6452 
6453    /* Set core name */
6454    manual_content_scan_set_menu_core_name(
6455       core_type, core_name);
6456 
6457    return action_cancel_pop_default(NULL, NULL, 0, 0);
6458 }
6459 
action_ok_push_dropdown_item_disk_index(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6460 static int action_ok_push_dropdown_item_disk_index(const char *path,
6461       const char *label, unsigned type, size_t idx, size_t entry_idx)
6462 {
6463    unsigned disk_index = (unsigned)idx;
6464 
6465    command_event(CMD_EVENT_DISK_INDEX, &disk_index);
6466 
6467    /* When choosing a disk, menu selection should
6468     * automatically be reset to the 'insert disk'
6469     * option */
6470    menu_entries_pop_stack(NULL, 0, 1);
6471    menu_navigation_set_selection(0);
6472 
6473    return 0;
6474 }
6475 
action_ok_push_dropdown_item_input_device_type(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6476 static int action_ok_push_dropdown_item_input_device_type(const char *path,
6477       const char *label, unsigned type, size_t idx, size_t entry_idx)
6478 {
6479    retro_ctx_controller_info_t pad;
6480    unsigned port                = 0;
6481    unsigned device              = 0;
6482 
6483    const char *menu_path        = NULL;
6484    enum msg_hash_enums enum_idx;
6485    rarch_setting_t     *setting;
6486    menu_entries_get_last_stack(&menu_path, NULL, NULL, NULL, NULL);
6487    enum_idx = (enum msg_hash_enums)atoi(menu_path);
6488    setting  = menu_setting_find_enum(enum_idx);
6489 
6490    if (!setting)
6491       return menu_cbs_exit();
6492 
6493    port   = setting->index_offset;
6494    device = atoi(label);
6495 
6496    input_config_set_device(port, device);
6497 
6498    pad.port   = port;
6499    pad.device = device;
6500 
6501    core_set_controller_port_device(&pad);
6502 
6503    return action_cancel_pop_default(NULL, NULL, 0, 0);
6504 }
6505 
action_ok_push_dropdown_item_input_device_index(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6506 static int action_ok_push_dropdown_item_input_device_index(const char *path,
6507       const char *label, unsigned type, size_t idx, size_t entry_idx)
6508 {
6509    settings_t *settings         = config_get_ptr();
6510 
6511    const char *menu_path        = NULL;
6512    enum msg_hash_enums enum_idx;
6513    rarch_setting_t     *setting;
6514    menu_entries_get_last_stack(&menu_path, NULL, NULL, NULL, NULL);
6515    enum_idx = (enum msg_hash_enums)atoi(menu_path);
6516    setting  = menu_setting_find_enum(enum_idx);
6517 
6518    if (!setting)
6519       return menu_cbs_exit();
6520 
6521    settings->uints.input_joypad_index[setting->index_offset] = (unsigned)entry_idx;
6522 
6523    return action_cancel_pop_default(NULL, NULL, 0, 0);
6524 }
6525 
action_ok_push_dropdown_item_input_description(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6526 static int action_ok_push_dropdown_item_input_description(const char *path,
6527       const char *label, unsigned type, size_t idx, size_t entry_idx)
6528 {
6529    unsigned remap_idx   = (unsigned)entry_idx;
6530    unsigned entry_type  = string_to_unsigned(label);
6531    settings_t *settings = config_get_ptr();
6532    unsigned user_idx;
6533    unsigned btn_idx;
6534 
6535    if (!settings ||
6536        (entry_type < MENU_SETTINGS_INPUT_DESC_BEGIN) ||
6537        ((remap_idx >= RARCH_CUSTOM_BIND_LIST_END) &&
6538             (remap_idx != RARCH_UNMAPPED)))
6539       return menu_cbs_exit();
6540 
6541    /* Determine user/button indices */
6542    user_idx = (entry_type - MENU_SETTINGS_INPUT_DESC_BEGIN)
6543       / (RARCH_FIRST_CUSTOM_BIND + 8);
6544    btn_idx  = (entry_type - MENU_SETTINGS_INPUT_DESC_BEGIN)
6545       - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx;
6546 
6547    if ((user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END))
6548       return menu_cbs_exit();
6549 
6550    /* Assign new mapping */
6551    settings->uints.input_remap_ids[user_idx][btn_idx] = remap_idx;
6552 
6553    return action_cancel_pop_default(NULL, NULL, 0, 0);
6554 }
6555 
action_ok_push_dropdown_item_input_description_kbd(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6556 static int action_ok_push_dropdown_item_input_description_kbd(
6557       const char *path,
6558       const char *label, unsigned type, size_t idx, size_t entry_idx)
6559 {
6560    unsigned key_id      = (unsigned)entry_idx;
6561    unsigned entry_type  = string_to_unsigned(label);
6562    settings_t *settings = config_get_ptr();
6563    unsigned user_idx;
6564    unsigned btn_idx;
6565 
6566    if (!settings ||
6567        (entry_type < MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) ||
6568        (key_id >= (RARCH_MAX_KEYS + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN)))
6569       return menu_cbs_exit();
6570 
6571    /* Determine user/button indices */
6572    user_idx = (entry_type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN)
6573       / RARCH_ANALOG_BIND_LIST_END;
6574    btn_idx  = (entry_type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN)
6575       - RARCH_ANALOG_BIND_LIST_END * user_idx;
6576 
6577    if ((user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END))
6578       return menu_cbs_exit();
6579 
6580    /* Assign new mapping */
6581    settings->uints.input_keymapper_ids[user_idx][btn_idx] = key_id;
6582 
6583    return action_cancel_pop_default(NULL, NULL, 0, 0);
6584 }
6585 
action_ok_push_default(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6586 static int action_ok_push_default(const char *path,
6587       const char *label, unsigned type, size_t idx, size_t entry_idx)
6588 {
6589    filebrowser_clear_type();
6590    return generic_action_ok_displaylist_push(path, NULL, label, type, idx,
6591          entry_idx, ACTION_OK_DL_PUSH_DEFAULT);
6592 }
6593 
action_ok_start_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6594 static int action_ok_start_core(const char *path,
6595       const char *label, unsigned type, size_t idx, size_t entry_idx)
6596 {
6597    content_ctx_info_t content_info;
6598 
6599    content_info.argc                   = 0;
6600    content_info.argv                   = NULL;
6601    content_info.args                   = NULL;
6602    content_info.environ_get            = NULL;
6603 
6604    path_clear(RARCH_PATH_BASENAME);
6605    if (!task_push_start_current_core(&content_info))
6606       return -1;
6607 
6608    return 0;
6609 }
6610 
action_ok_load_archive(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6611 static int action_ok_load_archive(const char *path,
6612       const char *label, unsigned type, size_t idx, size_t entry_idx)
6613 {
6614    const char *menu_path           = NULL;
6615    const char *content_path        = NULL;
6616    menu_handle_t *menu             = menu_driver_get_ptr();
6617 
6618    if (!menu)
6619       return menu_cbs_exit();
6620 
6621    menu_path    = menu->scratch2_buf;
6622    content_path = menu->scratch_buf;
6623 
6624    fill_pathname_join(menu->detect_content_path,
6625          menu_path, content_path,
6626          sizeof(menu->detect_content_path));
6627 
6628    generic_action_ok_command(CMD_EVENT_LOAD_CORE);
6629 
6630    return default_action_ok_load_content_with_core_from_menu(
6631          menu->detect_content_path,
6632          CORE_TYPE_PLAIN);
6633 }
6634 
action_ok_load_archive_detect_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6635 static int action_ok_load_archive_detect_core(const char *path,
6636       const char *label, unsigned type, size_t idx, size_t entry_idx)
6637 {
6638    char new_core_path[PATH_MAX_LENGTH];
6639    menu_content_ctx_defer_info_t def_info;
6640    int ret                             = 0;
6641    core_info_list_t *list              = NULL;
6642    const char *menu_path               = NULL;
6643    const char *content_path            = NULL;
6644    menu_handle_t *menu                 = menu_driver_get_ptr();
6645 
6646    if (!menu)
6647       return menu_cbs_exit();
6648 
6649    menu_path           = menu->scratch2_buf;
6650    content_path        = menu->scratch_buf;
6651 
6652    core_info_get_list(&list);
6653 
6654    def_info.data       = list;
6655    def_info.dir        = menu_path;
6656    def_info.path       = content_path;
6657    def_info.menu_label = label;
6658    def_info.s          = menu->deferred_path;
6659    def_info.len        = sizeof(menu->deferred_path);
6660 
6661    new_core_path[0]    = '\0';
6662 
6663    if (menu_content_find_first_core(&def_info, false,
6664             new_core_path, sizeof(new_core_path)))
6665       ret = -1;
6666 
6667    fill_pathname_join(menu->detect_content_path, menu_path, content_path,
6668          sizeof(menu->detect_content_path));
6669 
6670    switch (ret)
6671    {
6672       case -1:
6673          {
6674             content_ctx_info_t content_info;
6675 
6676             content_info.argc                   = 0;
6677             content_info.argv                   = NULL;
6678             content_info.args                   = NULL;
6679             content_info.environ_get            = NULL;
6680 
6681             ret                                 = 0;
6682 
6683             if (!task_push_load_content_with_new_core_from_menu(
6684                      new_core_path, def_info.s,
6685                      &content_info,
6686                      CORE_TYPE_PLAIN,
6687                      NULL, NULL))
6688                ret = -1;
6689             else
6690                menu_driver_set_last_start_content(def_info.s);
6691          }
6692          break;
6693       case 0:
6694          idx = menu_navigation_get_selection();
6695          ret = generic_action_ok_displaylist_push(path, NULL,
6696                label, type,
6697                idx, entry_idx, ACTION_OK_DL_DEFERRED_CORE_LIST);
6698          break;
6699       default:
6700          break;
6701    }
6702 
6703    return ret;
6704 }
6705 
action_ok_help_send_debug_info(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6706 static int action_ok_help_send_debug_info(const char *path,
6707       const char *label, unsigned type, size_t idx, size_t entry_idx)
6708 {
6709    command_event(CMD_EVENT_SEND_DEBUG_INFO, NULL);
6710    return 0;
6711 }
6712 
DEFAULT_ACTION_OK_HELP(action_ok_help_audio_video_troubleshooting,MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING,MENU_DIALOG_HELP_AUDIO_VIDEO_TROUBLESHOOTING)6713 DEFAULT_ACTION_OK_HELP(action_ok_help_audio_video_troubleshooting, MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING, MENU_DIALOG_HELP_AUDIO_VIDEO_TROUBLESHOOTING)
6714 DEFAULT_ACTION_OK_HELP(action_ok_help, MENU_ENUM_LABEL_HELP, MENU_DIALOG_WELCOME)
6715 DEFAULT_ACTION_OK_HELP(action_ok_help_controls, MENU_ENUM_LABEL_HELP_CONTROLS, MENU_DIALOG_HELP_CONTROLS)
6716 DEFAULT_ACTION_OK_HELP(action_ok_help_what_is_a_core, MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE, MENU_DIALOG_HELP_WHAT_IS_A_CORE)
6717 DEFAULT_ACTION_OK_HELP(action_ok_help_scanning_content, MENU_ENUM_LABEL_HELP_SCANNING_CONTENT, MENU_DIALOG_HELP_SCANNING_CONTENT)
6718 DEFAULT_ACTION_OK_HELP(action_ok_help_change_virtual_gamepad, MENU_ENUM_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD, MENU_DIALOG_HELP_CHANGE_VIRTUAL_GAMEPAD)
6719 DEFAULT_ACTION_OK_HELP(action_ok_help_load_content, MENU_ENUM_LABEL_HELP_LOADING_CONTENT, MENU_DIALOG_HELP_LOADING_CONTENT)
6720 
6721 static int generic_dropdown_box_list(size_t idx, unsigned lbl)
6722 {
6723    generic_action_ok_displaylist_push(
6724          NULL,
6725          NULL, NULL, 0, idx, 0,
6726          lbl);
6727    return 0;
6728 }
6729 
action_ok_video_resolution(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6730 static int action_ok_video_resolution(const char *path,
6731       const char *label, unsigned type, size_t idx, size_t entry_idx)
6732 {
6733 #if defined(GEKKO) || !defined(__PSL1GHT__) && defined(__PS3__)
6734    unsigned width   = 0;
6735    unsigned  height = 0;
6736 
6737    if (video_driver_get_video_output_size(&width, &height))
6738    {
6739       char msg[PATH_MAX_LENGTH];
6740 
6741       msg[0] = '\0';
6742 
6743 #if defined(_WIN32) || !defined(__PSL1GHT__) && defined(__PS3__)
6744       generic_action_ok_command(CMD_EVENT_REINIT);
6745 #endif
6746       video_driver_set_video_mode(width, height, true);
6747 #ifdef GEKKO
6748       if (width == 0 || height == 0)
6749          strcpy_literal(msg, "Applying: DEFAULT");
6750       else
6751 #endif
6752          snprintf(msg, sizeof(msg),
6753                "Applying: %dx%d\n START to reset",
6754                width, height);
6755       runloop_msg_queue_push(msg, 1, 100, true, NULL,
6756             MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
6757    }
6758 
6759    return 0;
6760 #else
6761    return generic_dropdown_box_list(idx,
6762          ACTION_OK_DL_DROPDOWN_BOX_LIST_RESOLUTION);
6763 #endif
6764 }
6765 
action_ok_playlist_default_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6766 static int action_ok_playlist_default_core(const char *path,
6767       const char *label, unsigned type, size_t idx, size_t entry_idx)
6768 {
6769    return generic_dropdown_box_list(idx,
6770          ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE);
6771 }
6772 
action_ok_playlist_label_display_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6773 static int action_ok_playlist_label_display_mode(const char *path,
6774       const char *label, unsigned type, size_t idx, size_t entry_idx)
6775 {
6776    return generic_dropdown_box_list(idx,
6777          ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE);
6778 }
6779 
action_ok_playlist_right_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6780 static int action_ok_playlist_right_thumbnail_mode(const char *path,
6781       const char *label, unsigned type, size_t idx, size_t entry_idx)
6782 {
6783    return generic_dropdown_box_list(idx,
6784          ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE);
6785 }
6786 
action_ok_playlist_left_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6787 static int action_ok_playlist_left_thumbnail_mode(const char *path,
6788       const char *label, unsigned type, size_t idx, size_t entry_idx)
6789 {
6790    return generic_dropdown_box_list(idx,
6791          ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE);
6792 }
6793 
action_ok_playlist_sort_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6794 static int action_ok_playlist_sort_mode(const char *path,
6795       const char *label, unsigned type, size_t idx, size_t entry_idx)
6796 {
6797    return generic_dropdown_box_list(idx,
6798          ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE);
6799 }
6800 
action_ok_remappings_port_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6801 static int action_ok_remappings_port_list(const char *path,
6802       const char *label, unsigned type, size_t idx, size_t entry_idx)
6803 {
6804    generic_action_ok_displaylist_push(
6805          path,
6806          NULL, label, 0, idx, 0,
6807          ACTION_OK_DL_REMAPPINGS_PORT_LIST);
6808    return 0;
6809 }
6810 
action_ok_shader_parameter_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6811 static int action_ok_shader_parameter_dropdown_box_list(const char *path,
6812       const char *label, unsigned type, size_t idx, size_t entry_idx)
6813 {
6814    return generic_dropdown_box_list(idx,
6815          ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PARAMETER);
6816 }
6817 
action_ok_shader_preset_parameter_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6818 static int action_ok_shader_preset_parameter_dropdown_box_list(
6819       const char *path,
6820       const char *label, unsigned type, size_t idx, size_t entry_idx)
6821 {
6822    return generic_dropdown_box_list(idx,
6823          ACTION_OK_DL_DROPDOWN_BOX_LIST_SHADER_PRESET_PARAMETER);
6824 }
6825 
action_ok_manual_content_scan_system_name(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6826 static int action_ok_manual_content_scan_system_name(const char *path,
6827       const char *label, unsigned type, size_t idx, size_t entry_idx)
6828 {
6829    return generic_dropdown_box_list(idx,
6830          ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME);
6831 }
6832 
action_ok_manual_content_scan_core_name(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6833 static int action_ok_manual_content_scan_core_name(const char *path,
6834       const char *label, unsigned type, size_t idx, size_t entry_idx)
6835 {
6836    return generic_dropdown_box_list(idx,
6837          ACTION_OK_DL_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME);
6838 }
6839 
action_ok_video_shader_num_passes_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6840 static int action_ok_video_shader_num_passes_dropdown_box_list(
6841       const char *path,
6842       const char *label, unsigned type, size_t idx, size_t entry_idx)
6843 {
6844    return generic_dropdown_box_list(idx,
6845          ACTION_OK_DL_DROPDOWN_BOX_LIST_VIDEO_SHADER_NUM_PASSES);
6846 }
6847 
action_ok_disk_index_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6848 static int action_ok_disk_index_dropdown_box_list(const char *path,
6849       const char *label, unsigned type, size_t idx, size_t entry_idx)
6850 {
6851    return generic_dropdown_box_list(idx,
6852          ACTION_OK_DL_DROPDOWN_BOX_LIST_DISK_INDEX);
6853 }
6854 
action_ok_input_description_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6855 static int action_ok_input_description_dropdown_box_list(const char *path,
6856       const char *label, unsigned type, size_t idx, size_t entry_idx)
6857 {
6858    return generic_action_ok_displaylist_push(
6859       path, NULL, label, type, idx, entry_idx,
6860       ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION);
6861 }
6862 
action_ok_input_description_kbd_dropdown_box_list(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6863 static int action_ok_input_description_kbd_dropdown_box_list(
6864       const char *path,
6865       const char *label, unsigned type, size_t idx, size_t entry_idx)
6866 {
6867    return generic_action_ok_displaylist_push(
6868       path, NULL, label, type, idx, entry_idx,
6869       ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD);
6870 }
6871 
action_ok_disk_cycle_tray_status(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6872 static int action_ok_disk_cycle_tray_status(const char *path,
6873       const char *label, unsigned type, size_t idx, size_t entry_idx)
6874 {
6875    bool disk_ejected              = false;
6876    bool print_log                 = false;
6877    rarch_system_info_t *sys_info  = runloop_get_system_info();
6878    settings_t *settings           = config_get_ptr();
6879 #ifdef HAVE_AUDIOMIXER
6880    bool audio_enable_menu         = settings->bools.audio_enable_menu;
6881    bool audio_enable_menu_ok      = settings->bools.audio_enable_menu_ok;
6882 #endif
6883    bool menu_insert_disk_resume   = settings->bools.menu_insert_disk_resume;
6884 
6885    if (!settings)
6886       return menu_cbs_exit();
6887 
6888 #ifdef HAVE_AUDIOMIXER
6889    if (audio_enable_menu && audio_enable_menu_ok)
6890       audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
6891 #endif
6892 
6893    /* Get disk eject state *before* toggling drive status */
6894    if (sys_info)
6895       disk_ejected = disk_control_get_eject_state(&sys_info->disk_control);
6896 
6897    /* Only want to display a notification if we are
6898     * going to resume content immediately after
6899     * inserting a disk (i.e. if quick menu remains
6900     * open, there is sufficient visual feedback
6901     * without a notification) */
6902    print_log = menu_insert_disk_resume && disk_ejected;
6903 
6904    if (!command_event(CMD_EVENT_DISK_EJECT_TOGGLE, &print_log))
6905       return menu_cbs_exit();
6906 
6907    /* If we reach this point, then tray toggle
6908     * was successful */
6909    disk_ejected = !disk_ejected;
6910 
6911    /* If disk is now ejected, menu selection should
6912     * automatically increment to the 'current disk
6913     * index' option */
6914    if (disk_ejected)
6915       menu_navigation_set_selection(1);
6916 
6917    /* If disk is now inserted and user has enabled
6918     * 'menu_insert_disk_resume', resume running content */
6919    if (!disk_ejected && menu_insert_disk_resume)
6920       generic_action_ok_command(CMD_EVENT_RESUME);
6921 
6922    return 0;
6923 }
6924 
action_ok_disk_image_append(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6925 static int action_ok_disk_image_append(const char *path,
6926       const char *label, unsigned type, size_t idx, size_t entry_idx)
6927 {
6928    char image_path[PATH_MAX_LENGTH];
6929    rarch_system_info_t *sys_info = runloop_get_system_info();
6930    menu_handle_t *menu           = menu_driver_get_ptr();
6931    const char *menu_path         = NULL;
6932    settings_t *settings          = config_get_ptr();
6933 #ifdef HAVE_AUDIOMIXER
6934    bool audio_enable_menu        = settings->bools.audio_enable_menu;
6935    bool audio_enable_menu_ok     = settings->bools.audio_enable_menu_ok;
6936 #endif
6937    bool menu_insert_disk_resume  = settings->bools.menu_insert_disk_resume;
6938 
6939    image_path[0]                 = '\0';
6940 
6941    if (!menu)
6942       return menu_cbs_exit();
6943 
6944 #ifdef HAVE_AUDIOMIXER
6945    if (audio_enable_menu && audio_enable_menu_ok)
6946       audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
6947 #endif
6948 
6949    /* Get file path of new disk image */
6950    menu_entries_get_last_stack(&menu_path,
6951          NULL, NULL, NULL, NULL);
6952 
6953    if (!string_is_empty(menu_path))
6954    {
6955       if (!string_is_empty(path))
6956          fill_pathname_join(image_path,
6957                menu_path, path, sizeof(image_path));
6958       else
6959          strlcpy(image_path, menu_path, sizeof(image_path));
6960    }
6961 
6962    /* Append image */
6963    command_event(CMD_EVENT_DISK_APPEND_IMAGE, image_path);
6964 
6965    /* In all cases, return to the disk options menu */
6966    menu_entries_flush_stack(msg_hash_to_str(MENU_ENUM_LABEL_DISK_OPTIONS), 0);
6967 
6968    /* > If disk tray is open, reset menu selection to
6969     *   the 'insert disk' option
6970     * > If disk try is closed and user has enabled
6971     *   'menu_insert_disk_resume', resume running content */
6972    if (sys_info && disk_control_get_eject_state(&sys_info->disk_control))
6973       menu_navigation_set_selection(0);
6974    else if (menu_insert_disk_resume)
6975       generic_action_ok_command(CMD_EVENT_RESUME);
6976 
6977    return 0;
6978 }
6979 
action_ok_manual_content_scan_start(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6980 static int action_ok_manual_content_scan_start(const char *path,
6981       const char *label, unsigned type, size_t idx, size_t entry_idx)
6982 {
6983    playlist_config_t playlist_config;
6984    settings_t *settings                = config_get_ptr();
6985    const char *directory_playlist      = settings->paths.directory_playlist;
6986 
6987    /* Note: playlist_config.path will set by the
6988     * task itself */
6989    playlist_config.capacity            = COLLECTION_SIZE;
6990    playlist_config.old_format          = settings->bools.playlist_use_old_format;
6991    playlist_config.compress            = settings->bools.playlist_compression;
6992    playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match;
6993    playlist_config_set_base_content_directory(&playlist_config, settings->bools.playlist_portable_paths ? settings->paths.directory_menu_content : NULL);
6994 
6995    task_push_manual_content_scan(&playlist_config, directory_playlist);
6996    return 0;
6997 }
6998 
action_ok_netplay_enable_host(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)6999 static int action_ok_netplay_enable_host(const char *path,
7000       const char *label, unsigned type, size_t idx, size_t entry_idx)
7001 {
7002 #ifdef HAVE_NETWORKING
7003    if (command_event(CMD_EVENT_NETPLAY_ENABLE_HOST, NULL))
7004       return generic_action_ok_command(CMD_EVENT_RESUME);
7005 #endif
7006    return -1;
7007 }
7008 
7009 #ifdef HAVE_NETWORKING
action_ok_netplay_enable_client_hostname_cb(void * ignore,const char * hostname)7010 static void action_ok_netplay_enable_client_hostname_cb(
7011    void *ignore, const char *hostname)
7012 {
7013 
7014    if (hostname && hostname[0])
7015    {
7016       bool contentless   = false;
7017       bool is_inited     = false;
7018       char *tmp_hostname = strdup(hostname);
7019 
7020       content_get_status(&contentless, &is_inited);
7021 
7022       if (!is_inited)
7023       {
7024          command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED,
7025                (void*)tmp_hostname);
7026          runloop_msg_queue_push(
7027             msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED),
7028             1, 480, true,
7029             NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
7030       }
7031       else
7032       {
7033          command_event(CMD_EVENT_NETPLAY_INIT_DIRECT,
7034                (void*)tmp_hostname);
7035          generic_action_ok_command(CMD_EVENT_RESUME);
7036       }
7037 
7038       free(tmp_hostname);
7039    }
7040    else
7041    {
7042       menu_input_dialog_end();
7043       return;
7044    }
7045 
7046    menu_input_dialog_end();
7047    retroarch_menu_running_finished(false);
7048 }
7049 #endif
7050 
action_ok_netplay_enable_client(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7051 static int action_ok_netplay_enable_client(const char *path,
7052       const char *label, unsigned type, size_t idx, size_t entry_idx)
7053 {
7054 #ifdef HAVE_NETWORKING
7055    menu_input_ctx_line_t line;
7056    settings_t       *settings = config_get_ptr();
7057    const char *netplay_server = settings->paths.netplay_server;
7058 
7059    if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
7060       generic_action_ok_command(CMD_EVENT_NETPLAY_DEINIT);
7061    netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL);
7062 
7063    if (!string_is_empty(netplay_server))
7064    {
7065       action_ok_netplay_enable_client_hostname_cb(NULL, netplay_server);
7066       return 0;
7067    }
7068    else
7069    {
7070       line.label         = msg_hash_to_str(
7071             MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS);
7072       line.label_setting = "no_setting";
7073       line.type          = 0;
7074       line.idx           = 0;
7075       line.cb            = action_ok_netplay_enable_client_hostname_cb;
7076 
7077       if (menu_input_dialog_start(&line))
7078          return 0;
7079    }
7080 #endif
7081    return -1;
7082 }
7083 
action_ok_netplay_disconnect(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7084 static int action_ok_netplay_disconnect(const char *path,
7085       const char *label, unsigned type, size_t idx, size_t entry_idx)
7086 {
7087 #ifdef HAVE_NETWORKING
7088    generic_action_ok_command(CMD_EVENT_NETPLAY_DISCONNECT);
7089 
7090    return generic_action_ok_command(CMD_EVENT_RESUME);
7091 #else
7092    return -1;
7093 #endif
7094 }
7095 
action_ok_core_create_backup(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7096 static int action_ok_core_create_backup(const char *path,
7097       const char *label, unsigned type, size_t idx, size_t entry_idx)
7098 {
7099    const char *core_path             = label;
7100    settings_t *settings              = config_get_ptr();
7101    unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
7102    const char *dir_core_assets       = settings->paths.directory_core_assets;
7103 
7104    if (string_is_empty(core_path))
7105       return -1;
7106 
7107    task_push_core_backup(core_path, NULL, 0, CORE_BACKUP_MODE_MANUAL,
7108          (size_t)auto_backup_history_size, dir_core_assets, false);
7109 
7110    return 0;
7111 }
7112 
action_ok_core_restore_backup(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7113 static int action_ok_core_restore_backup(const char *path,
7114       const char *label, unsigned type, size_t idx, size_t entry_idx)
7115 {
7116    const char *backup_path  = label;
7117    bool core_loaded         = false;
7118    settings_t *settings     = config_get_ptr();
7119    const char *dir_libretro = settings->paths.directory_libretro;
7120 
7121    if (string_is_empty(backup_path))
7122       return -1;
7123 
7124    /* If core to be restored is currently loaded, the task
7125     * will unload it
7126     * > In this case, must flush the menu stack
7127     *   (otherwise user will be faced with 'no information
7128     *   available' when popping the stack - this would be
7129     *   confusing/ugly) */
7130    if (task_push_core_restore(backup_path, dir_libretro, &core_loaded) &&
7131        core_loaded)
7132       menu_entries_flush_stack(NULL, 0);
7133 
7134    return 0;
7135 }
7136 
action_ok_core_delete_backup(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7137 static int action_ok_core_delete_backup(const char *path,
7138       const char *label, unsigned type, size_t idx, size_t entry_idx)
7139 {
7140    const char *backup_path = label;
7141    bool refresh            = false;
7142 
7143    if (string_is_empty(backup_path))
7144       return -1;
7145 
7146    /* Delete backup file (if it exists) */
7147    if (path_is_valid(backup_path))
7148       filestream_delete(backup_path);
7149 
7150    /* Refresh menu */
7151    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
7152    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
7153 
7154    return 0;
7155 }
7156 
7157 /* Do not declare this static - it is also used
7158  * in menu_cbs_left.c and menu_cbs_right.c */
action_ok_core_lock(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7159 int action_ok_core_lock(const char *path,
7160       const char *label, unsigned type, size_t idx, size_t entry_idx)
7161 {
7162    const char *core_path = path;
7163    bool lock             = false;
7164    bool refresh          = false;
7165    int ret               = 0;
7166 
7167    if (string_is_empty(core_path))
7168       return -1;
7169 
7170    /* Simply toggle current lock status */
7171    lock = !core_info_get_core_lock(core_path, true);
7172 
7173    if (!core_info_set_core_lock(core_path, lock))
7174    {
7175       const char *core_name = NULL;
7176       core_info_t *core_info = NULL;
7177       char msg[PATH_MAX_LENGTH];
7178 
7179       msg[0] = '\0';
7180 
7181       /* Need to fetch core name for error message */
7182 
7183       /* If core is found, use display name */
7184       if (core_info_find(core_path, &core_info) &&
7185           core_info->display_name)
7186          core_name = core_info->display_name;
7187       /* If not, use core file name */
7188       else
7189          core_name = path_basename_nocompression(core_path);
7190 
7191       /* Build error message */
7192       strlcpy(
7193             msg,
7194             msg_hash_to_str(lock ?
7195                   MSG_CORE_LOCK_FAILED : MSG_CORE_UNLOCK_FAILED),
7196             sizeof(msg));
7197 
7198       if (!string_is_empty(core_name))
7199          strlcat(msg, core_name, sizeof(msg));
7200 
7201       /* Generate log + notification */
7202       RARCH_ERR("%s\n", msg);
7203 
7204       runloop_msg_queue_push(
7205          msg,
7206          1, 100, true,
7207          NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
7208 
7209       ret = -1;
7210    }
7211 
7212    /* Whenever lock status is changed, menu must be
7213     * refreshed - do this even in the event of an error,
7214     * since we don't want to leave the menu in an
7215     * undefined state */
7216    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
7217    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
7218 
7219    return ret;
7220 }
7221 
action_ok_core_delete(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7222 static int action_ok_core_delete(const char *path,
7223       const char *label, unsigned type, size_t idx, size_t entry_idx)
7224 {
7225    const char *core_path = label;
7226 
7227    if (string_is_empty(core_path))
7228       return -1;
7229 
7230    /* Check whether core is locked */
7231    if (core_info_get_core_lock(core_path, true))
7232    {
7233       const char *core_name  = NULL;
7234       core_info_t *core_info = NULL;
7235       char msg[PATH_MAX_LENGTH];
7236 
7237       msg[0] = '\0';
7238 
7239       /* Need to fetch core name for notification */
7240 
7241       /* If core is found, use display name */
7242       if (core_info_find(core_path, &core_info) &&
7243           core_info->display_name)
7244          core_name = core_info->display_name;
7245       /* If not, use core file name */
7246       else
7247          core_name = path_basename_nocompression(core_path);
7248 
7249       /* Build notification message */
7250       strlcpy(msg, msg_hash_to_str(MSG_CORE_DELETE_DISABLED), sizeof(msg));
7251 
7252       if (!string_is_empty(core_name))
7253          strlcat(msg, core_name, sizeof(msg));
7254 
7255       runloop_msg_queue_push(
7256          msg,
7257          1, 100, true,
7258          NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
7259 
7260       /* We do not consider this an 'error' - we are
7261        * merely telling the user that this operation
7262        * is not currently supported */
7263       return 0;
7264    }
7265 
7266    /* Check if core to be deleted is currently
7267     * loaded - if so, unload it */
7268    if (rarch_ctl(RARCH_CTL_IS_CORE_LOADED, (void*)core_path))
7269       generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
7270 
7271    /* Delete core file */
7272 #if defined(ANDROID)
7273    /* If this is a Play Store build and the
7274     * core is currently installed via
7275     * play feature delivery, must delete
7276     * the core via the play feature delivery
7277     * interface */
7278    if (play_feature_delivery_enabled())
7279    {
7280       const char *core_filename = path_basename_nocompression(core_path);
7281       char backup_core_path[PATH_MAX_LENGTH];
7282 
7283       backup_core_path[0] = '\0';
7284 
7285       if (play_feature_delivery_core_installed(core_filename))
7286          play_feature_delivery_delete(core_filename);
7287       else
7288          filestream_delete(core_path);
7289 
7290       /* When installing cores via play feature
7291        * delivery, there is a low probability of
7292        * backup core files being left behind if
7293        * something interrupts the install process
7294        * (i.e. a crash or user exit while the
7295        * install task is running). To prevent the
7296        * accumulation of mess, additionally check
7297        * for and remove any such backups when deleting
7298        * a core */
7299       strlcpy(backup_core_path, core_path,
7300             sizeof(backup_core_path));
7301       strlcat(backup_core_path, FILE_PATH_BACKUP_EXTENSION,
7302             sizeof(backup_core_path));
7303 
7304       if (!string_is_empty(backup_core_path) &&
7305           path_is_valid(backup_core_path))
7306          filestream_delete(backup_core_path);
7307    }
7308    else
7309 #endif
7310       filestream_delete(core_path);
7311 
7312    /* Reload core info files */
7313    command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
7314 
7315    /* Return to higher level menu */
7316    return action_cancel_pop_default(NULL, NULL, 0, 0);
7317 }
7318 
action_ok_delete_playlist(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7319 static int action_ok_delete_playlist(const char *path,
7320       const char *label, unsigned type, size_t idx, size_t entry_idx)
7321 {
7322    playlist_t *playlist = playlist_get_cached();
7323    menu_ctx_environment_t menu_environ;
7324 
7325    if (!playlist)
7326       return -1;
7327 
7328    menu_environ.type = MENU_ENVIRON_NONE;
7329    menu_environ.data = NULL;
7330 
7331    path = playlist_get_conf_path(playlist);
7332 
7333    filestream_delete(path);
7334 
7335    menu_environ.type = MENU_ENVIRON_RESET_HORIZONTAL_LIST;
7336 
7337    menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ);
7338 
7339    return action_cancel_pop_default(NULL, NULL, 0, 0);
7340 }
7341 
action_ok_pl_content_thumbnails(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7342 static int action_ok_pl_content_thumbnails(const char *path,
7343       const char *label, unsigned type, size_t idx, size_t entry_idx)
7344 {
7345 #ifdef HAVE_NETWORKING
7346    settings_t *settings = config_get_ptr();
7347 
7348    if (settings)
7349    {
7350       playlist_config_t playlist_config;
7351       const char *path_dir_playlist       = settings->paths.directory_playlist;
7352       const char *path_dir_thumbnails     = settings->paths.directory_thumbnails;
7353 
7354       playlist_config.capacity            = COLLECTION_SIZE;
7355       playlist_config.old_format          = settings->bools.playlist_use_old_format;
7356       playlist_config.compress            = settings->bools.playlist_compression;
7357       playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match;
7358 
7359       if (!string_is_empty(path_dir_playlist))
7360       {
7361          char playlist_path[PATH_MAX_LENGTH];
7362          playlist_path[0] = '\0';
7363 
7364          fill_pathname_join(
7365                playlist_path, path_dir_playlist, label,
7366                sizeof(playlist_path));
7367          playlist_config_set_path(&playlist_config, playlist_path);
7368 
7369          task_push_pl_thumbnail_download(path, &playlist_config,
7370                path_dir_thumbnails);
7371 
7372          return 0;
7373       }
7374    }
7375 #endif
7376    return -1;
7377 }
7378 
7379 #ifdef HAVE_NETWORKING
action_ok_pl_entry_content_thumbnails(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7380 static int action_ok_pl_entry_content_thumbnails(const char *path,
7381       const char *label, unsigned type, size_t idx, size_t entry_idx)
7382 {
7383    char system[PATH_MAX_LENGTH];
7384    playlist_t *playlist = playlist_get_cached();
7385    menu_handle_t *menu  = menu_driver_get_ptr();
7386 
7387    system[0] = '\0';
7388 
7389    if (!playlist)
7390       return -1;
7391 
7392    if (!menu)
7393       return menu_cbs_exit();
7394 
7395    menu_driver_get_thumbnail_system(system, sizeof(system));
7396 
7397    task_push_pl_entry_thumbnail_download(system,
7398          playlist, menu->rpl_entry_selection_ptr,
7399          true, false);
7400 
7401    return 0;
7402 }
7403 #endif
7404 
action_ok_playlist_reset_cores(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7405 static int action_ok_playlist_reset_cores(const char *path,
7406       const char *label, unsigned type, size_t idx, size_t entry_idx)
7407 {
7408    playlist_t *playlist               = playlist_get_cached();
7409    playlist_config_t *playlist_config = NULL;
7410 
7411    if (!playlist)
7412       return -1;
7413 
7414    playlist_config = playlist_get_config(playlist);
7415 
7416    if (!playlist_config || string_is_empty(playlist_config->path))
7417       return -1;
7418 
7419    task_push_pl_manager_reset_cores(playlist_config);
7420 
7421    return 0;
7422 }
7423 
action_ok_playlist_clean(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)7424 static int action_ok_playlist_clean(const char *path,
7425       const char *label, unsigned type, size_t idx, size_t entry_idx)
7426 {
7427    playlist_t *playlist               = playlist_get_cached();
7428    playlist_config_t *playlist_config = NULL;
7429 
7430    if (!playlist)
7431       return -1;
7432 
7433    playlist_config = playlist_get_config(playlist);
7434 
7435    if (!playlist_config || string_is_empty(playlist_config->path))
7436       return -1;
7437 
7438    task_push_pl_manager_clean_playlist(playlist_config);
7439 
7440    return 0;
7441 }
7442 
is_rdb_entry(enum msg_hash_enums enum_idx)7443 static int is_rdb_entry(enum msg_hash_enums enum_idx)
7444 {
7445    switch (enum_idx)
7446    {
7447       case MENU_ENUM_LABEL_RDB_ENTRY_PUBLISHER:
7448       case MENU_ENUM_LABEL_RDB_ENTRY_DEVELOPER:
7449       case MENU_ENUM_LABEL_RDB_ENTRY_ORIGIN:
7450       case MENU_ENUM_LABEL_RDB_ENTRY_FRANCHISE:
7451       case MENU_ENUM_LABEL_RDB_ENTRY_ENHANCEMENT_HW:
7452       case MENU_ENUM_LABEL_RDB_ENTRY_ESRB_RATING:
7453       case MENU_ENUM_LABEL_RDB_ENTRY_BBFC_RATING:
7454       case MENU_ENUM_LABEL_RDB_ENTRY_ELSPA_RATING:
7455       case MENU_ENUM_LABEL_RDB_ENTRY_PEGI_RATING:
7456       case MENU_ENUM_LABEL_RDB_ENTRY_CERO_RATING:
7457       case MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_RATING:
7458       case MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_ISSUE:
7459       case MENU_ENUM_LABEL_RDB_ENTRY_FAMITSU_MAGAZINE_RATING:
7460       case MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_MONTH:
7461       case MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_YEAR:
7462       case MENU_ENUM_LABEL_RDB_ENTRY_MAX_USERS:
7463          break;
7464       default:
7465          return -1;
7466    }
7467 
7468    return 0;
7469 }
7470 
menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t * cbs,const char * label)7471 static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
7472       const char *label)
7473 {
7474    if (cbs->enum_idx != MSG_UNKNOWN)
7475    {
7476       const char     *str = msg_hash_to_str(cbs->enum_idx);
7477 
7478       if (str)
7479       {
7480          if (is_rdb_entry(cbs->enum_idx) == 0)
7481          {
7482             BIND_ACTION_OK(cbs, action_ok_rdb_entry_submenu);
7483             return 0;
7484          }
7485 
7486          if (string_ends_with_size(str, "input_binds_list",
7487                   strlen(str),
7488                   STRLEN_CONST("input_binds_list")))
7489          {
7490             unsigned i;
7491 
7492             for (i = 0; i < MAX_USERS; i++)
7493             {
7494                unsigned first_char = atoi(&str[0]);
7495 
7496                if (first_char != ((i+1)))
7497                   continue;
7498 
7499                BIND_ACTION_OK(cbs, action_ok_push_user_binds_list);
7500                return 0;
7501             }
7502          }
7503       }
7504    }
7505 
7506    if (menu_setting_get_browser_selection_type(cbs->setting) == ST_DIR)
7507    {
7508       BIND_ACTION_OK(cbs, action_ok_push_filebrowser_list_dir_select);
7509       return 0;
7510    }
7511 
7512    if (cbs->enum_idx != MSG_UNKNOWN)
7513    {
7514       unsigned i;
7515       typedef struct temp_ok_list
7516       {
7517          enum msg_hash_enums type;
7518          int (*cb)(const char *path, const char *label, unsigned type,
7519                size_t idx, size_t entry_idx);
7520       } temp_ok_list_t;
7521 
7522       temp_ok_list_t ok_list[] = {
7523          {MENU_ENUM_LABEL_QUICK_MENU_START_RECORDING,          action_ok_start_recording},
7524          {MENU_ENUM_LABEL_QUICK_MENU_START_STREAMING,          action_ok_start_streaming},
7525          {MENU_ENUM_LABEL_QUICK_MENU_STOP_RECORDING,           action_ok_stop_recording},
7526          {MENU_ENUM_LABEL_QUICK_MENU_STOP_STREAMING,           action_ok_stop_streaming},
7527 #ifdef HAVE_CHEATS
7528          {MENU_ENUM_LABEL_CHEAT_START_OR_CONT,                 action_ok_cheat_start_or_cont},
7529          {MENU_ENUM_LABEL_CHEAT_ADD_NEW_TOP,                   action_ok_cheat_add_top},
7530          {MENU_ENUM_LABEL_CHEAT_RELOAD_CHEATS,                 action_ok_cheat_reload_cheats},
7531          {MENU_ENUM_LABEL_CHEAT_ADD_NEW_BOTTOM,                action_ok_cheat_add_bottom},
7532          {MENU_ENUM_LABEL_CHEAT_DELETE_ALL,                    action_ok_cheat_delete_all},
7533          {MENU_ENUM_LABEL_CHEAT_ADD_NEW_AFTER,                 action_ok_cheat_add_new_after},
7534          {MENU_ENUM_LABEL_CHEAT_ADD_NEW_BEFORE,                action_ok_cheat_add_new_before},
7535          {MENU_ENUM_LABEL_CHEAT_COPY_AFTER,                    action_ok_cheat_copy_after},
7536          {MENU_ENUM_LABEL_CHEAT_COPY_BEFORE,                   action_ok_cheat_copy_before},
7537          {MENU_ENUM_LABEL_CHEAT_DELETE,                        action_ok_cheat_delete},
7538 #endif
7539          {MENU_ENUM_LABEL_RUN_MUSIC,                           action_ok_audio_run},
7540 #ifdef HAVE_AUDIOMIXER
7541          {MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION,         action_ok_audio_add_to_mixer_and_collection},
7542          {MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY,action_ok_audio_add_to_mixer_and_collection_and_play},
7543          {MENU_ENUM_LABEL_ADD_TO_MIXER,                        action_ok_audio_add_to_mixer},
7544          {MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY,               action_ok_audio_add_to_mixer_and_play},
7545 #endif
7546 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
7547          {MENU_ENUM_LABEL_VIDEO_SHADER_PASS,                   action_ok_shader_pass},
7548          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET,                 action_ok_shader_preset},
7549          {MENU_ENUM_LABEL_VIDEO_SHADER_PARAMETERS,             action_ok_shader_parameters},
7550          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_PARAMETERS,      action_ok_shader_parameters},
7551          {MENU_ENUM_LABEL_SHADER_APPLY_CHANGES,                action_ok_shader_apply_changes},
7552          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE,          action_ok_shader_preset_remove},
7553          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE,            action_ok_shader_preset_save},
7554          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS,         action_ok_shader_preset_save_as},
7555          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GLOBAL,     action_ok_shader_preset_save_global},
7556          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_CORE,       action_ok_shader_preset_save_core},
7557          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_PARENT,     action_ok_shader_preset_save_parent},
7558          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GAME,       action_ok_shader_preset_save_game},
7559          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GLOBAL,   action_ok_shader_preset_remove_global},
7560          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_CORE,     action_ok_shader_preset_remove_core},
7561          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_PARENT,   action_ok_shader_preset_remove_parent},
7562          {MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GAME,     action_ok_shader_preset_remove_game},
7563          {MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS,                 action_ok_update_shaders_glsl},
7564          {MENU_ENUM_LABEL_UPDATE_CG_SHADERS,                   action_ok_update_shaders_cg},
7565          {MENU_ENUM_LABEL_UPDATE_SLANG_SHADERS,                action_ok_update_shaders_slang},
7566 #endif
7567 #ifdef HAVE_AUDIOMIXER
7568          {MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS,                action_ok_push_audio_mixer_settings_list},
7569 #endif
7570 #ifdef HAVE_NETWORKING
7571          {MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT,               action_ok_core_content_list},
7572          {MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS,          action_ok_core_content_dirs_list},
7573          {MENU_ENUM_LABEL_CORE_UPDATER_LIST,                   action_ok_core_updater_list},
7574          {MENU_ENUM_LABEL_UPDATE_INSTALLED_CORES,              action_ok_update_installed_cores},
7575 #if defined(ANDROID)
7576          {MENU_ENUM_LABEL_SWITCH_INSTALLED_CORES_PFD,          action_ok_switch_installed_cores_pfd},
7577 #endif
7578          {MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST,             action_ok_thumbnails_updater_list},
7579          {MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST,          action_ok_pl_thumbnails_updater_list},
7580          {MENU_ENUM_LABEL_DOWNLOAD_PL_ENTRY_THUMBNAILS,        action_ok_pl_entry_content_thumbnails},
7581          {MENU_ENUM_LABEL_UPDATE_LAKKA,                        action_ok_lakka_list},
7582          {MENU_ENUM_LABEL_NETPLAY_REFRESH_ROOMS,               action_ok_push_netplay_refresh_rooms},
7583 #endif
7584 #ifdef HAVE_VIDEO_LAYOUT
7585          {MENU_ENUM_LABEL_ONSCREEN_VIDEO_LAYOUT_SETTINGS,      action_ok_onscreen_video_layout_list},
7586 #endif
7587 #ifdef HAVE_LAKKA_SWITCH
7588          {MENU_ENUM_LABEL_SWITCH_GPU_PROFILE,                  action_ok_push_default},
7589 #endif
7590 #if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX)
7591          {MENU_ENUM_LABEL_SWITCH_CPU_PROFILE,                  action_ok_push_default},
7592 #endif
7593          {MENU_ENUM_LABEL_MENU_WALLPAPER,                      action_ok_menu_wallpaper},
7594          {MENU_ENUM_LABEL_VIDEO_FONT_PATH,                     action_ok_video_font},
7595          {MENU_ENUM_LABEL_GOTO_FAVORITES,                      action_ok_goto_favorites},
7596          {MENU_ENUM_LABEL_GOTO_MUSIC,                          action_ok_goto_music},
7597          {MENU_ENUM_LABEL_GOTO_IMAGES,                         action_ok_goto_images},
7598          {MENU_ENUM_LABEL_GOTO_VIDEO,                          action_ok_goto_video},
7599          {MENU_ENUM_LABEL_GOTO_EXPLORE,                        action_ok_goto_explore},
7600          {MENU_ENUM_LABEL_BROWSE_START,                        action_ok_browse_url_start},
7601          {MENU_ENUM_LABEL_FILE_BROWSER_CORE,                   action_ok_load_core},
7602          {MENU_ENUM_LABEL_FILE_BROWSER_CORE_SELECT_FROM_COLLECTION, action_ok_core_deferred_set},
7603          {MENU_ENUM_LABEL_FILE_BROWSER_CORE_SELECT_FROM_COLLECTION_CURRENT_CORE,action_ok_core_deferred_set},
7604          {MENU_ENUM_LABEL_START_CORE,                          action_ok_start_core},
7605          {MENU_ENUM_LABEL_START_NET_RETROPAD,                  action_ok_start_net_retropad_core},
7606          {MENU_ENUM_LABEL_START_GONG,                          action_ok_start_gong_core},
7607          {MENU_ENUM_LABEL_START_VIDEO_PROCESSOR,               action_ok_start_video_processor_core},
7608          {MENU_ENUM_LABEL_OPEN_ARCHIVE_DETECT_CORE,            action_ok_open_archive_detect_core},
7609          {MENU_ENUM_LABEL_OPEN_ARCHIVE,                        action_ok_open_archive},
7610          {MENU_ENUM_LABEL_LOAD_ARCHIVE_DETECT_CORE,            action_ok_load_archive_detect_core},
7611          {MENU_ENUM_LABEL_LOAD_ARCHIVE,                        action_ok_load_archive},
7612          {MENU_ENUM_LABEL_CUSTOM_BIND_ALL,                     action_ok_lookup_setting},
7613          {MENU_ENUM_LABEL_SAVE_STATE,                          action_ok_save_state},
7614          {MENU_ENUM_LABEL_LOAD_STATE,                          action_ok_load_state},
7615          {MENU_ENUM_LABEL_UNDO_LOAD_STATE,                     action_ok_undo_load_state},
7616          {MENU_ENUM_LABEL_UNDO_SAVE_STATE,                     action_ok_undo_save_state},
7617          {MENU_ENUM_LABEL_RESUME_CONTENT,                      action_ok_resume_content},
7618          {MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST,           action_ok_add_to_favorites_playlist},
7619          {MENU_ENUM_LABEL_SET_CORE_ASSOCIATION,                action_ok_set_core_association},
7620          {MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION,              action_ok_reset_core_association},
7621          {MENU_ENUM_LABEL_ADD_TO_FAVORITES,                    action_ok_add_to_favorites},
7622          {MENU_ENUM_LABEL_RESTART_CONTENT,                     action_ok_restart_content},
7623          {MENU_ENUM_LABEL_TAKE_SCREENSHOT,                     action_ok_screenshot},
7624          {MENU_ENUM_LABEL_RENAME_ENTRY,                        action_ok_rename_entry},
7625          {MENU_ENUM_LABEL_DELETE_ENTRY,                        action_ok_delete_entry},
7626          {MENU_ENUM_LABEL_MENU_DISABLE_KIOSK_MODE,             action_ok_disable_kiosk_mode},
7627          {MENU_ENUM_LABEL_XMB_MAIN_MENU_ENABLE_SETTINGS,       action_ok_enable_settings},
7628          {MENU_ENUM_LABEL_SHOW_WIMP,                           action_ok_show_wimp},
7629          {MENU_ENUM_LABEL_QUIT_RETROARCH,                      action_ok_quit},
7630          {MENU_ENUM_LABEL_CLOSE_CONTENT,                       action_ok_close_content},
7631          {MENU_ENUM_LABEL_SAVE_NEW_CONFIG,                     action_ok_save_new_config},
7632          {MENU_ENUM_LABEL_HELP,                                action_ok_help},
7633          {MENU_ENUM_LABEL_HELP_CONTROLS,                       action_ok_help_controls},
7634          {MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE,                 action_ok_help_what_is_a_core},
7635          {MENU_ENUM_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD,         action_ok_help_change_virtual_gamepad},
7636          {MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING,    action_ok_help_audio_video_troubleshooting},
7637          {MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO,                action_ok_help_send_debug_info},
7638          {MENU_ENUM_LABEL_HELP_SCANNING_CONTENT,               action_ok_help_scanning_content},
7639          {MENU_ENUM_LABEL_HELP_LOADING_CONTENT,                action_ok_help_load_content},
7640 #ifdef HAVE_CHEATS
7641          {MENU_ENUM_LABEL_CHEAT_FILE_LOAD,                     action_ok_cheat_file},
7642          {MENU_ENUM_LABEL_CHEAT_FILE_LOAD_APPEND,              action_ok_cheat_file_append},
7643          {MENU_ENUM_LABEL_UPDATE_CHEATS,                       action_ok_update_cheats},
7644          {MENU_ENUM_LABEL_CHEAT_ADD_MATCHES,                   cheat_manager_add_matches},
7645 #endif
7646          {MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN,                    action_ok_audio_dsp_plugin},
7647          {MENU_ENUM_LABEL_VIDEO_FILTER,                        action_ok_video_filter},
7648          {MENU_ENUM_LABEL_OVERLAY_PRESET,                      action_ok_overlay_preset},
7649 #if defined(HAVE_VIDEO_LAYOUT)
7650          {MENU_ENUM_LABEL_VIDEO_LAYOUT_PATH,                   action_ok_video_layout},
7651 #endif
7652          {MENU_ENUM_LABEL_REMAP_FILE_LOAD,                     action_ok_remap_file},
7653          {MENU_ENUM_LABEL_RECORD_CONFIG,                       action_ok_record_configfile},
7654          {MENU_ENUM_LABEL_STREAM_CONFIG,                       action_ok_stream_configfile},
7655 #ifdef HAVE_RGUI
7656          {MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET,              action_ok_rgui_menu_theme_preset},
7657 #endif
7658          {MENU_ENUM_LABEL_ACCOUNTS_LIST,                       action_ok_push_accounts_list},
7659          {MENU_ENUM_LABEL_ACCESSIBILITY_SETTINGS,              action_ok_push_accessibility_settings_list},
7660          {MENU_ENUM_LABEL_AI_SERVICE_SETTINGS,                 action_ok_push_ai_service_settings_list},
7661          {MENU_ENUM_LABEL_INPUT_SETTINGS,                      action_ok_push_input_settings_list},
7662          {MENU_ENUM_LABEL_INPUT_MENU_SETTINGS,                 action_ok_push_input_menu_settings_list},
7663          {MENU_ENUM_LABEL_INPUT_TURBO_FIRE_SETTINGS,           action_ok_push_input_turbo_fire_settings_list},
7664          {MENU_ENUM_LABEL_INPUT_HAPTIC_FEEDBACK_SETTINGS,      action_ok_push_input_haptic_feedback_settings_list},
7665          {MENU_ENUM_LABEL_DRIVER_SETTINGS,                     action_ok_push_driver_settings_list},
7666          {MENU_ENUM_LABEL_VIDEO_SETTINGS,                      action_ok_push_video_settings_list},
7667          {MENU_ENUM_LABEL_VIDEO_SYNCHRONIZATION_SETTINGS,      action_ok_push_video_synchronization_settings_list},
7668          {MENU_ENUM_LABEL_VIDEO_FULLSCREEN_MODE_SETTINGS,      action_ok_push_video_fullscreen_mode_settings_list},
7669          {MENU_ENUM_LABEL_VIDEO_WINDOWED_MODE_SETTINGS,        action_ok_push_video_windowed_mode_settings_list},
7670          {MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS,              action_ok_push_video_scaling_settings_list},
7671          {MENU_ENUM_LABEL_VIDEO_OUTPUT_SETTINGS,               action_ok_push_video_output_settings_list},
7672          {MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS,              action_ok_push_crt_switchres_settings_list},
7673          {MENU_ENUM_LABEL_AUDIO_SETTINGS,                      action_ok_push_audio_settings_list},
7674          {MENU_ENUM_LABEL_AUDIO_SYNCHRONIZATION_SETTINGS,      action_ok_push_audio_synchronization_settings_list},
7675          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR,             action_ok_push_manual_content_scan_dir_select},
7676          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME,     action_ok_manual_content_scan_system_name},
7677          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME,       action_ok_manual_content_scan_core_name},
7678          {MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES,             action_ok_video_shader_num_passes_dropdown_box_list},
7679          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DAT_FILE,        action_ok_manual_content_scan_dat_file},
7680          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START,           action_ok_manual_content_scan_start},
7681          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE, action_ok_playlist_label_display_mode},
7682          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE,action_ok_playlist_right_thumbnail_mode},
7683          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE,action_ok_playlist_left_thumbnail_mode},
7684          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE,          action_ok_playlist_sort_mode},
7685          {MENU_ENUM_LABEL_UPDATE_ASSETS,                       action_ok_update_assets},
7686          {MENU_ENUM_LABEL_UPDATE_CORE_INFO_FILES,              action_ok_update_core_info_files},
7687          {MENU_ENUM_LABEL_UPDATE_OVERLAYS,                     action_ok_update_overlays},
7688          {MENU_ENUM_LABEL_UPDATE_DATABASES,                    action_ok_update_databases},
7689          {MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES,          action_ok_update_autoconfig_profiles},
7690          {MENU_ENUM_LABEL_NETPLAY_ENABLE_HOST,                 action_ok_netplay_enable_host},
7691          {MENU_ENUM_LABEL_NETPLAY_ENABLE_CLIENT,               action_ok_netplay_enable_client},
7692          {MENU_ENUM_LABEL_NETPLAY_DISCONNECT,                  action_ok_netplay_disconnect},
7693          {MENU_ENUM_LABEL_CORE_DELETE,                         action_ok_core_delete},
7694          {MENU_ENUM_LABEL_CORE_CREATE_BACKUP,                  action_ok_core_create_backup},
7695          {MENU_ENUM_LABEL_DELETE_PLAYLIST,                     action_ok_delete_playlist},
7696          {MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,              action_ok_push_default},
7697          {MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE,                   action_ok_cheevos_toggle_hardcore_mode},
7698          {MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_CANCEL,            action_ok_close_submenu},
7699          {MENU_ENUM_LABEL_ACHIEVEMENT_RESUME,                  action_ok_cheevos_toggle_hardcore_mode},
7700          {MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL,           action_ok_close_submenu },
7701          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST,            action_ok_push_manual_content_scan_list},
7702          {MENU_ENUM_LABEL_AUDIO_OUTPUT_SETTINGS,               action_ok_push_audio_output_settings_list},
7703          {MENU_ENUM_LABEL_AUDIO_RESAMPLER_SETTINGS,            action_ok_push_audio_resampler_settings_list},
7704          {MENU_ENUM_LABEL_LATENCY_SETTINGS,                    action_ok_push_latency_settings_list},
7705          {MENU_ENUM_LABEL_CORE_SETTINGS,                       action_ok_push_core_settings_list},
7706          {MENU_ENUM_LABEL_CORE_INFORMATION,                    action_ok_push_core_information_list},
7707          {MENU_ENUM_LABEL_CORE_MANAGER_ENTRY,                  action_ok_push_core_information_list},
7708          {MENU_ENUM_LABEL_CORE_RESTORE_BACKUP_LIST,            action_ok_push_core_restore_backup_list},
7709          {MENU_ENUM_LABEL_CORE_DELETE_BACKUP_LIST,             action_ok_push_core_delete_backup_list},
7710          {MENU_ENUM_LABEL_CONFIGURATION_SETTINGS,              action_ok_push_configuration_settings_list},
7711          {MENU_ENUM_LABEL_PLAYLIST_SETTINGS,                   action_ok_push_playlist_settings_list},
7712          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST,               action_ok_push_playlist_manager_list},
7713          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS,           action_ok_push_playlist_manager_settings},
7714          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_RESET_CORES,        action_ok_playlist_reset_cores},
7715          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_CLEAN_PLAYLIST,     action_ok_playlist_clean},
7716          {MENU_ENUM_LABEL_RECORDING_SETTINGS,                  action_ok_push_recording_settings_list},
7717          {MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS,                  action_ok_push_input_hotkey_binds_list},
7718          {MENU_ENUM_LABEL_ACCOUNTS_RETRO_ACHIEVEMENTS,         action_ok_push_accounts_cheevos_list},
7719          {MENU_ENUM_LABEL_ACCOUNTS_YOUTUBE,                    action_ok_push_accounts_youtube_list},
7720          {MENU_ENUM_LABEL_ACCOUNTS_TWITCH,                     action_ok_push_accounts_twitch_list},
7721          {MENU_ENUM_LABEL_ACCOUNTS_FACEBOOK,                   action_ok_push_accounts_facebook_list},
7722          {MENU_ENUM_LABEL_DUMP_DISC,                           action_ok_push_dump_disc_list},
7723          {MENU_ENUM_LABEL_LOAD_DISC,                           action_ok_push_load_disc_list},
7724          {MENU_ENUM_LABEL_SHADER_OPTIONS,                      action_ok_push_default},
7725          {MENU_ENUM_LABEL_CORE_OPTIONS,                        action_ok_push_default},
7726          {MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_LIST,           action_ok_push_core_option_override_list},
7727          {MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS,                  action_ok_push_default},
7728          {MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS,        action_ok_push_default},
7729          {MENU_ENUM_LABEL_DISC_INFORMATION,                    action_ok_push_default},
7730          {MENU_ENUM_LABEL_SYSTEM_INFORMATION,                  action_ok_push_default},
7731          {MENU_ENUM_LABEL_NETWORK_INFORMATION,                 action_ok_push_default},
7732          {MENU_ENUM_LABEL_ACHIEVEMENT_LIST,                    action_ok_push_default},
7733          {MENU_ENUM_LABEL_ACHIEVEMENT_LIST_HARDCORE,           action_ok_push_default},
7734          {MENU_ENUM_LABEL_DISK_OPTIONS,                        action_ok_push_default},
7735          {MENU_ENUM_LABEL_SETTINGS,                            action_ok_push_default},
7736          {MENU_ENUM_LABEL_FRONTEND_COUNTERS,                   action_ok_push_default},
7737          {MENU_ENUM_LABEL_CORE_COUNTERS,                       action_ok_push_default},
7738          {MENU_ENUM_LABEL_MANAGEMENT,                          action_ok_push_default},
7739          {MENU_ENUM_LABEL_ONLINE_UPDATER,                      action_ok_push_default},
7740          {MENU_ENUM_LABEL_NETPLAY,                             action_ok_push_default},
7741          {MENU_ENUM_LABEL_LOAD_CONTENT_LIST,                   action_ok_push_default},
7742          {MENU_ENUM_LABEL_ADD_CONTENT_LIST,                    action_ok_push_default},
7743          {MENU_ENUM_LABEL_CONFIGURATIONS_LIST,                 action_ok_push_default},
7744          {MENU_ENUM_LABEL_HELP_LIST,                           action_ok_push_default},
7745          {MENU_ENUM_LABEL_INFORMATION_LIST,                    action_ok_push_default},
7746          {MENU_ENUM_LABEL_INFORMATION,                         action_ok_push_default},
7747          {MENU_ENUM_LABEL_CONTENT_SETTINGS,                    action_ok_push_default},
7748          {MENU_ENUM_LABEL_LOAD_CONTENT_SPECIAL,                action_ok_push_filebrowser_list_file_select},
7749          {MENU_ENUM_LABEL_SCAN_DIRECTORY,                      action_ok_scan_directory_list},
7750          {MENU_ENUM_LABEL_SCAN_FILE,                           action_ok_push_scan_file},
7751          {MENU_ENUM_LABEL_FAVORITES,                           action_ok_push_content_list},
7752          {MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR,      action_ok_push_random_dir},
7753          {MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST,    action_ok_push_downloads_dir},
7754          {MENU_ENUM_LABEL_DETECT_CORE_LIST_OK,                 action_ok_file_load_detect_core},
7755          {MENU_ENUM_LABEL_DETECT_CORE_LIST_OK_CURRENT_CORE,    action_ok_file_load_current_core},
7756          {MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY,                action_ok_push_generic_list},
7757          {MENU_ENUM_LABEL_CURSOR_MANAGER_LIST,                 action_ok_push_generic_list},
7758          {MENU_ENUM_LABEL_DATABASE_MANAGER_LIST,               action_ok_push_generic_list},
7759 #ifdef HAVE_CHEATS
7760          {MENU_ENUM_LABEL_CHEAT_APPLY_CHANGES,                 action_ok_cheat_apply_changes},
7761          {MENU_ENUM_LABEL_CHEAT_FILE_SAVE_AS,                  action_ok_cheat_file_save_as},
7762 #endif
7763          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_CORE,                action_ok_remap_file_save_core},
7764          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR,         action_ok_remap_file_save_content_dir},
7765          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_GAME,                action_ok_remap_file_save_game},
7766          {MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CORE,              action_ok_remap_file_remove_core},
7767          {MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CONTENT_DIR,       action_ok_remap_file_remove_content_dir},
7768          {MENU_ENUM_LABEL_REMAP_FILE_REMOVE_GAME,              action_ok_remap_file_remove_game},
7769          {MENU_ENUM_LABEL_PLAYLISTS_TAB,                       action_ok_content_collection_list},
7770          {MENU_ENUM_LABEL_BROWSE_URL_LIST,                     action_ok_browse_url_list},
7771          {MENU_ENUM_LABEL_CORE_LIST,                           action_ok_core_list},
7772          {MENU_ENUM_LABEL_SIDELOAD_CORE_LIST,                  action_ok_sideload_core_list},
7773          {MENU_ENUM_LABEL_DISK_IMAGE_APPEND,                   action_ok_disk_image_append_list},
7774          {MENU_ENUM_LABEL_SUBSYSTEM_ADD,                       action_ok_subsystem_add_list},
7775          {MENU_ENUM_LABEL_SUBSYSTEM_LOAD,                      action_ok_subsystem_add_load},
7776          {MENU_ENUM_LABEL_CONFIGURATIONS,                      action_ok_configurations_list},
7777          {MENU_ENUM_LABEL_SAVING_SETTINGS,                     action_ok_saving_list},
7778          {MENU_ENUM_LABEL_LOGGING_SETTINGS,                    action_ok_logging_list},
7779          {MENU_ENUM_LABEL_FRAME_THROTTLE_SETTINGS,             action_ok_frame_throttle_list},
7780          {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS,         action_ok_frame_time_counter_list},
7781          {MENU_ENUM_LABEL_REWIND_SETTINGS,                     action_ok_rewind_list},
7782          {MENU_ENUM_LABEL_ONSCREEN_DISPLAY_SETTINGS,           action_ok_onscreen_display_list},
7783          {MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS,     action_ok_onscreen_notifications_list},
7784          {MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS, action_ok_onscreen_notifications_views_list},
7785          {MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS,           action_ok_onscreen_overlay_list},
7786          {MENU_ENUM_LABEL_MENU_SETTINGS,                       action_ok_menu_list},
7787          {MENU_ENUM_LABEL_MENU_VIEWS_SETTINGS,                 action_ok_menu_views_list},
7788          {MENU_ENUM_LABEL_QUICK_MENU_OVERRIDE_OPTIONS,         action_ok_quick_menu_override_options},
7789          {MENU_ENUM_LABEL_SETTINGS_VIEWS_SETTINGS,             action_ok_settings_views_list},
7790          {MENU_ENUM_LABEL_QUICK_MENU_VIEWS_SETTINGS,           action_ok_quick_menu_views_list},
7791          {MENU_ENUM_LABEL_USER_INTERFACE_SETTINGS,             action_ok_user_interface_list},
7792          {MENU_ENUM_LABEL_POWER_MANAGEMENT_SETTINGS,           action_ok_power_management_list},
7793          {MENU_ENUM_LABEL_CPU_PERFPOWER,                       action_ok_cpu_perfpower_list},
7794          {MENU_ENUM_LABEL_CPU_POLICY_ENTRY,                    action_ok_cpu_policy_entry},
7795          {MENU_ENUM_LABEL_MENU_SOUNDS,                         action_ok_menu_sounds_list},
7796          {MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS,          action_ok_menu_file_browser_list},
7797          {MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS,   action_ok_open_uwp_permission_settings},
7798          {MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER,            action_ok_open_picker},
7799          {MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS,         action_ok_retro_achievements_list},
7800          {MENU_ENUM_LABEL_UPDATER_SETTINGS,                    action_ok_updater_list},
7801          {MENU_ENUM_LABEL_BLUETOOTH_SETTINGS,                  action_ok_bluetooth_list},
7802 #ifdef HAVE_NETWORKING
7803          {MENU_ENUM_LABEL_WIFI_SETTINGS,                       action_ok_wifi_list},
7804          {MENU_ENUM_LABEL_WIFI_NETWORK_SCAN,                   action_ok_wifi_networks_list},
7805          {MENU_ENUM_LABEL_WIFI_DISCONNECT,                     action_ok_wifi_disconnect},
7806 #endif
7807          {MENU_ENUM_LABEL_NETWORK_HOSTING_SETTINGS,            action_ok_network_hosting_list},
7808          {MENU_ENUM_LABEL_SUBSYSTEM_SETTINGS,                  action_ok_subsystem_list},
7809          {MENU_ENUM_LABEL_NETWORK_SETTINGS,                    action_ok_network_list},
7810          {MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM,                action_ok_netplay_connect_room},
7811          {MENU_ENUM_LABEL_LAKKA_SERVICES,                      action_ok_lakka_services},
7812          {MENU_ENUM_LABEL_NETPLAY_SETTINGS,                    action_ok_netplay_sublist},
7813          {MENU_ENUM_LABEL_USER_SETTINGS,                       action_ok_user_list},
7814          {MENU_ENUM_LABEL_DIRECTORY_SETTINGS,                  action_ok_directory_list},
7815          {MENU_ENUM_LABEL_PRIVACY_SETTINGS,                    action_ok_privacy_list},
7816          {MENU_ENUM_LABEL_MIDI_SETTINGS,                       action_ok_midi_list},
7817          {MENU_ENUM_LABEL_SCREEN_RESOLUTION,                   action_ok_video_resolution},
7818          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE,       action_ok_playlist_default_core},
7819          {MENU_ENUM_LABEL_CORE_MANAGER_LIST,                   action_ok_push_core_manager_list},
7820          {MENU_ENUM_LABEL_EXPLORE_TAB,                         action_ok_push_default},
7821       };
7822 
7823       for (i = 0; i < ARRAY_SIZE(ok_list); i++)
7824       {
7825          if (cbs->enum_idx == ok_list[i].type)
7826          {
7827             BIND_ACTION_OK(cbs, ok_list[i].cb);
7828             return 0;
7829          }
7830       }
7831    }
7832    else
7833    {
7834       unsigned i;
7835       typedef struct temp_ok_list
7836       {
7837          enum msg_hash_enums type;
7838          int (*cb)(const char *path, const char *label, unsigned type,
7839                size_t idx, size_t entry_idx);
7840       } temp_ok_list_t;
7841 
7842       temp_ok_list_t ok_list[] = {
7843          {MENU_ENUM_LABEL_OPEN_ARCHIVE_DETECT_CORE,            action_ok_open_archive_detect_core},
7844          {MENU_ENUM_LABEL_OPEN_ARCHIVE,                        action_ok_open_archive},
7845          {MENU_ENUM_LABEL_LOAD_ARCHIVE_DETECT_CORE,            action_ok_load_archive_detect_core},
7846          {MENU_ENUM_LABEL_LOAD_ARCHIVE,                        action_ok_load_archive},
7847          {MENU_ENUM_LABEL_CHEAT_FILE_LOAD,                     action_ok_cheat_file},
7848          {MENU_ENUM_LABEL_CHEAT_FILE_LOAD_APPEND,              action_ok_cheat_file_append},
7849          {MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN,                    action_ok_audio_dsp_plugin},
7850          {MENU_ENUM_LABEL_VIDEO_FILTER,                        action_ok_video_filter},
7851          {MENU_ENUM_LABEL_OVERLAY_PRESET,                      action_ok_overlay_preset},
7852 #if defined(HAVE_VIDEO_LAYOUT)
7853          {MENU_ENUM_LABEL_VIDEO_LAYOUT_PATH,                   action_ok_video_layout},
7854 #endif
7855          {MENU_ENUM_LABEL_REMAP_FILE_LOAD,                     action_ok_remap_file},
7856          {MENU_ENUM_LABEL_RECORD_CONFIG,                       action_ok_record_configfile},
7857          {MENU_ENUM_LABEL_STREAM_CONFIG,                       action_ok_stream_configfile},
7858          {MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET,              action_ok_rgui_menu_theme_preset},
7859          {MENU_ENUM_LABEL_ACCOUNTS_RETRO_ACHIEVEMENTS,         action_ok_push_accounts_cheevos_list},
7860          {MENU_ENUM_LABEL_FAVORITES,                           action_ok_push_content_list},
7861          {MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST,    action_ok_push_downloads_dir},
7862          {MENU_ENUM_LABEL_DETECT_CORE_LIST_OK,                 action_ok_file_load_detect_core},
7863 #ifdef HAVE_CHEATS
7864          {MENU_ENUM_LABEL_CHEAT_APPLY_CHANGES,                 action_ok_cheat_apply_changes},
7865          {MENU_ENUM_LABEL_CHEAT_FILE_SAVE_AS,                  action_ok_cheat_file_save_as},
7866 #endif
7867          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_CORE,                action_ok_remap_file_save_core},
7868          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR,         action_ok_remap_file_save_content_dir},
7869          {MENU_ENUM_LABEL_REMAP_FILE_SAVE_GAME,                action_ok_remap_file_save_game},
7870          {MENU_ENUM_LABEL_DISK_IMAGE_APPEND,                   action_ok_disk_image_append_list},
7871          {MENU_ENUM_LABEL_SUBSYSTEM_ADD,                       action_ok_subsystem_add_list},
7872          {MENU_ENUM_LABEL_SCREEN_RESOLUTION,                   action_ok_video_resolution},
7873          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE,       action_ok_playlist_default_core},
7874          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE, action_ok_playlist_label_display_mode},
7875          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE, action_ok_playlist_right_thumbnail_mode},
7876          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE, action_ok_playlist_left_thumbnail_mode},
7877          {MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE,          action_ok_playlist_sort_mode},
7878          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME, action_ok_manual_content_scan_system_name},
7879          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME, action_ok_manual_content_scan_core_name},
7880          {MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DAT_FILE, action_ok_manual_content_scan_dat_file},
7881       };
7882 
7883       for (i = 0; i < ARRAY_SIZE(ok_list); i++)
7884       {
7885          if (string_is_equal(label, msg_hash_to_str(ok_list[i].type)))
7886          {
7887             BIND_ACTION_OK(cbs, ok_list[i].cb);
7888             return 0;
7889          }
7890       }
7891    }
7892 
7893    return -1;
7894 }
7895 
menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t * cbs,const char * label,const char * menu_label,unsigned type)7896 static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
7897       const char *label, const char *menu_label, unsigned type)
7898 {
7899    if (type == MENU_SET_CDROM_LIST)
7900    {
7901       BIND_ACTION_OK(cbs, action_ok_dump_cdrom);
7902    }
7903    else if (type == MENU_SET_CDROM_INFO)
7904    {
7905       BIND_ACTION_OK(cbs, action_ok_cdrom_info_list);
7906    }
7907    else if (type == MENU_SET_LOAD_CDROM_LIST)
7908    {
7909       BIND_ACTION_OK(cbs, action_ok_load_cdrom);
7910    }
7911    else if (type == MENU_SETTINGS_CUSTOM_BIND_KEYBOARD ||
7912          type == MENU_SETTINGS_CUSTOM_BIND)
7913    {
7914       BIND_ACTION_OK(cbs, action_ok_lookup_setting);
7915    }
7916 #ifdef HAVE_AUDIOMIXER
7917    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN
7918       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_END)
7919    {
7920       BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play);
7921    }
7922    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN
7923       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_END)
7924    {
7925       BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play_looped);
7926    }
7927    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN
7928       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_END)
7929    {
7930       BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play_sequential);
7931    }
7932    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN
7933       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_END)
7934    {
7935       BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_remove);
7936    }
7937    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_BEGIN
7938       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_END)
7939    {
7940       BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_stop);
7941    }
7942    else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_BEGIN
7943       && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_END)
7944    {
7945       BIND_ACTION_OK(cbs, action_ok_mixer_stream_actions);
7946    }
7947 #endif
7948    else if (type >= MENU_SETTINGS_REMAPPING_PORT_BEGIN
7949          && type <= MENU_SETTINGS_REMAPPING_PORT_END)
7950    {
7951       BIND_ACTION_OK(cbs, action_ok_remappings_port_list);
7952    }
7953    else if (type >= MENU_SETTINGS_SHADER_PARAMETER_0
7954          && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST)
7955    {
7956       BIND_ACTION_OK(cbs, action_ok_shader_parameter_dropdown_box_list);
7957    }
7958    else if (type >= MENU_SETTINGS_SHADER_PRESET_PARAMETER_0
7959          && type <= MENU_SETTINGS_SHADER_PRESET_PARAMETER_LAST)
7960    {
7961       BIND_ACTION_OK(cbs, action_ok_shader_preset_parameter_dropdown_box_list);
7962    }
7963    else if (type >= MENU_SETTINGS_CHEAT_BEGIN
7964          && type <= MENU_SETTINGS_CHEAT_END)
7965    {
7966       BIND_ACTION_OK(cbs, action_ok_cheat);
7967    }
7968    else if ((type >= MENU_SETTINGS_CORE_OPTION_START) &&
7969             (type < MENU_SETTINGS_CHEEVOS_START))
7970    {
7971       BIND_ACTION_OK(cbs, action_ok_core_option_dropdown_list);
7972    }
7973    else if ((type >= MENU_SETTINGS_INPUT_DESC_BEGIN) &&
7974             (type <= MENU_SETTINGS_INPUT_DESC_END))
7975    {
7976       BIND_ACTION_OK(cbs, action_ok_input_description_dropdown_box_list);
7977    }
7978    else if ((type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) &&
7979             (type <= MENU_SETTINGS_INPUT_DESC_KBD_END))
7980    {
7981       BIND_ACTION_OK(cbs, action_ok_input_description_kbd_dropdown_box_list);
7982    }
7983    else
7984    {
7985       switch (type)
7986       {
7987          case MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM:
7988             BIND_ACTION_OK(cbs, action_ok_push_dropdown_setting_core_options_item);
7989             break;
7990          case MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM_SPECIAL:
7991             BIND_ACTION_OK(cbs, action_ok_push_dropdown_setting_core_options_item_special);
7992             break;
7993          case MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM:
7994          case MENU_SETTING_DROPDOWN_SETTING_INT_ITEM:
7995          case MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM:
7996          case MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM:
7997          case MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM_SPECIAL:
7998          case MENU_SETTING_DROPDOWN_SETTING_INT_ITEM_SPECIAL:
7999          case MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM_SPECIAL:
8000             BIND_ACTION_OK(cbs, action_ok_push_dropdown_setting);
8001             break;
8002          case MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM_SPECIAL:
8003             BIND_ACTION_OK(cbs, action_ok_push_dropdown_setting_uint_item_special);
8004             break;
8005          case MENU_SETTING_DROPDOWN_ITEM:
8006             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item);
8007             break;
8008          case MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PARAM:
8009             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_video_shader_param);
8010             break;
8011          case MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PRESET_PARAM:
8012             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_video_shader_preset_param);
8013             break;
8014          case MENU_SETTING_DROPDOWN_ITEM_RESOLUTION:
8015             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_resolution);
8016             break;
8017          case MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_NUM_PASS:
8018             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_video_shader_num_pass);
8019             break;
8020          case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE:
8021             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_default_core);
8022             break;
8023          case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LABEL_DISPLAY_MODE:
8024             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_label_display_mode);
8025             break;
8026          case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_RIGHT_THUMBNAIL_MODE:
8027             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_right_thumbnail_mode);
8028             break;
8029          case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LEFT_THUMBNAIL_MODE:
8030             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_left_thumbnail_mode);
8031             break;
8032          case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_SORT_MODE:
8033             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_sort_mode);
8034             break;
8035          case MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
8036             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_manual_content_scan_system_name);
8037             break;
8038          case MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME:
8039             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_manual_content_scan_core_name);
8040             break;
8041          case MENU_SETTING_DROPDOWN_ITEM_DISK_INDEX:
8042             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_disk_index);
8043             break;
8044          case MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE:
8045             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_device_type);
8046             break;
8047          case MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_INDEX:
8048             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_device_index);
8049             break;
8050          case MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION:
8051             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_description);
8052             break;
8053          case MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION_KBD:
8054             BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_description_kbd);
8055             break;
8056          case MENU_SETTING_ACTION_CORE_DISK_OPTIONS:
8057             BIND_ACTION_OK(cbs, action_ok_push_default);
8058             break;
8059          case FILE_TYPE_PLAYLIST_ENTRY:
8060             BIND_ACTION_OK(cbs, action_ok_playlist_entry_collection);
8061             break;
8062 #ifdef HAVE_LAKKA_SWITCH
8063          case MENU_SET_SWITCH_GPU_PROFILE:
8064             BIND_ACTION_OK(cbs, action_ok_set_switch_gpu_profile);
8065             break;
8066 #endif
8067 #if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX)
8068          case MENU_SET_SWITCH_CPU_PROFILE:
8069             BIND_ACTION_OK(cbs, action_ok_set_switch_cpu_profile);
8070             break;
8071 #endif
8072          case FILE_TYPE_RPL_ENTRY:
8073             BIND_ACTION_OK(cbs, action_ok_rpl_entry);
8074             break;
8075          case FILE_TYPE_PLAYLIST_COLLECTION:
8076             BIND_ACTION_OK(cbs, action_ok_playlist_collection);
8077             break;
8078          case FILE_TYPE_CONTENTLIST_ENTRY:
8079             BIND_ACTION_OK(cbs, action_ok_push_generic_list);
8080             break;
8081          case FILE_TYPE_CHEAT:
8082             if (string_is_equal(menu_label,
8083                      msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_FILE_LOAD_APPEND)))
8084             {
8085                BIND_ACTION_OK(cbs, action_ok_cheat_file_load_append);
8086             }
8087             else
8088             {
8089                BIND_ACTION_OK(cbs, action_ok_cheat_file_load);
8090             }
8091             break;
8092          case FILE_TYPE_RECORD_CONFIG:
8093             BIND_ACTION_OK(cbs, action_ok_record_configfile_load);
8094             break;
8095          case FILE_TYPE_STREAM_CONFIG:
8096             BIND_ACTION_OK(cbs, action_ok_stream_configfile_load);
8097             break;
8098          case FILE_TYPE_RGUI_THEME_PRESET:
8099             BIND_ACTION_OK(cbs, action_ok_rgui_menu_theme_preset_load);
8100             break;
8101          case FILE_TYPE_REMAP:
8102             BIND_ACTION_OK(cbs, action_ok_remap_file_load);
8103             break;
8104          case FILE_TYPE_SHADER_PRESET:
8105 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
8106             /* TODO/FIXME - handle scan case */
8107             BIND_ACTION_OK(cbs, action_ok_shader_preset_load);
8108 #endif
8109             break;
8110          case FILE_TYPE_SHADER:
8111 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
8112             /* TODO/FIXME - handle scan case */
8113             BIND_ACTION_OK(cbs, action_ok_shader_pass_load);
8114 #endif
8115             break;
8116          case FILE_TYPE_IMAGE:
8117             /* TODO/FIXME - handle scan case */
8118             BIND_ACTION_OK(cbs, action_ok_menu_wallpaper_load);
8119             break;
8120          case FILE_TYPE_USE_DIRECTORY:
8121             BIND_ACTION_OK(cbs, action_ok_path_use_directory);
8122             break;
8123 #ifdef HAVE_LIBRETRODB
8124          case FILE_TYPE_SCAN_DIRECTORY:
8125             BIND_ACTION_OK(cbs, action_ok_path_scan_directory);
8126             break;
8127 #endif
8128          case FILE_TYPE_MANUAL_SCAN_DIRECTORY:
8129             BIND_ACTION_OK(cbs, action_ok_path_manual_scan_directory);
8130             break;
8131          case FILE_TYPE_MANUAL_SCAN_DAT:
8132             BIND_ACTION_OK(cbs, action_ok_set_manual_content_scan_dat_file);
8133             break;
8134          case FILE_TYPE_CONFIG:
8135             BIND_ACTION_OK(cbs, action_ok_config_load);
8136             break;
8137          case FILE_TYPE_PARENT_DIRECTORY:
8138             BIND_ACTION_OK(cbs, action_ok_parent_directory_push);
8139             break;
8140          case FILE_TYPE_DIRECTORY:
8141             if (cbs->enum_idx != MSG_UNKNOWN
8142                   || string_is_equal(menu_label,
8143                      msg_hash_to_str(MENU_ENUM_LABEL_DISK_IMAGE_APPEND))
8144                   || string_is_equal(menu_label,
8145                      msg_hash_to_str(MENU_ENUM_LABEL_SUBSYSTEM_ADD))
8146                   || string_is_equal(menu_label,
8147                      msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FONT_PATH))
8148                   || string_is_equal(menu_label,
8149                      msg_hash_to_str(MENU_ENUM_LABEL_XMB_FONT))
8150                   || string_is_equal(menu_label,
8151                      msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN))
8152                   || string_is_equal(menu_label,
8153                      msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FILTER)))
8154                BIND_ACTION_OK(cbs, action_ok_directory_push);
8155             else
8156                BIND_ACTION_OK(cbs, action_ok_push_random_dir);
8157             break;
8158          case FILE_TYPE_CARCHIVE:
8159             if (filebrowser_get_type() == FILEBROWSER_SCAN_FILE)
8160             {
8161 #ifdef HAVE_LIBRETRODB
8162                BIND_ACTION_OK(cbs, action_ok_scan_file);
8163 #endif
8164             }
8165             else
8166             {
8167                if (string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES)))
8168                {
8169                   BIND_ACTION_OK(cbs, action_ok_compressed_archive_push_detect_core);
8170                }
8171                else
8172                {
8173                   BIND_ACTION_OK(cbs, action_ok_compressed_archive_push);
8174                }
8175             }
8176             break;
8177          case FILE_TYPE_CORE:
8178             if (cbs->enum_idx != MSG_UNKNOWN)
8179             {
8180                switch (cbs->enum_idx)
8181                {
8182                   case MENU_ENUM_LABEL_CORE_UPDATER_LIST:
8183                      BIND_ACTION_OK(cbs, action_ok_deferred_list_stub);
8184                      break;
8185                   case MSG_UNKNOWN:
8186                   default:
8187                      break;
8188                }
8189             }
8190             else
8191             {
8192                if (string_is_equal(menu_label,
8193                         msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CORE_LIST)))
8194                {
8195                   BIND_ACTION_OK(cbs, action_ok_load_core_deferred);
8196                }
8197                else if (string_is_equal(menu_label,
8198                         msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CORE_LIST_SET)))
8199                {
8200                   BIND_ACTION_OK(cbs, action_ok_core_deferred_set);
8201                }
8202                else if (string_is_equal(menu_label,
8203                         msg_hash_to_str(MENU_ENUM_LABEL_CORE_LIST)))
8204                {
8205                   BIND_ACTION_OK(cbs, action_ok_load_core);
8206                }
8207             }
8208             break;
8209          case FILE_TYPE_DOWNLOAD_CORE_CONTENT:
8210             BIND_ACTION_OK(cbs, action_ok_core_content_download);
8211             break;
8212          case FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT:
8213             BIND_ACTION_OK(cbs, action_ok_core_content_thumbnails);
8214             break;
8215          case FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT:
8216             BIND_ACTION_OK(cbs, action_ok_pl_content_thumbnails);
8217             break;
8218          case FILE_TYPE_DOWNLOAD_CORE:
8219             BIND_ACTION_OK(cbs, action_ok_core_updater_download);
8220             break;
8221          case FILE_TYPE_SIDELOAD_CORE:
8222             BIND_ACTION_OK(cbs, action_ok_sideload_core);
8223             break;
8224          case FILE_TYPE_DOWNLOAD_URL:
8225             BIND_ACTION_OK(cbs, action_ok_download_url);
8226             break;
8227          case FILE_TYPE_DOWNLOAD_THUMBNAIL:
8228             BIND_ACTION_OK(cbs, action_ok_thumbnails_updater_download);
8229             break;
8230          case FILE_TYPE_DOWNLOAD_LAKKA:
8231             BIND_ACTION_OK(cbs, action_ok_lakka_download);
8232             break;
8233          case FILE_TYPE_DOWNLOAD_CORE_INFO:
8234             break;
8235          case FILE_TYPE_RDB:
8236             if (string_is_equal(menu_label,
8237                      msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST)))
8238             {
8239                BIND_ACTION_OK(cbs, action_ok_deferred_list_stub);
8240             }
8241             else if (string_is_equal(menu_label,
8242                      msg_hash_to_str(MENU_ENUM_LABEL_DATABASE_MANAGER_LIST)))
8243             {
8244                BIND_ACTION_OK(cbs, action_ok_database_manager_list);
8245             }
8246             /* TODO/FIXME - refactor this */
8247             else if (string_is_equal(menu_label, "Horizontal Menu"))
8248             {
8249                BIND_ACTION_OK(cbs, action_ok_database_manager_list);
8250             }
8251             break;
8252          case FILE_TYPE_RDB_ENTRY:
8253             BIND_ACTION_OK(cbs, action_ok_rdb_entry);
8254             break;
8255          case MENU_BLUETOOTH:
8256             BIND_ACTION_OK(cbs, action_ok_bluetooth);
8257             break;
8258          case MENU_WIFI:
8259 #ifdef HAVE_NETWORKING
8260             BIND_ACTION_OK(cbs, action_ok_wifi);
8261 #endif
8262             break;
8263          case MENU_NETPLAY_LAN_SCAN:
8264             BIND_ACTION_OK(cbs, action_ok_netplay_lan_scan);
8265             break;
8266          case FILE_TYPE_CURSOR:
8267             if (string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST)))
8268             {
8269                BIND_ACTION_OK(cbs, action_ok_deferred_list_stub);
8270             }
8271             else if (string_is_equal(menu_label,
8272                      msg_hash_to_str(MENU_ENUM_LABEL_CURSOR_MANAGER_LIST)))
8273             {
8274                BIND_ACTION_OK(cbs, action_ok_cursor_manager_list);
8275             }
8276             break;
8277          case FILE_TYPE_VIDEOFILTER:
8278             BIND_ACTION_OK(cbs, action_ok_set_path_videofilter);
8279             break;
8280          case FILE_TYPE_FONT:
8281             BIND_ACTION_OK(cbs, action_ok_set_path);
8282             break;
8283          case FILE_TYPE_VIDEO_FONT:
8284             BIND_ACTION_OK(cbs, action_ok_set_path_video_font);
8285             break;
8286          case FILE_TYPE_OVERLAY:
8287             BIND_ACTION_OK(cbs, action_ok_set_path_overlay);
8288             break;
8289 #ifdef HAVE_VIDEO_LAYOUT
8290          case FILE_TYPE_VIDEO_LAYOUT:
8291             BIND_ACTION_OK(cbs, action_ok_set_path_video_layout);
8292             break;
8293 #endif
8294          case FILE_TYPE_AUDIOFILTER:
8295             BIND_ACTION_OK(cbs, action_ok_set_path_audiofilter);
8296             break;
8297          case FILE_TYPE_IN_CARCHIVE:
8298          case FILE_TYPE_PLAIN:
8299             if (filebrowser_get_type() == FILEBROWSER_SCAN_FILE)
8300             {
8301 #ifdef HAVE_LIBRETRODB
8302                BIND_ACTION_OK(cbs, action_ok_scan_file);
8303 #endif
8304             }
8305             else if (cbs->enum_idx != MSG_UNKNOWN)
8306             {
8307                switch (cbs->enum_idx)
8308                {
8309                   case MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST:
8310                   case MENU_ENUM_LABEL_FAVORITES:
8311                   case MENU_ENUM_LABEL_DEFERRED_ARCHIVE_OPEN_DETECT_CORE:
8312 #ifdef HAVE_COMPRESSION
8313                      if (type == FILE_TYPE_IN_CARCHIVE)
8314                      {
8315                         BIND_ACTION_OK(cbs, action_ok_file_load_with_detect_core_carchive);
8316                      }
8317                      else
8318 #endif
8319                      {
8320                         BIND_ACTION_OK(cbs, action_ok_file_load_with_detect_core);
8321                      }
8322                      break;
8323                   case MENU_ENUM_LABEL_DISK_IMAGE_APPEND:
8324                      BIND_ACTION_OK(cbs, action_ok_disk_image_append);
8325                      break;
8326                   case MENU_ENUM_LABEL_SUBSYSTEM_ADD:
8327                      BIND_ACTION_OK(cbs, action_ok_subsystem_add);
8328                      break;
8329                   default:
8330                      BIND_ACTION_OK(cbs, action_ok_file_load);
8331                      break;
8332                }
8333             }
8334             else
8335             {
8336                if (
8337                      string_is_equal(menu_label, "deferred_archive_open_detect_core") ||
8338                      string_is_equal(menu_label, "downloaded_file_detect_core_list") ||
8339                      string_is_equal(menu_label, "favorites")
8340                   )
8341                {
8342 #ifdef HAVE_COMPRESSION
8343                   if (type == FILE_TYPE_IN_CARCHIVE)
8344                   {
8345                      BIND_ACTION_OK(cbs, action_ok_file_load_with_detect_core_carchive);
8346                   }
8347                   else
8348 #endif
8349                   {
8350                      BIND_ACTION_OK(cbs, action_ok_file_load_with_detect_core);
8351                   }
8352                }
8353                else if (string_is_equal(menu_label, "disk_image_append"))
8354                {
8355                   BIND_ACTION_OK(cbs, action_ok_disk_image_append);
8356                }
8357                else if (string_is_equal(menu_label, "subsystem_add"))
8358                {
8359                   BIND_ACTION_OK(cbs, action_ok_subsystem_add);
8360                }
8361                else
8362                {
8363                   BIND_ACTION_OK(cbs, action_ok_file_load);
8364                }
8365             }
8366             break;
8367          case FILE_TYPE_MOVIE:
8368 #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
8369             /* TODO/FIXME - handle scan case */
8370             BIND_ACTION_OK(cbs, action_ok_file_load_ffmpeg);
8371 #endif
8372             break;
8373          case FILE_TYPE_MUSIC:
8374             BIND_ACTION_OK(cbs, action_ok_file_load_music);
8375             break;
8376          case FILE_TYPE_IMAGEVIEWER:
8377             /* TODO/FIXME - handle scan case */
8378             BIND_ACTION_OK(cbs, action_ok_file_load_imageviewer);
8379             break;
8380          case FILE_TYPE_DIRECT_LOAD:
8381             BIND_ACTION_OK(cbs, action_ok_file_load);
8382             break;
8383          case MENU_SETTINGS:
8384          case MENU_SETTING_GROUP:
8385          case MENU_SETTING_SUBGROUP:
8386             BIND_ACTION_OK(cbs, action_ok_push_default);
8387             break;
8388          case MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_CYCLE_TRAY_STATUS:
8389             BIND_ACTION_OK(cbs, action_ok_disk_cycle_tray_status);
8390             break;
8391          case MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_INDEX:
8392             BIND_ACTION_OK(cbs, action_ok_disk_index_dropdown_box_list);
8393             break;
8394          case MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_CREATE:
8395             BIND_ACTION_OK(cbs, action_ok_game_specific_core_options_create);
8396             break;
8397          case MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE:
8398             BIND_ACTION_OK(cbs, action_ok_folder_specific_core_options_create);
8399             break;
8400          case MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_REMOVE:
8401             BIND_ACTION_OK(cbs, action_ok_game_specific_core_options_remove);
8402             break;
8403          case MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE:
8404             BIND_ACTION_OK(cbs, action_ok_folder_specific_core_options_remove);
8405             break;
8406          case MENU_SETTING_ACTION_CORE_OPTIONS_RESET:
8407             BIND_ACTION_OK(cbs, action_ok_core_options_reset);
8408             break;
8409          case MENU_SETTING_ITEM_CORE_RESTORE_BACKUP:
8410             BIND_ACTION_OK(cbs, action_ok_core_restore_backup);
8411             break;
8412          case MENU_SETTING_ITEM_CORE_DELETE_BACKUP:
8413             BIND_ACTION_OK(cbs, action_ok_core_delete_backup);
8414             break;
8415          case MENU_SETTING_ACTION_CORE_LOCK:
8416             BIND_ACTION_OK(cbs, action_ok_core_lock);
8417             break;
8418          case MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE:
8419             BIND_ACTION_OK(cbs, action_ok_video_filter_remove);
8420             break;
8421          case MENU_SETTING_ACTION_AUDIO_DSP_PLUGIN_REMOVE:
8422             BIND_ACTION_OK(cbs, action_ok_audio_dsp_plugin_remove);
8423             break;
8424          default:
8425             return -1;
8426       }
8427    }
8428 
8429    return 0;
8430 }
8431 
menu_cbs_init_bind_ok(menu_file_list_cbs_t * cbs,const char * path,const char * label,unsigned type,size_t idx,const char * menu_label)8432 int menu_cbs_init_bind_ok(menu_file_list_cbs_t *cbs,
8433       const char *path, const char *label, unsigned type, size_t idx,
8434       const char *menu_label)
8435 {
8436    if (!cbs)
8437       return -1;
8438 
8439    BIND_ACTION_OK(cbs, action_ok_lookup_setting);
8440 
8441    if (menu_cbs_init_bind_ok_compare_label(cbs, label) == 0)
8442       return 0;
8443 
8444    if (menu_cbs_init_bind_ok_compare_type(cbs, label,
8445             menu_label, type) == 0)
8446       return 0;
8447 
8448    return -1;
8449 }
8450