From 4f83e66cd4e00bfa225f54b2c314a3d42d09ca7a Mon Sep 17 00:00:00 2001 From: Dana Conrad Date: Sun, 18 Apr 2021 13:00:41 -0500 Subject: FS#13287 - Load a newly saved playlist and resume where it was Works from any playlist saving operation accessed from the While Playing Screen, all other playlist saving operations are unchanged. Now a user-selectable setting! Located in General Settings -> Playlists -> Current Playlist -> Reload After Saving (Yes/No) Change-Id: I5085c3f4c56c518a812d5ee015d15cc4dca19a28 --- apps/filetree.c | 22 ++++++---- apps/filetree.h | 2 +- apps/iap/iap-lingo4.c | 3 +- apps/lang/english.lang | 14 ++++++ apps/menus/playlist_menu.c | 62 ++++++++++++++++++++++++++- apps/onplay.c | 1 + apps/settings.h | 1 + apps/settings_list.c | 2 + manual/configure_rockbox/playlist_options.tex | 7 +++ 9 files changed, 102 insertions(+), 12 deletions(-) diff --git a/apps/filetree.c b/apps/filetree.c index f8a1263e7f..5c6443cc34 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -86,12 +86,12 @@ int ft_build_playlist(struct tree_context* c, int start_index) * or started via bookmark autoload, true otherwise. * * Pointers to both the full pathname and the separated parts needed to - * avoid allocating yet another path buffer on the stack (and save some + * avoid allocating yet another path buffer on the stack (and save some * code; the caller typically needs to create the full pathname anyway)... */ -bool ft_play_playlist(char* pathname, char* dirname, char* filename) +bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning) { - if (global_settings.party_mode && audio_status()) + if (global_settings.party_mode && audio_status()) { splash(HZ, ID2P(LANG_PARTY_MODE)); return false; @@ -105,9 +105,13 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) splash(0, ID2P(LANG_WAIT)); /* about to create a new current playlist... - allow user to cancel the operation */ - if (!warn_on_pl_erase()) - return false; + * allow user to cancel the operation. + * Do not show if skip_dyn_warning is true */ + if (!skip_dyn_warning) + { + if (!warn_on_pl_erase()) + return false; + } if (playlist_create(dirname, filename) != -1) { @@ -115,11 +119,11 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) { playlist_shuffle(current_tick, -1); } - + playlist_start(0, 0, 0); return true; } - + return false; } @@ -465,7 +469,7 @@ int ft_enter(struct tree_context* c) switch ( file_attr & FILE_ATTR_MASK ) { case FILE_ATTR_M3U: - play = ft_play_playlist(buf, c->currdir, file->name); + play = ft_play_playlist(buf, c->currdir, file->name, false); if (play) { diff --git a/apps/filetree.h b/apps/filetree.h index fb329813c1..178ba0e973 100644 --- a/apps/filetree.h +++ b/apps/filetree.h @@ -26,6 +26,6 @@ int ft_load(struct tree_context* c, const char* tempdir); int ft_enter(struct tree_context* c); int ft_exit(struct tree_context* c); int ft_build_playlist(struct tree_context* c, int start_index); -bool ft_play_playlist(char* pathname, char* dirname, char* filename); +bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning); #endif diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c index b601501b3d..4ec5c462a1 100644 --- a/apps/iap/iap-lingo4.c +++ b/apps/iap/iap-lingo4.c @@ -108,7 +108,8 @@ static void seek_to_playlist(unsigned long index) MAX_PATH); ft_play_playlist(selected_playlist, global_settings.playlist_catalog_dir, - strrchr(selected_playlist, '/') + 1); + strrchr(selected_playlist, '/') + 1, + false); } static unsigned long nbr_total_playlists(void) diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 9cd31363c9..4cbc6f30f6 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -15778,3 +15778,17 @@ *: "Always Autolock" + + id: LANG_PLAYLIST_RELOAD_AFTER_SAVE + desc: reload playlist after saving + user: core + + *: "Reload After Saving" + + + *: "Reload After Saving" + + + *: "Reload After Saving" + + diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c index 3122a4090f..b84abe0b37 100644 --- a/apps/menus/playlist_menu.c +++ b/apps/menus/playlist_menu.c @@ -38,9 +38,19 @@ #include "talk.h" #include "playlist_catalog.h" #include "splash.h" +#include "filetree.h" +/* load a screen to save the playlist passed in (or current playlist if NULL is passed) */ int save_playlist_screen(struct playlist_info* playlist) { + + char directoryonly[MAX_PATH+3]; + char *filename; + + int resume_index; + uint32_t resume_elapsed; + uint32_t resume_offset; + char temp[MAX_PATH+1], *dot; int len; @@ -71,6 +81,55 @@ int save_playlist_screen(struct playlist_info* playlist) /* reload in case playlist was saved to cwd */ reload_directory(); + + /* only reload newly saved playlist if: + * playlist is null AND setting is turned on + * + * if playlist is null, we should be dealing with the current playlist, + * and thus we got here from the wps screen. That means we want to reload + * the current playlist so the user can make bookmarks. */ + if ((global_settings.playlist_reload_after_save == true) && + (playlist == NULL)) + { + + /* at least one slash exists in temp */ + if (strrchr(temp, '/') != NULL) + { + filename = strrchr(temp, '/') + 1; + + if (temp[0] == '/') /* most common situation - first char is a slash */ + { + strcpy(directoryonly, temp); + directoryonly[filename - temp] = '\0'; + } else /* there is a slash, but not at the beginning of temp - prepend one */ + { + directoryonly[0] = '/'; + + strcpy(directoryonly+1, temp); + directoryonly[filename - temp + 1] = '\0'; + } + } else /* temp doesn't contain any slashes, uncommon? */ + { + directoryonly[0] = '/'; + directoryonly[1] = '\0'; + filename = temp; + } + + /* can't trust index from id3 (don't know why), get it from playlist */ + resume_index = playlist_get_current()->index; + + struct mp3entry* id3 = audio_current_track(); + + /* record elapsed and offset so they don't change when we load new playlist */ + resume_elapsed = id3->elapsed; + resume_offset = id3->offset; + + ft_play_playlist(temp, directoryonly, filename, true); + playlist_start(resume_index, resume_elapsed, resume_offset); + } + /* cancelled out of name selection */ + } else { + return 1; } return 0; @@ -112,9 +171,10 @@ MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS), MENUITEM_SETTING(warn_on_erase, &global_settings.warnon_erase_dynplaylist, NULL); MENUITEM_SETTING(show_shuffled_adding_options, &global_settings.show_shuffled_adding_options, NULL); MENUITEM_SETTING(show_queue_options, &global_settings.show_queue_options, NULL); +MENUITEM_SETTING(playlist_reload_after_save, &global_settings.playlist_reload_after_save, NULL); MAKE_MENU(currentplaylist_settings_menu, ID2P(LANG_CURRENT_PLAYLIST), NULL, Icon_Playlist, - &warn_on_erase, &show_shuffled_adding_options, &show_queue_options); + &warn_on_erase, &show_shuffled_adding_options, &show_queue_options, &playlist_reload_after_save); MAKE_MENU(playlist_settings, ID2P(LANG_PLAYLISTS), NULL, Icon_Playlist, diff --git a/apps/onplay.c b/apps/onplay.c index d72f592f2e..0942d69d3f 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -456,6 +456,7 @@ static bool shuffle_playlist(void) } static bool save_playlist(void) { + /* save_playlist_screen should load the newly saved playlist and resume */ save_playlist_screen(NULL); return false; } diff --git a/apps/settings.h b/apps/settings.h index 5d6d4cb717..fedec8e025 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -576,6 +576,7 @@ struct user_settings bool constrain_next_folder; /* whether next_folder is constrained to directories within start_directory */ int recursive_dir_insert; /* should directories be inserted recursively */ + bool playlist_reload_after_save; /* reload and resume playlist after saving */ bool fade_on_stop; /* fade on pause/unpause/stop */ bool playlist_shuffle; bool warnon_erase_dynplaylist; /* warn when erasing dynamic playlist */ diff --git a/apps/settings_list.c b/apps/settings_list.c index 4a0bf96864..c13df734e6 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1277,6 +1277,8 @@ const struct settings_list settings[] = { CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON, "recursive directory insert", off_on_ask, NULL , 3 , ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)), + OFFON_SETTING(0, playlist_reload_after_save, LANG_PLAYLIST_RELOAD_AFTER_SAVE, + false, "reload after saving playlist", NULL), /* bookmarks */ CHOICE_SETTING(0, autocreatebookmark, LANG_BOOKMARK_SETTINGS_AUTOCREATE, BOOKMARK_NO, "autocreate bookmarks", diff --git a/manual/configure_rockbox/playlist_options.tex b/manual/configure_rockbox/playlist_options.tex index bd493d6e4b..4f6024127e 100644 --- a/manual/configure_rockbox/playlist_options.tex +++ b/manual/configure_rockbox/playlist_options.tex @@ -41,6 +41,13 @@ related to playlists. If set to \setting{In Submenu}, Rockbox will move the options into a separate submenu. + \item[Reload After Saving.] + If set to \setting{Yes}, saving the current playlist from the While Playing Screen's + Context Menu will cause Rockbox to load the newly saved playlist and resume it to the + current position. This is useful for creating bookmarks after modifying or customizing + a playlist. Saving playlists outside of the While Playing Screen's Context Menu will + not be affected by this setting. + \end{description} \end{description} -- cgit