diff --git a/apps/lang/english.lang b/apps/lang/english.lang index c843471831..4689660176 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -15807,16 +15807,16 @@ id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core - *: "Clear List & Play Next" + *: "" - *: "Clear List & Play Next" + *: "" - *: "Clear List & Play Next" + *: "" @@ -15877,16 +15877,16 @@ id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core - *: "Clear List & Play Shuffled" + *: "" - *: "Clear List & Play Shuffled" + *: "" - *: "Clear List & Play Shuffled" + *: "" @@ -16326,3 +16326,31 @@ *: "Track Info" + + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + + *: "Play" + + + *: "Play" + + + *: "Play" + + + + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + + *: "Play Shuffled" + + + *: "Play Shuffled" + + + *: "Play Shuffled" + + diff --git a/apps/onplay.c b/apps/onplay.c index a78cf7ceac..729fe40f0a 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -476,16 +476,40 @@ MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_PLAYLIST), &playlist_save_item, &reshuffle_item, &playing_time_item ); -/* CONTEXT_[TREE|ID3DB|STD] playlist options */ -static bool add_to_playlist(int position, bool queue) +/* argument for add_to_playlist (for use by menu callbacks) */ +struct add_to_pl_param { - bool new_playlist = false; - if (!(audio_status() & AUDIO_STATUS_PLAY)) - { - new_playlist = true; - if (position == PLAYLIST_REPLACE) - position = PLAYLIST_INSERT; - } + int8_t position; + unsigned int queue: 1; + unsigned int replace: 1; +}; + +static struct add_to_pl_param addtopl_insert = {PLAYLIST_INSERT, 0, 0}; +static struct add_to_pl_param addtopl_insert_first = {PLAYLIST_INSERT_FIRST, 0, 0}; +static struct add_to_pl_param addtopl_insert_last = {PLAYLIST_INSERT_LAST, 0, 0}; +static struct add_to_pl_param addtopl_insert_shuf = {PLAYLIST_INSERT_SHUFFLED, 0, 0}; +static struct add_to_pl_param addtopl_insert_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, 0, 0}; + +static struct add_to_pl_param addtopl_queue = {PLAYLIST_INSERT, 1, 0}; +static struct add_to_pl_param addtopl_queue_first = {PLAYLIST_INSERT_FIRST, 1, 0}; +static struct add_to_pl_param addtopl_queue_last = {PLAYLIST_INSERT_LAST, 1, 0}; +static struct add_to_pl_param addtopl_queue_shuf = {PLAYLIST_INSERT_SHUFFLED, 1, 0}; +static struct add_to_pl_param addtopl_queue_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, 1, 0}; + +static struct add_to_pl_param addtopl_replace = {PLAYLIST_INSERT, 0, 1}; +static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_SHUFFLED, 0, 1}; + +/* CONTEXT_[TREE|ID3DB|STD] playlist options */ +static int add_to_playlist(void* arg) +{ + struct add_to_pl_param* param = arg; + int position = param->position; + bool new_playlist = param->replace ? true : false; + bool queue = param->queue ? true : false; + + /* warn if replacing the playlist */ + if (new_playlist && !warn_on_pl_erase()) + return 0; const char *lines[] = { ID2P(LANG_RECURSE_DIRECTORY_QUESTION), @@ -568,121 +592,59 @@ static bool view_playlist(void) return result; } -static int playlist_insert_func(void *param) -{ - if (((intptr_t)param == PLAYLIST_REPLACE || - (((intptr_t)param == PLAYLIST_INSERT_SHUFFLED || (intptr_t)param == PLAYLIST_INSERT) - && !(audio_status() & AUDIO_STATUS_PLAY))) && !warn_on_pl_erase()) - return 0; - add_to_playlist((intptr_t)param, false); - return 0; -} - -static int playlist_queue_func(void *param) -{ - add_to_playlist((intptr_t)param, true); - return 0; -} - -static int treeplaylist_wplayback_callback(int action, - const struct menu_item_ex* this_item, - struct gui_synclist *this_list); - static int treeplaylist_callback(int action, const struct menu_item_ex *this_item, struct gui_synclist *this_list); /* insert items */ MENUITEM_FUNCTION(i_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT), - playlist_insert_func, (intptr_t*)PLAYLIST_INSERT, - treeplaylist_wplayback_callback, Icon_Playlist); -MENUITEM_FUNCTION(i_first_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_FIRST), - playlist_insert_func, (intptr_t*)PLAYLIST_INSERT_FIRST, - treeplaylist_wplayback_callback, Icon_Playlist); -MENUITEM_FUNCTION(i_last_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_LAST), - playlist_insert_func, (intptr_t*)PLAYLIST_INSERT_LAST, - treeplaylist_wplayback_callback, Icon_Playlist); -MENUITEM_FUNCTION(i_shuf_pl_item, MENU_FUNC_USEPARAM, - ID2P(LANG_INSERT_SHUFFLED), playlist_insert_func, - (intptr_t*)PLAYLIST_INSERT_SHUFFLED, + add_to_playlist, &addtopl_insert, treeplaylist_callback, Icon_Playlist); -MENUITEM_FUNCTION(i_last_shuf_pl_item, MENU_FUNC_USEPARAM, - ID2P(LANG_INSERT_LAST_SHUFFLED), playlist_insert_func, - (intptr_t*)PLAYLIST_INSERT_LAST_SHUFFLED, +MENUITEM_FUNCTION(i_first_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_FIRST), + add_to_playlist, &addtopl_insert_first, + treeplaylist_callback, Icon_Playlist); +MENUITEM_FUNCTION(i_last_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_LAST), + add_to_playlist, &addtopl_insert_last, + treeplaylist_callback, Icon_Playlist); +MENUITEM_FUNCTION(i_shuf_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_SHUFFLED), + add_to_playlist, &addtopl_insert_shuf, + treeplaylist_callback, Icon_Playlist); +MENUITEM_FUNCTION(i_last_shuf_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_INSERT_LAST_SHUFFLED), + add_to_playlist, &addtopl_insert_last_shuf, treeplaylist_callback, Icon_Playlist); /* queue items */ MENUITEM_FUNCTION(q_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT, + add_to_playlist, &addtopl_queue, treeplaylist_callback, Icon_Playlist); MENUITEM_FUNCTION(q_first_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_FIRST), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT_FIRST, + add_to_playlist, &addtopl_queue_first, treeplaylist_callback, Icon_Playlist); MENUITEM_FUNCTION(q_last_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_LAST), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT_LAST, + add_to_playlist, &addtopl_queue_last, treeplaylist_callback, Icon_Playlist); -MENUITEM_FUNCTION(q_shuf_pl_item, MENU_FUNC_USEPARAM, - ID2P(LANG_QUEUE_SHUFFLED), playlist_queue_func, - (intptr_t*)PLAYLIST_INSERT_SHUFFLED, +MENUITEM_FUNCTION(q_shuf_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_SHUFFLED), + add_to_playlist, &addtopl_queue_shuf, treeplaylist_callback, Icon_Playlist); -MENUITEM_FUNCTION(q_last_shuf_pl_item, MENU_FUNC_USEPARAM, - ID2P(LANG_QUEUE_LAST_SHUFFLED), playlist_queue_func, - (intptr_t*)PLAYLIST_INSERT_LAST_SHUFFLED, - treeplaylist_callback, Icon_Playlist); - -/* queue items in submenu */ -MENUITEM_FUNCTION(q_pl_submenu_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT, - NULL, Icon_Playlist); -MENUITEM_FUNCTION(q_first_pl_submenu_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_FIRST), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT_FIRST, - NULL, Icon_Playlist); -MENUITEM_FUNCTION(q_last_pl_submenu_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_LAST), - playlist_queue_func, (intptr_t*)PLAYLIST_INSERT_LAST, - NULL, Icon_Playlist); -MENUITEM_FUNCTION(q_shuf_pl_submenu_item, MENU_FUNC_USEPARAM, - ID2P(LANG_QUEUE_SHUFFLED), playlist_queue_func, - (intptr_t*)PLAYLIST_INSERT_SHUFFLED, - treeplaylist_callback, Icon_Playlist); -MENUITEM_FUNCTION(q_last_shuf_pl_submenu_item, MENU_FUNC_USEPARAM, - ID2P(LANG_QUEUE_LAST_SHUFFLED), playlist_queue_func, - (intptr_t*)PLAYLIST_INSERT_LAST_SHUFFLED, +MENUITEM_FUNCTION(q_last_shuf_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE_LAST_SHUFFLED), + add_to_playlist, &addtopl_queue_last_shuf, treeplaylist_callback, Icon_Playlist); +/* queue submenu */ MAKE_ONPLAYMENU(queue_menu, ID2P(LANG_QUEUE_MENU), - treeplaylist_wplayback_callback, Icon_Playlist, - &q_pl_submenu_item, - &q_first_pl_submenu_item, - &q_last_pl_submenu_item, - &q_shuf_pl_submenu_item, - &q_last_shuf_pl_submenu_item); - -static int treeplaylist_wplayback_callback(int action, - const struct menu_item_ex* this_item, - struct gui_synclist *this_list) -{ - (void)this_list; - switch (action) - { - case ACTION_REQUEST_MENUITEM: - if ((audio_status() & AUDIO_STATUS_PLAY) && - (this_item != &queue_menu || - global_settings.show_queue_options == QUEUE_SHOW_IN_SUBMENU)) - return action; - else - return ACTION_EXIT_MENUITEM; - break; - } - return action; -} + treeplaylist_callback, Icon_Playlist, + &q_pl_item, + &q_first_pl_item, + &q_last_pl_item, + &q_shuf_pl_item, + &q_last_shuf_pl_item); /* replace playlist */ -MENUITEM_FUNCTION(replace_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_CLEAR_LIST_AND_PLAY_NEXT), - playlist_insert_func, (intptr_t*)PLAYLIST_REPLACE, - NULL, Icon_Playlist); +MENUITEM_FUNCTION(replace_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_PLAY), + add_to_playlist, &addtopl_replace, + treeplaylist_callback, Icon_Playlist); -MENUITEM_FUNCTION(replace_shuf_pl_item, MENU_FUNC_USEPARAM, - ID2P(LANG_CLEAR_LIST_AND_PLAY_SHUFFLED), playlist_insert_func, - (intptr_t*)PLAYLIST_INSERT_SHUFFLED, +MENUITEM_FUNCTION(replace_shuf_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_PLAY_SHUFFLED), + add_to_playlist, &addtopl_replace_shuffled, treeplaylist_callback, Icon_Playlist); MAKE_ONPLAYMENU(tree_playlist_menu, ID2P(LANG_CURRENT_PLAYLIST), @@ -713,70 +675,71 @@ static int treeplaylist_callback(int action, const struct menu_item_ex *this_item, struct gui_synclist *this_list) { + static bool in_queue_submenu = false; + (void)this_list; switch (action) { - case ACTION_REQUEST_MENUITEM: - if (this_item == &tree_playlist_menu) + case ACTION_REQUEST_MENUITEM: + if (this_item == &tree_playlist_menu) + { + if ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO && + (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U && + (selected_file_attr & ATTR_DIRECTORY) == 0) + return ACTION_EXIT_MENUITEM; + } + else if (this_item == &queue_menu) + { + if (global_settings.show_queue_options != QUEUE_SHOW_IN_SUBMENU) + return ACTION_EXIT_MENUITEM; + + /* queueing options only work during playback */ + if (!(audio_status() & AUDIO_STATUS_PLAY)) + return ACTION_EXIT_MENUITEM; + } + else if ((this_item->flags & MENU_TYPE_MASK) == MT_FUNCTION_CALL && + this_item->function->function_w_param == add_to_playlist) + { + struct add_to_pl_param *param = this_item->function->param; + + if (param->queue) { - if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO || - (selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U || - (selected_file_attr & ATTR_DIRECTORY)) - return action; + if (global_settings.show_queue_options != QUEUE_SHOW_AT_TOPLEVEL && + !in_queue_submenu) + return ACTION_EXIT_MENUITEM; } - else if ((this_item == &q_pl_item || - this_item == &q_first_pl_item || - this_item == &q_last_pl_item) && - global_settings.show_queue_options == QUEUE_SHOW_AT_TOPLEVEL && - (audio_status() & AUDIO_STATUS_PLAY)) + + if (param->position == PLAYLIST_INSERT_SHUFFLED || + param->position == PLAYLIST_INSERT_LAST_SHUFFLED) { - return action; + if (!global_settings.show_shuffled_adding_options) + return ACTION_EXIT_MENUITEM; + + if ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U && + (selected_file_attr & ATTR_DIRECTORY) == 0) + return ACTION_EXIT_MENUITEM; } - else if (this_item == &i_shuf_pl_item) + + if (!param->replace) { - if (global_settings.show_shuffled_adding_options && - (audio_status() & AUDIO_STATUS_PLAY)) - { - return action; - } + if (!(audio_status() & AUDIO_STATUS_PLAY)) + return ACTION_EXIT_MENUITEM; } - else if (this_item == &replace_shuf_pl_item) - { - if (global_settings.show_shuffled_adding_options && - !(audio_status() & AUDIO_STATUS_PLAY) && - ((selected_file_attr & ATTR_DIRECTORY) || - ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))) - { - return action; - } - } - else if (this_item == &q_shuf_pl_submenu_item || - (this_item == &q_shuf_pl_item && - global_settings.show_queue_options == QUEUE_SHOW_AT_TOPLEVEL)) - { - if (global_settings.show_shuffled_adding_options && - (audio_status() & AUDIO_STATUS_PLAY)) - { - return action; - } - } - else if (this_item == &i_last_shuf_pl_item || - this_item == &q_last_shuf_pl_submenu_item || - (this_item == &q_last_shuf_pl_item && - global_settings.show_queue_options == QUEUE_SHOW_AT_TOPLEVEL)) - { - if (global_settings.show_shuffled_adding_options && - (playlist_amount() > 0) && - (audio_status() & AUDIO_STATUS_PLAY) && - ((selected_file_attr & ATTR_DIRECTORY) || - ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))) - { - return action; - } - } - return ACTION_EXIT_MENUITEM; - break; + } + + break; + + case ACTION_ENTER_MENUITEM: + if (this_item == &queue_menu) + in_queue_submenu = true; + break; + + case ACTION_EXIT_MENUITEM: + if (this_item == &queue_menu) + in_queue_submenu = false; + break; } + return action; } @@ -1840,7 +1803,7 @@ static int playlist_insert_shuffled(void) (selected_file_attr & ATTR_DIRECTORY) || ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)) { - playlist_insert_func((intptr_t*)PLAYLIST_INSERT_SHUFFLED); + add_to_playlist(&addtopl_insert_shuf); return ONPLAY_START_PLAY; } @@ -1883,7 +1846,7 @@ static struct hotkey_assignment hotkey_items[] = { HOTKEY_FUNC(delete_item, NULL), ONPLAY_RELOAD_DIR }, { HOTKEY_INSERT, LANG_INSERT, - HOTKEY_FUNC(playlist_insert_func, (intptr_t*)PLAYLIST_INSERT), + HOTKEY_FUNC(add_to_playlist, (intptr_t*)&addtopl_insert), ONPLAY_RELOAD_DIR }, { HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED, HOTKEY_FUNC(playlist_insert_shuffled, NULL), diff --git a/manual/working_with_playlists/main.tex b/manual/working_with_playlists/main.tex index d478dcd283..0d1ab7ef04 100644 --- a/manual/working_with_playlists/main.tex +++ b/manual/working_with_playlists/main.tex @@ -48,11 +48,11 @@ song. rather than erasing the current playlist, see the section below on how to add music to a playlist.} -\subsubsection{By using the Clear List \& Play Next function} -The \setting{Clear List \& Play Next} function as described in -\ref{ref:currentplaylist_submenu} will replace the dynamic playlist with the selected -tracks. If a track is currently playing, it is only removed once it’s finished -playing. +\subsubsection{By using the Play or Play Shuffled functions} +The \setting{Play} function as described in \ref{ref:currentplaylist_submenu} +will replace the dynamic playlist with the selected tracks. The \setting{Play +Shuffled} function is similar, except the selected tracks will be added to the +playlist in a random order. \subsubsection{\label{ref:playlist_catalogue}By using the Playlist catalogue} The \setting{Playlist catalogue} makes it possible to modify and create @@ -96,20 +96,6 @@ have not been added yet, immediately after the currently playing track. \item [Insert Last Shuffled.] Add tracks in a random order to the end of the playlist. \end{description} -If you want the existing playlist entries to first be removed before -selected tracks are inserted, the following two options will achieve that effect. -They are also available when playback is stopped, whereas the rest of the options -require music to be playing or paused. - -\begin{description} -\item [Clear List \& Play Next.] Replace all entries in the dynamic playlist with -selected tracks. If a track is currently playing, it will be removed once it’s -finished playing. - -\item [Clear List \& Play Shuffled.] Similar, except tracks are added in random order. -Only available when playback is stopped. -\end{description} - Another possibility is to add tracks \emph{temporarily} to the dynamic playlist. In Rockbox’s parlance, this is called queuing. Queued tracks are automatically removed from the playlist after they have been played. They are also not saved @@ -127,6 +113,17 @@ to the playlist file (see \reference{ref:playlistoptions}). \item [Queue Last Shuffled.] Corresponds to \setting{Insert Last Shuffled}. \end{description} +If you'd like to replace the current playlist with the new selection, the +following two options will achieve that effect. + +\begin{description} +\item [Play.] Replace all entries in the dynamic playlist with the selected + tracks and start playing the new playlist immediately. + +\item [Play Shuffled.] Similar, except the tracks will be added to the new + playlist in random order. +\end{description} + \note{You can hide the options to add shuffled tracks or to queue tracks, if you wish. The latter can also be put into its own submenu. Simply go to \setting{Settings} $\rightarrow$ \setting{General Settings} $\rightarrow$ \setting{Playlists}