/** * menu_content_find_first_core: * @core_info : Core info list handle. * @dir : Directory. Gets joined with @path. * @path : Path. Gets joined with @dir. * @menu_label : Label identifier of menu setting. * @s : Deferred core path. Will be filled in * by function. * @len : Size of @s. * * Gets deferred core. * * Returns: false if there are multiple deferred cores and a * selection needs to be made from a list, otherwise * returns true and fills in @s with path to core. **/ static bool menu_content_find_first_core(void *data) { char new_core_path[PATH_MAX_LENGTH]; const core_info_t *info = NULL; size_t supported = 0; menu_content_ctx_defer_info_t *def_info = (menu_content_ctx_defer_info_t *)data; core_info_list_t *core_info = (core_info_list_t*)def_info->data; uint32_t menu_label_hash = menu_hash_calculate(def_info->menu_label); if ( !string_is_empty(def_info->dir) && !string_is_empty(def_info->path)) fill_pathname_join(def_info->s, def_info->dir, def_info->path, def_info->len); #ifdef HAVE_COMPRESSION if (path_is_compressed_file(def_info->dir)) { /* In case of a compressed archive, we have to join with a hash */ /* We are going to write at the position of dir: */ retro_assert(strlen(def_info->dir) < strlen(def_info->s)); def_info->s[strlen(def_info->dir)] = '#'; } #endif if (core_info) core_info_list_get_supported_cores(core_info, def_info->s, &info, &supported); /* We started the menu with 'Load Content', we are * going to use the current core to load this. */ if (menu_label_hash == MENU_LABEL_LOAD_CONTENT) { core_info_ctl(CORE_INFO_CTL_CURRENT_CORE_GET, (void*)&info); if (info) { RARCH_LOG("Use the current core (%s) to load this content...\n", info->path); supported = 1; } } /* There are multiple deferred cores and a * selection needs to be made from a list, return 0. */ if (supported != 1) return false; if (info) strlcpy(new_core_path, info->path, sizeof(new_core_path)); runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, def_info->s); if (path_file_exists(new_core_path)) runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, new_core_path); return true; }
static bool content_file_init_extract( struct string_list *content, content_information_ctx_t *content_ctx, const struct retro_subsystem_info *special, union string_list_elem_attr *attr, char **error_string ) { unsigned i; for (i = 0; i < content->size; i++) { char temp_content[PATH_MAX_LENGTH]; char new_path[PATH_MAX_LENGTH]; bool block_extract = content->elems[i].attr.i & 1; const char *path = content->elems[i].data; const char *valid_ext = special ? special->roms[i].valid_extensions : content_ctx->valid_extensions; bool contains_compressed = path_contains_compressed_file(path); /* Block extract check. */ if (block_extract) continue; /* just use the first file in the archive */ if (!contains_compressed && !path_is_compressed_file(path)) continue; temp_content[0] = new_path[0] = '\0'; strlcpy(temp_content, path, sizeof(temp_content)); if (!valid_ext || !file_archive_extract_file( temp_content, sizeof(temp_content), valid_ext, !string_is_empty(content_ctx->directory_cache) ? content_ctx->directory_cache : NULL, new_path, sizeof(new_path))) { char str[1024]; snprintf(str, sizeof(str), "%s: %s.\n", msg_hash_to_str( MSG_FAILED_TO_EXTRACT_CONTENT_FROM_COMPRESSED_FILE), temp_content); return false; } string_list_set(content, i, new_path); if (!string_list_append(content_ctx->temporary_content, new_path, *attr)) return false; } return true; }
static int database_info_list_iterate_end_no_match( database_info_handle_t *db, database_state_handle_t *db_state, const char *path) { /* Reached end of database list, * CRC match probably didn't succeed. */ /* If this was a compressed file and no match in the database * list was found then expand the search list to include the * archive's contents. */ if (path_is_compressed_file(path) && !path_contains_compressed_file(path)) { struct string_list *archive_list = file_archive_get_file_list(path, NULL); if (archive_list && archive_list->size > 0) { unsigned i; for (i = 0; i < archive_list->size; i++) { char *new_path = (char*)malloc( PATH_MAX_LENGTH * sizeof(char)); size_t path_size = PATH_MAX_LENGTH * sizeof(char); size_t path_len = strlen(path); new_path[0] = '\0'; strlcpy(new_path, path, path_size); if (path_len + strlen(archive_list->elems[i].data) + 1 < PATH_MAX_LENGTH) { new_path[path_len] = '#'; strlcpy(new_path + path_len + 1, archive_list->elems[i].data, path_size - path_len); } string_list_append(db->list, new_path, archive_list->elems[i].attr); free(new_path); } string_list_free(archive_list); } } db_state->list_index = 0; db_state->entry_index = 0; if (db_state->crc != 0) db_state->crc = 0; return 0; }
/** * rarch_defer_core: * @core_info : Core info list handle. * @dir : Directory. Gets joined with @path. * @path : Path. Gets joined with @dir. * @menu_label : Label identifier of menu setting. * @s : Deferred core path. Will be filled in * by function. * @len : Size of @s. * * Gets deferred core. * * Returns: 0 if there are multiple deferred cores and a * selection needs to be made from a list, otherwise * returns -1 and fills in @s with path to core. **/ int rarch_defer_core(core_info_list_t *core_info, const char *dir, const char *path, const char *menu_label, char *s, size_t len) { char new_core_path[PATH_MAX_LENGTH] = {0}; const core_info_t *info = NULL; size_t supported = 0; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); uint32_t menu_label_hash = msg_hash_calculate(menu_label); fill_pathname_join(s, dir, path, len); #ifdef HAVE_COMPRESSION if (path_is_compressed_file(dir)) { /* In case of a compressed archive, we have to join with a hash */ /* We are going to write at the position of dir: */ rarch_assert(strlen(dir) < strlen(s)); s[strlen(dir)] = '#'; } #endif if (core_info) core_info_list_get_supported_cores(core_info, s, &info, &supported); if (menu_label_hash == MENU_LABEL_LOAD_CONTENT) { info = (const core_info_t*)&global->core_info.current; if (info) { strlcpy(new_core_path, info->path, sizeof(new_core_path)); supported = 1; } } else strlcpy(new_core_path, info->path, sizeof(new_core_path)); /* There are multiple deferred cores and a * selection needs to be made from a list, return 0. */ if (supported != 1) return 0; strlcpy(global->path.fullpath, s, sizeof(global->path.fullpath)); if (path_file_exists(new_core_path)) strlcpy(settings->libretro, new_core_path, sizeof(settings->libretro)); return -1; }
/** * parse_dir_entry: * @name : name of the directory listing entry. * @file_path : file path of the directory listing entry. * @is_dir : is the directory listing a directory? * @include_dirs : include directories as part of the finished directory listing? * @include_compressed : Include compressed files, even if not part of ext_list. * @list : pointer to directory listing. * @ext_list : pointer to allowed file extensions listing. * @file_ext : file extension of the directory listing entry. * * Parses a directory listing. * * Returns: zero on success, -1 on error, 1 if we should * continue to the next entry in the directory listing. **/ static int parse_dir_entry(const char *name, char *file_path, bool is_dir, bool include_dirs, bool include_compressed, struct string_list *list, struct string_list *ext_list, const char *file_ext) { union string_list_elem_attr attr; bool is_compressed_file = false; bool supported_by_core = false; attr.i = RARCH_FILETYPE_UNSET; if (!is_dir) { is_compressed_file = path_is_compressed_file(file_path); if (string_list_find_elem_prefix(ext_list, ".", file_ext)) supported_by_core = true; } if (!include_dirs && is_dir) return 1; if (!strcmp(name, ".") || !strcmp(name, "..")) return 1; if (!is_dir && ext_list && ((!is_compressed_file && !supported_by_core) || (!supported_by_core && !include_compressed))) return 1; if (is_dir) attr.i = RARCH_DIRECTORY; if (is_compressed_file) attr.i = RARCH_COMPRESSED_ARCHIVE; /* The order of these ifs is important. * If the file format is explicitly supported by the libretro-core, we * need to immediately load it and not designate it as a compressed file. * * Example: .zip could be supported as a image by the core and as a * compressed_file. In that case, we have to interpret it as a image. * * */ if (supported_by_core) attr.i = RARCH_PLAIN_FILE; if (!string_list_append(list, file_path, attr)) return -1; return 0; }
void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const char *path, const core_info_t **infos, size_t *num_infos) { size_t i; struct string_list *list = NULL; size_t supported = 0; if (!core_info_list) return; core_info_tmp_path = path; #ifdef HAVE_COMPRESSION if (path_is_compressed_file(path)) list = file_archive_get_file_list(path, NULL); core_info_tmp_list = list; #endif /* Let supported core come first in list so we can return * a pointer to them. */ qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), core_info_qsort_cmp); for (i = 0; i < core_info_list->count; i++, supported++) { const core_info_t *core = &core_info_list->list[i]; if (core_info_does_support_file(core, path)) continue; #ifdef HAVE_COMPRESSION if (core_info_does_support_any_file(core, list)) continue; #endif break; } if (list) string_list_free(list); *infos = core_info_list->list; *num_infos = supported; }
database_info_handle_t *database_info_file_init(const char *path, enum database_type type) { union string_list_elem_attr attr = {0}; database_info_handle_t *db = (database_info_handle_t*) calloc(1, sizeof(*db)); if (!db) return NULL; db->list = string_list_new(); if (!db->list) goto error; string_list_append(db->list, path, attr); if (path_is_compressed_file(path)) { struct string_list *archive_list =path_is_compressed_file(path) ? file_archive_get_file_list(path, NULL) : NULL; if (archive_list && archive_list->size > 0) { unsigned i; for (i = 0; i < archive_list->size; i++) { char new_path[PATH_MAX_LENGTH]; size_t path_len = strlen(path); new_path[0] = '\0'; strlcpy(new_path, path, sizeof(new_path)); if (path_len + strlen(archive_list->elems[i].data) + 1 < PATH_MAX_LENGTH) { new_path[path_len] = '#'; strlcpy(new_path + path_len + 1, archive_list->elems[i].data, sizeof(new_path) - path_len); } string_list_append(db->list, new_path, archive_list->elems[i].attr); } string_list_free(archive_list); } } db->list_ptr = 0; db->status = DATABASE_STATUS_ITERATE; db->type = type; return db; error: if (db) free(db); return NULL; }
/** * menu_content_find_first_core: * @core_info : Core info list handle. * @dir : Directory. Gets joined with @path. * @path : Path. Gets joined with @dir. * @menu_label : Label identifier of menu setting. * @s : Deferred core path. Will be filled in * by function. * @len : Size of @s. * * Gets deferred core. * * Returns: false if there are multiple deferred cores and a * selection needs to be made from a list, otherwise * returns true and fills in @s with path to core. **/ bool menu_content_find_first_core(menu_content_ctx_defer_info_t *def_info, bool load_content_with_current_core, char *new_core_path, size_t len) { const core_info_t *info = NULL; core_info_list_t *core_info = NULL; const char *default_info_dir = NULL; size_t supported = 0; if (def_info) { core_info = (core_info_list_t*)def_info->data; default_info_dir = def_info->dir; } if (!string_is_empty(default_info_dir)) { const char *default_info_path = NULL; size_t default_info_length = 0; if (def_info) { default_info_path = def_info->path; default_info_length = def_info->len; } if (!string_is_empty(default_info_path)) fill_pathname_join(def_info->s, default_info_dir, default_info_path, default_info_length); #ifdef HAVE_COMPRESSION if (path_is_compressed_file(default_info_dir)) { size_t len = strlen(default_info_dir); /* In case of a compressed archive, we have to join with a hash */ /* We are going to write at the position of dir: */ retro_assert(len < strlen(def_info->s)); def_info->s[len] = '#'; } #endif } if (core_info) core_info_list_get_supported_cores(core_info, def_info->s, &info, &supported); /* We started the menu with 'Load Content', we are * going to use the current core to load this. */ if (load_content_with_current_core) { core_info_get_current_core((core_info_t**)&info); if (info) { RARCH_LOG("Use the current core (%s) to load this content...\n", info->path); supported = 1; } } /* There are multiple deferred cores and a * selection needs to be made from a list, return 0. */ if (supported != 1) return false; if (info) strlcpy(new_core_path, info->path, len); return true; }
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; }
/* Takes a list of files and folders and adds them to the currently selected playlist. Folders will have their contents added recursively. */ void MainWindow::addFilesToPlaylist(QStringList files) { QStringList list; QString currentPlaylistPath; QListWidgetItem *currentItem = m_listWidget->currentItem(); QByteArray currentPlaylistArray; QScopedPointer<QProgressDialog> dialog(NULL); PlaylistEntryDialog *playlistDialog = playlistEntryDialog(); QHash<QString, QString> selectedCore; QHash<QString, QString> itemToAdd; QString selectedDatabase; QString selectedName; QString selectedPath; const char *currentPlaylistData = NULL; playlist_t *playlist = NULL; int i; /* Assume a blank list means we will manually enter in all fields. */ if (files.isEmpty()) { /* Make sure hash isn't blank, that would mean there's multiple entries to add at once. */ itemToAdd["label"] = ""; itemToAdd["path"] = ""; } else if (files.count() == 1) { QString path = files.at(0); QFileInfo info(path); if (info.isFile()) { itemToAdd["label"] = info.completeBaseName(); itemToAdd["path"] = path; } } if (currentItem) { currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); if (!currentPlaylistPath.isEmpty()) { currentPlaylistArray = currentPlaylistPath.toUtf8(); currentPlaylistData = currentPlaylistArray.constData(); } } if (currentPlaylistPath == ALL_PLAYLISTS_TOKEN) { showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); return; } /* a blank itemToAdd means there will be multiple */ if (!playlistDialog->showDialog(itemToAdd)) return; selectedName = m_playlistEntryDialog->getSelectedName(); selectedPath = m_playlistEntryDialog->getSelectedPath(); selectedCore = m_playlistEntryDialog->getSelectedCore(); selectedDatabase = m_playlistEntryDialog->getSelectedDatabase(); if (selectedDatabase.isEmpty()) selectedDatabase = QFileInfo(currentPlaylistPath).fileName(); else selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION); dialog.reset(new QProgressDialog(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES), "Cancel", 0, 0, this)); dialog->setWindowModality(Qt::ApplicationModal); if (selectedName.isEmpty() || selectedPath.isEmpty() || selectedDatabase.isEmpty()) { showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); return; } if (files.isEmpty()) files.append(selectedPath); for (i = 0; i < files.count(); i++) { QString path(files.at(i)); QFileInfo fileInfo(path); if (dialog->wasCanceled()) return; if (i % 25 == 0) { /* Needed to update progress dialog while doing a lot of stuff on the main thread. */ qApp->processEvents(); } if (fileInfo.isDir()) { QDir dir(path); addDirectoryFilesToList(list, dir); continue; } if (fileInfo.isFile()) list.append(fileInfo.absoluteFilePath()); else if (files.count() == 1) { /* If adding a single file, tell user that it doesn't exist. */ showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); return; } } dialog->setLabelText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST)); dialog->setMaximum(list.count()); playlist = playlist_init(currentPlaylistData, COLLECTION_SIZE); for (i = 0; i < list.count(); i++) { QString fileName = list.at(i); QFileInfo fileInfo; QByteArray fileBaseNameArray; QByteArray pathArray; QByteArray corePathArray; QByteArray coreNameArray; QByteArray databaseArray; const char *pathData = NULL; const char *fileNameNoExten = NULL; const char *corePathData = NULL; const char *coreNameData = NULL; const char *databaseData = NULL; if (dialog->wasCanceled()) { playlist_free(playlist); return; } if (fileName.isEmpty()) continue; fileInfo = fileName; if (files.count() == 1 && list.count() == 1 && i == 0) { fileBaseNameArray = selectedName.toUtf8(); pathArray = QDir::toNativeSeparators(selectedPath).toUtf8(); } else { fileBaseNameArray = fileInfo.completeBaseName().toUtf8(); pathArray = QDir::toNativeSeparators(fileName).toUtf8(); } fileNameNoExten = fileBaseNameArray.constData(); /* a modal QProgressDialog calls processEvents() automatically in setValue() */ dialog->setValue(i + 1); pathData = pathArray.constData(); if (selectedCore.isEmpty()) { corePathData = "DETECT"; coreNameData = "DETECT"; } else { corePathArray = QDir::toNativeSeparators(selectedCore.value("core_path")).toUtf8(); coreNameArray = selectedCore.value("core_name").toUtf8(); corePathData = corePathArray.constData(); coreNameData = coreNameArray.constData(); } databaseArray = selectedDatabase.toUtf8(); databaseData = databaseArray.constData(); if (path_is_compressed_file(pathData)) { struct string_list *list = file_archive_get_file_list(pathData, NULL); if (list) { if (list->size == 1) { /* assume archives with one file should have that file loaded directly */ pathArray = QDir::toNativeSeparators(QString(pathData) + "#" + list->elems[0].data).toUtf8(); pathData = pathArray.constData(); } string_list_free(list); } } playlist_push(playlist, pathData, fileNameNoExten, corePathData, coreNameData, "00000000|crc", databaseData); } playlist_write_file(playlist); playlist_free(playlist); reloadPlaylists(); }
bool MainWindow::updateCurrentPlaylistEntry(const QHash<QString, QString> &contentHash) { QString playlistPath = getCurrentPlaylistPath(); QString path; QString label; QString corePath; QString coreName; QString dbName; QString crc32; QByteArray playlistPathArray; QByteArray pathArray; QByteArray labelArray; QByteArray corePathArray; QByteArray coreNameArray; QByteArray dbNameArray; QByteArray crc32Array; const char *playlistPathData = NULL; const char *pathData = NULL; const char *labelData = NULL; const char *corePathData = NULL; const char *coreNameData = NULL; const char *dbNameData = NULL; const char *crc32Data = NULL; playlist_t *playlist = NULL; unsigned index = 0; bool ok = false; if (playlistPath.isEmpty() || contentHash.isEmpty() || !contentHash.contains("index")) return false; index = contentHash.value("index").toUInt(&ok); if (!ok) return false; path = contentHash.value("path"); label = contentHash.value("label"); coreName = contentHash.value("core_name"); corePath = contentHash.value("core_path"); dbName = contentHash.value("db_name"); crc32 = contentHash.value("crc32"); if (path.isEmpty() || label.isEmpty() || coreName.isEmpty() || corePath.isEmpty() || dbName.isEmpty() || crc32.isEmpty() ) return false; playlistPathArray = playlistPath.toUtf8(); pathArray = QDir::toNativeSeparators(path).toUtf8(); labelArray = label.toUtf8(); coreNameArray = coreName.toUtf8(); corePathArray = QDir::toNativeSeparators(corePath).toUtf8(); dbNameArray = (dbName + file_path_str(FILE_PATH_LPL_EXTENSION)).toUtf8(); crc32Array = crc32.toUtf8(); playlistPathData = playlistPathArray.constData(); pathData = pathArray.constData(); labelData = labelArray.constData(); coreNameData = coreNameArray.constData(); corePathData = corePathArray.constData(); dbNameData = dbNameArray.constData(); crc32Data = crc32Array.constData(); if (path_is_compressed_file(pathData)) { struct string_list *list = file_archive_get_file_list(pathData, NULL); if (list) { if (list->size == 1) { /* assume archives with one file should have that file loaded directly */ pathArray = QDir::toNativeSeparators(QString(pathData) + "#" + list->elems[0].data).toUtf8(); pathData = pathArray.constData(); } string_list_free(list); } } playlist = playlist_init(playlistPathData, COLLECTION_SIZE); playlist_update(playlist, index, pathData, labelData, corePathData, coreNameData, crc32Data, dbNameData); playlist_write_file(playlist); playlist_free(playlist); reloadPlaylists(); return true; }
static bool init_content_file_extract( struct string_list *temporary_content, struct string_list *content, const struct retro_subsystem_info *special, union string_list_elem_attr *attr ) { unsigned i; settings_t *settings = config_get_ptr(); rarch_system_info_t *system = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); for (i = 0; i < content->size; i++) { char temp_content[PATH_MAX_LENGTH]; char new_path[PATH_MAX_LENGTH]; bool contains_compressed = NULL; bool block_extract = content->elems[i].attr.i & 1; const char *valid_ext = system->info.valid_extensions; /* Block extract check. */ if (block_extract) continue; contains_compressed = path_contains_compressed_file(content->elems[i].data); if (special) valid_ext = special->roms[i].valid_extensions; if (!contains_compressed) { /* just use the first file in the archive */ if (!path_is_compressed_file(content->elems[i].data)) continue; } temp_content[0] = new_path[0] = '\0'; strlcpy(temp_content, content->elems[i].data, sizeof(temp_content)); if (!valid_ext || !file_archive_extract_file(temp_content, sizeof(temp_content), valid_ext, *settings->directory.cache ? settings->directory.cache : NULL, new_path, sizeof(new_path))) { RARCH_ERR("%s: %s.\n", msg_hash_to_str( MSG_FAILED_TO_EXTRACT_CONTENT_FROM_COMPRESSED_FILE), temp_content); runloop_msg_queue_push( msg_hash_to_str(MSG_FAILED_TO_EXTRACT_CONTENT_FROM_COMPRESSED_FILE) , 2, 180, true); return false; } string_list_set(content, i, new_path); if (!string_list_append(temporary_content, new_path, *attr)) return false; } return true; }
void filebrowser_parse(void *data, unsigned type_data, bool extensions_honored) { size_t i, list_size; struct string_list *str_list = NULL; unsigned items_found = 0; unsigned files_count = 0; unsigned dirs_count = 0; settings_t *settings = config_get_ptr(); menu_displaylist_info_t *info = (menu_displaylist_info_t*)data; enum menu_displaylist_ctl_state type = (enum menu_displaylist_ctl_state) type_data; bool path_is_compressed = path_is_compressed_file(info->path); bool filter_ext = settings->menu.navigation.browser.filter.supported_extensions_enable; if (string_is_equal(info->label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE))) filter_ext = false; if (extensions_honored) filter_ext = true; if (path_is_compressed) str_list = file_archive_get_file_list(info->path, info->exts); else str_list = dir_list_new(info->path, filter_ext ? info->exts : NULL, true, settings->show_hidden_files, true, false); #ifdef HAVE_LIBRETRODB if (filebrowser_types == FILEBROWSER_SCAN_DIR) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY), MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY, FILE_TYPE_SCAN_DIRECTORY, 0 ,0); #endif if (filebrowser_types == FILEBROWSER_SELECT_DIR) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_USE_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_USE_THIS_DIRECTORY), MENU_ENUM_LABEL_USE_THIS_DIRECTORY, FILE_TYPE_USE_DIRECTORY, 0 ,0); if (!str_list) { const char *str = path_is_compressed ? msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNABLE_TO_READ_COMPRESSED_FILE) : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND); menu_entries_append_enum(info->list, str, "", MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, 0, 0, 0); goto end; } dir_list_sort(str_list, true); list_size = str_list->size; if (list_size == 0) { string_list_free(str_list); str_list = NULL; } else { for (i = 0; i < list_size; i++) { char label[PATH_MAX_LENGTH]; bool is_dir = false; enum msg_hash_enums enum_idx = MSG_UNKNOWN; enum msg_file_type file_type = FILE_TYPE_NONE; const char *path = str_list->elems[i].data; label[0] = '\0'; switch (str_list->elems[i].attr.i) { case RARCH_DIRECTORY: file_type = FILE_TYPE_DIRECTORY; break; case RARCH_COMPRESSED_ARCHIVE: file_type = FILE_TYPE_CARCHIVE; break; case RARCH_COMPRESSED_FILE_IN_ARCHIVE: file_type = FILE_TYPE_IN_CARCHIVE; break; case RARCH_PLAIN_FILE: default: file_type = (enum msg_file_type)info->type_default; switch (type) { /* in case of deferred_core_list we have to interpret * every archive as an archive to disallow instant loading */ case DISPLAYLIST_CORES_DETECTED: if (path_is_compressed_file(path)) file_type = FILE_TYPE_CARCHIVE; break; default: break; } break; } is_dir = (file_type == FILE_TYPE_DIRECTORY); if (!is_dir) { if (filebrowser_types == FILEBROWSER_SELECT_DIR) continue; if (filebrowser_types == FILEBROWSER_SCAN_DIR) continue; } /* Need to preserve slash first time. */ if (!string_is_empty(info->path) && !path_is_compressed) path = path_basename(path); if (filebrowser_types == FILEBROWSER_SELECT_COLLECTION) { if (is_dir) file_type = FILE_TYPE_DIRECTORY; else file_type = FILE_TYPE_PLAYLIST_COLLECTION; } if (!is_dir && (settings->multimedia.builtin_mediaplayer_enable || settings->multimedia.builtin_imageviewer_enable)) { switch (path_is_media_type(path)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG if (settings->multimedia.builtin_mediaplayer_enable) file_type = FILE_TYPE_MOVIE; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG if (settings->multimedia.builtin_mediaplayer_enable) file_type = FILE_TYPE_MUSIC; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER if (settings->multimedia.builtin_imageviewer_enable && type != DISPLAYLIST_IMAGES) file_type = FILE_TYPE_IMAGEVIEWER; else file_type = FILE_TYPE_IMAGE; #endif break; default: break; } } switch (file_type) { case FILE_TYPE_PLAIN: #if 0 enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_PLAIN_FILE; #endif files_count++; break; case FILE_TYPE_MOVIE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MOVIE_OPEN; files_count++; break; case FILE_TYPE_MUSIC: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MUSIC_OPEN; files_count++; break; case FILE_TYPE_IMAGE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE; files_count++; break; case FILE_TYPE_IMAGEVIEWER: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE_OPEN_WITH_VIEWER; files_count++; break; case FILE_TYPE_DIRECTORY: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY; dirs_count++; break; default: break; } items_found++; menu_entries_append_enum(info->list, path, label, enum_idx, file_type, 0, 0); } } if (str_list && str_list->size > 0) string_list_free(str_list); if (items_found == 0) { menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0); } /* We don't want to show 'filter by extension' for this. */ if (filebrowser_types == FILEBROWSER_SELECT_DIR) goto end; if (filebrowser_types == FILEBROWSER_SCAN_DIR) goto end; if (!extensions_honored && files_count > 0) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE), msg_hash_to_str(MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE), MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, 0, 0 ,0); end: menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY), info->path, MENU_ENUM_LABEL_PARENT_DIRECTORY, FILE_TYPE_PARENT_DIRECTORY, 0, 0); }