diff options
author | Dana Conrad <dconrad@fastmail.com> | 2021-04-18 13:00:41 -0500 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2021-05-03 20:10:27 +0000 |
commit | 4f83e66cd4e00bfa225f54b2c314a3d42d09ca7a (patch) | |
tree | 186717c39b55272249efc681091912a49e4872f2 | |
parent | 49edfc237ba9ae27eee5e915e86989d9ee01b1da (diff) | |
download | rockbox-4f83e66cd4e00bfa225f54b2c314a3d42d09ca7a.tar.gz rockbox-4f83e66cd4e00bfa225f54b2c314a3d42d09ca7a.zip |
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
-rw-r--r-- | apps/filetree.c | 22 | ||||
-rw-r--r-- | apps/filetree.h | 2 | ||||
-rw-r--r-- | apps/iap/iap-lingo4.c | 3 | ||||
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/menus/playlist_menu.c | 62 | ||||
-rw-r--r-- | apps/onplay.c | 1 | ||||
-rw-r--r-- | apps/settings.h | 1 | ||||
-rw-r--r-- | apps/settings_list.c | 2 | ||||
-rw-r--r-- | 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) | |||
86 | * or started via bookmark autoload, true otherwise. | 86 | * or started via bookmark autoload, true otherwise. |
87 | * | 87 | * |
88 | * Pointers to both the full pathname and the separated parts needed to | 88 | * Pointers to both the full pathname and the separated parts needed to |
89 | * avoid allocating yet another path buffer on the stack (and save some | 89 | * avoid allocating yet another path buffer on the stack (and save some |
90 | * code; the caller typically needs to create the full pathname anyway)... | 90 | * code; the caller typically needs to create the full pathname anyway)... |
91 | */ | 91 | */ |
92 | bool ft_play_playlist(char* pathname, char* dirname, char* filename) | 92 | bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning) |
93 | { | 93 | { |
94 | if (global_settings.party_mode && audio_status()) | 94 | if (global_settings.party_mode && audio_status()) |
95 | { | 95 | { |
96 | splash(HZ, ID2P(LANG_PARTY_MODE)); | 96 | splash(HZ, ID2P(LANG_PARTY_MODE)); |
97 | return false; | 97 | return false; |
@@ -105,9 +105,13 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) | |||
105 | splash(0, ID2P(LANG_WAIT)); | 105 | splash(0, ID2P(LANG_WAIT)); |
106 | 106 | ||
107 | /* about to create a new current playlist... | 107 | /* about to create a new current playlist... |
108 | allow user to cancel the operation */ | 108 | * allow user to cancel the operation. |
109 | if (!warn_on_pl_erase()) | 109 | * Do not show if skip_dyn_warning is true */ |
110 | return false; | 110 | if (!skip_dyn_warning) |
111 | { | ||
112 | if (!warn_on_pl_erase()) | ||
113 | return false; | ||
114 | } | ||
111 | 115 | ||
112 | if (playlist_create(dirname, filename) != -1) | 116 | if (playlist_create(dirname, filename) != -1) |
113 | { | 117 | { |
@@ -115,11 +119,11 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) | |||
115 | { | 119 | { |
116 | playlist_shuffle(current_tick, -1); | 120 | playlist_shuffle(current_tick, -1); |
117 | } | 121 | } |
118 | 122 | ||
119 | playlist_start(0, 0, 0); | 123 | playlist_start(0, 0, 0); |
120 | return true; | 124 | return true; |
121 | } | 125 | } |
122 | 126 | ||
123 | return false; | 127 | return false; |
124 | } | 128 | } |
125 | 129 | ||
@@ -465,7 +469,7 @@ int ft_enter(struct tree_context* c) | |||
465 | 469 | ||
466 | switch ( file_attr & FILE_ATTR_MASK ) { | 470 | switch ( file_attr & FILE_ATTR_MASK ) { |
467 | case FILE_ATTR_M3U: | 471 | case FILE_ATTR_M3U: |
468 | play = ft_play_playlist(buf, c->currdir, file->name); | 472 | play = ft_play_playlist(buf, c->currdir, file->name, false); |
469 | 473 | ||
470 | if (play) | 474 | if (play) |
471 | { | 475 | { |
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); | |||
26 | int ft_enter(struct tree_context* c); | 26 | int ft_enter(struct tree_context* c); |
27 | int ft_exit(struct tree_context* c); | 27 | int ft_exit(struct tree_context* c); |
28 | int ft_build_playlist(struct tree_context* c, int start_index); | 28 | int ft_build_playlist(struct tree_context* c, int start_index); |
29 | bool ft_play_playlist(char* pathname, char* dirname, char* filename); | 29 | bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning); |
30 | 30 | ||
31 | #endif | 31 | #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) | |||
108 | MAX_PATH); | 108 | MAX_PATH); |
109 | ft_play_playlist(selected_playlist, | 109 | ft_play_playlist(selected_playlist, |
110 | global_settings.playlist_catalog_dir, | 110 | global_settings.playlist_catalog_dir, |
111 | strrchr(selected_playlist, '/') + 1); | 111 | strrchr(selected_playlist, '/') + 1, |
112 | false); | ||
112 | } | 113 | } |
113 | 114 | ||
114 | static unsigned long nbr_total_playlists(void) | 115 | 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 @@ | |||
15778 | *: "Always Autolock" | 15778 | *: "Always Autolock" |
15779 | </voice> | 15779 | </voice> |
15780 | </phrase> | 15780 | </phrase> |
15781 | <phrase> | ||
15782 | id: LANG_PLAYLIST_RELOAD_AFTER_SAVE | ||
15783 | desc: reload playlist after saving | ||
15784 | user: core | ||
15785 | <source> | ||
15786 | *: "Reload After Saving" | ||
15787 | </source> | ||
15788 | <dest> | ||
15789 | *: "Reload After Saving" | ||
15790 | </dest> | ||
15791 | <voice> | ||
15792 | *: "Reload After Saving" | ||
15793 | </voice> | ||
15794 | </phrase> | ||
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 @@ | |||
38 | #include "talk.h" | 38 | #include "talk.h" |
39 | #include "playlist_catalog.h" | 39 | #include "playlist_catalog.h" |
40 | #include "splash.h" | 40 | #include "splash.h" |
41 | #include "filetree.h" | ||
41 | 42 | ||
43 | /* load a screen to save the playlist passed in (or current playlist if NULL is passed) */ | ||
42 | int save_playlist_screen(struct playlist_info* playlist) | 44 | int save_playlist_screen(struct playlist_info* playlist) |
43 | { | 45 | { |
46 | |||
47 | char directoryonly[MAX_PATH+3]; | ||
48 | char *filename; | ||
49 | |||
50 | int resume_index; | ||
51 | uint32_t resume_elapsed; | ||
52 | uint32_t resume_offset; | ||
53 | |||
44 | char temp[MAX_PATH+1], *dot; | 54 | char temp[MAX_PATH+1], *dot; |
45 | int len; | 55 | int len; |
46 | 56 | ||
@@ -71,6 +81,55 @@ int save_playlist_screen(struct playlist_info* playlist) | |||
71 | 81 | ||
72 | /* reload in case playlist was saved to cwd */ | 82 | /* reload in case playlist was saved to cwd */ |
73 | reload_directory(); | 83 | reload_directory(); |
84 | |||
85 | /* only reload newly saved playlist if: | ||
86 | * playlist is null AND setting is turned on | ||
87 | * | ||
88 | * if playlist is null, we should be dealing with the current playlist, | ||
89 | * and thus we got here from the wps screen. That means we want to reload | ||
90 | * the current playlist so the user can make bookmarks. */ | ||
91 | if ((global_settings.playlist_reload_after_save == true) && | ||
92 | (playlist == NULL)) | ||
93 | { | ||
94 | |||
95 | /* at least one slash exists in temp */ | ||
96 | if (strrchr(temp, '/') != NULL) | ||
97 | { | ||
98 | filename = strrchr(temp, '/') + 1; | ||
99 | |||
100 | if (temp[0] == '/') /* most common situation - first char is a slash */ | ||
101 | { | ||
102 | strcpy(directoryonly, temp); | ||
103 | directoryonly[filename - temp] = '\0'; | ||
104 | } else /* there is a slash, but not at the beginning of temp - prepend one */ | ||
105 | { | ||
106 | directoryonly[0] = '/'; | ||
107 | |||
108 | strcpy(directoryonly+1, temp); | ||
109 | directoryonly[filename - temp + 1] = '\0'; | ||
110 | } | ||
111 | } else /* temp doesn't contain any slashes, uncommon? */ | ||
112 | { | ||
113 | directoryonly[0] = '/'; | ||
114 | directoryonly[1] = '\0'; | ||
115 | filename = temp; | ||
116 | } | ||
117 | |||
118 | /* can't trust index from id3 (don't know why), get it from playlist */ | ||
119 | resume_index = playlist_get_current()->index; | ||
120 | |||
121 | struct mp3entry* id3 = audio_current_track(); | ||
122 | |||
123 | /* record elapsed and offset so they don't change when we load new playlist */ | ||
124 | resume_elapsed = id3->elapsed; | ||
125 | resume_offset = id3->offset; | ||
126 | |||
127 | ft_play_playlist(temp, directoryonly, filename, true); | ||
128 | playlist_start(resume_index, resume_elapsed, resume_offset); | ||
129 | } | ||
130 | /* cancelled out of name selection */ | ||
131 | } else { | ||
132 | return 1; | ||
74 | } | 133 | } |
75 | 134 | ||
76 | return 0; | 135 | return 0; |
@@ -112,9 +171,10 @@ MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS), | |||
112 | MENUITEM_SETTING(warn_on_erase, &global_settings.warnon_erase_dynplaylist, NULL); | 171 | MENUITEM_SETTING(warn_on_erase, &global_settings.warnon_erase_dynplaylist, NULL); |
113 | MENUITEM_SETTING(show_shuffled_adding_options, &global_settings.show_shuffled_adding_options, NULL); | 172 | MENUITEM_SETTING(show_shuffled_adding_options, &global_settings.show_shuffled_adding_options, NULL); |
114 | MENUITEM_SETTING(show_queue_options, &global_settings.show_queue_options, NULL); | 173 | MENUITEM_SETTING(show_queue_options, &global_settings.show_queue_options, NULL); |
174 | MENUITEM_SETTING(playlist_reload_after_save, &global_settings.playlist_reload_after_save, NULL); | ||
115 | MAKE_MENU(currentplaylist_settings_menu, ID2P(LANG_CURRENT_PLAYLIST), | 175 | MAKE_MENU(currentplaylist_settings_menu, ID2P(LANG_CURRENT_PLAYLIST), |
116 | NULL, Icon_Playlist, | 176 | NULL, Icon_Playlist, |
117 | &warn_on_erase, &show_shuffled_adding_options, &show_queue_options); | 177 | &warn_on_erase, &show_shuffled_adding_options, &show_queue_options, &playlist_reload_after_save); |
118 | 178 | ||
119 | MAKE_MENU(playlist_settings, ID2P(LANG_PLAYLISTS), NULL, | 179 | MAKE_MENU(playlist_settings, ID2P(LANG_PLAYLISTS), NULL, |
120 | Icon_Playlist, | 180 | 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) | |||
456 | } | 456 | } |
457 | static bool save_playlist(void) | 457 | static bool save_playlist(void) |
458 | { | 458 | { |
459 | /* save_playlist_screen should load the newly saved playlist and resume */ | ||
459 | save_playlist_screen(NULL); | 460 | save_playlist_screen(NULL); |
460 | return false; | 461 | return false; |
461 | } | 462 | } |
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 | |||
576 | bool constrain_next_folder; /* whether next_folder is constrained to | 576 | bool constrain_next_folder; /* whether next_folder is constrained to |
577 | directories within start_directory */ | 577 | directories within start_directory */ |
578 | int recursive_dir_insert; /* should directories be inserted recursively */ | 578 | int recursive_dir_insert; /* should directories be inserted recursively */ |
579 | bool playlist_reload_after_save; /* reload and resume playlist after saving */ | ||
579 | bool fade_on_stop; /* fade on pause/unpause/stop */ | 580 | bool fade_on_stop; /* fade on pause/unpause/stop */ |
580 | bool playlist_shuffle; | 581 | bool playlist_shuffle; |
581 | bool warnon_erase_dynplaylist; /* warn when erasing dynamic playlist */ | 582 | 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[] = { | |||
1277 | CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON, | 1277 | CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON, |
1278 | "recursive directory insert", off_on_ask, NULL , 3 , | 1278 | "recursive directory insert", off_on_ask, NULL , 3 , |
1279 | ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)), | 1279 | ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)), |
1280 | OFFON_SETTING(0, playlist_reload_after_save, LANG_PLAYLIST_RELOAD_AFTER_SAVE, | ||
1281 | false, "reload after saving playlist", NULL), | ||
1280 | /* bookmarks */ | 1282 | /* bookmarks */ |
1281 | CHOICE_SETTING(0, autocreatebookmark, LANG_BOOKMARK_SETTINGS_AUTOCREATE, | 1283 | CHOICE_SETTING(0, autocreatebookmark, LANG_BOOKMARK_SETTINGS_AUTOCREATE, |
1282 | BOOKMARK_NO, "autocreate bookmarks", | 1284 | 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. | |||
41 | If set to \setting{In Submenu}, Rockbox will move the options into a | 41 | If set to \setting{In Submenu}, Rockbox will move the options into a |
42 | separate submenu. | 42 | separate submenu. |
43 | 43 | ||
44 | \item[Reload After Saving.] | ||
45 | If set to \setting{Yes}, saving the current playlist from the While Playing Screen's | ||
46 | Context Menu will cause Rockbox to load the newly saved playlist and resume it to the | ||
47 | current position. This is useful for creating bookmarks after modifying or customizing | ||
48 | a playlist. Saving playlists outside of the While Playing Screen's Context Menu will | ||
49 | not be affected by this setting. | ||
50 | |||
44 | \end{description} | 51 | \end{description} |
45 | 52 | ||
46 | \end{description} | 53 | \end{description} |