static bool input_autoconfigure_joypad_from_conf_dir( autoconfig_params_t *params) { size_t i; int ret = 0; int index = -1; int current_best = 0; config_file_t *conf = NULL; struct string_list *list = NULL; char path[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); fill_pathname_join(path,settings->input.autoconfig_dir, settings->input.joypad_driver, sizeof(path)); if (settings) list = dir_list_new(path, "cfg", false); if (!list || !list->size) list = dir_list_new(settings->input.autoconfig_dir, "cfg", false); if(!list) return false; RARCH_LOG("Autoconfig: %d profiles found\n", list->size); for (i = 0; i < list->size; i++) { conf = config_file_new(list->elems[i].data); ret = input_try_autoconfigure_joypad_from_conf(conf, params); if(ret >= current_best) { index = i; current_best = ret; } config_file_free(conf); } if(index >= 0 && current_best > 0) { RARCH_LOG("Autoconf: best configuration score=%d\n", current_best); conf = config_file_new(list->elems[index].data); input_autoconfigure_joypad_add(conf, params); config_file_free(conf); } else ret = 0; string_list_free(list); if (ret == 0) return false; return true; }
static void find_and_set_first_file(void) { //Last fallback - we'll need to start the first executable file // we can find in the RetroArch cores directory #if defined(_XBOX) char ** dir_list = dir_list_new("game:\\", ".xex"); #elif defined(__CELLOS_LV2__) char ** dir_list = dir_list_new(LIBRETRO_DIR_PATH, ".SELF"); #endif if (!dir_list) { RARCH_ERR("Failed last fallback - RetroArch Salamander will exit.\n"); return; } char * first_executable = dir_list[0]; if(first_executable) { #ifdef _XBOX //Check if it's RetroArch Salamander itself - if so, first_executable needs to //be overridden char fname_tmp[MAX_PATH_LENGTH]; fill_pathname_base(fname_tmp, first_executable, sizeof(fname_tmp)); if(strcmp(fname_tmp, "RetroArch-Salamander.xex") == 0) { RARCH_WARN("First entry is RetroArch Salamander itself, increment entry by one and check if it exists.\n"); first_executable = dir_list[1]; fill_pathname_base(fname_tmp, first_executable, sizeof(fname_tmp)); if(!first_executable) { RARCH_WARN("There is no second entry - no choice but to boot RetroArch Salamander\n"); first_executable = dir_list[0]; fill_pathname_base(fname_tmp, first_executable, sizeof(fname_tmp)); } } snprintf(first_executable, sizeof(first_executable), "game:\\%s", fname_tmp); #endif RARCH_LOG("Start first entry in libretro cores dir: [%s].\n", first_executable); strlcpy(libretro_path, first_executable, sizeof(libretro_path)); } else { RARCH_ERR("Failed last fallback - RetroArch Salamander will exit.\n"); } dir_list_free(dir_list); }
database_info_handle_t *database_info_dir_init(const char *dir, enum database_type type, retro_task_t *task, bool show_hidden_files) { core_info_list_t *core_info_list = NULL; struct string_list *list = NULL; database_info_handle_t *db = (database_info_handle_t*) calloc(1, sizeof(*db)); if (!db) return NULL; core_info_get_list(&core_info_list); list = dir_list_new(dir, core_info_list->all_ext, false, show_hidden_files, false, true); if (!list) { free(db); return NULL; } dir_list_prioritize(list); db->list = list; db->list_ptr = 0; db->status = DATABASE_STATUS_ITERATE; db->type = type; return db; }
static void lakka_init_items(lakka_handle_t *lakka, int i, menu_category_t *category, core_info_t *info, const char* path) { int num_items, j; struct string_list *list = NULL; if (category == NULL || info == NULL) return; list = (struct string_list*)dir_list_new(path, info->supported_extensions, true); dir_list_sort(list, true); num_items = list ? list->size : 0; for (j = 0; j < num_items; j++) { if (list->elems[j].attr.i == RARCH_DIRECTORY) // is a directory lakka_init_items(lakka, i, category, info, list->elems[j].data); else { lakka_init_item(lakka, i, j, category, info, list, path_basename(list->elems[j].data)); } } string_list_free(list); }
static bool find_first_libretro(char *path, size_t size, const char *dir, const char *rom_path) { bool ret = false; const char *ext = path_get_extension(rom_path); if (!ext || !*ext) { RARCH_ERR("Path has no extension. Cannot infer libretro implementation.\n"); return false; } RARCH_LOG("Searching for valid libretro implementation in: \"%s\".\n", dir); struct string_list *list = dir_list_new(dir, DYNAMIC_EXT, false); if (!list) { RARCH_ERR("Couldn't open directory: \"%s\".\n", dir); return false; } for (size_t i = 0; i < list->size && !ret; i++) { RARCH_LOG("Checking library: \"%s\".\n", list->elems[i].data); dylib_t lib = dylib_load(list->elems[i].data); if (!lib) continue; void (*proc)(struct retro_system_info*) = (void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info"); if (!proc) { dylib_close(lib); continue; } struct retro_system_info info = {0}; proc(&info); if (!info.valid_extensions) { dylib_close(lib); continue; } struct string_list *supported_ext = string_split(info.valid_extensions, "|"); if (string_list_find_elem(supported_ext, ext)) { strlcpy(path, list->elems[i].data, size); ret = true; } string_list_free(supported_ext); dylib_close(lib); } dir_list_free(list); return ret; }
static void menu_entries_content_list_push( file_list_t *list, core_info_t *info, const char* path) { unsigned j; struct string_list *str_list = NULL; if (!info) return; str_list = (struct string_list*)dir_list_new(path, info->supported_extensions, true); if (!str_list) return; dir_list_sort(str_list, true); for (j = 0; j < str_list->size; j++) { const char *name = str_list->elems[j].data; if (!name) continue; if (str_list->elems[j].attr.i == RARCH_DIRECTORY) menu_entries_content_list_push(list, info, name); else menu_list_push( list, name, "content_actions", MENU_FILE_CONTENTLIST_ENTRY, 0); } string_list_free(str_list); }
rarch_softfilter_t *rarch_softfilter_new(const char *filter_config, unsigned threads, enum retro_pixel_format in_pixel_format, unsigned max_width, unsigned max_height) { softfilter_simd_mask_t cpu_features = retro_get_cpu_features(); char basedir[PATH_MAX_LENGTH] = {0}; struct string_list *plugs = NULL; rarch_softfilter_t *filt = NULL; (void)basedir; filt = (rarch_softfilter_t*)calloc(1, sizeof(*filt)); if (!filt) return NULL; filt->conf = config_file_new(filter_config); if (!filt->conf) { RARCH_ERR("[SoftFilter]: Did not find config: %s\n", filter_config); goto error; } #if defined(HAVE_DYLIB) fill_pathname_basedir(basedir, filter_config, sizeof(basedir)); plugs = dir_list_new(basedir, EXT_EXECUTABLES, false, false); if (!plugs) { RARCH_ERR("[SoftFilter]: Could not build up string list...\n"); goto error; } #endif if (!append_softfilter_plugs(filt, plugs)) { RARCH_ERR("[SoftFitler]: Failed to append softfilter plugins...\n"); goto error; } if (plugs) string_list_free(plugs); plugs = NULL; if (!create_softfilter_graph(filt, in_pixel_format, max_width, max_height, cpu_features, threads)) { RARCH_ERR("[SoftFitler]: Failed to create softfilter graph...\n"); goto error; } return filt; error: if (plugs) string_list_free(plugs); plugs = NULL; rarch_softfilter_free(filt); return NULL; }
void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver) { size_t i; if (!g_settings.input.autodetect_enable) return; // This will be the case if input driver is reinit. No reason to spam autoconfigure messages // every time (fine in log). bool block_osd_spam = g_settings.input.autoconfigured[index] && name; for (i = 0; i < RARCH_BIND_LIST_END; i++) { g_settings.input.autoconf_binds[index][i].joykey = NO_BTN; g_settings.input.autoconf_binds[index][i].joyaxis = AXIS_NONE; } g_settings.input.autoconfigured[index] = false; if (!name) return; // false = load from both cfg files and internal bool internal_only = !*g_settings.input.autoconfig_dir; #ifdef HAVE_BUILTIN_AUTOCONFIG // First internal for (i = 0; input_builtin_autoconfs[i]; i++) { config_file_t *conf = config_file_new_from_string(input_builtin_autoconfs[i]); bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, block_osd_spam); config_file_free(conf); if (success) break; } #endif // Now try files if (!internal_only) { struct string_list *list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false); if (!list) return; for (i = 0; i < list->size; i++) { config_file_t *conf = config_file_new(list->elems[i].data); if (!conf) continue; bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, block_osd_spam); config_file_free(conf); if (success) break; } string_list_free(list); } }
/*We need to set libretro to the first entry in the cores * directory so that it will be saved to the config file */ static void find_first_libretro_core(char *first_file, size_t size_of_first_file, const char *dir, const char * ext) { size_t i; bool ret = false; struct string_list *list = dir_list_new(dir, ext, false, true, false, false); if (!list) { RARCH_ERR("Couldn't read directory." " Cannot infer default libretro core.\n"); return; } RARCH_LOG("Searching for valid libretro implementation in: \"%s\".\n", dir); for (i = 0; i < list->size && !ret; i++) { char fname[PATH_MAX_LENGTH]; char salamander_name[PATH_MAX_LENGTH]; const char *libretro_elem = (const char*)list->elems[i].data; RARCH_LOG("Checking library: \"%s\".\n", libretro_elem); if (!libretro_elem) continue; fill_pathname_base(fname, libretro_elem, sizeof(fname)); if (!frontend_driver_get_salamander_basename( salamander_name, sizeof(salamander_name))) break; if (!strncmp(fname, salamander_name, sizeof(fname))) { if (list->size == (i + 1)) { RARCH_WARN("Entry is RetroArch Salamander itself, " "but is last entry. No choice but to set it.\n"); strlcpy(first_file, fname, size_of_first_file); } continue; } strlcpy(first_file, fname, size_of_first_file); RARCH_LOG("First found libretro core is: \"%s\".\n", first_file); ret = true; } dir_list_free(list); }
void rarch_manage_libretro_set_first_file(char *first_file, size_t size_of_first_file, const char *libretro_path, const char * exe_ext) { //We need to set libretro to the first entry in the cores //directory so that it will be saved to the config file struct string_list *dir_list = dir_list_new(libretro_path, exe_ext, false); const char * first_exe; if (!dir_list) { RARCH_ERR("Couldn't read directory.\n"); RARCH_ERR("Failed to set first entry to libretro path.\n"); goto end; } first_exe = dir_list->elems[0].data; if(first_exe) { #ifdef _XBOX char fname_tmp[PATH_MAX]; fill_pathname_base(fname_tmp, first_exe, sizeof(fname_tmp)); if(strcmp(fname_tmp, "RetroArch-Salamander.xex") == 0) { RARCH_WARN("First entry is RetroArch Salamander itself, increment entry by one and check if it exists.\n"); first_exe = dir_list->elems[1].data; fill_pathname_base(fname_tmp, first_exe, sizeof(fname_tmp)); if(!first_exe) { RARCH_ERR("Unlikely error happened - no second entry - no choice but to set it to RetroArch Salamander\n"); first_exe = dir_list->elems[0].data; fill_pathname_base(fname_tmp, first_exe, sizeof(fname_tmp)); } } strlcpy(first_file, fname_tmp, size_of_first_file); #else strlcpy(first_file, first_exe, size_of_first_file); #endif RARCH_LOG("Set first entry in libretro core dir to libretro path: [%s].\n", first_file); } end: dir_list_free(dir_list); }
static int find_rom_canonical_name(const char *hash, char *game_name, size_t max_len) { // TODO: Error handling size_t i; int rv; int fd; int offs; char *dat_path; const char *dat_name; const char *dat_name_dot; struct string_list *files; files = dir_list_new("db", "dat", false); if (!files) { return -1; } for (i = 0; i < files->size; i++) { dat_path = files->elems[i].data; dat_name = path_basename(dat_path); dat_name_dot = strchr(dat_name, '.'); if (!dat_name_dot) { continue; } offs = dat_name_dot - dat_name + 1; memcpy(game_name, dat_name, offs); fd = open(dat_path, O_RDONLY); if (fd < 0) { continue; } if (find_hash(fd, hash, game_name + offs, max_len - offs) == 0) { rv = 0; close(fd); goto clean; } close(fd); } rv = -1; clean: dir_list_free(files); return rv; }
//We need to set libretro to the first entry in the cores //directory so that it will be saved to the config file static void find_first_libretro_core(char *first_file, size_t size_of_first_file, const char *dir, const char * ext) { struct string_list *list; size_t i; bool ret = false; RARCH_LOG("Searching for valid libretro implementation in: \"%s\".\n", dir); list = (struct string_list*)dir_list_new(dir, ext, false); if (!list) { RARCH_ERR("Couldn't read directory. Cannot infer default libretro core.\n"); return; } for (i = 0; i < list->size && !ret; i++) { char fname[PATH_MAX]; const char *libretro_elem = (const char*)list->elems[i].data; RARCH_LOG("Checking library: \"%s\".\n", libretro_elem); if (!libretro_elem) continue; fill_pathname_base(fname, libretro_elem, sizeof(fname)); if (strncmp(fname, SALAMANDER_FILE, sizeof(fname)) == 0) { if ((i + 1) == list->size) { RARCH_WARN("Entry is RetroArch Salamander itself, but is last entry. No choice but to set it.\n"); strlcpy(first_file, fname, size_of_first_file); } continue; } strlcpy(first_file, fname, size_of_first_file); RARCH_LOG("First found libretro core is: \"%s\".\n", first_file); ret = true; } dir_list_free(list); }
rarch_dsp_filter_t *rarch_dsp_filter_new( const char *filter_config, float sample_rate) { char basedir[PATH_MAX_LENGTH] = {0}; struct string_list *plugs = NULL; rarch_dsp_filter_t *dsp = NULL; (void)basedir; dsp = (rarch_dsp_filter_t*)calloc(1, sizeof(*dsp)); if (!dsp) return NULL; dsp->conf = config_file_new(filter_config); if (!dsp->conf) /* Did not find config. */ goto error; #if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB) fill_pathname_basedir(basedir, filter_config, sizeof(basedir)); plugs = dir_list_new(basedir, EXT_EXECUTABLES, false, false); if (!plugs) goto error; #endif #if defined(HAVE_DYLIB) || defined(HAVE_FILTERS_BUILTIN) if (!append_plugs(dsp, plugs)) goto error; #endif if (plugs) string_list_free(plugs); plugs = NULL; if (!create_filter_graph(dsp, sample_rate)) goto error; return dsp; error: if (plugs) string_list_free(plugs); rarch_dsp_filter_free(dsp); return NULL; }
static void init_shader_dir(void) { unsigned i; if (!*g_settings.video.shader_dir) return; g_extern.shader_dir.list = dir_list_new(g_settings.video.shader_dir, "cg|cgp|glsl|glslp", false); if (!g_extern.shader_dir.list || g_extern.shader_dir.list->size == 0) { deinit_shader_dir(); return; } g_extern.shader_dir.ptr = 0; dir_list_sort(g_extern.shader_dir.list, false); for (i = 0; i < g_extern.shader_dir.list->size; i++) RARCH_LOG("Found shader \"%s\"\n", g_extern.shader_dir.list->elems[i].data); }
static bool directory_parse(void *data, const char *path) { filebrowser_t *filebrowser = (filebrowser_t*)data; struct string_list *list = dir_list_new(path, filebrowser->current_dir.extensions, true); if(!list || list->size < 1) return false; dir_list_sort(list, true); filebrowser->current_dir.ptr = 0; strlcpy(filebrowser->current_dir.directory_path, path, sizeof(filebrowser->current_dir.directory_path)); if (filebrowser->list) dir_list_free(filebrowser->list); filebrowser->list = list; return true; }
static void task_database_handler(retro_task_t *task) { const char *name = NULL; database_info_handle_t *dbinfo = NULL; database_state_handle_t *dbstate = NULL; db_handle_t *db = NULL; if (!task) goto task_finished; db = (db_handle_t*)task->state; if (!db) goto task_finished; if (!db->scan_started) { db->scan_started = true; if (!string_is_empty(db->fullpath)) { if (db->is_directory) db->handle = database_info_dir_init(db->fullpath, DATABASE_TYPE_ITERATE, task, db->show_hidden_files); else db->handle = database_info_file_init(db->fullpath, DATABASE_TYPE_ITERATE, task); } task_free_title(task); if (db->handle) db->handle->status = DATABASE_STATUS_ITERATE_BEGIN; } dbinfo = db->handle; dbstate = &db->state; if (!dbinfo || task_get_cancelled(task)) goto task_finished; switch (dbinfo->status) { case DATABASE_STATUS_ITERATE_BEGIN: if (dbstate && !dbstate->list) { if (!string_is_empty(db->content_database_path)) dbstate->list = dir_list_new( db->content_database_path, "rdb", false, db->show_hidden_files, false, false); /* If the scan path matches a database path exactly then * save time by only processing that database. */ if (dbstate->list && db->is_directory) { size_t i; char *dirname = NULL; if (!string_is_empty(db->fullpath)) dirname = find_last_slash(db->fullpath) + 1; if (!string_is_empty(dirname)) { for (i = 0; i < dbstate->list->size; i++) { const char *data = dbstate->list->elems[i].data; char *dbname = NULL; bool strmatch = false; char *dbpath = strdup(data); path_remove_extension(dbpath); dbname = find_last_slash(dbpath) + 1; strmatch = strcasecmp(dbname, dirname) == 0; free(dbpath); if (strmatch) { struct string_list *single_list = string_list_new(); string_list_append(single_list, data, dbstate->list->elems[i].attr); dir_list_free(dbstate->list); dbstate->list = single_list; break; } } } } } dbinfo->status = DATABASE_STATUS_ITERATE_START; break; case DATABASE_STATUS_ITERATE_START: name = database_info_get_current_element_name(dbinfo); task_database_cleanup_state(dbstate); dbstate->list_index = 0; dbstate->entry_index = 0; task_database_iterate_start(dbinfo, name); break; case DATABASE_STATUS_ITERATE: if (task_database_iterate(db, dbstate, dbinfo) == 0) { dbinfo->status = DATABASE_STATUS_ITERATE_NEXT; dbinfo->type = DATABASE_TYPE_ITERATE; } break; case DATABASE_STATUS_ITERATE_NEXT: if (task_database_iterate_next(dbinfo) == 0) { dbinfo->status = DATABASE_STATUS_ITERATE_START; dbinfo->type = DATABASE_TYPE_ITERATE; } else { const char *msg = NULL; if (db->is_directory) msg = msg_hash_to_str(MSG_SCANNING_OF_DIRECTORY_FINISHED); else msg = msg_hash_to_str(MSG_SCANNING_OF_FILE_FINISHED); #ifdef RARCH_INTERNAL runloop_msg_queue_push(msg, 0, 180, true); #else fprintf(stderr, "msg: %s\n", msg); #endif ui_companion_driver_notify_refresh(); goto task_finished; } break; default: case DATABASE_STATUS_FREE: case DATABASE_STATUS_NONE: goto task_finished; } return; task_finished: if (task) task_set_finished(task, true); if (dbstate) { if (dbstate->list) dir_list_free(dbstate->list); } if (db) { if (!string_is_empty(db->playlist_directory)) free(db->playlist_directory); if (!string_is_empty(db->content_database_path)) free(db->content_database_path); if (!string_is_empty(db->fullpath)) free(db->fullpath); if (db->state.buf) free(db->state.buf); if (db->handle) database_info_free(db->handle); free(db); } if (dbinfo) free(dbinfo); }
static void *gfx_ctx_drm_init(void *video_driver) { int fd, i; unsigned monitor_index; unsigned gpu_index = 0; const char *gpu = NULL; struct string_list *gpu_descriptors = NULL; gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*) calloc(1, sizeof(gfx_ctx_drm_data_t)); if (!drm) return NULL; gpu_descriptors = dir_list_new("/dev/dri", NULL, false, true, false, false); nextgpu: free_drm_resources(drm); if (!gpu_descriptors || gpu_index == gpu_descriptors->size) { RARCH_ERR("[KMS]: Couldn't find a suitable DRM device.\n"); goto error; } gpu = gpu_descriptors->elems[gpu_index++].data; drm->drm = filestream_open(gpu, RFILE_MODE_READ_WRITE, -1); if (!drm->drm) { RARCH_WARN("[KMS]: Couldn't open DRM device.\n"); goto nextgpu; } fd = filestream_get_fd(drm->drm); if (!drm_get_resources(fd)) goto nextgpu; if (!drm_get_connector(fd)) goto nextgpu; if (!drm_get_encoder(fd)) goto nextgpu; drm_setup(fd); /* First mode is assumed to be the "optimal" * one for get_video_size() purposes. */ drm->fb_width = g_drm_connector->modes[0].hdisplay; drm->fb_height = g_drm_connector->modes[0].vdisplay; g_gbm_dev = gbm_create_device(fd); if (!g_gbm_dev) { RARCH_WARN("[KMS]: Couldn't create GBM device.\n"); goto nextgpu; } dir_list_free(gpu_descriptors); /* Setup the flip handler. */ g_drm_fds.fd = fd; g_drm_fds.events = POLLIN; g_drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; g_drm_evctx.page_flip_handler = drm_flip_handler; g_drm_fd = fd; return drm; error: dir_list_free(gpu_descriptors); gfx_ctx_drm_destroy_resources(drm); if (drm) free(drm); return NULL; }
static bool input_autoconfigure_joypad_from_conf_dir( autoconfig_params_t *params) { size_t i; char path[PATH_MAX_LENGTH]; int ret = 0; int index = -1; int current_best = 0; config_file_t *conf = NULL; struct string_list *list = NULL; settings_t *settings = config_get_ptr(); if (!settings) return false; fill_pathname_join(path, settings->input.autoconfig_dir, settings->input.joypad_driver, sizeof(path)); list = dir_list_new(path, "cfg", false, false); if (!list || !list->size) list = dir_list_new(settings->input.autoconfig_dir, "cfg", false, false); if(!list) return false; RARCH_LOG("Autodetect: %d profiles found\n", list->size); for (i = 0; i < list->size; i++) { conf = config_file_new(list->elems[i].data); ret = input_try_autoconfigure_joypad_from_conf(conf, params); if(ret >= current_best) { index = i; current_best = ret; } config_file_free(conf); } if(index >= 0 && current_best > 0) { conf = config_file_new(list->elems[index].data); RARCH_LOG("Autodetect: selected configuration: %s\n", conf->path); input_autoconfigure_joypad_add(conf, params); config_file_free(conf); ret = 1; } else { char msg[PATH_MAX_LENGTH]; RARCH_LOG("Autodetect: no profiles found for %s (%d/%d)", params->name, params->vid, params->pid); snprintf(msg, sizeof(msg), "%s (%ld/%ld) not configured", params->name, (long)params->vid, (long)params->pid); rarch_main_msg_queue_push(msg, 0, 60, false); ret = 0; } string_list_free(list); if (ret == 0) return false; return true; }
static int zarch_zui_render_lay_root_load(zui_t *zui, struct zui_tabbed *tabbed) { char parent_dir[PATH_MAX_LENGTH]; settings_t *settings = config_get_ptr(); core_info_list_t *list = NULL; parent_dir[0] = '\0'; if (zarch_zui_tab(zui, tabbed, "Load", 1)) { unsigned cwd_offset; if (!zui->load_cwd) zui->load_cwd = strdup(settings->directory.menu_content); if (!zui->load_dlist) { core_info_t *core_info = NULL; core_info_get_current_core(&core_info); zui->load_dlist = dir_list_new(zui->load_cwd, core_info->supported_extensions, true, true, false, true); dir_list_sort(zui->load_dlist, true); zui->load_dlist_first = 0; } cwd_offset = MIN(strlen(zui->load_cwd), 60); zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]); if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home")) zarch_zui_render_lay_root_load_free(zui); if (zui->load_dlist) { fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir)); if (!string_is_empty(parent_dir) && zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL, false /* TODO/FIXME */)) { zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir); } else { static int gamepad_index = 0; unsigned size = zui->load_dlist->size; unsigned i, j = 1; unsigned skip = 0; for (i = 0; i < size; ++i) { const char *basename = path_basename(zui->load_dlist->elems[i].data); if (basename[0] != '.') break; skip++; } if (zarch_zui_gamepad_input(zui, &gamepad_index, &zui->load_dlist_first, skip)) zui->load_dlist_first = gamepad_index; for (i = skip + zui->load_dlist_first; i < size; ++i) { char label[PATH_MAX_LENGTH]; const char *path = NULL; const char *basename = NULL; if (j > 10) break; label[0] = '\0'; path = zui->load_dlist->elems[i].data; basename = path_basename(path); *label = 0; strncat(label, " ", sizeof(label)-1); strncat(label, basename, sizeof(label)-1); if (path_is_directory(path)) strncat(label, "/", sizeof(label)-1); if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * ZUI_ITEM_SIZE_PX, label, i, NULL, gamepad_index == (signed)(i-skip))) { if (path_is_directory(path)) { zarch_zui_render_lay_root_load_set_new_path(zui, path); break; } zui->pick_cores = NULL; zui->pick_supported = 0; strlcpy(zui->pick_content, path, sizeof(zui->pick_content)); core_info_get_list(&list); core_info_list_get_supported_cores(list, path, &zui->pick_cores, &zui->pick_supported); zarch_layout = LAY_PICK_CORE; break; } j++; } } } } else if (zui->load_dlist) { dir_list_free(zui->load_dlist); zui->load_dlist = NULL; } return 0; }
void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver) { if (!g_settings.input.autodetect_enable) return; // This will be the case if input driver is reinit. No reason to spam autoconfigure messages // every time (fine in log). bool block_osd_spam = g_settings.input.autoconfigured[index] && name; for (unsigned i = 0; i < RARCH_BIND_LIST_END; i++) { g_settings.input.autoconf_binds[index][i].joykey = NO_BTN; g_settings.input.autoconf_binds[index][i].joyaxis = AXIS_NONE; } g_settings.input.autoconfigured[index] = false; if (!name) return; if (!*g_settings.input.autoconfig_dir) return; struct string_list *list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false); if (!list) return; char ident[1024]; char input_driver[1024]; for (size_t i = 0; i < list->size; i++) { *ident = *input_driver = '\0'; config_file_t *conf = config_file_new(list->elems[i].data); if (!conf) continue; config_get_array(conf, "input_device", ident, sizeof(ident)); config_get_array(conf, "input_driver", input_driver, sizeof(input_driver)); if (!strcmp(ident, name) && !strcmp(driver, input_driver)) { g_settings.input.autoconfigured[index] = true; input_autoconfigure_joypad_conf(conf, g_settings.input.autoconf_binds[index]); char msg[512]; snprintf(msg, sizeof(msg), "Joypad port #%u (%s) configured.", index, name); if (!block_osd_spam) msg_queue_push(g_extern.msg_queue, msg, 0, 60); RARCH_LOG("%s\n", msg); config_file_free(conf); break; } else config_file_free(conf); } string_list_free(list); }
core_info_list_t *core_info_list_new(const char *modules_path) { struct string_list *contents = dir_list_new(modules_path, EXT_EXECUTABLES, false); size_t all_ext_len, i; core_info_t *core_info = NULL; core_info_list_t *core_info_list = NULL; if (!contents) return NULL; core_info_list = (core_info_list_t*)calloc(1, sizeof(*core_info_list)); if (!core_info_list) goto error; core_info = (core_info_t*)calloc(contents->size, sizeof(*core_info)); if (!core_info) goto error; core_info_list->list = core_info; core_info_list->count = contents->size; for (i = 0; i < contents->size; i++) { char info_path_base[PATH_MAX], info_path[PATH_MAX]; core_info[i].path = strdup(contents->elems[i].data); if (!core_info[i].path) break; fill_pathname_base(info_path_base, contents->elems[i].data, sizeof(info_path_base)); path_remove_extension(info_path_base); #if defined(RARCH_MOBILE) || defined(RARCH_CONSOLE) char *substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; #endif strlcat(info_path_base, ".info", sizeof(info_path_base)); fill_pathname_join(info_path, (*g_settings.libretro_info_path) ? g_settings.libretro_info_path : modules_path, info_path_base, sizeof(info_path)); core_info[i].data = config_file_new(info_path); if (core_info[i].data) { config_get_string(core_info[i].data, "display_name", &core_info[i].display_name); if (config_get_string(core_info[i].data, "supported_extensions", &core_info[i].supported_extensions) && core_info[i].supported_extensions) core_info[i].supported_extensions_list = string_split(core_info[i].supported_extensions, "|"); if (config_get_string(core_info[i].data, "authors", &core_info[i].authors) && core_info[i].authors) core_info[i].authors_list = string_split(core_info[i].authors, "|"); } if (!core_info[i].display_name) core_info[i].display_name = strdup(path_basename(core_info[i].path)); } all_ext_len = 0; for (i = 0; i < core_info_list->count; i++) { all_ext_len += core_info_list->list[i].supported_extensions ? (strlen(core_info_list->list[i].supported_extensions) + 2) : 0; } if (all_ext_len) { all_ext_len += strlen("|zip"); core_info_list->all_ext = (char*)calloc(1, all_ext_len); } if (core_info_list->all_ext) { for (i = 0; i < core_info_list->count; i++) { if (core_info_list->list[i].supported_extensions) { strlcat(core_info_list->all_ext, core_info_list->list[i].supported_extensions, all_ext_len); strlcat(core_info_list->all_ext, "|", all_ext_len); } } strlcat(core_info_list->all_ext, "|zip", all_ext_len); } dir_list_free(contents); return core_info_list; error: if (contents) dir_list_free(contents); core_info_list_free(core_info_list); return NULL; }
int menu_entries_parse_list( file_list_t *list, file_list_t *menu_list, const char *dir, const char *label, unsigned type, unsigned default_type_plain, const char *exts, rarch_setting_t *setting) { size_t i, list_size; bool path_is_compressed, push_dir; int device = 0; struct string_list *str_list = NULL; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); (void)device; if (!list || !menu_list) return -1; menu_list_clear(list); if (!*dir) { menu_entries_parse_drive_list(list); menu_driver_populate_entries(dir, label, type); return 0; } #if defined(GEKKO) && defined(HW_RVL) slock_lock(gx_device_mutex); device = gx_get_device_from_path(dir); if (device != -1 && !gx_devices[device].mounted && gx_devices[device].interface->isInserted()) fatMountSimple(gx_devices[device].name, gx_devices[device].interface); slock_unlock(gx_device_mutex); #endif path_is_compressed = path_is_compressed_file(dir); push_dir = (setting && setting->browser_selection_type == ST_DIR); if (path_is_compressed) str_list = compressed_file_list_new(dir,exts); else str_list = dir_list_new(dir, settings->menu.navigation.browser.filter.supported_extensions_enable ? exts : NULL, true); if (push_dir) menu_list_push(list, "<Use this directory>", "", MENU_FILE_USE_DIRECTORY, 0); if (!str_list) return -1; dir_list_sort(str_list, true); list_size = str_list->size; for (i = 0; i < str_list->size; i++) { bool is_dir; const char *path = NULL; menu_file_type_t file_type = MENU_FILE_NONE; switch (str_list->elems[i].attr.i) { case RARCH_DIRECTORY: file_type = MENU_FILE_DIRECTORY; break; case RARCH_COMPRESSED_ARCHIVE: file_type = MENU_FILE_CARCHIVE; break; case RARCH_COMPRESSED_FILE_IN_ARCHIVE: file_type = MENU_FILE_IN_CARCHIVE; break; case RARCH_PLAIN_FILE: default: if (!strcmp(label, "detect_core_list")) { if (path_is_compressed_file(str_list->elems[i].data)) { /* in case of deferred_core_list we have to interpret * every archive as an archive to disallow instant loading */ file_type = MENU_FILE_CARCHIVE; break; } } file_type = (menu_file_type_t)default_type_plain; break; } is_dir = (file_type == MENU_FILE_DIRECTORY); if (push_dir && !is_dir) continue; /* Need to preserve slash first time. */ path = str_list->elems[i].data; if (*dir && !path_is_compressed) path = path_basename(path); #ifdef HAVE_LIBRETRO_MANAGEMENT #ifdef RARCH_CONSOLE if (!strcmp(label, "core_list") && (is_dir || strcasecmp(path, SALAMANDER_FILE) == 0)) continue; #endif #endif /* Push type further down in the chain. * Needed for shader manager currently. */ if (!strcmp(label, "core_list")) { /* Compressed cores are unsupported */ if (file_type == MENU_FILE_CARCHIVE) continue; menu_list_push(list, path, "", is_dir ? MENU_FILE_DIRECTORY : MENU_FILE_CORE, 0); } else menu_list_push(list, path, "", file_type, 0); } string_list_free(str_list); if (!strcmp(label, "core_list")) { driver_t *driver = driver_get_ptr(); menu_list_get_last_stack(driver->menu->menu_list, &dir, NULL, NULL); list_size = file_list_get_size(list); for (i = 0; i < list_size; i++) { char core_path[PATH_MAX_LENGTH], display_name[PATH_MAX_LENGTH]; const char *path = NULL; menu_list_get_at_offset(list, i, &path, NULL, &type); if (type != MENU_FILE_CORE) continue; fill_pathname_join(core_path, dir, path, sizeof(core_path)); if (global->core_info && core_info_list_get_display_name(global->core_info, core_path, display_name, sizeof(display_name))) menu_list_set_alt_at_offset(list, i, display_name); } menu_list_sort_on_alt(list); } menu_list_populate_generic(list, dir, label, type); return 0; }
static void lakka_init_items(int i, menu_category_t *category, core_info_t *info, const char* path) { int num_items, j, n, k; struct string_list *list = (struct string_list*)dir_list_new(path, info->supported_extensions, true); dir_list_sort(list, true); num_items = list ? list->size : 0; for (j = 0; j < num_items; j++) { if (list->elems[j].attr.b) // is a directory lakka_init_items(i, category, info, list->elems[j].data); else { menu_item_t *item; n = category->num_items; category->num_items++; category->items = (menu_item_t*)realloc(category->items, category->num_items * sizeof(menu_item_t)); item = (menu_item_t*)&category->items[n]; strlcpy(item->name, path_basename(list->elems[j].data), sizeof(item->name)); strlcpy(item->rom, list->elems[j].data, sizeof(item->rom)); item->alpha = i != menu_active_category ? 0 : n ? 0.5 : 1; item->zoom = n ? I_PASSIVE_ZOOM : I_ACTIVE_ZOOM; item->y = n ? VSPACING*(3+n) : VSPACING*2.4; item->active_subitem = 0; item->num_subitems = 5; item->subitems = (menu_subitem_t*)calloc(item->num_subitems, sizeof(menu_subitem_t)); for (k = 0; k < item->num_subitems; k++) { menu_subitem_t *subitem = (menu_subitem_t*)&item->subitems[k]; if (!subitem) continue; switch (k) { case 0: strlcpy(subitem->name, "Run", sizeof(subitem->name)); break; case 1: strlcpy(subitem->name, "Save State", sizeof(subitem->name)); break; case 2: strlcpy(subitem->name, "Load State", sizeof(subitem->name)); break; case 3: strlcpy(subitem->name, "Take Screenshot", sizeof(subitem->name)); break; case 4: strlcpy(subitem->name, "Reset", sizeof(subitem->name)); break; } subitem->alpha = 0; subitem->zoom = k ? I_PASSIVE_ZOOM : I_ACTIVE_ZOOM; subitem->y = k ? VSPACING * (3+k) : VSPACING * 2.4; if (font_driver) font_driver->render_msg(font, subitem->name, &subitem->out); } } } }
void core_info_get_name(const char *path, char *s, size_t len, const char *path_info, const char *dir_cores, const char *exts, bool dir_show_hidden_files, bool get_display_name) { size_t i; const char *path_basedir = !string_is_empty(path_info) ? path_info : dir_cores; struct string_list *contents = dir_list_new( dir_cores, exts, false, dir_show_hidden_files, false, false); const char *core_path_basename = path_basename(path); if (!contents) return; for (i = 0; i < contents->size; i++) { size_t path_size = PATH_MAX_LENGTH * sizeof(char); char *info_path = NULL; config_file_t *conf = NULL; char *new_core_name = NULL; const char *current_path = contents->elems[i].data; if (!string_is_equal(path_basename(current_path), core_path_basename)) continue; info_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); info_path[0] = '\0'; if (!core_info_list_iterate(info_path, path_size, path_basedir, contents, i) && path_is_valid(info_path)) { free(info_path); continue; } conf = config_file_new(info_path); if (!conf) { free(info_path); continue; } if (config_get_string(conf, get_display_name ? "display_name" : "corename", &new_core_name)) { strlcpy(s, new_core_name, len); free(new_core_name); } config_file_free(conf); free(info_path); break; } if (contents) dir_list_free(contents); contents = NULL; }
void input_config_autoconfigure_joypad(unsigned idx, const char *name, int32_t vid, int32_t pid, const char *drv) { size_t i; bool internal_only, block_osd_spam; struct string_list *list = NULL; if (!g_settings.input.autodetect_enable) return; /* This will be the case if input driver is reinit. * No reason to spam autoconfigure messages * every time (fine in log). */ block_osd_spam = g_settings.input.autoconfigured[idx] && name; for (i = 0; i < RARCH_BIND_LIST_END; i++) { g_settings.input.autoconf_binds[idx][i].joykey = NO_BTN; g_settings.input.autoconf_binds[idx][i].joyaxis = AXIS_NONE; g_settings.input.autoconf_binds[idx][i].joykey_label[0] = '\0'; g_settings.input.autoconf_binds[idx][i].joyaxis_label[0] = '\0'; } g_settings.input.autoconfigured[idx] = false; if (!name) return; /* if false, load from both cfg files and internal */ internal_only = !*g_settings.input.autoconfig_dir; #if defined(HAVE_BUILTIN_AUTOCONFIG) /* First internal */ for (i = 0; input_builtin_autoconfs[i]; i++) { config_file_t *conf = (config_file_t*) config_file_new_from_string(input_builtin_autoconfs[i]); bool success = input_try_autoconfigure_joypad_from_conf(conf, idx, name, drv, vid, pid, block_osd_spam); config_file_free(conf); if (success) break; } #endif if (internal_only) return; /* Now try files */ list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false); if (!list) return; for (i = 0; i < list->size; i++) { bool success; config_file_t *conf = config_file_new(list->elems[i].data); if (!conf) continue; success = input_try_autoconfigure_joypad_from_conf(conf, idx, name, drv, vid, pid, block_osd_spam); config_file_free(conf); if (success) break; } string_list_free(list); }
core_info_list_t *core_info_list_new(const char *modules_path) { size_t i; core_info_t *core_info = NULL; core_info_list_t *core_info_list = NULL; struct string_list *contents = (struct string_list*)dir_list_new(modules_path, EXT_EXECUTABLES, false); if (!contents) return NULL; core_info_list = (core_info_list_t*)calloc(1, sizeof(*core_info_list)); if (!core_info_list) goto error; core_info = (core_info_t*)calloc(contents->size, sizeof(*core_info)); if (!core_info) goto error; core_info_list->list = core_info; core_info_list->count = contents->size; for (i = 0; i < contents->size; i++) { char info_path_base[PATH_MAX], info_path[PATH_MAX]; core_info[i].path = strdup(contents->elems[i].data); if (!core_info[i].path) break; fill_pathname_base(info_path_base, contents->elems[i].data, sizeof(info_path_base)); path_remove_extension(info_path_base); #if defined(RARCH_MOBILE) || defined(RARCH_CONSOLE) char *substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; #endif strlcat(info_path_base, ".info", sizeof(info_path_base)); fill_pathname_join(info_path, (*g_settings.libretro_info_path) ? g_settings.libretro_info_path : modules_path, info_path_base, sizeof(info_path)); core_info[i].data = config_file_new(info_path); if (core_info[i].data) { unsigned count = 0; config_get_string(core_info[i].data, "display_name", &core_info[i].display_name); config_get_string(core_info[i].data, "systemname", &core_info[i].systemname); config_get_uint(core_info[i].data, "firmware_count", &count); core_info[i].firmware_count = count; if (config_get_string(core_info[i].data, "supported_extensions", &core_info[i].supported_extensions) && core_info[i].supported_extensions) core_info[i].supported_extensions_list = string_split(core_info[i].supported_extensions, "|"); if (config_get_string(core_info[i].data, "authors", &core_info[i].authors) && core_info[i].authors) core_info[i].authors_list = string_split(core_info[i].authors, "|"); if (config_get_string(core_info[i].data, "permissions", &core_info[i].permissions) && core_info[i].permissions) core_info[i].permissions_list = string_split(core_info[i].permissions, "|"); if (config_get_string(core_info[i].data, "notes", &core_info[i].notes) && core_info[i].notes) core_info[i].note_list = string_split(core_info[i].notes, "|"); } if (!core_info[i].display_name) core_info[i].display_name = strdup(path_basename(core_info[i].path)); } core_info_list_resolve_all_extensions(core_info_list); core_info_list_resolve_all_firmware(core_info_list); dir_list_free(contents); return core_info_list; error: if (contents) dir_list_free(contents); core_info_list_free(core_info_list); return NULL; }
struct string_list *dir_list_new_special(const char *input_dir, enum dir_list_type type, const char *filter) { char ext_shaders[PATH_MAX_LENGTH]; char ext_name[PATH_MAX_LENGTH]; const char *dir = NULL; const char *exts = NULL; bool include_dirs = false; settings_t *settings = config_get_ptr(); (void)input_dir; (void)settings; ext_shaders[0] = '\0'; switch (type) { case DIR_LIST_AUTOCONFIG: dir = input_dir; exts = filter; break; case DIR_LIST_CORES: dir = settings->directory.libretro; if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name))) return NULL; exts = ext_name; break; case DIR_LIST_CORE_INFO: { core_info_list_t *list = NULL; core_info_get_list(&list); dir = input_dir; exts = list->all_ext; } break; case DIR_LIST_SHADERS: dir = settings->directory.video_shader; #ifdef HAVE_CG strlcat(ext_shaders, "cg|cgp", sizeof(ext_shaders)); #endif #ifdef HAVE_GLSL strlcat(ext_shaders, "glsl|glslp", sizeof(ext_shaders)); #endif #ifdef HAVE_VULKAN strlcat(ext_shaders, "slang|slangp", sizeof(ext_shaders)); #endif exts = ext_shaders; break; case DIR_LIST_COLLECTIONS: dir = settings->directory.playlist; exts = "lpl"; break; case DIR_LIST_DATABASES: dir = settings->path.content_database; exts = "rdb"; break; case DIR_LIST_PLAIN: dir = input_dir; exts = filter; break; case DIR_LIST_NONE: default: return NULL; } return dir_list_new(dir, exts, include_dirs, type == DIR_LIST_CORE_INFO); }
static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed) { char parent_dir[PATH_MAX_LENGTH]; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (zarch_zui_tab(zui, tabbed, "Load", 1)) { unsigned cwd_offset; if (!zui->load_cwd) zui->load_cwd = strdup(settings->menu_content_directory); if (!zui->load_dlist) { zui->load_dlist = dir_list_new(zui->load_cwd, global->core_info.current->supported_extensions, true, true); dir_list_sort(zui->load_dlist, true); zui->load_dlist_first = 0; } cwd_offset = min(strlen(zui->load_cwd), 60); zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]); if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home")) zarch_zui_render_lay_root_load_free(zui); if (zui->load_dlist) { fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir)); if (parent_dir[0] != '\0' && zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */)) { zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir); } else { unsigned size = zui->load_dlist->size; unsigned i, j = 1; unsigned skip = 0; for (i = 0; i < size; ++i) { const char *basename = path_basename(zui->load_dlist->elems[i].data); if (basename[0] != '.') break; skip++; } zui->load_dlist_first += zui->mouse.wheel; if (zui->load_dlist_first < 0) zui->load_dlist_first = 0; else if (zui->load_dlist_first > size - 5) zui->load_dlist_first = size - 5; zui->load_dlist_first = min(max(zui->load_dlist_first, 0), size - 5 - skip); for (i = skip + zui->load_dlist_first; i < size; ++i) { char label[PATH_MAX_LENGTH]; const char *path = NULL; const char *basename = NULL; if (j > 10) break; path = zui->load_dlist->elems[i].data; basename = path_basename(path); *label = 0; strncat(label, " ", sizeof(label)-1); strncat(label, basename, sizeof(label)-1); if (path_is_directory(path)) strncat(label, "/", sizeof(label)-1); if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * 54, label, i, NULL)) { if (path_is_directory(path)) { zarch_zui_render_lay_root_load_set_new_path(zui, path); break; } zui->pick_cores = NULL; zui->pick_supported = 0; strncpy(zui->pick_content, path, sizeof(zui->pick_content)-1); core_info_list_get_supported_cores(global->core_info.list, path, &zui->pick_cores, &zui->pick_supported); layout = LAY_PICK_CORE; break; } j++; } } } } else if (zui->load_dlist) { dir_list_free(zui->load_dlist); zui->load_dlist = NULL; } return 0; }
bool nk_wnd_file_picker(nk_menu_handle_t *nk, char* title, char* in, char* out, char* filter) { struct nk_panel layout; struct nk_context *ctx = &nk->ctx; const int id = NK_WND_FILE_PICKER; int i = 0; static file_list_t *drives = NULL; static struct string_list *files = NULL; settings_t *settings = config_get_ptr(); bool ret = false; if (!drives) { drives = (file_list_t*)calloc(1, sizeof(file_list_t)); frontend_driver_parse_drive_list(drives, false); } if (!string_is_empty(in) && string_is_empty(path)) { strlcpy(path, in, sizeof(path)); files = dir_list_new(path, filter, true, settings->bools.show_hidden_files, true, false); } if (!assets_loaded) load_icons(nk); if (nk_begin(ctx, title, nk_rect(10, 10, 500, 400), NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_MOVABLE| NK_WINDOW_BORDER)) { nk_layout_row_dynamic(ctx, 30, 4); if (drives->size == 0) { if(nk_button_image_label(ctx, icons.disk, "/", NK_TEXT_CENTERED)) { fill_pathname_join(path, "/", "", sizeof(path)); files = dir_list_new(path, filter, true, settings->bools.show_hidden_files, true, false); } } else { for (i = 0; i < drives->size; i++) { if(nk_button_image_label(ctx, icons.disk, drives->list[i].path, NK_TEXT_CENTERED)) { fill_pathname_join(path, drives->list[i].path, "", sizeof(path)); files = dir_list_new(path, filter, true, settings->bools.show_hidden_files, true, false); } } } nk_layout_row_dynamic(ctx, 30, 1); if (files) { for (i = 0; i < files->size; i++) { if (nk_button_image_label(ctx, path_is_directory(files->elems[i].data) ? icons.folder : icons.file, path_basename(files->elems[i].data), NK_TEXT_RIGHT)) { strlcpy (path, files->elems[i].data, sizeof(path)); if (path_is_directory (path)) files = dir_list_new(path, filter, true, settings->bools.show_hidden_files, true, false); } } } nk_layout_row_dynamic(ctx, 30, 1); { if (nk_button_text(ctx, "OK", 2)) { ret = true; strlcpy(out, path, sizeof(path)); nk->window[NK_WND_FILE_PICKER].open = false; path[0] = '\0'; } } } /* sort the dir list with directories first */ dir_list_sort(files, true); /* copy the path variable to out*/ /* save position and size to restore after context reset */ nk_wnd_set_state(nk, id, nk_window_get_position(ctx), nk_window_get_size(ctx)); nk_end(ctx); return ret; }
static bool gfx_ctx_drm_egl_init(void *data) { const char *gpu; int i; unsigned monitor_index; unsigned gpu_index = 0; unsigned monitor = max(g_settings.video.monitor_index, 1); struct string_list *gpu_descriptors = NULL; gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)calloc(1, sizeof(gfx_ctx_drm_egl_data_t)); if (!drm) return NULL; drm->g_drm_fd = -1; gpu_descriptors = (struct string_list*)dir_list_new("/dev/dri", NULL, false); nextgpu: free_drm_resources(drm); if (!gpu_descriptors || gpu_index == gpu_descriptors->size) { RARCH_ERR("[KMS/EGL]: Couldn't find a suitable DRM device.\n"); goto error; } gpu = gpu_descriptors->elems[gpu_index++].data; drm->g_drm_fd = open(gpu, O_RDWR); if (drm->g_drm_fd < 0) { RARCH_WARN("[KMS/EGL]: Couldn't open DRM device.\n"); goto nextgpu; } drm->g_resources = drmModeGetResources(drm->g_drm_fd); if (!drm->g_resources) { RARCH_WARN("[KMS/EGL]: Couldn't get device resources.\n"); goto nextgpu; } /* Enumerate all connectors. */ monitor_index = 0; RARCH_LOG("[KMS/EGL]: Found %d connectors.\n", drm->g_resources->count_connectors); for (i = 0; i < drm->g_resources->count_connectors; i++) { drmModeConnectorPtr conn = drmModeGetConnector( drm->g_drm_fd, drm->g_resources->connectors[i]); if (conn) { bool connected = conn->connection == DRM_MODE_CONNECTED; RARCH_LOG("[KMS/EGL]: Connector %d connected: %s\n", i, connected ? "yes" : "no"); RARCH_LOG("[KMS/EGL]: Connector %d has %d modes.\n", i, conn->count_modes); if (connected && conn->count_modes > 0) { monitor_index++; RARCH_LOG("[KMS/EGL]: Connector %d assigned to monitor index: #%u.\n", i, monitor_index); } drmModeFreeConnector(conn); } } monitor_index = 0; for (i = 0; i < drm->g_resources->count_connectors; i++) { drm->g_connector = drmModeGetConnector(drm->g_drm_fd, drm->g_resources->connectors[i]); if (!drm->g_connector) continue; if (drm->g_connector->connection == DRM_MODE_CONNECTED && drm->g_connector->count_modes > 0) { monitor_index++; if (monitor_index == monitor) break; } drmModeFreeConnector(drm->g_connector); drm->g_connector = NULL; } if (!drm->g_connector) { RARCH_WARN("[KMS/EGL]: Couldn't get device connector.\n"); goto nextgpu; } for (i = 0; i < drm->g_resources->count_encoders; i++) { drm->g_encoder = drmModeGetEncoder(drm->g_drm_fd, drm->g_resources->encoders[i]); if (!drm->g_encoder) continue; if (drm->g_encoder->encoder_id == drm->g_connector->encoder_id) break; drmModeFreeEncoder(drm->g_encoder); drm->g_encoder = NULL; } if (!drm->g_encoder) { RARCH_WARN("[KMS/EGL]: Couldn't find DRM encoder.\n"); goto nextgpu; } for (i = 0; i < drm->g_connector->count_modes; i++) { RARCH_LOG("[KMS/EGL]: Mode %d: (%s) %d x %d, %u Hz\n", i, drm->g_connector->modes[i].name, drm->g_connector->modes[i].hdisplay, drm->g_connector->modes[i].vdisplay, drm->g_connector->modes[i].vrefresh); } drm->g_crtc_id = drm->g_encoder->crtc_id; drm->g_orig_crtc = drmModeGetCrtc(drm->g_drm_fd, drm->g_crtc_id); if (!drm->g_orig_crtc) RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n"); drm->g_connector_id = drm->g_connector->connector_id; /* First mode is assumed to be the "optimal" * one for get_video_size() purposes. */ drm->g_fb_width = drm->g_connector->modes[0].hdisplay; drm->g_fb_height = drm->g_connector->modes[0].vdisplay; drm->g_gbm_dev = gbm_create_device(drm->g_drm_fd); if (!drm->g_gbm_dev) { RARCH_WARN("[KMS/EGL]: Couldn't create GBM device.\n"); goto nextgpu; } dir_list_free(gpu_descriptors); driver.video_context_data = drm; return true; error: dir_list_free(gpu_descriptors); gfx_ctx_drm_egl_destroy_resources(drm); if (drm) free(drm); return false; }