1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2011-2017 - Daniel De Matteis
3  *
4  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
5  *  of the GNU General Public License as published by the Free Software Found-
6  *  ation, either version 3 of the License, or (at your option) any later version.
7  *
8  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10  *  PURPOSE.  See the GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License along with RetroArch.
13  *  If not, see <http://www.gnu.org/licenses/>.
14  */
15 
16 #include <compat/strl.h>
17 #include <file/file_path.h>
18 #include <lists/string_list.h>
19 #include <string/stdstring.h>
20 
21 #ifdef HAVE_CONFIG_H
22 #include "../../config.h"
23 #endif
24 
25 #include "../menu_driver.h"
26 #include "../menu_cbs.h"
27 #include "../menu_input.h"
28 #include "../menu_setting.h"
29 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
30 #include "../menu_shader.h"
31 #endif
32 
33 #include "../../configuration.h"
34 #include "../../core.h"
35 #include "../../core_info.h"
36 #include "../../core_option_manager.h"
37 #ifdef HAVE_CHEATS
38 #include "../../cheat_manager.h"
39 #endif
40 #include "../../retroarch.h"
41 #include "../../verbosity.h"
42 #include "../../performance_counters.h"
43 #include "../../playlist.h"
44 #include "../../manual_content_scan.h"
45 
46 #include "../../input/input_remapping.h"
47 
48 #include "../../config.def.h"
49 
50 #ifdef HAVE_NETWORKING
51 #include "../../core_updater_list.h"
52 #endif
53 
54 #ifndef BIND_ACTION_START
55 #define BIND_ACTION_START(cbs, name) (cbs)->action_start = (name)
56 #endif
57 
58 /* Forward declarations */
59 int generic_action_ok_command(enum event_command cmd);
60 int action_ok_push_playlist_manager_settings(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx);
61 int action_ok_push_core_information_list(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx);
62 
63 #ifdef HAVE_AUDIOMIXER
action_start_audio_mixer_stream_volume(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)64 static int action_start_audio_mixer_stream_volume(
65       const char *path, const char *label,
66       unsigned type, size_t idx, size_t entry_idx)
67 {
68    unsigned         offset      = (type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN);
69 
70    if (offset >= AUDIO_MIXER_MAX_STREAMS)
71       return 0;
72 
73    audio_driver_mixer_set_stream_volume(offset, 1.0f);
74 
75    return 0;
76 }
77 #endif
78 
action_start_remap_file_load(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)79 static int action_start_remap_file_load(
80       const char *path, const char *label,
81       unsigned type, size_t idx, size_t entry_idx)
82 {
83    input_remapping_deinit();
84    input_remapping_set_defaults(false);
85    return 0;
86 }
87 
action_start_shader_preset(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)88 static int action_start_shader_preset(
89       const char *path, const char *label,
90       unsigned type, size_t idx, size_t entry_idx)
91 {
92 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
93    bool refresh                = false;
94    struct video_shader *shader = menu_shader_get();
95 
96    shader->passes = 0;
97 
98    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
99    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
100    command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
101 #endif
102    return 0;
103 }
104 
action_start_video_filter_file_load(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)105 static int action_start_video_filter_file_load(
106       const char *path, const char *label,
107       unsigned type, size_t idx, size_t entry_idx)
108 {
109    settings_t *settings = config_get_ptr();
110 
111    if (!settings)
112       return menu_cbs_exit();
113 
114    if (!string_is_empty(settings->paths.path_softfilter_plugin))
115    {
116       bool refresh = false;
117 
118       /* Unload video filter */
119       settings->paths.path_softfilter_plugin[0] = '\0';
120       command_event(CMD_EVENT_REINIT, NULL);
121 
122       /* Refresh menu */
123       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
124       menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
125    }
126 
127    return 0;
128 }
129 
action_start_audio_dsp_plugin_file_load(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)130 static int action_start_audio_dsp_plugin_file_load(
131       const char *path, const char *label,
132       unsigned type, size_t idx, size_t entry_idx)
133 {
134    settings_t *settings = config_get_ptr();
135 
136    if (!settings)
137       return menu_cbs_exit();
138 
139    if (!string_is_empty(settings->paths.path_audio_dsp_plugin))
140    {
141       bool refresh = false;
142 
143       /* Unload dsp plugin filter */
144       settings->paths.path_audio_dsp_plugin[0] = '\0';
145       command_event(CMD_EVENT_DSP_FILTER_INIT, NULL);
146 
147       /* Refresh menu */
148       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
149       menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
150    }
151 
152    return 0;
153 }
154 
generic_action_start_performance_counters(struct retro_perf_counter ** counters,unsigned offset,unsigned type,const char * label)155 static int generic_action_start_performance_counters(struct retro_perf_counter **counters,
156       unsigned offset, unsigned type, const char *label)
157 {
158    if (counters[offset])
159    {
160       counters[offset]->total    = 0;
161       counters[offset]->call_cnt = 0;
162    }
163 
164    return 0;
165 }
166 
action_start_performance_counters_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)167 static int action_start_performance_counters_core(
168       const char *path, const char *label,
169       unsigned type, size_t idx, size_t entry_idx)
170 {
171    struct retro_perf_counter **counters = retro_get_perf_counter_libretro();
172    unsigned offset = type - MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN;
173 
174    return generic_action_start_performance_counters(counters, offset, type, label);
175 }
176 
action_start_performance_counters_frontend(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)177 static int action_start_performance_counters_frontend(
178       const char *path, const char *label,
179       unsigned type, size_t idx, size_t entry_idx)
180 {
181    struct retro_perf_counter **counters = retro_get_perf_counter_rarch();
182    unsigned offset = type - MENU_SETTINGS_PERF_COUNTERS_BEGIN;
183    return generic_action_start_performance_counters(counters, offset, type, label);
184 }
185 
action_start_input_desc(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)186 static int action_start_input_desc(
187       const char *path, const char *label,
188       unsigned type, size_t idx, size_t entry_idx)
189 {
190    settings_t *settings        = config_get_ptr();
191    rarch_system_info_t *system = runloop_get_system_info();
192    unsigned user_idx;
193    unsigned btn_idx;
194    unsigned mapped_port;
195 
196    (void)label;
197 
198    if (!settings || !system)
199       return 0;
200 
201    user_idx    = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8);
202    btn_idx     = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx;
203    mapped_port = settings->uints.input_remap_ports[user_idx];
204 
205    if ((user_idx >= MAX_USERS) ||
206        (mapped_port >= MAX_USERS) ||
207        (btn_idx >= RARCH_CUSTOM_BIND_LIST_END))
208       return 0;
209 
210    /* Check whether core has defined this input */
211    if (!string_is_empty(system->input_desc_btn[mapped_port][btn_idx]))
212    {
213       const struct retro_keybind *keyptr = &input_config_binds[user_idx][btn_idx];
214       settings->uints.input_remap_ids[user_idx][btn_idx] = keyptr->id;
215    }
216    else
217       settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_UNMAPPED;
218 
219    return 0;
220 }
221 
action_start_input_desc_kbd(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)222 static int action_start_input_desc_kbd(
223       const char *path, const char *label,
224       unsigned type, size_t idx, size_t entry_idx)
225 {
226    settings_t *settings = config_get_ptr();
227    unsigned user_idx;
228    unsigned btn_idx;
229 
230    (void)label;
231 
232    if (!settings)
233       return 0;
234 
235    user_idx = (type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) / RARCH_ANALOG_BIND_LIST_END;
236    btn_idx  = (type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) - RARCH_ANALOG_BIND_LIST_END * user_idx;
237 
238    if ((user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END))
239       return 0;
240 
241    /* By default, inputs are unmapped */
242    settings->uints.input_keymapper_ids[user_idx][btn_idx] = RETROK_FIRST;
243 
244    return 0;
245 }
246 
247 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
action_start_shader_action_parameter_generic(unsigned type,unsigned offset)248 static int action_start_shader_action_parameter_generic(
249       unsigned type, unsigned offset)
250 {
251    video_shader_ctx_t shader_info;
252    struct video_shader_parameter *param = NULL;
253    unsigned parameter                   = type - offset;
254 
255    video_shader_driver_get_current_shader(&shader_info);
256 
257    if (!shader_info.data)
258       return 0;
259 
260    param          = &shader_info.data->parameters
261       [parameter];
262    param->current = param->initial;
263    param->current = MIN(MAX(param->minimum, param->current), param->maximum);
264 
265    return menu_shader_manager_clear_parameter(menu_shader_get(), parameter);
266 }
267 
action_start_shader_action_parameter(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)268 static int action_start_shader_action_parameter(
269       const char *path, const char *label,
270       unsigned type, size_t idx, size_t entry_idx)
271 {
272    return action_start_shader_action_parameter_generic(type, MENU_SETTINGS_SHADER_PARAMETER_0);
273 }
274 
action_start_shader_action_preset_parameter(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)275 static int action_start_shader_action_preset_parameter(
276       const char *path, const char *label,
277       unsigned type, size_t idx, size_t entry_idx)
278 {
279    return action_start_shader_action_parameter_generic(type, MENU_SETTINGS_SHADER_PRESET_PARAMETER_0);
280 }
281 
action_start_shader_pass(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)282 static int action_start_shader_pass(
283       const char *path, const char *label,
284       unsigned type, size_t idx, size_t entry_idx)
285 {
286    menu_handle_t *menu       = menu_driver_get_ptr();
287 
288    if (!menu)
289       return menu_cbs_exit();
290 
291    menu->scratchpad.unsigned_var = type - MENU_SETTINGS_SHADER_PASS_0;
292 
293    menu_shader_manager_clear_pass_path(menu_shader_get(),
294          menu->scratchpad.unsigned_var);
295 
296    return 0;
297 }
298 
action_start_shader_scale_pass(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)299 static int action_start_shader_scale_pass(
300       const char *path, const char *label,
301       unsigned type, size_t idx, size_t entry_idx)
302 {
303    unsigned pass                         = type - MENU_SETTINGS_SHADER_PASS_SCALE_0;
304 
305    menu_shader_manager_clear_pass_scale(menu_shader_get(), pass);
306 
307    return 0;
308 }
309 
action_start_shader_filter_pass(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)310 static int action_start_shader_filter_pass(
311       const char *path, const char *label,
312       unsigned type, size_t idx, size_t entry_idx)
313 {
314    unsigned pass                         = type - MENU_SETTINGS_SHADER_PASS_FILTER_0;
315    return menu_shader_manager_clear_pass_filter(menu_shader_get(), pass);
316 }
317 #endif
318 
action_start_netplay_mitm_server(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)319 static int action_start_netplay_mitm_server(
320       const char *path, const char *label,
321       unsigned type, size_t idx, size_t entry_idx)
322 {
323    settings_t *settings = config_get_ptr();
324    configuration_set_string(settings,
325          settings->arrays.netplay_mitm_server,
326          DEFAULT_NETPLAY_MITM_SERVER);
327    return 0;
328 }
329 
330 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
action_start_shader_watch_for_changes(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)331 static int action_start_shader_watch_for_changes(
332       const char *path, const char *label,
333       unsigned type, size_t idx, size_t entry_idx)
334 {
335    settings_t *settings = config_get_ptr();
336    settings->bools.video_shader_watch_files = DEFAULT_VIDEO_SHADER_WATCH_FILES;
337    return 0;
338 }
339 
action_start_shader_num_passes(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)340 static int action_start_shader_num_passes(
341       const char *path, const char *label,
342       unsigned type, size_t idx, size_t entry_idx)
343 {
344    return menu_shader_manager_clear_num_passes(menu_shader_get());
345 }
346 #endif
347 
348 #ifdef HAVE_CHEATS
action_start_cheat_num_passes(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)349 static int action_start_cheat_num_passes(
350       const char *path, const char *label,
351       unsigned type, size_t idx, size_t entry_idx)
352 {
353    if (cheat_manager_get_size())
354    {
355       bool refresh                = false;
356       menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
357       cheat_manager_realloc(0, CHEAT_HANDLER_TYPE_EMU);
358    }
359 
360    return 0;
361 }
362 #endif
363 
action_start_core_setting(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)364 static int action_start_core_setting(
365       const char *path, const char *label,
366       unsigned type, size_t idx, size_t entry_idx)
367 {
368    unsigned core_idx               = type - MENU_SETTINGS_CORE_OPTION_START;
369    core_option_manager_t *coreopts = NULL;
370 
371    if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
372       core_option_manager_set_default(coreopts, core_idx);
373 
374    return 0;
375 }
376 
action_start_playlist_association(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)377 static int action_start_playlist_association(
378       const char *path, const char *label,
379       unsigned type, size_t idx, size_t entry_idx)
380 {
381    playlist_t *playlist = playlist_get_cached();
382 
383    if (!playlist)
384       return -1;
385 
386    /* Set default core path + name to DETECT */
387    playlist_set_default_core_path(playlist, FILE_PATH_DETECT);
388    playlist_set_default_core_name(playlist, FILE_PATH_DETECT);
389    playlist_write_file(playlist);
390 
391    return 0;
392 }
393 
action_start_playlist_label_display_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)394 static int action_start_playlist_label_display_mode(
395       const char *path, const char *label,
396       unsigned type, size_t idx, size_t entry_idx)
397 {
398    playlist_t *playlist = playlist_get_cached();
399 
400    if (!playlist)
401       return -1;
402 
403    /* Set label display mode to the default */
404    playlist_set_label_display_mode(playlist, LABEL_DISPLAY_MODE_DEFAULT);
405    playlist_write_file(playlist);
406 
407    return 0;
408 }
409 
action_start_playlist_right_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)410 static int action_start_playlist_right_thumbnail_mode(
411       const char *path, const char *label,
412       unsigned type, size_t idx, size_t entry_idx)
413 {
414    playlist_t *playlist = playlist_get_cached();
415 
416    if (!playlist)
417       return -1;
418 
419    /* Set thumbnail_mode to default value */
420    playlist_set_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_RIGHT, PLAYLIST_THUMBNAIL_MODE_DEFAULT);
421    playlist_write_file(playlist);
422 
423    return 0;
424 }
425 
action_start_playlist_left_thumbnail_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)426 static int action_start_playlist_left_thumbnail_mode(
427       const char *path, const char *label,
428       unsigned type, size_t idx, size_t entry_idx)
429 {
430    playlist_t *playlist = playlist_get_cached();
431 
432    if (!playlist)
433       return -1;
434 
435    /* Set thumbnail_mode to default value */
436    playlist_set_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_LEFT, PLAYLIST_THUMBNAIL_MODE_DEFAULT);
437    playlist_write_file(playlist);
438 
439    return 0;
440 }
441 
action_start_playlist_sort_mode(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)442 static int action_start_playlist_sort_mode(
443       const char *path, const char *label,
444       unsigned type, size_t idx, size_t entry_idx)
445 {
446    playlist_t *playlist = playlist_get_cached();
447 
448    if (!playlist)
449       return -1;
450 
451    /* Set sort mode to the default */
452    playlist_set_sort_mode(playlist, PLAYLIST_SORT_MODE_DEFAULT);
453    playlist_write_file(playlist);
454 
455    return 0;
456 }
457 
action_start_manual_content_scan_dir(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)458 static int action_start_manual_content_scan_dir(
459       const char *path, const char *label,
460       unsigned type, size_t idx, size_t entry_idx)
461 {
462    /* Reset content directory */
463    manual_content_scan_set_menu_content_dir("");
464    return 0;
465 }
466 
action_start_manual_content_scan_system_name(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)467 static int action_start_manual_content_scan_system_name(
468       const char *path, const char *label,
469       unsigned type, size_t idx, size_t entry_idx)
470 {
471    /* Reset system name */
472    manual_content_scan_set_menu_system_name(
473          MANUAL_CONTENT_SCAN_SYSTEM_NAME_CONTENT_DIR, "");
474    return 0;
475 }
476 
action_start_manual_content_scan_core_name(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)477 static int action_start_manual_content_scan_core_name(
478       const char *path, const char *label,
479       unsigned type, size_t idx, size_t entry_idx)
480 {
481    /* Reset core name */
482    manual_content_scan_set_menu_core_name(
483          MANUAL_CONTENT_SCAN_CORE_DETECT, "");
484    return 0;
485 }
486 
action_start_video_resolution(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)487 static int action_start_video_resolution(
488       const char *path, const char *label,
489       unsigned type, size_t idx, size_t entry_idx)
490 {
491 #if defined(GEKKO) || !defined(__PSL1GHT__) && !defined(__PS3__)
492    unsigned width = 0, height = 0;
493    global_t *global = global_get_ptr();
494 
495    /*  Reset the resolution id to zero */
496    global->console.screen.resolutions.current.id = 0;
497 
498    if (video_driver_get_video_output_size(&width, &height))
499    {
500       char msg[PATH_MAX_LENGTH];
501 
502       msg[0] = '\0';
503 
504 #if defined(_WIN32) || !defined(__PSL1GHT__) && !defined(__PS3__)
505       generic_action_ok_command(CMD_EVENT_REINIT);
506 #endif
507       video_driver_set_video_mode(width, height, true);
508 #ifdef GEKKO
509       if (width == 0 || height == 0)
510          strlcpy(msg, "Resetting to: DEFAULT", sizeof(msg));
511       else
512 #endif
513          snprintf(msg, sizeof(msg),
514                "Resetting to: %dx%d", width, height);
515       runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
516    }
517 #endif
518 
519    return 0;
520 }
521 
action_start_load_core(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)522 static int action_start_load_core(
523       const char *path, const char *label,
524       unsigned type, size_t idx, size_t entry_idx)
525 {
526    int ret                     = generic_action_ok_command(
527          CMD_EVENT_UNLOAD_CORE);
528    bool refresh                = false;
529 
530    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
531    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
532    return ret;
533 }
534 
535 #ifdef HAVE_NETWORKING
action_start_core_updater_entry(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)536 static int action_start_core_updater_entry(
537       const char *path, const char *label,
538       unsigned type, size_t idx, size_t entry_idx)
539 {
540    core_updater_list_t *core_list         = core_updater_list_get_cached();
541    const core_updater_list_entry_t *entry = NULL;
542 
543    /* If specified core is installed, go to core
544     * information menu */
545    if (core_list &&
546        core_updater_list_get_filename(core_list, path, &entry) &&
547        !string_is_empty(entry->local_core_path) &&
548        path_is_valid(entry->local_core_path))
549       return action_ok_push_core_information_list(
550             entry->local_core_path, label, type, idx, entry_idx);
551 
552    /* Otherwise do nothing */
553    return 0;
554 }
555 #endif
556 
action_start_core_lock(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)557 static int action_start_core_lock(
558       const char *path, const char *label,
559       unsigned type, size_t idx, size_t entry_idx)
560 {
561    const char *core_path = path;
562    bool refresh          = false;
563    int ret               = 0;
564 
565    if (string_is_empty(core_path))
566       return -1;
567 
568    /* Core should be unlocked by default
569     * > If it is currently unlocked, do nothing */
570    if (!core_info_get_core_lock(core_path, true))
571       return ret;
572 
573    /* ...Otherwise, attempt to unlock it */
574    if (!core_info_set_core_lock(core_path, false))
575    {
576       const char *core_name  = NULL;
577       core_info_t *core_info = NULL;
578       char msg[PATH_MAX_LENGTH];
579 
580       msg[0] = '\0';
581 
582       /* Need to fetch core name for error message */
583 
584       /* If core is found, use display name */
585       if (core_info_find(core_path, &core_info) &&
586           core_info->display_name)
587          core_name = core_info->display_name;
588       /* If not, use core file name */
589       else
590          core_name = path_basename(core_path);
591 
592       /* Build error message */
593       strlcpy(msg, msg_hash_to_str(MSG_CORE_UNLOCK_FAILED), sizeof(msg));
594 
595       if (!string_is_empty(core_name))
596          strlcat(msg, core_name, sizeof(msg));
597 
598       /* Generate log + notification */
599       RARCH_ERR("%s\n", msg);
600 
601       runloop_msg_queue_push(
602          msg,
603          1, 100, true,
604          NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
605 
606       ret = -1;
607    }
608 
609    /* Whenever lock status is changed, menu must be
610     * refreshed - do this even in the event of an error,
611     * since we don't want to leave the menu in an
612     * undefined state */
613    menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
614    menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
615 
616    return ret;
617 }
618 
action_start_lookup_setting(const char * path,const char * label,unsigned type,size_t idx,size_t entry_idx)619 static int action_start_lookup_setting(
620       const char *path, const char *label,
621       unsigned type, size_t idx, size_t entry_idx)
622 {
623    return menu_setting_set(type, MENU_ACTION_START, false);
624 }
625 
menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t * cbs)626 static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs)
627 {
628    if (cbs->enum_idx != MSG_UNKNOWN)
629    {
630       switch (cbs->enum_idx)
631       {
632          case MENU_ENUM_LABEL_CORE_LIST:
633             BIND_ACTION_START(cbs, action_start_load_core);
634             break;
635          case MENU_ENUM_LABEL_VIDEO_SHADER_PRESET:
636             BIND_ACTION_START(cbs, action_start_shader_preset);
637             break;
638          case MENU_ENUM_LABEL_REMAP_FILE_LOAD:
639             BIND_ACTION_START(cbs, action_start_remap_file_load);
640             break;
641          case MENU_ENUM_LABEL_VIDEO_FILTER:
642             BIND_ACTION_START(cbs, action_start_video_filter_file_load);
643             break;
644          case MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN:
645             BIND_ACTION_START(cbs, action_start_audio_dsp_plugin_file_load);
646             break;
647          case MENU_ENUM_LABEL_VIDEO_SHADER_PASS:
648 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
649             BIND_ACTION_START(cbs, action_start_shader_pass);
650 #endif
651             break;
652          case MENU_ENUM_LABEL_VIDEO_SHADER_SCALE_PASS:
653 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
654             BIND_ACTION_START(cbs, action_start_shader_scale_pass);
655 #endif
656             break;
657          case MENU_ENUM_LABEL_VIDEO_SHADER_FILTER_PASS:
658 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
659             BIND_ACTION_START(cbs, action_start_shader_filter_pass);
660 #endif
661             break;
662          case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES:
663 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
664             BIND_ACTION_START(cbs, action_start_shader_watch_for_changes);
665 #endif
666             break;
667          case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES:
668 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
669             BIND_ACTION_START(cbs, action_start_shader_num_passes);
670 #endif
671             break;
672          case MENU_ENUM_LABEL_CHEAT_NUM_PASSES:
673 #ifdef HAVE_CHEATS
674             BIND_ACTION_START(cbs, action_start_cheat_num_passes);
675 #endif
676             break;
677          case MENU_ENUM_LABEL_SCREEN_RESOLUTION:
678             BIND_ACTION_START(cbs, action_start_video_resolution);
679             break;
680          case MENU_ENUM_LABEL_NETPLAY_MITM_SERVER:
681             BIND_ACTION_START(cbs, action_start_netplay_mitm_server);
682             break;
683          case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE:
684             BIND_ACTION_START(cbs, action_start_playlist_association);
685             break;
686          case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE:
687             BIND_ACTION_START(cbs, action_start_playlist_label_display_mode);
688             break;
689          case MENU_ENUM_LABEL_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE:
690             BIND_ACTION_START(cbs, action_start_playlist_right_thumbnail_mode);
691             break;
692          case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE:
693             BIND_ACTION_START(cbs, action_start_playlist_left_thumbnail_mode);
694             break;
695          case MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE:
696             BIND_ACTION_START(cbs, action_start_playlist_sort_mode);
697             break;
698          case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR:
699             BIND_ACTION_START(cbs, action_start_manual_content_scan_dir);
700             break;
701          case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME:
702             BIND_ACTION_START(cbs, action_start_manual_content_scan_system_name);
703             break;
704          case MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME:
705             BIND_ACTION_START(cbs, action_start_manual_content_scan_core_name);
706             break;
707          default:
708             return -1;
709       }
710    }
711    else
712       return -1;
713 
714    return 0;
715 }
716 
menu_cbs_init_bind_start_compare_type(menu_file_list_cbs_t * cbs,unsigned type)717 static int menu_cbs_init_bind_start_compare_type(menu_file_list_cbs_t *cbs,
718       unsigned type)
719 {
720 #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
721    if (type >= MENU_SETTINGS_SHADER_PARAMETER_0
722          && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST)
723    {
724       BIND_ACTION_START(cbs, action_start_shader_action_parameter);
725    }
726    else if (type >= MENU_SETTINGS_SHADER_PRESET_PARAMETER_0
727          && type <= MENU_SETTINGS_SHADER_PRESET_PARAMETER_LAST)
728    {
729       BIND_ACTION_START(cbs, action_start_shader_action_preset_parameter);
730    }
731    else
732 #endif
733    if (type >= MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN &&
734          type <= MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_END)
735    {
736       BIND_ACTION_START(cbs, action_start_performance_counters_core);
737    }
738    else if (type >= MENU_SETTINGS_INPUT_DESC_BEGIN
739          && type <= MENU_SETTINGS_INPUT_DESC_END)
740    {
741       BIND_ACTION_START(cbs, action_start_input_desc);
742    }
743    else if (type >= MENU_SETTINGS_INPUT_DESC_KBD_BEGIN
744          && type <= MENU_SETTINGS_INPUT_DESC_KBD_END)
745    {
746       BIND_ACTION_START(cbs, action_start_input_desc_kbd);
747    }
748    else if (type >= MENU_SETTINGS_PERF_COUNTERS_BEGIN &&
749          type <= MENU_SETTINGS_PERF_COUNTERS_END)
750    {
751       BIND_ACTION_START(cbs, action_start_performance_counters_frontend);
752    }
753    else if ((type >= MENU_SETTINGS_CORE_OPTION_START) &&
754             (type < MENU_SETTINGS_CHEEVOS_START))
755    {
756       BIND_ACTION_START(cbs, action_start_core_setting);
757    }
758    else
759    {
760       switch (type)
761       {
762          case FILE_TYPE_PLAYLIST_COLLECTION:
763             BIND_ACTION_START(cbs, action_ok_push_playlist_manager_settings);
764             break;
765 #ifdef HAVE_NETWORKING
766          case FILE_TYPE_DOWNLOAD_CORE:
767             BIND_ACTION_START(cbs, action_start_core_updater_entry);
768             break;
769 #endif
770          case MENU_SETTING_ACTION_CORE_LOCK:
771             BIND_ACTION_START(cbs, action_start_core_lock);
772             break;
773          default:
774             return -1;
775       }
776    }
777 
778    return 0;
779 }
780 
menu_cbs_init_bind_start(menu_file_list_cbs_t * cbs,const char * path,const char * label,unsigned type,size_t idx)781 int menu_cbs_init_bind_start(menu_file_list_cbs_t *cbs,
782       const char *path, const char *label, unsigned type, size_t idx)
783 {
784    if (!cbs)
785       return -1;
786 
787 #ifdef HAVE_AUDIOMIXER
788    if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN
789          && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END)
790    {
791       BIND_ACTION_START(cbs, action_start_audio_mixer_stream_volume);
792       return 0;
793    }
794 #endif
795 
796    BIND_ACTION_START(cbs, action_start_lookup_setting);
797 
798    if (menu_cbs_init_bind_start_compare_label(cbs) == 0)
799       return 0;
800 
801    if (menu_cbs_init_bind_start_compare_type(cbs, type) == 0)
802       return 0;
803 
804    return -1;
805 }
806