From fa9290cf1ee7620fdca5403e88155d3ea4e11a68 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Tue, 21 Apr 2020 16:44:26 +0100 Subject: [PATCH 1/4] Add optional playlist compression --- config.def.h | 3 + configuration.c | 1 + configuration.h | 1 + intl/msg_hash_lbl.h | 2 + intl/msg_hash_us.h | 12 + .../include/streams/interface_stream.h | 6 +- libretro-common/streams/interface_stream.c | 28 + menu/cbs/menu_cbs_left.c | 16 +- menu/cbs/menu_cbs_ok.c | 49 +- menu/cbs/menu_cbs_right.c | 16 +- menu/cbs/menu_cbs_start.c | 45 +- menu/cbs/menu_cbs_sublabel.c | 8 + menu/menu_displaylist.c | 10 +- menu/menu_setting.c | 18 + msg_hash.h | 1 + playlist.c | 547 ++++++++++-------- playlist.h | 22 +- retroarch.c | 24 +- tasks/task_content.c | 3 +- tasks/task_database.c | 9 +- tasks/task_manual_content_scan.c | 10 +- tasks/task_playlist_manager.c | 17 +- tasks/task_screenshot.c | 5 +- ui/drivers/qt/options/playlists.cpp | 1 + ui/drivers/qt/qt_playlist.cpp | 17 +- 25 files changed, 563 insertions(+), 308 deletions(-) diff --git a/config.def.h b/config.def.h index 332fc5a716..93fc7dd534 100644 --- a/config.def.h +++ b/config.def.h @@ -963,6 +963,9 @@ static const int default_content_favorites_size = 200; /* File format to use when writing playlists to disk */ #define DEFAULT_PLAYLIST_USE_OLD_FORMAT false +/* When creating/updating playlists, compress written data */ +#define DEFAULT_PLAYLIST_COMPRESSION false + #ifdef HAVE_MENU /* Specify when to display 'core name' inline on playlist entries */ #define DEFAULT_PLAYLIST_SHOW_INLINE_CORE_NAME PLAYLIST_INLINE_CORE_DISPLAY_HIST_FAV diff --git a/configuration.c b/configuration.c index 02c3cd8441..1609259ca6 100644 --- a/configuration.c +++ b/configuration.c @@ -1651,6 +1651,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, #endif SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, DEFAULT_PLAYLIST_USE_OLD_FORMAT, false); + SETTING_BOOL("playlist_compression", &settings->bools.playlist_compression, true, DEFAULT_PLAYLIST_COMPRESSION, false); SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, DEFAULT_CONTENT_RUNTIME_LOG, false); SETTING_BOOL("content_runtime_log_aggregate", &settings->bools.content_runtime_log_aggregate, true, DEFAULT_CONTENT_RUNTIME_LOG_AGGREGATE, false); SETTING_BOOL("playlist_show_sublabels", &settings->bools.playlist_show_sublabels, true, DEFAULT_PLAYLIST_SHOW_SUBLABELS, false); diff --git a/configuration.h b/configuration.h index 13be111aa9..d5199ebd9f 100644 --- a/configuration.h +++ b/configuration.h @@ -379,6 +379,7 @@ typedef struct settings bool sustained_performance_mode; bool playlist_use_old_format; + bool playlist_compression; bool content_runtime_log; bool content_runtime_log_aggregate; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index f23664bb7e..a955990196 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -2058,6 +2058,8 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_3DS_DISPLAY_MODE, #endif MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, "playlist_use_old_format") +MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_COMPRESSION, + "playlist_compression") MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_OK, "menu_sound_ok") MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_CANCEL, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index b2a10648a9..c22c827fd7 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -4407,6 +4407,18 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_PLAYLIST_USE_OLD_FORMAT, "Save playlists using old format" ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PLAYLIST_USE_OLD_FORMAT, + "Write playlists using depreciated plain text format. When disabled, playlists are formatted using JSON." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_PLAYLIST_COMPRESSION, + "Compress playlists" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PLAYLIST_COMPRESSION, + "Archive playlist data when writing to disk. Reduces file size and loading times at the expense of (negligibly) increased CPU usage. May be used with either old or new format playlists." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_PLAYLIST_SHOW_INLINE_CORE_NAME, "Show associated cores in playlists" diff --git a/libretro-common/include/streams/interface_stream.h b/libretro-common/include/streams/interface_stream.h index 4cfc982e12..4ebc2f2389 100644 --- a/libretro-common/include/streams/interface_stream.h +++ b/libretro-common/include/streams/interface_stream.h @@ -92,6 +92,8 @@ void intfstream_rewind(intfstream_internal_t *intf); int64_t intfstream_tell(intfstream_internal_t *intf); +int intfstream_eof(intfstream_internal_t *intf); + void intfstream_putc(intfstream_internal_t *intf, int c); int intfstream_close(intfstream_internal_t *intf); @@ -106,7 +108,7 @@ uint32_t intfstream_get_frame_size(intfstream_internal_t *intf); bool intfstream_is_compressed(intfstream_internal_t *intf); -intfstream_t* intfstream_open_file(const char *path, +intfstream_t *intfstream_open_file(const char *path, unsigned mode, unsigned hints); intfstream_t *intfstream_open_memory(void *data, @@ -118,7 +120,7 @@ intfstream_t *intfstream_open_writable_memory(void *data, intfstream_t *intfstream_open_chd_track(const char *path, unsigned mode, unsigned hints, int32_t track); -intfstream_t* intfstream_open_rzip_file(const char *path, +intfstream_t *intfstream_open_rzip_file(const char *path, unsigned mode); RETRO_END_DECLS diff --git a/libretro-common/streams/interface_stream.c b/libretro-common/streams/interface_stream.c index 67957bd169..ba933ced5c 100644 --- a/libretro-common/streams/interface_stream.c +++ b/libretro-common/streams/interface_stream.c @@ -490,6 +490,34 @@ int64_t intfstream_tell(intfstream_internal_t *intf) return -1; } +int intfstream_eof(intfstream_internal_t *intf) +{ + if (!intf) + return -1; + + switch (intf->type) + { + case INTFSTREAM_FILE: + return filestream_eof(intf->file.fp); + case INTFSTREAM_MEMORY: + /* TODO: Add this functionality to + * memory_stream interface */ + break; + case INTFSTREAM_CHD: + /* TODO: Add this functionality to + * chd_stream interface */ + break; + case INTFSTREAM_RZIP: +#if defined(HAVE_ZLIB) + return rzipstream_eof(intf->rzip.fp); +#else + break; +#endif + } + + return -1; +} + void intfstream_rewind(intfstream_internal_t *intf) { switch (intf->type) diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 93eb732ce0..329cc6f86d 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -390,6 +390,7 @@ static int playlist_association_left(unsigned type, const char *label, size_t i, next, current = 0; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_t *playlist = playlist_get_cached(); core_info_list_t *core_info_list = NULL; core_info_t *core_info = NULL; @@ -448,7 +449,8 @@ static int playlist_association_left(unsigned type, const char *label, /* Update playlist */ playlist_set_default_core_path(playlist, core_info->path); playlist_set_default_core_name(playlist, core_info->display_name); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -459,6 +461,7 @@ static int playlist_label_display_mode_left(unsigned type, const char *label, enum playlist_label_display_mode label_display_mode; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_t *playlist = playlist_get_cached(); if (!playlist) @@ -472,7 +475,8 @@ static int playlist_label_display_mode_left(unsigned type, const char *label, label_display_mode = LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX; playlist_set_label_display_mode(playlist, label_display_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -482,6 +486,7 @@ static void playlist_thumbnail_mode_left(playlist_t *playlist, enum playlist_thu { settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; enum playlist_thumbnail_mode thumbnail_mode = playlist_get_thumbnail_mode(playlist, thumbnail_id); @@ -491,7 +496,8 @@ static void playlist_thumbnail_mode_left(playlist_t *playlist, enum playlist_thu thumbnail_mode = PLAYLIST_THUMBNAIL_MODE_BOXARTS; playlist_set_thumbnail_mode(playlist, thumbnail_id, thumbnail_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); } static int playlist_right_thumbnail_mode_left(unsigned type, const char *label, @@ -526,6 +532,7 @@ static int playlist_sort_mode_left(unsigned type, const char *label, enum playlist_sort_mode sort_mode; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_t *playlist = playlist_get_cached(); if (!playlist) @@ -539,7 +546,8 @@ static int playlist_sort_mode_left(unsigned type, const char *label, sort_mode = PLAYLIST_SORT_MODE_OFF; playlist_set_sort_mode(playlist, sort_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index eece239717..0417ee9350 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -2038,6 +2038,7 @@ static int action_ok_playlist_entry_collection(const char *path, menu_handle_t *menu = menu_driver_get_ptr(); settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical; const char *path_content_history = settings->paths.path_content_history; const char *path_content_music_history = settings->paths.path_content_music_history; @@ -2163,7 +2164,8 @@ static int action_ok_playlist_entry_collection(const char *path, playlist, selection_ptr, &update_entry, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); } else { @@ -2205,6 +2207,7 @@ static int action_ok_playlist_entry(const char *path, playlist_t *playlist = playlist_get_cached(); menu_handle_t *menu = menu_driver_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; new_core_path[0] = '\0'; @@ -2258,7 +2261,8 @@ static int action_ok_playlist_entry(const char *path, command_playlist_update_write(NULL, selection_ptr, &entry, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); } } else @@ -2292,6 +2296,7 @@ static int action_ok_playlist_entry_start_content(const char *path, playlist_t *playlist = playlist_get_cached(); menu_handle_t *menu = menu_driver_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (!playlist || !menu) return menu_cbs_exit(); @@ -2347,7 +2352,8 @@ static int action_ok_playlist_entry_start_content(const char *path, playlist, selection_ptr, &entry, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); } } @@ -2611,6 +2617,7 @@ static int action_ok_audio_add_to_mixer_and_collection(const char *path, menu_handle_t *menu = menu_driver_get_ptr(); bool playlist_fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; combined_path[0] = '\0'; @@ -2627,7 +2634,8 @@ static int action_ok_audio_add_to_mixer_and_collection(const char *path, command_playlist_push_write(g_defaults.music_history, &entry, playlist_fuzzy_archive_match, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); if (filestream_exists(combined_path)) task_push_audio_mixer_load(combined_path, @@ -2647,6 +2655,7 @@ static int action_ok_audio_add_to_mixer_and_collection_and_play(const char *path settings_t *settings = config_get_ptr(); bool playlist_fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; combined_path[0] = '\0'; @@ -2663,8 +2672,8 @@ static int action_ok_audio_add_to_mixer_and_collection_and_play(const char *path command_playlist_push_write(g_defaults.music_history, &entry, playlist_fuzzy_archive_match, - playlist_use_old_format - ); + playlist_use_old_format, + playlist_compression); if (filestream_exists(combined_path)) task_push_audio_mixer_load_and_play(combined_path, @@ -2726,6 +2735,7 @@ static void menu_input_st_string_cb_rename_entry(void *userdata, { settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (str && *str) { const char *label = menu_input_dialog_get_buffer(); @@ -2741,7 +2751,8 @@ static void menu_input_st_string_cb_rename_entry(void *userdata, command_playlist_update_write(NULL, menu_input_dialog_get_kb_idx(), &entry, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); } } @@ -3332,6 +3343,7 @@ static int action_ok_core_deferred_set(const char *new_core_path, const char *path_dir_libretro = settings->paths.directory_libretro; bool show_hidden_files = settings->bools.show_hidden_files; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; ext_name[0] = '\0'; core_display_name[0] = '\0'; @@ -3364,7 +3376,8 @@ static int action_ok_core_deferred_set(const char *new_core_path, NULL, menu->scratchpad.unsigned_var, &entry, - playlist_use_old_format); + playlist_use_old_format, + playlist_compression); /* Provide visual feedback */ strlcpy(msg, msg_hash_to_str(MSG_SET_CORE_ASSOCIATION), sizeof(msg)); @@ -4952,6 +4965,7 @@ static int action_ok_delete_entry(const char *path, char *def_conf_fav_path = NULL; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_t *playlist = playlist_get_cached(); menu_handle_t *menu = menu_driver_get_ptr(); @@ -4987,7 +5001,8 @@ static int action_ok_delete_entry(const char *path, if (playlist) { playlist_delete_index(playlist, menu->rpl_entry_selection_ptr); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); } new_selection_ptr = menu_navigation_get_selection(); @@ -5858,6 +5873,7 @@ static int action_ok_push_dropdown_item_playlist_default_core(const char *path, const char* core_name = path; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; /* Get core list */ core_info_get_list(&core_info_list); @@ -5907,7 +5923,8 @@ static int action_ok_push_dropdown_item_playlist_default_core(const char *path, } /* In all cases, update file on disk */ - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return action_cancel_pop_default(NULL, NULL, 0, 0); } @@ -5920,11 +5937,13 @@ static int action_ok_push_dropdown_item_playlist_label_display_mode( settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_set_label_display_mode(playlist, (enum playlist_label_display_mode)idx); /* In all cases, update file on disk */ - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return action_cancel_pop_default(NULL, NULL, 0, 0); } @@ -5934,13 +5953,15 @@ static int generic_set_thumbnail_mode(enum playlist_thumbnail_id thumbnail_id, s settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (!playlist) return -1; playlist_set_thumbnail_mode(playlist, thumbnail_id, (enum playlist_thumbnail_mode)idx); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return action_cancel_pop_default(NULL, NULL, 0, 0); } @@ -5964,9 +5985,11 @@ static int action_ok_push_dropdown_item_playlist_sort_mode( settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_set_sort_mode(playlist, (enum playlist_sort_mode)idx); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return action_cancel_pop_default(NULL, NULL, 0, 0); } diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 8982e1dbde..f001fe838c 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -483,6 +483,7 @@ static int playlist_association_right(unsigned type, const char *label, settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; core_path[0] = '\0'; @@ -545,7 +546,8 @@ static int playlist_association_right(unsigned type, const char *label, /* Update playlist */ playlist_set_default_core_path(playlist, core_info->path); playlist_set_default_core_name(playlist, core_info->display_name); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -557,6 +559,7 @@ static int playlist_label_display_mode_right(unsigned type, const char *label, settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (!playlist) return -1; @@ -569,7 +572,8 @@ static int playlist_label_display_mode_right(unsigned type, const char *label, label_display_mode = LABEL_DISPLAY_MODE_DEFAULT; playlist_set_label_display_mode(playlist, label_display_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -579,6 +583,7 @@ static void playlist_thumbnail_mode_right(playlist_t *playlist, enum playlist_th { settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; enum playlist_thumbnail_mode thumbnail_mode = playlist_get_thumbnail_mode(playlist, thumbnail_id); @@ -588,7 +593,8 @@ static void playlist_thumbnail_mode_right(playlist_t *playlist, enum playlist_th thumbnail_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT; playlist_set_thumbnail_mode(playlist, thumbnail_id, thumbnail_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); } static int playlist_right_thumbnail_mode_right(unsigned type, const char *label, @@ -624,6 +630,7 @@ static int playlist_sort_mode_right(unsigned type, const char *label, settings_t *settings = config_get_ptr(); playlist_t *playlist = playlist_get_cached(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (!playlist) return -1; @@ -636,7 +643,8 @@ static int playlist_sort_mode_right(unsigned type, const char *label, sort_mode = PLAYLIST_SORT_MODE_DEFAULT; playlist_set_sort_mode(playlist, sort_mode); - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index dc216c4493..d53b139586 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -297,8 +297,10 @@ static int action_start_playlist_association( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - settings_t *settings = config_get_ptr(); - playlist_t *playlist = playlist_get_cached(); + settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; + playlist_t *playlist = playlist_get_cached(); if (!playlist) return -1; @@ -306,7 +308,8 @@ static int action_start_playlist_association( /* Set default core path + name to DETECT */ playlist_set_default_core_path(playlist, file_path_str(FILE_PATH_DETECT)); playlist_set_default_core_name(playlist, file_path_str(FILE_PATH_DETECT)); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -315,15 +318,18 @@ static int action_start_playlist_label_display_mode( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - settings_t *settings = config_get_ptr(); - playlist_t *playlist = playlist_get_cached(); + settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; + playlist_t *playlist = playlist_get_cached(); if (!playlist) return -1; /* Set label display mode to the default */ playlist_set_label_display_mode(playlist, LABEL_DISPLAY_MODE_DEFAULT); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -332,15 +338,18 @@ static int action_start_playlist_right_thumbnail_mode( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - settings_t *settings = config_get_ptr(); - playlist_t *playlist = playlist_get_cached(); + settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; + playlist_t *playlist = playlist_get_cached(); if (!playlist) return -1; /* Set thumbnail_mode to default value */ playlist_set_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_RIGHT, PLAYLIST_THUMBNAIL_MODE_DEFAULT); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -349,15 +358,18 @@ static int action_start_playlist_left_thumbnail_mode( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - settings_t *settings = config_get_ptr(); - playlist_t *playlist = playlist_get_cached(); + settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; + playlist_t *playlist = playlist_get_cached(); if (!playlist) return -1; /* Set thumbnail_mode to default value */ playlist_set_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_LEFT, PLAYLIST_THUMBNAIL_MODE_DEFAULT); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } @@ -366,15 +378,18 @@ static int action_start_playlist_sort_mode( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - settings_t *settings = config_get_ptr(); - playlist_t *playlist = playlist_get_cached(); + settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; + playlist_t *playlist = playlist_get_cached(); if (!playlist) return -1; /* Set sort mode to the default */ playlist_set_sort_mode(playlist, PLAYLIST_SORT_MODE_DEFAULT); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); return 0; } diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index c26f18148b..b215df055f 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -759,6 +759,8 @@ default_sublabel_macro(action_bind_sublabel_menu_ticker_smooth, default_sublabel_macro(action_bind_sublabel_playlist_show_inline_core_name, MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_INLINE_CORE_NAME) default_sublabel_macro(action_bind_sublabel_playlist_sort_alphabetical, MENU_ENUM_SUBLABEL_PLAYLIST_SORT_ALPHABETICAL) default_sublabel_macro(action_bind_sublabel_playlist_fuzzy_archive_match, MENU_ENUM_SUBLABEL_PLAYLIST_FUZZY_ARCHIVE_MATCH) +default_sublabel_macro(action_bind_sublabel_playlist_use_old_format, MENU_ENUM_SUBLABEL_PLAYLIST_USE_OLD_FORMAT) +default_sublabel_macro(action_bind_sublabel_playlist_compression, MENU_ENUM_SUBLABEL_PLAYLIST_COMPRESSION) default_sublabel_macro(action_bind_sublabel_menu_rgui_full_width_layout, MENU_ENUM_SUBLABEL_MENU_RGUI_FULL_WIDTH_LAYOUT) default_sublabel_macro(action_bind_sublabel_menu_rgui_extended_ascii, MENU_ENUM_SUBLABEL_MENU_RGUI_EXTENDED_ASCII) default_sublabel_macro(action_bind_sublabel_thumbnails_updater_list, MENU_ENUM_SUBLABEL_THUMBNAILS_UPDATER_LIST) @@ -3286,6 +3288,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_PLAYLIST_FUZZY_ARCHIVE_MATCH: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_fuzzy_archive_match); break; + case MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_use_old_format); + break; + case MENU_ENUM_LABEL_PLAYLIST_COMPRESSION: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_compression); + break; case MENU_ENUM_LABEL_MENU_RGUI_FULL_WIDTH_LAYOUT: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_full_width_layout); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index e58440cacc..5b545d56c9 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1737,6 +1737,8 @@ static void menu_displaylist_set_new_playlist( int content_favorites_size = settings->ints.content_favorites_size; unsigned content_history_size = settings->uints.content_history_size; bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical; + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; menu->db_playlist_file[0] = '\0'; @@ -1756,7 +1758,9 @@ static void menu_displaylist_set_new_playlist( playlist_size = (unsigned)content_favorites_size; } - if (playlist_init_cached(path, playlist_size)) + if (playlist_init_cached( + path, playlist_size, + playlist_use_old_format, playlist_compression)) { playlist_t *playlist = playlist_get_cached(); enum playlist_sort_mode current_sort_mode = playlist_get_sort_mode(playlist); @@ -2989,9 +2993,8 @@ static bool menu_displaylist_parse_playlist_manager_settings( MENU_SETTING_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE, 0, 0); /* Sorting mode - * > Only enabled when using the new playlist format * > Not relevant for history playlists */ - if (!playlist_use_old_format && !is_content_history) + if (!is_content_history) menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_SORT_MODE), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE), @@ -4263,6 +4266,7 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_PLAYLIST_ENTRY_REMOVE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, PARSE_ONLY_BOOL, true}, + {MENU_ENUM_LABEL_PLAYLIST_COMPRESSION, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_INLINE_CORE_NAME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE, PARSE_ONLY_UINT, false}, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index bcf8d6b501..e383905927 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -15647,6 +15647,24 @@ static bool setting_append_list( SD_FLAG_NONE ); +#if defined(HAVE_ZLIB) + CONFIG_BOOL( + list, list_info, + &settings->bools.playlist_compression, + MENU_ENUM_LABEL_PLAYLIST_COMPRESSION, + MENU_ENUM_LABEL_VALUE_PLAYLIST_COMPRESSION, + DEFAULT_PLAYLIST_COMPRESSION, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); +#endif + CONFIG_BOOL( list, list_info, &settings->bools.playlist_show_sublabels, diff --git a/msg_hash.h b/msg_hash.h index 091809e036..eb140b10fe 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2696,6 +2696,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_HOLD_START, MENU_ENUM_LABEL_VALUE_DOWN_SELECT, MENU_LABEL(PLAYLIST_USE_OLD_FORMAT), + MENU_LABEL(PLAYLIST_COMPRESSION), MENU_LABEL(MENU_SOUNDS), MENU_LABEL(MENU_SOUND_OK), MENU_LABEL(MENU_SOUND_CANCEL), diff --git a/playlist.c b/playlist.c index 83c6a7bdc0..26e7e7b223 100644 --- a/playlist.c +++ b/playlist.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,8 @@ struct content_playlist { bool modified; + bool old_format; + bool compressed; enum playlist_label_display_mode label_display_mode; enum playlist_thumbnail_mode right_thumbnail_mode; @@ -69,7 +70,7 @@ typedef struct JSON_Parser parser; JSON_Writer writer; - RFILE *file; + intfstream_t *file; playlist_t *playlist; struct playlist_entry *current_entry; char *current_meta_string; @@ -1016,7 +1017,7 @@ static JSON_Writer_HandlerResult JSONOutputHandler(JSON_Writer writer, const cha JSONContext *context = (JSONContext*)JSON_Writer_GetUserData(writer); (void)writer; /* unused */ - return filestream_write(context->file, pBytes, length) == length ? JSON_Writer_Continue : JSON_Writer_Abort; + return intfstream_write(context->file, pBytes, length) == length ? JSON_Writer_Continue : JSON_Writer_Abort; } static void JSONLogError(JSONContext *pCtx) @@ -1042,13 +1043,13 @@ static void JSONLogError(JSONContext *pCtx) void playlist_write_runtime_file(playlist_t *playlist) { size_t i; - RFILE *file = NULL; + intfstream_t *file = NULL; JSONContext context = {0}; if (!playlist || !playlist->modified) return; - file = filestream_open(playlist->conf_path, + file = intfstream_open_file(playlist->conf_path, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) @@ -1058,7 +1059,7 @@ void playlist_write_runtime_file(playlist_t *playlist) } context.writer = JSON_Writer_Create(NULL); - context.file = file; + context.file = file; if (!context.writer) { @@ -1263,23 +1264,47 @@ void playlist_write_runtime_file(playlist_t *playlist) JSON_Writer_WriteNewLine(context.writer); JSON_Writer_Free(context.writer); - playlist->modified = false; + playlist->modified = false; + playlist->old_format = false; + playlist->compressed = false; RARCH_LOG("Written to playlist file: %s\n", playlist->conf_path); end: - filestream_close(file); + intfstream_close(file); + free(file); } -void playlist_write_file(playlist_t *playlist, bool use_old_format) +void playlist_write_file( + playlist_t *playlist, + bool use_old_format, bool compress) { size_t i; - RFILE *file = NULL; + intfstream_t *file = NULL; - if (!playlist || !playlist->modified) + /* Playlist will be written if any of the + * following are true: + * > 'modified' flag is set + * > Current playlist format (old/new) does not + * match requested + * > Current playlist compression status does + * not match requested */ + if (!playlist || + !(playlist->modified || +#if defined(HAVE_ZLIB) + (playlist->compressed != compress) || +#endif + (playlist->old_format != use_old_format))) return; - file = filestream_open(playlist->conf_path, - RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); +#if defined(HAVE_ZLIB) + if (compress) + file = intfstream_open_rzip_file(playlist->conf_path, + RETRO_VFS_FILE_ACCESS_WRITE); + else +#endif + file = intfstream_open_file(playlist->conf_path, + RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) { @@ -1291,32 +1316,33 @@ void playlist_write_file(playlist_t *playlist, bool use_old_format) if (use_old_format) { for (i = 0; i < playlist->size; i++) - filestream_printf(file, "%s\n%s\n%s\n%s\n%s\n%s\n", - playlist->entries[i].path ? playlist->entries[i].path : "", - playlist->entries[i].label ? playlist->entries[i].label : "", - playlist->entries[i].core_path, - playlist->entries[i].core_name, - playlist->entries[i].crc32 ? playlist->entries[i].crc32 : "", - playlist->entries[i].db_name ? playlist->entries[i].db_name : "" + intfstream_printf(file, "%s\n%s\n%s\n%s\n%s\n%s\n", + playlist->entries[i].path ? playlist->entries[i].path : "", + playlist->entries[i].label ? playlist->entries[i].label : "", + playlist->entries[i].core_path ? playlist->entries[i].core_path : "", + playlist->entries[i].core_name ? playlist->entries[i].core_name : "", + playlist->entries[i].crc32 ? playlist->entries[i].crc32 : "", + playlist->entries[i].db_name ? playlist->entries[i].db_name : "" ); /* Add metadata lines * > We add these at the end of the file to prevent * breakage if the playlist is loaded with an older - * version of RetroArch - * > There is only room for four entries. At present - * the following metadata is excluded: - * - sort_mode */ - filestream_printf( + * version of RetroArch */ + intfstream_printf( file, "default_core_path = \"%s\"\n" "default_core_name = \"%s\"\n" "label_display_mode = \"%d\"\n" - "thumbnail_mode = \"%d|%d\"\n", - playlist->default_core_path ? "" : playlist->default_core_path, - playlist->default_core_name ? "" : playlist->default_core_name, + "thumbnail_mode = \"%d|%d\"\n" + "sort_mode = \"%d\"\n", + playlist->default_core_path ? playlist->default_core_path : "", + playlist->default_core_name ? playlist->default_core_name : "", playlist->label_display_mode, - playlist->right_thumbnail_mode, playlist->left_thumbnail_mode); + playlist->right_thumbnail_mode, playlist->left_thumbnail_mode, + playlist->sort_mode); + + playlist->old_format = true; } else #endif @@ -1626,13 +1652,17 @@ void playlist_write_file(playlist_t *playlist, bool use_old_format) JSON_Writer_WriteEndObject(context.writer); JSON_Writer_WriteNewLine(context.writer); JSON_Writer_Free(context.writer); + + playlist->old_format = false; } - playlist->modified = false; + playlist->modified = false; + playlist->compressed = intfstream_is_compressed(file); RARCH_LOG("Written to playlist file: %s\n", playlist->conf_path); end: - filestream_close(file); + intfstream_close(file); + free(file); } /** @@ -2083,54 +2113,62 @@ static bool playlist_read_file( playlist_t *playlist, const char *path) { unsigned i; - bool new_format = true; - RFILE *file = filestream_open(path, - RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + int test_char; + intfstream_t *file = NULL; + +#if defined(HAVE_ZLIB) + /* Always use RZIP interface when reading playlists + * > this will automatically handle uncompressed + * data */ + file = intfstream_open_rzip_file(path, + RETRO_VFS_FILE_ACCESS_READ); +#else + file = intfstream_open_file(path, + RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); +#endif + + playlist->compressed = intfstream_is_compressed(file); /* If playlist file does not exist, - * create an empty playlist instead. - */ + * create an empty playlist instead */ if (!file) return true; - /* Detect format of playlist */ + /* Detect format of playlist + * > Read file until we find the first printable + * non-whitespace ASCII character */ + do { - int test_char; + test_char = intfstream_getc(file); - /* Read file until we find the first printable non-whitespace - * ASCII character */ - do - { - test_char = filestream_getc(file); + if (test_char == EOF) /* read error or end of file */ + goto end; + } + while (!isgraph(test_char) || test_char > 0x7F); - if (test_char == EOF) /* read error or end of file */ - goto end; - } - while (!isgraph(test_char) || test_char > 0x7F); - - if (test_char == '{') - { - /* New playlist format detected */ - /*RARCH_LOG("New playlist format detected.\n");*/ - new_format = true; - } - else - { - /* old playlist format detected */ - /*RARCH_LOG("Old playlist format detected.\n");*/ - new_format = false; - } - - /* Reset file to start */ - filestream_seek(file, 0, SEEK_SET); + if (test_char == '{') + { + /* New playlist format detected */ + /*RARCH_LOG("New playlist format detected.\n");*/ + playlist->old_format = false; + } + else + { + /* old playlist format detected */ + /*RARCH_LOG("Old playlist format detected.\n");*/ + playlist->old_format = true; } - if (new_format) + /* Reset file to start */ + intfstream_rewind(file); + + if (!playlist->old_format) { JSONContext context = {0}; - context.parser = JSON_Parser_Create(NULL); - context.file = file; - context.playlist = playlist; + context.parser = JSON_Parser_Create(NULL); + context.file = file; + context.playlist = playlist; if (!context.parser) { @@ -2164,12 +2202,12 @@ static bool playlist_read_file( JSON_Parser_SetEndArrayHandler(context.parser, &JSONEndArrayHandler); JSON_Parser_SetUserData(context.parser, &context); - while (!filestream_eof(file)) + while (!intfstream_eof(file)) { char chunk[4096] = {0}; - int64_t length = filestream_read(file, chunk, sizeof(chunk)); + int64_t length = intfstream_read(file, chunk, sizeof(chunk)); - if (!length && !filestream_eof(file)) + if (!length && !intfstream_eof(file)) { RARCH_WARN("Could not read JSON input.\n"); goto json_cleanup; @@ -2209,188 +2247,203 @@ json_cleanup: } else { - char buf[PLAYLIST_ENTRIES][1024] = {{0}}; - char metadata_line[1024]; - char default_core_path[1024]; - char default_core_name[1024]; - char metadata_char = 0; - size_t metadata_counter = 0; + char line_buf[PLAYLIST_ENTRIES][1024] = {{0}}; + /* Unnecessary, but harmless */ for (i = 0; i < PLAYLIST_ENTRIES; i++) - buf[i][0] = '\0'; - - metadata_line[0] = '\0'; - default_core_path[0] = '\0'; - default_core_name[0] = '\0'; - - /* Attempt to read metadata lines at end of file */ - filestream_seek(file, -1, SEEK_END); - if (filestream_error(file)) - goto end; - - /* > Exclude trailing newline */ - metadata_char = filestream_getc(file); - - while ((metadata_char == '\n') || - (metadata_char == '\r')) - { - filestream_seek(file, -2, SEEK_CUR); - if (filestream_error(file)) - goto end; - - metadata_char = filestream_getc(file); - } - - /* Search backwards for the next four newlines */ - while (metadata_counter < 4) - { - filestream_seek(file, -2, SEEK_CUR); - if (filestream_error(file)) - goto end; - - metadata_char = filestream_getc(file); - if (metadata_char == '\n') - metadata_counter++; - } - - /* > Get default_core_path */ - if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) - goto end; - - if (strncmp("default_core_path", - metadata_line, - STRLEN_CONST("default_core_path")) == 0) - get_old_format_metadata_value( - metadata_line, default_core_path, sizeof(default_core_path)); - - /* > Get default_core_name */ - if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) - goto end; - - if (strncmp("default_core_name", - metadata_line, - STRLEN_CONST("default_core_name")) == 0) - get_old_format_metadata_value( - metadata_line, default_core_name, sizeof(default_core_name)); - - /* > Get label_display_mode */ - if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) - goto end; - - if (strncmp("label_display_mode", - metadata_line, - STRLEN_CONST("label_display_mode")) == 0) - { - unsigned display_mode; - char display_mode_str[4] = {0}; - - get_old_format_metadata_value( - metadata_line, display_mode_str, sizeof(display_mode_str)); - - display_mode = string_to_unsigned(display_mode_str); - - if (display_mode <= LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX) - playlist->label_display_mode = (enum playlist_label_display_mode)display_mode; - } - - /* > Get thumbnail modes */ - if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) - goto end; - - if (strncmp("thumbnail_mode", - metadata_line, - STRLEN_CONST("thumbnail_mode")) == 0) - { - char thumbnail_mode_str[8] = {0}; - struct string_list *thumbnail_modes = NULL; - - get_old_format_metadata_value( - metadata_line, thumbnail_mode_str, sizeof(thumbnail_mode_str)); - - thumbnail_modes = string_split(thumbnail_mode_str, "|"); - - if (thumbnail_modes) - { - if (thumbnail_modes->size == 2) - { - unsigned thumbnail_mode; - - /* Right thumbnail mode */ - thumbnail_mode = string_to_unsigned(thumbnail_modes->elems[0].data); - if (thumbnail_mode <= PLAYLIST_THUMBNAIL_MODE_BOXARTS) - playlist->right_thumbnail_mode = (enum playlist_thumbnail_mode)thumbnail_mode; - - /* Left thumbnail mode */ - thumbnail_mode = string_to_unsigned(thumbnail_modes->elems[1].data); - if (thumbnail_mode <= PLAYLIST_THUMBNAIL_MODE_BOXARTS) - playlist->left_thumbnail_mode = (enum playlist_thumbnail_mode)thumbnail_mode; - } - - string_list_free(thumbnail_modes); - } - } - - /* > Populate default core path/name, if required - * (if one is empty, the other should be ignored) */ - if (!string_is_empty(default_core_path) && - !string_is_empty(default_core_name)) - { - playlist->default_core_path = strdup(default_core_path); - playlist->default_core_name = strdup(default_core_name); - } - - /* > Sort mode is excluded from old format - * playlists - just set to default */ - playlist->sort_mode = PLAYLIST_SORT_MODE_DEFAULT; + line_buf[i][0] = '\0'; /* Read playlist entries */ - filestream_seek(file, 0, SEEK_SET); - if (filestream_error(file)) - goto end; - - for (playlist->size = 0; playlist->size < playlist->cap; ) + playlist->size = 0; + while (playlist->size < playlist->cap) { - unsigned i; - struct playlist_entry *entry = NULL; + size_t i; + size_t lines_read = 0; + + /* Attempt to read the next 'PLAYLIST_ENTRIES' + * lines from the file */ for (i = 0; i < PLAYLIST_ENTRIES; i++) { - char *last = NULL; - *buf[i] = '\0'; + *line_buf[i] = '\0'; - if (!filestream_gets(file, buf[i], sizeof(buf[i]))) - goto end; + if (intfstream_gets(file, line_buf[i], sizeof(line_buf[i]))) + { + char *last_char = NULL; - /* Read playlist entry and terminate string with NUL character - * regardless of Windows or Unix line endings - */ - if ((last = strrchr(buf[i], '\r'))) - *last = '\0'; - else if ((last = strrchr(buf[i], '\n'))) - *last = '\0'; + /* Ensure line is NUL terminated, regardless of + * Windows or Unix line endings */ + if ((last_char = strrchr(line_buf[i], '\r'))) + *last_char = '\0'; + else if ((last_char = strrchr(line_buf[i], '\n'))) + *last_char = '\0'; + + lines_read++; + } + else + break; } - entry = &playlist->entries[playlist->size]; + /* If a 'full set' of lines were read, then this + * is a valid playlist entry */ + if (lines_read >= PLAYLIST_ENTRIES) + { + struct playlist_entry *entry = + &playlist->entries[playlist->size]; - if (!*buf[2] || !*buf[3]) - continue; + if (!entry) + continue; - if (*buf[0]) - entry->path = strdup(buf[0]); - if (*buf[1]) - entry->label = strdup(buf[1]); + /* path */ + if (!string_is_empty(line_buf[0])) + entry->path = strdup(line_buf[0]); - entry->core_path = strdup(buf[2]); - entry->core_name = strdup(buf[3]); - if (*buf[4]) - entry->crc32 = strdup(buf[4]); - if (*buf[5]) - entry->db_name = strdup(buf[5]); - playlist->size++; + /* label */ + if (!string_is_empty(line_buf[1])) + entry->label = strdup(line_buf[1]); + + /* core_path */ + if (!string_is_empty(line_buf[2])) + entry->core_path = strdup(line_buf[2]); + + /* core_name */ + if (!string_is_empty(line_buf[3])) + entry->core_name = strdup(line_buf[3]); + + /* crc32 */ + if (!string_is_empty(line_buf[4])) + entry->crc32 = strdup(line_buf[4]); + + /* db_name */ + if (!string_is_empty(line_buf[5])) + entry->db_name = strdup(line_buf[5]); + + playlist->size++; + } + /* If fewer than 'PLAYLIST_ENTRIES' lines were + * read, then this is metadata */ + else + { + char default_core_path[1024]; + char default_core_name[1024]; + + default_core_path[0] = '\0'; + default_core_name[0] = '\0'; + + /* Get default_core_path */ + if (lines_read < 1) + break; + + if (strncmp("default_core_path", + line_buf[0], + STRLEN_CONST("default_core_path")) == 0) + get_old_format_metadata_value( + line_buf[0], default_core_path, sizeof(default_core_path)); + + /* Get default_core_name */ + if (lines_read < 2) + break; + + if (strncmp("default_core_name", + line_buf[1], + STRLEN_CONST("default_core_name")) == 0) + get_old_format_metadata_value( + line_buf[1], default_core_name, sizeof(default_core_name)); + + /* > Populate default core path/name, if required + * (if one is empty, the other should be ignored) */ + if (!string_is_empty(default_core_path) && + !string_is_empty(default_core_name)) + { + playlist->default_core_path = strdup(default_core_path); + playlist->default_core_name = strdup(default_core_name); + } + + /* Get label_display_mode */ + if (lines_read < 3) + break; + + if (strncmp("label_display_mode", + line_buf[2], + STRLEN_CONST("label_display_mode")) == 0) + { + unsigned display_mode; + char display_mode_str[4] = {0}; + + get_old_format_metadata_value( + line_buf[2], display_mode_str, sizeof(display_mode_str)); + + display_mode = string_to_unsigned(display_mode_str); + + if (display_mode <= LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX) + playlist->label_display_mode = (enum playlist_label_display_mode)display_mode; + } + + /* Get thumbnail modes */ + if (lines_read < 4) + break; + + if (strncmp("thumbnail_mode", + line_buf[3], + STRLEN_CONST("thumbnail_mode")) == 0) + { + char thumbnail_mode_str[8] = {0}; + struct string_list *thumbnail_modes = NULL; + + get_old_format_metadata_value( + line_buf[3], thumbnail_mode_str, sizeof(thumbnail_mode_str)); + + thumbnail_modes = string_split(thumbnail_mode_str, "|"); + + if (thumbnail_modes) + { + if (thumbnail_modes->size == 2) + { + unsigned thumbnail_mode; + + /* Right thumbnail mode */ + thumbnail_mode = string_to_unsigned(thumbnail_modes->elems[0].data); + if (thumbnail_mode <= PLAYLIST_THUMBNAIL_MODE_BOXARTS) + playlist->right_thumbnail_mode = (enum playlist_thumbnail_mode)thumbnail_mode; + + /* Left thumbnail mode */ + thumbnail_mode = string_to_unsigned(thumbnail_modes->elems[1].data); + if (thumbnail_mode <= PLAYLIST_THUMBNAIL_MODE_BOXARTS) + playlist->left_thumbnail_mode = (enum playlist_thumbnail_mode)thumbnail_mode; + } + + string_list_free(thumbnail_modes); + } + } + + /* Get sort_mode */ + if (lines_read < 5) + break; + + if (strncmp("sort_mode", + line_buf[4], + STRLEN_CONST("sort_mode")) == 0) + { + unsigned sort_mode; + char sort_mode_str[4] = {0}; + + get_old_format_metadata_value( + line_buf[4], sort_mode_str, sizeof(sort_mode_str)); + + sort_mode = string_to_unsigned(sort_mode_str); + + if (sort_mode <= PLAYLIST_SORT_MODE_OFF) + playlist->sort_mode = (enum playlist_sort_mode)sort_mode; + } + + /* All metadata parsed -> end of file */ + break; + } } } end: - filestream_close(file); + intfstream_close(file); + free(file); return true; } @@ -2407,12 +2460,24 @@ playlist_t *playlist_get_cached(void) return NULL; } -bool playlist_init_cached(const char *path, size_t size) +bool playlist_init_cached( + const char *path, size_t size, + bool use_old_format, bool compress) { playlist_t *playlist = playlist_init(path, size); if (!playlist) return false; + /* If playlist format/compression state + * does not match requested settings, update + * file on disk immediately */ + if ( +#if defined(HAVE_ZLIB) + (playlist->compressed != compress) || +#endif + (playlist->old_format != use_old_format)) + playlist_write_file(playlist, use_old_format, compress); + playlist_cached = playlist; return true; } @@ -2441,6 +2506,8 @@ playlist_t *playlist_init(const char *path, size_t size) } playlist->modified = false; + playlist->old_format = false; + playlist->compressed = false; playlist->size = 0; playlist->cap = size; playlist->conf_path = strdup(path); @@ -2553,20 +2620,22 @@ void command_playlist_push_write( playlist_t *playlist, const struct playlist_entry *entry, bool fuzzy_archive_match, - bool use_old_format) + bool use_old_format, + bool compress) { if (!playlist) return; if (playlist_push(playlist, entry, fuzzy_archive_match)) - playlist_write_file(playlist, use_old_format); + playlist_write_file(playlist, use_old_format, compress); } void command_playlist_update_write( playlist_t *plist, size_t idx, const struct playlist_entry *entry, - bool use_old_format) + bool use_old_format, + bool compress) { playlist_t *playlist = plist ? plist : playlist_get_cached(); @@ -2578,7 +2647,7 @@ void command_playlist_update_write( idx, entry); - playlist_write_file(playlist, use_old_format); + playlist_write_file(playlist, use_old_format, compress); } bool playlist_index_is_valid(playlist_t *playlist, size_t idx, diff --git a/playlist.h b/playlist.h index 57e55a2f20..0ec5fb4b81 100644 --- a/playlist.h +++ b/playlist.h @@ -246,7 +246,9 @@ char *playlist_get_conf_path(playlist_t *playlist); uint32_t playlist_get_size(playlist_t *playlist); -void playlist_write_file(playlist_t *playlist, bool use_old_format); +void playlist_write_file( + playlist_t *playlist, + bool use_old_format, bool compress); void playlist_write_runtime_file(playlist_t *playlist); @@ -256,19 +258,31 @@ void playlist_free_cached(void); playlist_t *playlist_get_cached(void); -bool playlist_init_cached(const char *path, size_t size); +/* If current on-disk playlist file referenced + * by 'path' does not match requested 'old format' + * or 'compression' state, file will be updated + * automatically + * > Since this function is called whenever a + * playlist is browsed via the menu, this is + * a simple method for ensuring that files + * are always kept synced with user settings */ +bool playlist_init_cached( + const char *path, size_t size, + bool use_old_format, bool compress); void command_playlist_push_write( playlist_t *playlist, const struct playlist_entry *entry, bool fuzzy_archive_match, - bool use_old_format); + bool use_old_format, + bool compress); void command_playlist_update_write( playlist_t *playlist, size_t idx, const struct playlist_entry *entry, - bool use_old_format); + bool use_old_format, + bool compress); /* Returns true if specified playlist index matches * specified content/core paths */ diff --git a/retroarch.c b/retroarch.c index 5757014390..45aec93d8b 100644 --- a/retroarch.c +++ b/retroarch.c @@ -8945,8 +8945,9 @@ bool command_event(enum event_command cmd, void *data) { settings_t *settings = configuration_settings; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_write_file(g_defaults.content_history, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); playlist_free(g_defaults.content_history); } g_defaults.content_history = NULL; @@ -8955,8 +8956,9 @@ bool command_event(enum event_command cmd, void *data) { settings_t *settings = configuration_settings; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_write_file(g_defaults.music_history, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); playlist_free(g_defaults.music_history); } g_defaults.music_history = NULL; @@ -8966,12 +8968,12 @@ bool command_event(enum event_command cmd, void *data) { settings_t *settings = configuration_settings; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_write_file(g_defaults.video_history, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); playlist_free(g_defaults.video_history); } g_defaults.video_history = NULL; - #endif #ifdef HAVE_IMAGEVIEWER @@ -8979,8 +8981,9 @@ bool command_event(enum event_command cmd, void *data) { settings_t *settings = configuration_settings; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_write_file(g_defaults.image_history, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); playlist_free(g_defaults.image_history); } g_defaults.image_history = NULL; @@ -9186,6 +9189,7 @@ bool command_event(enum event_command cmd, void *data) { struct playlist_entry entry = {0}; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical; bool playlist_fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; @@ -9209,7 +9213,7 @@ bool command_event(enum event_command cmd, void *data) playlist_qsort(g_defaults.content_favorites); playlist_write_file(g_defaults.content_favorites, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } } @@ -9225,6 +9229,7 @@ bool command_event(enum event_command cmd, void *data) size_t *playlist_index = (size_t*)data; struct playlist_entry entry = {0}; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; /* the update function reads our entry as const, * so these casts are safe */ @@ -9235,8 +9240,8 @@ bool command_event(enum event_command cmd, void *data) NULL, *playlist_index, &entry, - playlist_use_old_format - ); + playlist_use_old_format, + playlist_compression); runloop_msg_queue_push(msg_hash_to_str(MSG_RESET_CORE_ASSOCIATION), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); break; @@ -30677,9 +30682,10 @@ void rarch_favorites_deinit(void) { settings_t *settings = configuration_settings; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; playlist_write_file(g_defaults.content_favorites, - playlist_use_old_format); + playlist_use_old_format, playlist_compression); playlist_free(g_defaults.content_favorites); g_defaults.content_favorites = NULL; } diff --git a/tasks/task_content.c b/tasks/task_content.c index 7af9657528..6846d4a688 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -1444,7 +1444,8 @@ static void task_push_to_history_list( command_playlist_push_write( playlist_hist, &entry, settings->bools.playlist_fuzzy_archive_match, - settings->bools.playlist_use_old_format); + settings->bools.playlist_use_old_format, + settings->bools.playlist_compression); } } diff --git a/tasks/task_database.c b/tasks/task_database.c index 4069a78b7f..9d84ccc379 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -60,6 +60,7 @@ typedef struct db_handle { bool pl_fuzzy_archive_match; bool pl_use_old_format; + bool pl_compression; bool is_directory; bool scan_started; bool scan_without_core_match; @@ -880,7 +881,8 @@ static int database_info_list_iterate_found_match( playlist_push(playlist, &entry, _db->pl_fuzzy_archive_match); } - playlist_write_file(playlist, _db->pl_use_old_format); + playlist_write_file( + playlist, _db->pl_use_old_format, _db->pl_compression); playlist_free(playlist); database_info_list_free(db_state->info); @@ -1091,7 +1093,8 @@ static int task_database_iterate_playlist_lutro( free(game_title); } - playlist_write_file(playlist, _db->pl_use_old_format); + playlist_write_file( + playlist, _db->pl_use_old_format, _db->pl_compression); playlist_free(playlist); return 0; @@ -1407,9 +1410,11 @@ bool task_push_dbscan( db->scan_without_core_match = settings->bools.scan_without_core_match; db->pl_fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; db->pl_use_old_format = settings->bools.playlist_use_old_format; + db->pl_compression = settings->bools.playlist_compression; #else db->pl_fuzzy_archive_match = false; db->pl_use_old_format = false; + db->pl_compression = false; #endif db->show_hidden_files = db_dir_show_hidden_files; db->is_directory = directory; diff --git a/tasks/task_manual_content_scan.c b/tasks/task_manual_content_scan.c index 496783ffa0..ded2991499 100644 --- a/tasks/task_manual_content_scan.c +++ b/tasks/task_manual_content_scan.c @@ -63,6 +63,7 @@ typedef struct manual_scan_handle enum manual_scan_status status; bool fuzzy_archive_match; bool use_old_format; + bool compress; } manual_scan_handle_t; /* Frees task handle + all constituent objects */ @@ -309,7 +310,10 @@ static void task_manual_content_scan_handler(retro_task_t *task) playlist_qsort(manual_scan->playlist); /* Save playlist changes to disk */ - playlist_write_file(manual_scan->playlist, manual_scan->use_old_format); + playlist_write_file( + manual_scan->playlist, + manual_scan->use_old_format, + manual_scan->compress); /* If this is the currently cached playlist, then * it must be re-cached (otherwise changes will be @@ -323,7 +327,8 @@ static void task_manual_content_scan_handler(retro_task_t *task) { playlist_free_cached(); playlist_init_cached( - manual_scan->task_config->playlist_file, COLLECTION_SIZE); + manual_scan->task_config->playlist_file, COLLECTION_SIZE, + manual_scan->use_old_format, manual_scan->compress); } } @@ -412,6 +417,7 @@ bool task_push_manual_content_scan(void) manual_scan->status = MANUAL_SCAN_BEGIN; manual_scan->fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; manual_scan->use_old_format = settings->bools.playlist_use_old_format; + manual_scan->compress = settings->bools.playlist_compression; if (!manual_scan->m3u_list) goto error; diff --git a/tasks/task_playlist_manager.c b/tasks/task_playlist_manager.c index 6e72ba4c23..05d59c2484 100644 --- a/tasks/task_playlist_manager.c +++ b/tasks/task_playlist_manager.c @@ -50,6 +50,7 @@ enum pl_manager_status typedef struct pl_manager_handle { bool use_old_format; + bool compress; bool fuzzy_archive_match; enum pl_manager_status status; size_t list_size; @@ -99,7 +100,8 @@ static void free_pl_manager_handle(pl_manager_handle_t *pl_manager) } static void pl_manager_write_playlist( - playlist_t *playlist, const char *playlist_path, bool use_old_format) + playlist_t *playlist, const char *playlist_path, + bool use_old_format, bool compress) { playlist_t *cached_playlist = playlist_get_cached(); @@ -108,7 +110,7 @@ static void pl_manager_write_playlist( return; /* Write any changes to playlist file */ - playlist_write_file(playlist, use_old_format); + playlist_write_file(playlist, use_old_format, compress); /* If this is the currently cached playlist, then * it must be re-cached (otherwise changes will be @@ -119,7 +121,8 @@ static void pl_manager_write_playlist( if (string_is_equal(playlist_path, playlist_get_conf_path(cached_playlist))) { playlist_free_cached(); - playlist_init_cached(playlist_path, COLLECTION_SIZE); + playlist_init_cached( + playlist_path, COLLECTION_SIZE, use_old_format, compress); } } } @@ -227,7 +230,8 @@ static void task_pl_manager_reset_cores_handler(retro_task_t *task) pl_manager_write_playlist( pl_manager->playlist, pl_manager->playlist_path, - pl_manager->use_old_format); + pl_manager->use_old_format, + pl_manager->compress); /* Update progress display */ task_free_title(task); @@ -326,6 +330,7 @@ bool task_push_pl_manager_reset_cores(const char *playlist_path) pl_manager->m3u_index = 0; pl_manager->status = PL_MANAGER_BEGIN; pl_manager->use_old_format = settings->bools.playlist_use_old_format; + pl_manager->compress = settings->bools.playlist_compression; pl_manager->fuzzy_archive_match = false; /* Not relevant here */ task_queue_push(task); @@ -772,7 +777,8 @@ static void task_pl_manager_clean_playlist_handler(retro_task_t *task) pl_manager_write_playlist( pl_manager->playlist, pl_manager->playlist_path, - pl_manager->use_old_format); + pl_manager->use_old_format, + pl_manager->compress); /* Update progress display */ task_free_title(task); @@ -871,6 +877,7 @@ bool task_push_pl_manager_clean_playlist(const char *playlist_path) pl_manager->m3u_index = 0; pl_manager->status = PL_MANAGER_BEGIN; pl_manager->use_old_format = settings->bools.playlist_use_old_format; + pl_manager->compress = settings->bools.playlist_compression; pl_manager->fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; if (!pl_manager->m3u_list) diff --git a/tasks/task_screenshot.c b/tasks/task_screenshot.c index e8bba6cfa1..f1a34deb3a 100644 --- a/tasks/task_screenshot.c +++ b/tasks/task_screenshot.c @@ -68,6 +68,7 @@ struct screenshot_task_state bool history_list_enable; bool pl_fuzzy_archive_match; bool pl_use_old_format; + bool pl_compression; bool widgets_ready; int pitch; @@ -185,7 +186,8 @@ static void task_screenshot_handler(retro_task_t *task) command_playlist_push_write(g_defaults.image_history, &entry, state->pl_fuzzy_archive_match, - state->pl_use_old_format); + state->pl_use_old_format, + state->pl_compression); } #endif @@ -250,6 +252,7 @@ static bool screenshot_dump( state->pl_fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; state->pl_use_old_format = settings->bools.playlist_use_old_format; + state->pl_compression = settings->bools.playlist_compression; state->is_idle = is_idle; state->is_paused = is_paused; state->bgr24 = bgr24; diff --git a/ui/drivers/qt/options/playlists.cpp b/ui/drivers/qt/options/playlists.cpp index 785fa4095e..bbcec36e81 100644 --- a/ui/drivers/qt/options/playlists.cpp +++ b/ui/drivers/qt/options/playlists.cpp @@ -35,6 +35,7 @@ QWidget *PlaylistsPage::widget() /*layout->add(MENU_ENUM_LABEL_PLAYLIST_ENTRY_REMOVE); TOFIX */ layout->add(MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL); layout->add(MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT); + layout->add(MENU_ENUM_LABEL_PLAYLIST_COMPRESSION); layout->add(MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS); layout->add(MENU_ENUM_LABEL_PLAYLIST_FUZZY_ARCHIVE_MATCH); layout->add(MENU_ENUM_LABEL_SCAN_WITHOUT_CORE_MATCH); diff --git a/ui/drivers/qt/qt_playlist.cpp b/ui/drivers/qt/qt_playlist.cpp index 8ee7ab7d76..5e7cf62906 100644 --- a/ui/drivers/qt/qt_playlist.cpp +++ b/ui/drivers/qt/qt_playlist.cpp @@ -386,6 +386,7 @@ void MainWindow::addFilesToPlaylist(QStringList files) playlist_t *playlist = NULL; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; /* Assume a blank list means we will manually enter in all fields. */ if (files.isEmpty()) @@ -652,7 +653,8 @@ void MainWindow::addFilesToPlaylist(QStringList files) } } - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); playlist_free(playlist); reloadPlaylists(); @@ -687,6 +689,7 @@ bool MainWindow::updateCurrentPlaylistEntry( bool ok = false; settings_t *settings = config_get_ptr(); bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if ( playlistPath.isEmpty() || contentHash.isEmpty() || @@ -769,7 +772,8 @@ bool MainWindow::updateCurrentPlaylistEntry( playlist_update(playlist, index, &entry); } - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); playlist_free(playlist); reloadPlaylists(); @@ -800,6 +804,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) settings_t *settings = config_get_ptr(); const char *path_dir_playlist = settings->paths.directory_playlist; bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; QDir playlistDir(path_dir_playlist); QListWidgetItem *selectedItem = m_listWidget->itemAt( m_listWidget->viewport()->mapFromGlobal(cursorPos)); @@ -996,7 +1001,8 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) } /* Write changes to disk */ - playlist_write_file(playlist, playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); /* Free playlist, if required */ if (loadPlaylist) @@ -1342,6 +1348,8 @@ void MainWindow::deleteCurrentPlaylistItem() bool ok = false; bool isAllPlaylist = currentPlaylistIsAll(); settings_t *settings = config_get_ptr(); + bool playlist_use_old_format = settings->bools.playlist_use_old_format; + bool playlist_compression = settings->bools.playlist_compression; if (isAllPlaylist) return; @@ -1366,7 +1374,8 @@ void MainWindow::deleteCurrentPlaylistItem() playlist = playlist_init(playlistData, COLLECTION_SIZE); playlist_delete_index(playlist, index); - playlist_write_file(playlist, settings->bools.playlist_use_old_format); + playlist_write_file( + playlist, playlist_use_old_format, playlist_compression); playlist_free(playlist); reloadPlaylists(); From 25c6499c5d16f9c344d14b7c85fb4a274d6ba53d Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Thu, 23 Apr 2020 10:49:16 +0100 Subject: [PATCH 2/4] (playlist.c) Omit whitespace when writing compressed JSON format playlists --- playlist.c | 160 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 65 deletions(-) diff --git a/playlist.c b/playlist.c index 26e7e7b223..5699c0c784 100644 --- a/playlist.c +++ b/playlist.c @@ -1274,12 +1274,28 @@ end: free(file); } +/* No-op versions of JSON whitespace writers, + * used when generating compressed output */ +static JSON_Status JSON_CALL JSON_Writer_WriteNewLine_NULL(JSON_Writer writer) +{ + return JSON_Success; +} + +static JSON_Status JSON_CALL JSON_Writer_WriteSpace_NULL(JSON_Writer writer, size_t numberOfSpaces) +{ + return JSON_Success; +} + +static JSON_Status JSON_CALL (*json_write_new_line)(JSON_Writer writer) = JSON_Writer_WriteNewLine; +static JSON_Status JSON_CALL (*json_write_space)(JSON_Writer writer, size_t numberOfSpaces) = JSON_Writer_WriteSpace; + void playlist_write_file( playlist_t *playlist, bool use_old_format, bool compress) { size_t i; intfstream_t *file = NULL; + bool compressed = false; /* Playlist will be written if any of the * following are true: @@ -1312,6 +1328,9 @@ void playlist_write_file( return; } + /* Get current file compression state */ + compressed = intfstream_is_compressed(file); + #ifdef RARCH_INTERNAL if (use_old_format) { @@ -1358,28 +1377,39 @@ void playlist_write_file( goto end; } + /* Assign JSON whitespace functions + * > When compressing playlists, human readability + * is not a factor - can skip all indentation + * and new line characters */ + json_write_new_line = compressed ? + JSON_Writer_WriteNewLine_NULL : + JSON_Writer_WriteNewLine; + json_write_space = compressed ? + JSON_Writer_WriteSpace_NULL : + JSON_Writer_WriteSpace; + JSON_Writer_SetOutputEncoding(context.writer, JSON_UTF8); JSON_Writer_SetOutputHandler(context.writer, &JSONOutputHandler); JSON_Writer_SetUserData(context.writer, &context); JSON_Writer_WriteStartObject(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "version", STRLEN_CONST("version"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, "1.4", STRLEN_CONST("1.4"), JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "default_core_path", STRLEN_CONST("default_core_path"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->default_core_path ? playlist->default_core_path @@ -1389,13 +1419,13 @@ void playlist_write_file( : 0, JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "default_core_name", STRLEN_CONST("default_core_name"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->default_core_name ? playlist->default_core_name @@ -1405,79 +1435,79 @@ void playlist_write_file( : 0, JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); uint_str[0] = '\0'; snprintf(uint_str, sizeof(uint_str), "%u", playlist->label_display_mode); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "label_display_mode", STRLEN_CONST("label_display_mode"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteNumber(context.writer, uint_str, strlen(uint_str), JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); uint_str[0] = '\0'; snprintf(uint_str, sizeof(uint_str), "%u", playlist->right_thumbnail_mode); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "right_thumbnail_mode", STRLEN_CONST("right_thumbnail_mode"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteNumber(context.writer, uint_str, strlen(uint_str), JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); uint_str[0] = '\0'; snprintf(uint_str, sizeof(uint_str), "%u", playlist->left_thumbnail_mode); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "left_thumbnail_mode", STRLEN_CONST("left_thumbnail_mode"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteNumber(context.writer, uint_str, strlen(uint_str), JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); uint_str[0] = '\0'; snprintf(uint_str, sizeof(uint_str), "%u", playlist->sort_mode); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "sort_mode", STRLEN_CONST("sort_mode"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteNumber(context.writer, uint_str, strlen(uint_str), JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteString(context.writer, "items", STRLEN_CONST("items"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteStartArray(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); for (i = 0; i < playlist->size; i++) { - JSON_Writer_WriteSpace(context.writer, 4); + json_write_space(context.writer, 4); JSON_Writer_WriteStartObject(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "path", STRLEN_CONST("path"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].path ? playlist->entries[i].path @@ -1488,12 +1518,12 @@ void playlist_write_file( JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "label", STRLEN_CONST("label"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].label ? playlist->entries[i].label @@ -1504,12 +1534,12 @@ void playlist_write_file( JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "core_path", STRLEN_CONST("core_path"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].core_path ? playlist->entries[i].core_path @@ -1520,12 +1550,12 @@ void playlist_write_file( JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "core_name", STRLEN_CONST("core_name"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].core_name ? playlist->entries[i].core_name @@ -1536,12 +1566,12 @@ void playlist_write_file( JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "crc32", STRLEN_CONST("crc32"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].crc32 ? playlist->entries[i].crc32 : "", playlist->entries[i].crc32 ? strlen(playlist->entries[i].crc32) @@ -1549,12 +1579,12 @@ void playlist_write_file( JSON_UTF8); JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "db_name", STRLEN_CONST("db_name"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].db_name ? playlist->entries[i].db_name : "", playlist->entries[i].db_name ? strlen(playlist->entries[i].db_name) @@ -1564,12 +1594,12 @@ void playlist_write_file( if (!string_is_empty(playlist->entries[i].subsystem_ident)) { JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "subsystem_ident", STRLEN_CONST("subsystem_ident"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].subsystem_ident ? playlist->entries[i].subsystem_ident : "", playlist->entries[i].subsystem_ident ? strlen(playlist->entries[i].subsystem_ident) @@ -1580,12 +1610,12 @@ void playlist_write_file( if (!string_is_empty(playlist->entries[i].subsystem_name)) { JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "subsystem_name", STRLEN_CONST("subsystem_name"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteString(context.writer, playlist->entries[i].subsystem_name ? playlist->entries[i].subsystem_name @@ -1601,19 +1631,19 @@ void playlist_write_file( unsigned j; JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteString(context.writer, "subsystem_roms", STRLEN_CONST("subsystem_roms"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); - JSON_Writer_WriteSpace(context.writer, 1); + json_write_space(context.writer, 1); JSON_Writer_WriteStartArray(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); for (j = 0; j < playlist->entries[i].subsystem_roms->size; j++) { const struct string_list *roms = playlist->entries[i].subsystem_roms; - JSON_Writer_WriteSpace(context.writer, 8); + json_write_space(context.writer, 8); JSON_Writer_WriteString(context.writer, !string_is_empty(roms->elems[j].data) ? roms->elems[j].data @@ -1626,38 +1656,38 @@ void playlist_write_file( if (j < playlist->entries[i].subsystem_roms->size - 1) { JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); } } - JSON_Writer_WriteNewLine(context.writer); - JSON_Writer_WriteSpace(context.writer, 6); + json_write_new_line(context.writer); + json_write_space(context.writer, 6); JSON_Writer_WriteEndArray(context.writer); } - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); - JSON_Writer_WriteSpace(context.writer, 4); + json_write_space(context.writer, 4); JSON_Writer_WriteEndObject(context.writer); if (i < playlist->size - 1) JSON_Writer_WriteComma(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); } - JSON_Writer_WriteSpace(context.writer, 2); + json_write_space(context.writer, 2); JSON_Writer_WriteEndArray(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); JSON_Writer_WriteEndObject(context.writer); - JSON_Writer_WriteNewLine(context.writer); + json_write_new_line(context.writer); JSON_Writer_Free(context.writer); playlist->old_format = false; } playlist->modified = false; - playlist->compressed = intfstream_is_compressed(file); + playlist->compressed = compressed; RARCH_LOG("Written to playlist file: %s\n", playlist->conf_path); end: From 8cf629b3c26aaf34d939e0eae60729d62bf9525b Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Thu, 23 Apr 2020 11:55:17 +0100 Subject: [PATCH 3/4] (playlist.c) Minor clean-ups --- playlist.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/playlist.c b/playlist.c index 5699c0c784..4ba16390a3 100644 --- a/playlist.c +++ b/playlist.c @@ -2277,7 +2277,7 @@ json_cleanup: } else { - char line_buf[PLAYLIST_ENTRIES][1024] = {{0}}; + char line_buf[PLAYLIST_ENTRIES][PATH_MAX_LENGTH] = {{0}}; /* Unnecessary, but harmless */ for (i = 0; i < PLAYLIST_ENTRIES; i++) @@ -2302,10 +2302,8 @@ json_cleanup: /* Ensure line is NUL terminated, regardless of * Windows or Unix line endings */ - if ((last_char = strrchr(line_buf[i], '\r'))) - *last_char = '\0'; - else if ((last_char = strrchr(line_buf[i], '\n'))) - *last_char = '\0'; + string_replace_all_chars(line_buf[i], '\r', '\0'); + string_replace_all_chars(line_buf[i], '\n', '\0'); lines_read++; } @@ -2353,8 +2351,8 @@ json_cleanup: * read, then this is metadata */ else { - char default_core_path[1024]; - char default_core_name[1024]; + char default_core_path[PATH_MAX_LENGTH]; + char default_core_name[PATH_MAX_LENGTH]; default_core_path[0] = '\0'; default_core_name[0] = '\0'; From 69305fda9607760da0c9ce6a6912ccbff99a25d9 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Thu, 23 Apr 2020 12:04:08 +0100 Subject: [PATCH 4/4] (playlist.c) Remove unused variable --- playlist.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/playlist.c b/playlist.c index 4ba16390a3..30a6d97105 100644 --- a/playlist.c +++ b/playlist.c @@ -2298,8 +2298,6 @@ json_cleanup: if (intfstream_gets(file, line_buf[i], sizeof(line_buf[i]))) { - char *last_char = NULL; - /* Ensure line is NUL terminated, regardless of * Windows or Unix line endings */ string_replace_all_chars(line_buf[i], '\r', '\0');