bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) { static struct retro_system_info menu_driver_system; static bool menu_driver_pending_quick_menu = false; static bool menu_driver_pending_action = false; static bool menu_driver_prevent_populate = false; static bool menu_driver_load_no_content = false; static bool menu_driver_alive = false; static bool menu_driver_data_own = false; static bool menu_driver_pending_quit = false; static bool menu_driver_pending_shutdown = false; static playlist_t *menu_driver_playlist = NULL; static struct video_shader *menu_driver_shader = NULL; static menu_handle_t *menu_driver_data = NULL; static const menu_ctx_driver_t *menu_driver_ctx = NULL; static void *menu_userdata = NULL; settings_t *settings = config_get_ptr(); switch (state) { case RARCH_MENU_CTL_IS_PENDING_ACTION: if (!menu_driver_pending_action) return false; menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_ACTION, NULL); break; case RARCH_MENU_CTL_SET_PENDING_ACTION: menu_driver_pending_action = true; break; case RARCH_MENU_CTL_UNSET_PENDING_ACTION: menu_driver_pending_action = false; break; case RARCH_MENU_CTL_DRIVER_DATA_GET: { menu_handle_t **driver_data = (menu_handle_t**)data; if (!driver_data) return false; *driver_data = menu_driver_data; } break; case RARCH_MENU_CTL_IS_PENDING_QUICK_MENU: return menu_driver_pending_quick_menu; case RARCH_MENU_CTL_SET_PENDING_QUICK_MENU: menu_driver_pending_quick_menu = true; break; case RARCH_MENU_CTL_UNSET_PENDING_QUICK_MENU: menu_driver_pending_quick_menu = false; break; case RARCH_MENU_CTL_IS_PENDING_QUIT: return menu_driver_pending_quit; case RARCH_MENU_CTL_SET_PENDING_QUIT: menu_driver_pending_quit = true; break; case RARCH_MENU_CTL_UNSET_PENDING_QUIT: menu_driver_pending_quit = false; break; case RARCH_MENU_CTL_IS_PENDING_SHUTDOWN: return menu_driver_pending_shutdown; case RARCH_MENU_CTL_SET_PENDING_SHUTDOWN: menu_driver_pending_shutdown = true; break; case RARCH_MENU_CTL_UNSET_PENDING_SHUTDOWN: menu_driver_pending_shutdown = false; break; case RARCH_MENU_CTL_DESTROY: menu_driver_pending_quick_menu = false; menu_driver_pending_action = false; menu_driver_pending_quit = false; menu_driver_pending_shutdown = false; menu_driver_prevent_populate = false; menu_driver_load_no_content = false; menu_driver_alive = false; menu_driver_data_own = false; menu_driver_ctx = NULL; menu_userdata = NULL; break; case RARCH_MENU_CTL_PLAYLIST_FREE: if (menu_driver_playlist) playlist_free(menu_driver_playlist); menu_driver_playlist = NULL; break; case RARCH_MENU_CTL_FIND_DRIVER: { int i; driver_ctx_info_t drv; settings_t *settings = config_get_ptr(); drv.label = "menu_driver"; drv.s = settings->menu.driver; driver_ctl(RARCH_DRIVER_CTL_FIND_INDEX, &drv); i = drv.len; if (i >= 0) menu_driver_ctx = (const menu_ctx_driver_t*) menu_driver_find_handle(i); else { unsigned d; RARCH_WARN("Couldn't find any menu driver named \"%s\"\n", settings->menu.driver); RARCH_LOG_OUTPUT("Available menu drivers are:\n"); for (d = 0; menu_driver_find_handle(d); d++) RARCH_LOG_OUTPUT("\t%s\n", menu_driver_find_ident(d)); RARCH_WARN("Going to default to first menu driver...\n"); menu_driver_ctx = (const menu_ctx_driver_t*) menu_driver_find_handle(0); if (!menu_driver_ctx) { retroarch_fail(1, "find_menu_driver()"); return false; } } } break; case RARCH_MENU_CTL_PLAYLIST_INIT: { const char *path = (const char*)data; if (string_is_empty(path)) return false; menu_driver_playlist = playlist_init(path, COLLECTION_SIZE); } break; case RARCH_MENU_CTL_PLAYLIST_GET: { playlist_t **playlist = (playlist_t**)data; if (!playlist) return false; *playlist = menu_driver_playlist; } break; case RARCH_MENU_CTL_SYSTEM_INFO_GET: { struct retro_system_info **system = (struct retro_system_info**)data; if (!system) return false; *system = &menu_driver_system; } break; case RARCH_MENU_CTL_SYSTEM_INFO_DEINIT: libretro_free_system_info(&menu_driver_system); memset(&menu_driver_system, 0, sizeof(struct retro_system_info)); break; case RARCH_MENU_CTL_RENDER_MESSAGEBOX: if (menu_driver_ctx->render_messagebox) menu_driver_ctx->render_messagebox(menu_userdata, menu_driver_data->menu_state.msg); break; case RARCH_MENU_CTL_BLIT_RENDER: if (menu_driver_ctx->render) menu_driver_ctx->render(menu_userdata); break; case RARCH_MENU_CTL_RENDER: if (!menu_driver_data) return false; if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER) != BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_MESSAGEBOX)) BIT64_SET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER); if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER)) menu_display_set_framebuffer_dirty_flag(); if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_MESSAGEBOX) && !string_is_empty(menu_driver_data->menu_state.msg)) { menu_driver_ctl(RARCH_MENU_CTL_RENDER_MESSAGEBOX, NULL); if (ui_companion_is_on_foreground()) { const ui_companion_driver_t *ui = ui_companion_get_ptr(); if (ui->render_messagebox) ui->render_messagebox(menu_driver_data->menu_state.msg); } } if (BIT64_GET(menu_driver_data->state, MENU_STATE_BLIT)) { menu_animation_ctl(MENU_ANIMATION_CTL_UPDATE_TIME, NULL); menu_driver_ctl(RARCH_MENU_CTL_BLIT_RENDER, NULL); } if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL) && !runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL)) menu_display_libretro(); menu_driver_ctl(RARCH_MENU_CTL_SET_TEXTURE, NULL); menu_driver_data->state = 0; break; case RARCH_MENU_CTL_SHADER_DEINIT: #ifdef HAVE_SHADER_MANAGER if (menu_driver_shader) free(menu_driver_shader); menu_driver_shader = NULL; #endif break; case RARCH_MENU_CTL_SHADER_INIT: #ifdef HAVE_SHADER_MANAGER menu_driver_shader = (struct video_shader*) calloc(1, sizeof(struct video_shader)); if (!menu_driver_shader) return false; #endif break; case RARCH_MENU_CTL_SHADER_GET: { struct video_shader **shader = (struct video_shader**)data; if (!shader) return false; *shader = menu_driver_shader; } break; case RARCH_MENU_CTL_FRAME: if (!menu_driver_alive) return false; if (menu_driver_ctx->frame) menu_driver_ctx->frame(menu_userdata); break; case RARCH_MENU_CTL_SET_PREVENT_POPULATE: menu_driver_prevent_populate = true; break; case RARCH_MENU_CTL_UNSET_PREVENT_POPULATE: menu_driver_prevent_populate = false; break; case RARCH_MENU_CTL_IS_PREVENT_POPULATE: return menu_driver_prevent_populate; case RARCH_MENU_CTL_SET_TOGGLE: menu_driver_toggle(true); break; case RARCH_MENU_CTL_UNSET_TOGGLE: menu_driver_toggle(false); break; case RARCH_MENU_CTL_SET_ALIVE: menu_driver_alive = true; break; case RARCH_MENU_CTL_UNSET_ALIVE: menu_driver_alive = false; break; case RARCH_MENU_CTL_IS_ALIVE: return menu_driver_alive; case RARCH_MENU_CTL_SET_OWN_DRIVER: menu_driver_data_own = true; break; case RARCH_MENU_CTL_UNSET_OWN_DRIVER: if (!content_is_inited()) return false; menu_driver_data_own = false; break; case RARCH_MENU_CTL_SET_TEXTURE: if (menu_driver_ctx->set_texture) menu_driver_ctx->set_texture(); break; case RARCH_MENU_CTL_IS_SET_TEXTURE: if (!menu_driver_ctx) return false; return menu_driver_ctx->set_texture; case RARCH_MENU_CTL_OWNS_DRIVER: return menu_driver_data_own; case RARCH_MENU_CTL_DEINIT: menu_driver_ctl(RARCH_MENU_CTL_CONTEXT_DESTROY, NULL); if (menu_driver_ctl(RARCH_MENU_CTL_OWNS_DRIVER, NULL)) return true; if (menu_driver_data) { menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_FREE, NULL); menu_shader_free(menu_driver_data); menu_input_ctl(MENU_INPUT_CTL_DEINIT, NULL); menu_navigation_ctl(MENU_NAVIGATION_CTL_DEINIT, NULL); if (menu_driver_ctx && menu_driver_ctx->free) menu_driver_ctx->free(menu_userdata); if (menu_userdata) free(menu_userdata); menu_userdata = NULL; menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_DEINIT, NULL); menu_display_deinit(); menu_entries_ctl(MENU_ENTRIES_CTL_DEINIT, NULL); command_event(CMD_EVENT_HISTORY_DEINIT, NULL); core_info_deinit_list(); core_info_free_current_core(); free(menu_driver_data); } menu_driver_data = NULL; break; case RARCH_MENU_CTL_INIT: if (menu_driver_data) return true; menu_driver_data = (menu_handle_t*) menu_driver_ctx->init(&menu_userdata); if (!menu_driver_data || !menu_init(menu_driver_data)) { retroarch_fail(1, "init_menu()"); return false; } strlcpy(settings->menu.driver, menu_driver_ctx->ident, sizeof(settings->menu.driver)); if (menu_driver_ctx->lists_init) { if (!menu_driver_ctx->lists_init(menu_driver_data)) { retroarch_fail(1, "init_menu()"); return false; } } break; case RARCH_MENU_CTL_LOAD_NO_CONTENT_GET: { bool **ptr = (bool**)data; if (!ptr) return false; *ptr = (bool*)&menu_driver_load_no_content; } break; case RARCH_MENU_CTL_HAS_LOAD_NO_CONTENT: return menu_driver_load_no_content; case RARCH_MENU_CTL_SET_LOAD_NO_CONTENT: menu_driver_load_no_content = true; break; case RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT: menu_driver_load_no_content = false; break; case RARCH_MENU_CTL_NAVIGATION_INCREMENT: if (menu_driver_ctx->navigation_increment) menu_driver_ctx->navigation_increment(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_DECREMENT: if (menu_driver_ctx->navigation_decrement) menu_driver_ctx->navigation_decrement(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_SET: { bool *scroll = (bool*)data; if (!scroll) return false; if (menu_driver_ctx->navigation_set) menu_driver_ctx->navigation_set(menu_userdata, *scroll); } break; case RARCH_MENU_CTL_NAVIGATION_SET_LAST: if (menu_driver_ctx->navigation_set_last) menu_driver_ctx->navigation_set_last(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_ASCEND_ALPHABET: { size_t *ptr_out = (size_t*)data; if (!ptr_out) return false; if (menu_driver_ctx->navigation_ascend_alphabet) menu_driver_ctx->navigation_ascend_alphabet( menu_userdata, ptr_out); } case RARCH_MENU_CTL_NAVIGATION_DESCEND_ALPHABET: { size_t *ptr_out = (size_t*)data; if (!ptr_out) return false; if (menu_driver_ctx->navigation_descend_alphabet) menu_driver_ctx->navigation_descend_alphabet( menu_userdata, ptr_out); } break; case RARCH_MENU_CTL_NAVIGATION_CLEAR: { bool *pending_push = (bool*)data; if (!pending_push) return false; if (menu_driver_ctx->navigation_clear) menu_driver_ctx->navigation_clear( menu_userdata, pending_push); } break; case RARCH_MENU_CTL_POPULATE_ENTRIES: { menu_displaylist_info_t *info = (menu_displaylist_info_t*)data; if (!info) return false; if (menu_driver_ctx->populate_entries) menu_driver_ctx->populate_entries( menu_userdata, info->path, info->label, info->type); } break; case RARCH_MENU_CTL_LIST_GET_ENTRY: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_entry) { list->entry = NULL; return false; } list->entry = menu_driver_ctx->list_get_entry(menu_userdata, list->type, list->idx); } break; case RARCH_MENU_CTL_LIST_GET_SIZE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_size) { list->size = 0; return false; } list->size = menu_driver_ctx->list_get_size(menu_userdata, list->type); } break; case RARCH_MENU_CTL_LIST_GET_SELECTION: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_selection) { list->selection = 0; return false; } list->selection = menu_driver_ctx->list_get_selection(menu_userdata); } break; case RARCH_MENU_CTL_LIST_FREE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (menu_driver_ctx) { if (menu_driver_ctx->list_free) menu_driver_ctx->list_free(list->list, list->idx, list->list_size); } if (list->list) { file_list_free_userdata (list->list, list->idx); file_list_free_actiondata(list->list, list->idx); } } break; case RARCH_MENU_CTL_LIST_PUSH: { menu_ctx_displaylist_t *disp_list = (menu_ctx_displaylist_t*)data; if (menu_driver_ctx->list_push) if (menu_driver_ctx->list_push(menu_driver_data, menu_userdata, disp_list->info, disp_list->type) == 0) return true; } return false; case RARCH_MENU_CTL_LIST_CLEAR: { file_list_t *list = (file_list_t*)data; if (!list) return false; if (menu_driver_ctx->list_clear) menu_driver_ctx->list_clear(list); } break; case RARCH_MENU_CTL_TOGGLE: { bool *latch = (bool*)data; if (!latch) return false; if (menu_driver_ctx && menu_driver_ctx->toggle) menu_driver_ctx->toggle(menu_userdata, *latch); } break; case RARCH_MENU_CTL_REFRESH: { #if 0 bool refresh = false; menu_entries_ctl(MENU_ENTRIES_CTL_LIST_DEINIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_SETTINGS_DEINIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_INIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); #endif } break; case RARCH_MENU_CTL_CONTEXT_RESET: if (!menu_driver_ctx || !menu_driver_ctx->context_reset) return false; menu_driver_ctx->context_reset(menu_userdata); break; case RARCH_MENU_CTL_CONTEXT_DESTROY: if (!menu_driver_ctx || !menu_driver_ctx->context_destroy) return false; menu_driver_ctx->context_destroy(menu_userdata); break; case RARCH_MENU_CTL_SHADER_MANAGER_INIT: menu_shader_manager_init(menu_driver_data); break; case RARCH_MENU_CTL_LIST_SET_SELECTION: { file_list_t *list = (file_list_t*)data; if (!list) return false; if (!menu_driver_ctx || !menu_driver_ctx->list_set_selection) return false; menu_driver_ctx->list_set_selection(menu_userdata, list); } break; case RARCH_MENU_CTL_LIST_CACHE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!list || !menu_driver_ctx || !menu_driver_ctx->list_cache) return false; menu_driver_ctx->list_cache(menu_userdata, list->type, list->action); } break; case RARCH_MENU_CTL_LIST_INSERT: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!list || !menu_driver_ctx || !menu_driver_ctx->list_insert) return false; menu_driver_ctx->list_insert(menu_userdata, list->list, list->path, list->label, list->idx); } break; case RARCH_MENU_CTL_LOAD_IMAGE: { menu_ctx_load_image_t *load_image_info = (menu_ctx_load_image_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->load_image) return false; return menu_driver_ctx->load_image(menu_userdata, load_image_info->data, load_image_info->type); } case RARCH_MENU_CTL_ITERATE: { bool retcode = false; menu_ctx_iterate_t *iterate = (menu_ctx_iterate_t*)data; if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUICK_MENU, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUICK_MENU, NULL); menu_entries_flush_stack(NULL, MENU_SETTINGS); menu_display_set_msg_force(true); generic_action_ok_displaylist_push("", "", 0, 0, 0, ACTION_OK_DL_CONTENT_SETTINGS); if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUIT, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUIT, NULL); return false; } return true; } if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUIT, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUIT, NULL); return false; } if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_SHUTDOWN, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_SHUTDOWN, NULL); if (!command_event(CMD_EVENT_QUIT, NULL)) return false; return true; } if (!menu_driver_ctx || !menu_driver_ctx->iterate) return false; if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_ACTION, &retcode)) { iterate->action = pending_iter.action; pending_iter.action = MENU_ACTION_NOOP; } if (menu_driver_ctx->iterate(menu_driver_data, menu_userdata, iterate->action) == -1) return false; } break; case RARCH_MENU_CTL_ENVIRONMENT: { menu_ctx_environment_t *menu_environ = (menu_ctx_environment_t*)data; if (menu_driver_ctx->environ_cb) { if (menu_driver_ctx->environ_cb(menu_environ->type, menu_environ->data, menu_userdata) == 0) return true; } } return false; case RARCH_MENU_CTL_POINTER_TAP: { menu_ctx_pointer_t *point = (menu_ctx_pointer_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->pointer_tap) { point->retcode = 0; return false; } point->retcode = menu_driver_ctx->pointer_tap(menu_userdata, point->x, point->y, point->ptr, point->cbs, point->entry, point->action); } break; case RARCH_MENU_CTL_BIND_INIT: { menu_ctx_bind_t *bind = (menu_ctx_bind_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->bind_init) { bind->retcode = 0; return false; } bind->retcode = menu_driver_ctx->bind_init( bind->cbs, bind->path, bind->label, bind->type, bind->idx, bind->elem0, bind->elem1, bind->label_hash, bind->menu_label_hash); } break; case RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH: { size_t selection; if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection)) return false; if (!menu_driver_ctx || !menu_driver_ctx->update_thumbnail_path) return false; menu_driver_ctx->update_thumbnail_path(menu_userdata, selection); } break; case RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE: { if (!menu_driver_ctx || !menu_driver_ctx->update_thumbnail_image) return false; menu_driver_ctx->update_thumbnail_image(menu_userdata); } break; default: case RARCH_MENU_CTL_NONE: break; } return true; }
unsigned menu_event(uint64_t input, uint64_t trigger_input) { menu_animation_ctx_delta_t delta; float delta_time; /* Used for key repeat */ static float delay_timer = 0.0f; static float delay_count = 0.0f; unsigned ret = MENU_ACTION_NOOP; static bool initial_held = true; static bool first_held = false; bool set_scroll = false; bool mouse_enabled = false; size_t new_scroll_accel = 0; menu_input_t *menu_input = NULL; settings_t *settings = config_get_ptr(); if (input) { if (!first_held) { /* don't run anything first frame, only capture held inputs * for old_input_state. */ first_held = true; delay_timer = initial_held ? 12 : 6; delay_count = 0; } if (delay_count >= delay_timer) { uint64_t input_repeat = 0; BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_UP); BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_DOWN); BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_LEFT); BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_RIGHT); BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_L); BIT32_SET(input_repeat, RETRO_DEVICE_ID_JOYPAD_R); set_scroll = true; first_held = false; trigger_input |= input & input_repeat; menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL, &new_scroll_accel); new_scroll_accel = MIN(new_scroll_accel + 1, 64); } initial_held = false; } else { set_scroll = true; first_held = false; initial_held = true; } if (set_scroll) menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SCROLL_ACCEL, &new_scroll_accel); menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time); delta.current = delta_time; if (menu_animation_ctl(MENU_ANIMATION_CTL_IDEAL_DELTA_TIME_GET, &delta)) delay_count += delta.ideal; if (menu_input_dialog_get_display_kb()) { if (kbd_upper) strlcpy(kbd_grid, "!@#$%^&*()QWERTYUIOPASDFGHJKL:ZXCVBNM <>?", sizeof(kbd_grid)); else strlcpy(kbd_grid, "1234567890qwertyuiopasdfghjkl:zxcvbnm ,./", sizeof(kbd_grid)); if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) { if (kbd_index < 30) kbd_index = kbd_index + 10; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) { if (kbd_index >= 10) kbd_index = kbd_index - 10; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT)) { if (kbd_index < 39) kbd_index = kbd_index + 1; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT)) { if (kbd_index >= 1) kbd_index = kbd_index - 1; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y)) { kbd_upper = ! kbd_upper; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A)) { input_keyboard_event(true, kbd_grid[kbd_index], kbd_grid[kbd_index], 0, RETRO_DEVICE_KEYBOARD); } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B)) { input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); } /* send return key to close keyboard input window */ if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START)) input_keyboard_event(true, '\n', '\n', 0, RETRO_DEVICE_KEYBOARD); trigger_input = 0; } if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) ret = MENU_ACTION_UP; else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) ret = MENU_ACTION_DOWN; else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT)) ret = MENU_ACTION_LEFT; else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT)) ret = MENU_ACTION_RIGHT; else if (trigger_input & (UINT64_C(1) << settings->menu_scroll_up_btn)) ret = MENU_ACTION_SCROLL_UP; else if (trigger_input & (UINT64_C(1) << settings->menu_scroll_down_btn)) ret = MENU_ACTION_SCROLL_DOWN; else if (trigger_input & (UINT64_C(1) << settings->menu_cancel_btn)) ret = MENU_ACTION_CANCEL; else if (trigger_input & (UINT64_C(1) << settings->menu_ok_btn)) ret = MENU_ACTION_OK; else if (trigger_input & (UINT64_C(1) << settings->menu_search_btn)) ret = MENU_ACTION_SEARCH; else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y)) ret = MENU_ACTION_SCAN; else if (trigger_input & (UINT64_C(1) << settings->menu_default_btn)) ret = MENU_ACTION_START; else if (trigger_input & (UINT64_C(1) << settings->menu_info_btn)) ret = MENU_ACTION_INFO; else if (trigger_input & (UINT64_C(1) << RARCH_MENU_TOGGLE)) ret = MENU_ACTION_TOGGLE; if (menu_keyboard_key_state[RETROK_F11]) { command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL); menu_keyboard_key_state[RETROK_F11] = false; } if (runloop_cmd_press(trigger_input, RARCH_QUIT_KEY)) { int should_we_quit = true; if (!runloop_is_quit_confirm()) { if (settings && settings->confirm_on_exit) { if (!menu_dialog_is_active() && content_is_inited()) { if(menu_display_toggle_get_reason() != MENU_TOGGLE_REASON_USER) menu_display_toggle_set_reason(MENU_TOGGLE_REASON_MESSAGE); rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } menu_dialog_show_message(MENU_DIALOG_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT); should_we_quit = false; } if ((settings && !settings->confirm_on_exit) || should_we_quit) return MENU_ACTION_QUIT; } } mouse_enabled = settings->menu.mouse.enable; #ifdef HAVE_OVERLAY if (!mouse_enabled) mouse_enabled = !(settings->input.overlay_enable && input_overlay_is_alive(NULL)); #endif if (!(menu_input = menu_input_get_ptr())) return 0; if (!mouse_enabled) menu_input->mouse.ptr = 0; if (settings->menu.pointer.enable) menu_event_pointer(&ret); else { menu_input->pointer.x = 0; menu_input->pointer.y = 0; menu_input->pointer.dx = 0; menu_input->pointer.dy = 0; menu_input->pointer.accel = 0; menu_input->pointer.pressed[0] = false; menu_input->pointer.pressed[1] = false; menu_input->pointer.back = false; menu_input->pointer.ptr = 0; } return ret; }
static bool content_load_wrapper( content_ctx_info_t *content_info, bool launched_from_menu) { char name[PATH_MAX_LENGTH]; char msg[PATH_MAX_LENGTH]; char *fullpath = NULL; runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); #ifdef HAVE_MENU if (launched_from_menu) { /* redraw menu frame */ menu_display_set_msg_force(true); menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); fill_pathname_base(name, fullpath, sizeof(name)); } #endif if (!content_load(content_info)) goto error; if (launched_from_menu) { /** Show loading OSD message */ if (*fullpath) { snprintf(msg, sizeof(msg), "INFO - Loading %s ...", name); runloop_msg_queue_push(msg, 1, 1, false); } } /* Push entry to top of history playlist */ if (content_is_inited() || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *system = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) info = &system->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, fullpath, sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (*tmp) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && *tmp) { content_push_to_history_playlist( true, tmp, info); playlist_write_file(g_defaults.history); } } return true; error: if (launched_from_menu) { if (!string_is_empty(fullpath) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "Failed to load %s.\n", name); runloop_msg_queue_push(msg, 1, 90, false); } } return false; }
/* Time to exit out of the main loop? * Reasons for exiting: * a) Shutdown environment callback was invoked. * b) Quit key was pressed. * c) Frame count exceeds or equals maximum amount of frames to run. * d) Video driver no longer alive. * e) End of BSV movie and BSV EOF exit is true. (TODO/FIXME - explain better) */ static INLINE int runloop_iterate_time_to_exit(bool quit_key_pressed) { settings_t *settings = config_get_ptr(); bool time_to_exit = runloop_shutdown_initiated; time_to_exit = time_to_exit || quit_key_pressed; time_to_exit = time_to_exit || !video_driver_is_alive(); time_to_exit = time_to_exit || bsv_movie_ctl(BSV_MOVIE_CTL_END_EOF, NULL); time_to_exit = time_to_exit || (runloop_max_frames && (*(video_driver_get_frame_count_ptr()) >= runloop_max_frames)); time_to_exit = time_to_exit || runloop_exec; if (!time_to_exit) return 1; #ifdef HAVE_MENU if (!runloop_is_quit_confirm()) { if (settings && settings->confirm_on_exit) { if (menu_dialog_is_active()) return 1; if (content_is_inited()) { if(menu_display_toggle_get_reason() != MENU_TOGGLE_REASON_USER) menu_display_toggle_set_reason(MENU_TOGGLE_REASON_MESSAGE); rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } menu_dialog_show_message(MENU_DIALOG_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT); return 1; } } #endif if (runloop_exec) runloop_exec = false; if (runloop_core_shutdown_initiated && settings && settings->load_dummy_on_core_shutdown) { content_ctx_info_t content_info = {0}; if (!task_push_content_load_default( NULL, NULL, &content_info, CORE_TYPE_DUMMY, CONTENT_MODE_LOAD_NOTHING_WITH_DUMMY_CORE, NULL, NULL)) return -1; /* Loads dummy core instead of exiting RetroArch completely. * Aborts core shutdown if invoked. */ runloop_shutdown_initiated = false; runloop_core_shutdown_initiated = false; return 1; } /* Quits out of RetroArch main loop. */ return -1; }
/** * task_load_content: * * Loads content into currently selected core. * Will also optionally push the content entry to the history playlist. * * Returns: true (1) if successful, otherwise false (0). **/ static bool task_load_content(content_ctx_info_t *content_info, bool launched_from_menu, enum content_mode_load mode) { char name[256]; char msg[256]; name[0] = msg[0] = '\0'; if (launched_from_menu) { #ifdef HAVE_MENU /* redraw menu frame */ menu_display_set_msg_force(true); menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!path_is_empty(RARCH_PATH_CONTENT)) fill_pathname_base(name, path_get(RARCH_PATH_CONTENT), sizeof(name)); #endif /** Show loading OSD message */ if (!string_is_empty(path_get(RARCH_PATH_CONTENT))) { snprintf(msg, sizeof(msg), "%s %s ...", msg_hash_to_str(MSG_LOADING), name); runloop_msg_queue_push(msg, 2, 1, true); } } if (!content_load(content_info)) goto error; /* Push entry to top of history playlist */ if (content_is_inited() || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *system = NULL; tmp[0] = '\0'; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) info = &system->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (!string_is_empty(tmp)) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && *tmp) { const char *core_path = NULL; const char *core_name = NULL; playlist_t *playlist_tmp = g_defaults.content_history; switch (path_is_media_type(tmp)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.video_history; core_name = "movieplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.music_history; core_name = "musicplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER playlist_tmp = g_defaults.image_history; core_name = "imageviewer"; core_path = "builtin"; #endif break; default: core_path = path_get(RARCH_PATH_CORE); core_name = info->library_name; break; } if (content_push_to_history_playlist(playlist_tmp, tmp, core_name, core_path)) playlist_write_file(playlist_tmp); } } return true; error: if (launched_from_menu) { if (!path_is_empty(RARCH_PATH_CONTENT) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "%s %s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD), name); runloop_msg_queue_push(msg, 2, 90, true); } } return false; }