summaryrefslogtreecommitdiffstats
path: root/apps/onplay.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/onplay.c')
-rw-r--r--apps/onplay.c1039
1 files changed, 440 insertions, 599 deletions
diff --git a/apps/onplay.c b/apps/onplay.c
index d72f592f2e..ba06d13183 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -63,12 +63,16 @@
#include "viewport.h"
#include "pathfuncs.h"
#include "shortcuts.h"
+#include "misc.h"
static int context;
static const char *selected_file = NULL;
static char selected_file_path[MAX_PATH];
static int selected_file_attr = 0;
static int onplay_result = ONPLAY_OK;
+static bool in_queue_submenu = false;
+static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new);
+static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist);
extern struct menu_item_ex file_menu; /* settings_menu.c */
/* redefine MAKE_MENU so the MENU_EXITAFTERTHISMENU flag can be added easily */
@@ -125,8 +129,8 @@ static bool clipboard_clip(struct clipboard *clip, const char *path,
unsigned int attr, unsigned int flags)
{
/* if it fits it clips */
- if (strlcpy(clip->path, path, sizeof (clip->path))
- < sizeof (clip->path)) {
+ if (strmemccpy(clip->path, path, sizeof (clip->path)) != NULL)
+ {
clip->attr = attr;
clip->flags = flags;
return true;
@@ -142,16 +146,25 @@ static bool clipboard_clip(struct clipboard *clip, const char *path,
/* interface function. */
/* ----------------------------------------------------------------------- */
+
+static int bookmark_load_menu_wrapper(void)
+{
+ if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* get rid of parent activity */
+ pop_current_activity_without_refresh(); /* when called from ctxt menu */
+
+ return bookmark_load_menu();
+}
+
static int bookmark_menu_callback(int action,
const struct menu_item_ex *this_item,
struct gui_synclist *this_list);
MENUITEM_FUNCTION(bookmark_create_menu_item, 0,
ID2P(LANG_BOOKMARK_MENU_CREATE),
- bookmark_create_menu, NULL,
+ bookmark_create_menu,
bookmark_menu_callback, Icon_Bookmark);
MENUITEM_FUNCTION(bookmark_load_menu_item, 0,
ID2P(LANG_BOOKMARK_MENU_LIST),
- bookmark_load_menu, NULL,
+ bookmark_load_menu_wrapper,
bookmark_menu_callback, Icon_Bookmark);
MAKE_ONPLAYMENU(bookmark_menu, ID2P(LANG_BOOKMARK_MENU),
bookmark_menu_callback, Icon_Bookmark,
@@ -187,261 +200,6 @@ static int bookmark_menu_callback(int action,
return action;
}
-/* playing_time screen context */
-struct playing_time_info {
- int curr_playing; /* index of currently playing track in playlist */
- int nb_tracks; /* how many tracks in playlist */
- /* seconds before and after current position, and total. Datatype
- allows for values up to 68years. If I had kept it in ms
- though, it would have overflowed at 24days, which takes
- something like 8.5GB at 32kbps, and so we could conceivably
- have playlists lasting longer than that. */
- long secs_bef, secs_aft, secs_ttl;
- long trk_secs_bef, trk_secs_aft, trk_secs_ttl;
- /* kilobytes played before and after current pos, and total.
- Kilobytes because bytes would overflow. Data type range is up
- to 2TB. */
- long kbs_bef, kbs_aft, kbs_ttl;
-};
-
-/* list callback for playing_time screen */
-static const char * playing_time_get_or_speak_info(int selected_item, void * data,
- char *buf, size_t buffer_len,
- bool say_it)
-{
- struct playing_time_info *pti = (struct playing_time_info *)data;
- switch(selected_item) {
- case 0: { /* elapsed and total time */
- char timestr1[25], timestr2[25];
- format_time_auto(timestr1, sizeof(timestr1), pti->secs_bef,
- UNIT_SEC, false);
- format_time_auto(timestr2, sizeof(timestr2), pti->secs_ttl,
- UNIT_SEC, false);
- long elapsed_perc; /* percentage of duration elapsed */
- if (pti->secs_ttl == 0)
- elapsed_perc = 0;
- else if (pti->secs_ttl <= 0xFFFFFF)
- elapsed_perc = pti->secs_bef *100 / pti->secs_ttl;
- else /* sacrifice some precision to avoid overflow */
- elapsed_perc = (pti->secs_bef>>7) *100 /(pti->secs_ttl>>7);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_ELAPSED),
- timestr1, timestr2, elapsed_perc);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_ELAPSED,
- TALK_ID(pti->secs_bef, UNIT_TIME),
- VOICE_OF,
- TALK_ID(pti->secs_ttl, UNIT_TIME),
- VOICE_PAUSE,
- TALK_ID(elapsed_perc, UNIT_PERCENT));
- break;
- }
- case 1: { /* playlist remaining time */
- char timestr[25];
- format_time_auto(timestr, sizeof(timestr), pti->secs_aft,
- UNIT_SEC, false);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_REMAINING),
- timestr);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_REMAINING,
- TALK_ID(pti->secs_aft, UNIT_TIME));
- break;
- }
- case 2: { /* track elapsed and duration */
- char timestr1[25], timestr2[25];
- format_time_auto(timestr1, sizeof(timestr1), pti->trk_secs_bef,
- UNIT_SEC, false);
- format_time_auto(timestr2, sizeof(timestr2), pti->trk_secs_ttl,
- UNIT_SEC, false);
- long elapsed_perc; /* percentage of duration elapsed */
- if (pti->trk_secs_ttl == 0)
- elapsed_perc = 0;
- else if (pti->trk_secs_ttl <= 0xFFFFFF)
- elapsed_perc = pti->trk_secs_bef *100 / pti->trk_secs_ttl;
- else /* sacrifice some precision to avoid overflow */
- elapsed_perc = (pti->trk_secs_bef>>7) *100 /(pti->trk_secs_ttl>>7);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRK_ELAPSED),
- timestr1, timestr2, elapsed_perc);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_TRK_ELAPSED,
- TALK_ID(pti->trk_secs_bef, UNIT_TIME),
- VOICE_OF,
- TALK_ID(pti->trk_secs_ttl, UNIT_TIME),
- VOICE_PAUSE,
- TALK_ID(elapsed_perc, UNIT_PERCENT));
- break;
- }
- case 3: { /* track remaining time */
- char timestr[25];
- format_time_auto(timestr, sizeof(timestr), pti->trk_secs_aft,
- UNIT_SEC, false);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRK_REMAINING),
- timestr);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_TRK_REMAINING,
- TALK_ID(pti->trk_secs_aft, UNIT_TIME));
- break;
- }
- case 4: { /* track index */
- int track_perc = (pti->curr_playing+1) *100 / pti->nb_tracks;
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRACK),
- pti->curr_playing + 1, pti->nb_tracks, track_perc);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_TRACK,
- TALK_ID(pti->curr_playing+1, UNIT_INT),
- VOICE_OF,
- TALK_ID(pti->nb_tracks, UNIT_INT),
- VOICE_PAUSE,
- TALK_ID(track_perc, UNIT_PERCENT));
- break;
- }
- case 5: { /* storage size */
- char str1[10], str2[10], str3[10];
- output_dyn_value(str1, sizeof(str1), pti->kbs_ttl, kibyte_units, 3, true);
- output_dyn_value(str2, sizeof(str2), pti->kbs_bef, kibyte_units, 3, true);
- output_dyn_value(str3, sizeof(str3), pti->kbs_aft, kibyte_units, 3, true);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_STORAGE),
- str1,str2,str3);
- if (say_it) {
- talk_id(LANG_PLAYTIME_STORAGE, false);
- output_dyn_value(NULL, 0, pti->kbs_ttl, kibyte_units, 3, true);
- talk_ids(true, VOICE_PAUSE, VOICE_PLAYTIME_DONE);
- output_dyn_value(NULL, 0, pti->kbs_bef, kibyte_units, 3, true);
- talk_id(LANG_PLAYTIME_REMAINING, true);
- output_dyn_value(NULL, 0, pti->kbs_aft, kibyte_units, 3, true);
- }
- break;
- }
- case 6: { /* Average track file size */
- char str[10];
- long avg_track_size = pti->kbs_ttl /pti->nb_tracks;
- output_dyn_value(str, sizeof(str), avg_track_size, kibyte_units, 3, true);
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_AVG_TRACK_SIZE),
- str);
- if (say_it) {
- talk_id(LANG_PLAYTIME_AVG_TRACK_SIZE, false);
- output_dyn_value(NULL, 0, avg_track_size, kibyte_units, 3, true);
- }
- break;
- }
- case 7: { /* Average bitrate */
- /* Convert power of 2 kilobytes to power of 10 kilobits */
- long avg_bitrate = pti->kbs_ttl / pti->secs_ttl *1024 *8 /1000;
- snprintf(buf, buffer_len, str(LANG_PLAYTIME_AVG_BITRATE),
- avg_bitrate);
- if (say_it)
- talk_ids(false, LANG_PLAYTIME_AVG_BITRATE,
- TALK_ID(avg_bitrate, UNIT_KBIT));
- break;
- }
- }
- return buf;
-}
-
-static const char * playing_time_get_info(int selected_item, void * data,
- char *buffer, size_t buffer_len)
-{
- return playing_time_get_or_speak_info(selected_item, data,
- buffer, buffer_len, false);
-}
-
-static int playing_time_speak_info(int selected_item, void * data)
-{
- static char buffer[MAX_PATH];
- playing_time_get_or_speak_info(selected_item, data,
- buffer, MAX_PATH, true);
- return 0;
-}
-
-/* playing time screen: shows total and elapsed playlist duration and
- other stats */
-static bool playing_time(void)
-{
- unsigned long talked_tick = current_tick;
- struct playing_time_info pti;
- struct playlist_track_info pltrack;
- struct mp3entry id3;
- int i, fd, ret;
-
- pti.nb_tracks = playlist_amount();
- playlist_get_resume_info(&pti.curr_playing);
- struct mp3entry *curr_id3 = audio_current_track();
- if (pti.curr_playing == -1 || !curr_id3)
- return false;
- pti.secs_bef = pti.trk_secs_bef = curr_id3->elapsed/1000;
- pti.secs_aft = pti.trk_secs_aft
- = (curr_id3->length -curr_id3->elapsed)/1000;
- pti.kbs_bef = curr_id3->offset/1024;
- pti.kbs_aft = (curr_id3->filesize -curr_id3->offset)/1024;
-
- splash(0, ID2P(LANG_WAIT));
-
- /* Go through each file in the playlist and get its stats. For
- huge playlists this can take a while... The reference position
- is the position at the moment this function was invoked,
- although playback continues forward. */
- for (i = 0; i < pti.nb_tracks; i++) {
- /* Show a splash while we are loading. */
- splashf(0, str(LANG_LOADING_PERCENT),
- i*100/pti.nb_tracks, str(LANG_OFF_ABORT));
- /* Voice equivalent */
- if (TIME_AFTER(current_tick, talked_tick+5*HZ)) {
- talked_tick = current_tick;
- talk_ids(false, LANG_LOADING_PERCENT,
- TALK_ID(i*100/pti.nb_tracks, UNIT_PERCENT));
- }
- if (action_userabort(TIMEOUT_NOBLOCK))
- goto exit;
-
- if (i == pti.curr_playing)
- continue;
-
- if (playlist_get_track_info(NULL, i, &pltrack) < 0)
- goto error;
- if ((fd = open(pltrack.filename, O_RDONLY)) < 0)
- goto error;
- ret = get_metadata(&id3, fd, pltrack.filename);
- close(fd);
- if (!ret)
- goto error;
-
- if (i < pti.curr_playing) {
- pti.secs_bef += id3.length/1000;
- pti.kbs_bef += id3.filesize/1024;
- } else {
- pti.secs_aft += id3.length/1000;
- pti.kbs_aft += id3.filesize/1024;
- }
- }
-
- pti.secs_ttl = pti.secs_bef +pti.secs_aft;
- pti.trk_secs_ttl = pti.trk_secs_bef +pti.trk_secs_aft;
- pti.kbs_ttl = pti.kbs_bef +pti.kbs_aft;
-
- struct gui_synclist pt_lists;
- int key;
-
- gui_synclist_init(&pt_lists, &playing_time_get_info, &pti, true, 1, NULL);
- if (global_settings.talk_menu)
- gui_synclist_set_voice_callback(&pt_lists, playing_time_speak_info);
- gui_synclist_set_nb_items(&pt_lists, 8);
- gui_synclist_draw(&pt_lists);
-/* gui_syncstatusbar_draw(&statusbars, true); */
- gui_synclist_speak_item(&pt_lists);
- while (true) {
-/* gui_syncstatusbar_draw(&statusbars, false); */
- if (list_do_action(CONTEXT_LIST, HZ/2,
- &pt_lists, &key, LIST_WRAP_UNLESS_HELD) == 0
- && key!=ACTION_NONE && key!=ACTION_UNKNOWN)
- {
- talk_force_shutup();
- return(default_event_handler(key) == SYS_USB_CONNECTED);
- }
- }
- error:
- splash(HZ, ID2P(LANG_PLAYTIME_ERROR));
- exit:
- return false;
-}
/* CONTEXT_WPS playlist options */
@@ -451,40 +209,83 @@ static bool shuffle_playlist(void)
return false;
playlist_sort(NULL, true);
playlist_randomise(NULL, current_tick, true);
+ playlist_set_modified(NULL, true);
return false;
}
+
static bool save_playlist(void)
{
+ /* save_playlist_screen should load the newly saved playlist and resume */
save_playlist_screen(NULL);
return false;
}
-extern struct menu_item_ex view_cur_playlist; /* from playlist_menu.c */
+static int wps_view_cur_playlist(void)
+{
+ if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* get rid of parent activity */
+ pop_current_activity_without_refresh(); /* when called from ctxt menu */
+
+ playlist_viewer_ex(NULL, NULL);
+
+ return 0;
+}
+
+static void playing_time(void)
+{
+ plugin_load(PLUGIN_APPS_DIR"/playing_time.rock", NULL);
+}
+
+MENUITEM_FUNCTION(wps_view_cur_playlist_item, 0, ID2P(LANG_VIEW_DYNAMIC_PLAYLIST),
+ wps_view_cur_playlist, NULL, Icon_NOICON);
MENUITEM_FUNCTION(search_playlist_item, 0, ID2P(LANG_SEARCH_IN_PLAYLIST),
- search_playlist, NULL, NULL, Icon_Playlist);
+ search_playlist, NULL, Icon_Playlist);
MENUITEM_FUNCTION(playlist_save_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
- save_playlist, NULL, NULL, Icon_Playlist);
+ save_playlist, NULL, Icon_Playlist);
MENUITEM_FUNCTION(reshuffle_item, 0, ID2P(LANG_SHUFFLE_PLAYLIST),
- shuffle_playlist, NULL, NULL, Icon_Playlist);
+ shuffle_playlist, NULL, Icon_Playlist);
MENUITEM_FUNCTION(playing_time_item, 0, ID2P(LANG_PLAYING_TIME),
- playing_time, NULL, NULL, Icon_Playlist);
-MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_PLAYLIST),
+ playing_time, NULL, Icon_Playlist);
+MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_CURRENT_PLAYLIST),
NULL, Icon_Playlist,
- &view_cur_playlist, &search_playlist_item,
+ &wps_view_cur_playlist_item, &search_playlist_item,
&playlist_save_item, &reshuffle_item, &playing_time_item
);
-/* CONTEXT_[TREE|ID3DB] 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_LAST_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;
+ bool queue = !!param->queue;
+
+ /* warn if replacing the playlist */
+ if (new_playlist && !warn_on_pl_erase())
+ return 0;
const char *lines[] = {
ID2P(LANG_RECURSE_DIRECTORY_QUESTION),
@@ -494,6 +295,15 @@ static bool add_to_playlist(int position, bool queue)
splash(0, ID2P(LANG_WAIT));
+ if (new_playlist && global_settings.keep_current_track_on_replace_playlist)
+ {
+ if (audio_status() & AUDIO_STATUS_PLAY)
+ {
+ playlist_remove_all_tracks(NULL);
+ new_playlist = false;
+ }
+ }
+
if (new_playlist)
playlist_create(NULL, NULL);
@@ -507,9 +317,13 @@ static bool add_to_playlist(int position, bool queue)
}
#ifdef HAVE_TAGCACHE
- if (context == CONTEXT_ID3DB)
+ if ((context == CONTEXT_ID3DB) && (selected_file_attr & ATTR_DIRECTORY))
+ {
+ tagtree_current_playlist_insert(position, queue);
+ }
+ else if (context == CONTEXT_STD && ctx_current_playlist_insert != NULL)
{
- tagtree_insert_selection_playlist(position, queue);
+ ctx_current_playlist_insert(position, queue, false);
}
else
#endif
@@ -545,17 +359,17 @@ static bool add_to_playlist(int position, bool queue)
onplay_result = ONPLAY_START_PLAY;
}
+ playlist_set_modified(NULL, true);
return false;
}
static bool view_playlist(void)
{
- bool was_playing = audio_status() & AUDIO_STATUS_PLAY;
bool result;
- result = playlist_viewer_ex(selected_file);
+ result = playlist_viewer_ex(selected_file, NULL);
- if (!was_playing && (audio_status() & AUDIO_STATUS_PLAY) &&
+ if (result == PLAYLIST_VIEWER_OK &&
onplay_result == ONPLAY_OK)
/* playlist was started from viewer */
onplay_result = ONPLAY_START_PLAY;
@@ -563,136 +377,74 @@ 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 && !(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,
+MENUITEM_FUNCTION_W_PARAM(i_pl_item, 0, ID2P(LANG_ADD),
+ 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_W_PARAM(i_first_pl_item, 0, ID2P(LANG_PLAY_NEXT),
+ add_to_playlist, &addtopl_insert_first,
treeplaylist_callback, Icon_Playlist);
-/* queue items */
-MENUITEM_FUNCTION(q_pl_item, MENU_FUNC_USEPARAM, ID2P(LANG_QUEUE),
- playlist_queue_func, (intptr_t*)PLAYLIST_INSERT,
+MENUITEM_FUNCTION_W_PARAM(i_last_pl_item, 0, ID2P(LANG_PLAY_LAST),
+ add_to_playlist, &addtopl_insert_last,
+ treeplaylist_callback, Icon_Playlist);
+MENUITEM_FUNCTION_W_PARAM(i_shuf_pl_item, 0, ID2P(LANG_ADD_SHUFFLED),
+ add_to_playlist, &addtopl_insert_shuf,
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,
+MENUITEM_FUNCTION_W_PARAM(i_last_shuf_pl_item, 0, ID2P(LANG_PLAY_LAST_SHUFFLED),
+ add_to_playlist, &addtopl_insert_last_shuf,
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,
+/* queue items */
+MENUITEM_FUNCTION_W_PARAM(q_pl_item, 0, ID2P(LANG_QUEUE),
+ add_to_playlist, &addtopl_queue,
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_W_PARAM(q_first_pl_item, 0, ID2P(LANG_QUEUE_FIRST),
+ add_to_playlist, &addtopl_queue_first,
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,
+MENUITEM_FUNCTION_W_PARAM(q_last_pl_item, 0, ID2P(LANG_QUEUE_LAST),
+ add_to_playlist, &addtopl_queue_last,
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,
+MENUITEM_FUNCTION_W_PARAM(q_shuf_pl_item, 0, ID2P(LANG_QUEUE_SHUFFLED),
+ add_to_playlist, &addtopl_queue_shuf,
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_W_PARAM(q_last_shuf_pl_item, 0, 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_first_pl_item,
+ &q_pl_item,
+ &q_shuf_pl_item,
+ &q_last_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_W_PARAM(replace_pl_item, 0, 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_W_PARAM(replace_shuf_pl_item, 0, ID2P(LANG_PLAY_SHUFFLED),
+ add_to_playlist, &addtopl_replace_shuffled,
treeplaylist_callback, Icon_Playlist);
-MAKE_ONPLAYMENU(tree_playlist_menu, ID2P(LANG_CURRENT_PLAYLIST),
+MAKE_ONPLAYMENU(tree_playlist_menu, ID2P(LANG_PLAYING_NEXT),
treeplaylist_callback, Icon_Playlist,
/* insert */
- &i_pl_item,
&i_first_pl_item,
+ &i_pl_item,
&i_last_pl_item,
&i_shuf_pl_item,
&i_last_shuf_pl_item,
/* queue */
- &q_pl_item,
&q_first_pl_item,
+ &q_pl_item,
&q_last_pl_item,
&q_shuf_pl_item,
&q_last_shuf_pl_item,
@@ -711,77 +463,70 @@ static int treeplaylist_callback(int action,
(void)this_list;
switch (action)
{
- 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))
- return action;
- }
- 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))
- {
- return action;
- }
- else if (this_item == &i_shuf_pl_item)
- {
- if (global_settings.show_shuffled_adding_options &&
- (audio_status() & AUDIO_STATUS_PLAY))
- {
- return action;
- }
- }
- else if (this_item == &replace_shuf_pl_item)
+ 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_W_PARAM &&
+ this_item->function_param->function_w_param == add_to_playlist)
+ {
+ struct add_to_pl_param *param = this_item->function_param->param;
+
+ if (param->queue)
{
- 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;
- }
+ if (global_settings.show_queue_options != QUEUE_SHOW_AT_TOPLEVEL &&
+ !in_queue_submenu)
+ return ACTION_EXIT_MENUITEM;
}
- 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 (param->position == PLAYLIST_INSERT_SHUFFLED ||
+ param->position == PLAYLIST_INSERT_LAST_SHUFFLED)
{
- if (global_settings.show_shuffled_adding_options &&
- (audio_status() & AUDIO_STATUS_PLAY))
- {
- 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_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 (!param->replace)
{
- 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;
- }
+ if (!(audio_status() & AUDIO_STATUS_PLAY))
+ return ACTION_EXIT_MENUITEM;
}
- return ACTION_EXIT_MENUITEM;
- break;
+ }
+
+ break;
+
+ case ACTION_ENTER_MENUITEM:
+ in_queue_submenu = this_item == &queue_menu;
+ break;
}
+
return action;
}
-void onplay_show_playlist_menu(char* path)
+void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb))
{
+ context = CONTEXT_STD;
+ ctx_current_playlist_insert = playlist_insert_cb;
selected_file = path;
- if (dir_exists(path))
- selected_file_attr = ATTR_DIRECTORY;
- else
- selected_file_attr = filetype_get_attr(path);
+ selected_file_attr = attr;
+ in_queue_submenu = false;
do_menu(&tree_playlist_menu, NULL, NULL, false);
}
@@ -789,43 +534,33 @@ void onplay_show_playlist_menu(char* path)
static bool cat_add_to_a_playlist(void)
{
return catalog_add_to_a_playlist(selected_file, selected_file_attr,
- false, NULL);
+ false, NULL, ctx_add_to_playlist);
}
static bool cat_add_to_a_new_playlist(void)
{
return catalog_add_to_a_playlist(selected_file, selected_file_attr,
- true, NULL);
+ true, NULL, ctx_add_to_playlist);
}
-static int clipboard_callback(int action,
- const struct menu_item_ex *this_item,
- struct gui_synclist *this_list);
-
-static bool set_catalogdir(void)
-{
- catalog_set_directory(selected_file);
- settings_save();
- return false;
-}
-MENUITEM_FUNCTION(set_catalogdir_item, 0, ID2P(LANG_SET_AS_PLAYLISTCAT_DIR),
- set_catalogdir, NULL, clipboard_callback, Icon_Playlist);
static int cat_playlist_callback(int action,
const struct menu_item_ex *this_item,
struct gui_synclist *this_list);
-MENUITEM_FUNCTION(cat_add_to_list, 0, ID2P(LANG_CATALOG_ADD_TO),
- cat_add_to_a_playlist, 0, NULL, Icon_Playlist);
+MENUITEM_FUNCTION(cat_add_to_list, 0, ID2P(LANG_ADD_TO_EXISTING_PL),
+ cat_add_to_a_playlist, NULL, Icon_Playlist);
MENUITEM_FUNCTION(cat_add_to_new, 0, ID2P(LANG_CATALOG_ADD_TO_NEW),
- cat_add_to_a_new_playlist, 0, NULL, Icon_Playlist);
-MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_CATALOG),
+ cat_add_to_a_new_playlist, NULL, Icon_Playlist);
+MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_ADD_TO_PL),
cat_playlist_callback, Icon_Playlist,
- &cat_add_to_list, &cat_add_to_new, &set_catalogdir_item);
+ &cat_add_to_list, &cat_add_to_new);
-void onplay_show_playlist_cat_menu(char* track_name)
+void onplay_show_playlist_cat_menu(const char* track_name, int attr, void (*add_to_pl_cb))
{
+ context = CONTEXT_STD;
+ ctx_add_to_playlist = add_to_pl_cb;
selected_file = track_name;
- selected_file_attr = FILE_ATTR_AUDIO;
+ selected_file_attr = attr;
do_menu(&cat_playlist_menu, NULL, NULL, false);
}
@@ -842,13 +577,6 @@ static int cat_playlist_callback(int action,
{
return ACTION_EXIT_MENUITEM;
}
-#ifdef HAVE_TAGCACHE
- if (context == CONTEXT_ID3DB &&
- ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO))
- {
- return ACTION_EXIT_MENUITEM;
- }
-#endif
switch (action)
{
@@ -912,22 +640,6 @@ static bool poll_cancel_action(const char *path)
return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
}
-static int confirm_overwrite(void)
-{
- static const char *lines[] = { ID2P(LANG_REALLY_OVERWRITE) };
- static const struct text_message message = { lines, 1 };
- return gui_syncyesno_run(&message, NULL, NULL);
-}
-
-static int confirm_delete(const char *file)
-{
- const char *lines[] = { ID2P(LANG_REALLY_DELETE), file };
- const char *yes_lines[] = { ID2P(LANG_DELETING), file };
- const struct text_message message = { lines, 2 };
- const struct text_message yes_message = { yes_lines, 2 };
- return gui_syncyesno_run(&message, &yes_message, NULL);
-}
-
static bool check_new_name(const char *basename)
{
/* at least prevent escapes out of the base directory from keyboard-
@@ -1022,7 +734,7 @@ static int delete_file_dir(void)
{
const char *to_delete=selected_file;
const int to_delete_attr=selected_file_attr;
- if (confirm_delete(to_delete) != YESNO_YES) {
+ if (confirm_delete_yesno(to_delete) != YESNO_YES) {
return 1;
}
@@ -1068,7 +780,7 @@ static int rename_file(void)
size_t pathlen = oldbase - selection;
char *newbase = newname + pathlen;
- if (strlcpy(newname, selection, sizeof (newname)) >= sizeof (newname)) {
+ if (strmemccpy(newname, selection, sizeof (newname)) == NULL) {
/* Too long */
} else if (kbd_input(newbase, sizeof (newname) - pathlen, NULL) < 0) {
rc = OPRC_CANCELLED;
@@ -1399,7 +1111,7 @@ static int clipboard_paste(void)
case RELATE_DIFFERENT:
if (file_exists(target.path)) {
/* If user chooses not to overwrite, cancel */
- if (confirm_overwrite() == YESNO_NO) {
+ if (confirm_overwrite_yesno() == YESNO_NO) {
rc = OPRC_NOOVERWRT;
break;
}
@@ -1440,10 +1152,13 @@ static int clipboard_paste(void)
{
case OPRC_CANCELLED:
splash_cancelled();
+ /* Fallthrough */
case OPRC_SUCCESS:
onplay_result = ONPLAY_RELOAD_DIR;
+ /* Fallthrough */
case OPRC_NOOP:
clipboard_clear_selection(&clipboard);
+ /* Fallthrough */
case OPRC_NOOVERWRT:
break;
default:
@@ -1487,7 +1202,7 @@ static int ratingitem_callback(int action,
return action;
}
MENUITEM_FUNCTION(rating_item, 0, ID2P(LANG_MENU_SET_RATING),
- set_rating_inline, NULL,
+ set_rating_inline,
ratingitem_callback, Icon_Questionmark);
#endif
MENUITEM_RETURNVALUE(plugin_item, ID2P(LANG_OPEN_PLUGIN),
@@ -1520,22 +1235,27 @@ static int view_cue_item_callback(int action,
return action;
}
MENUITEM_FUNCTION(view_cue_item, 0, ID2P(LANG_BROWSE_CUESHEET),
- view_cue, NULL, view_cue_item_callback, Icon_NOICON);
+ view_cue, view_cue_item_callback, Icon_NOICON);
static int browse_id3_wrapper(void)
{
- if (browse_id3())
+ if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* get rid of parent activity */
+ pop_current_activity_without_refresh(); /* when called from ctxt menu */
+
+ if (browse_id3(audio_current_track(),
+ playlist_get_display_index(),
+ playlist_amount(), NULL, 1))
return GO_TO_ROOT;
return GO_TO_PREVIOUS;
}
/* CONTEXT_WPS items */
MENUITEM_FUNCTION(browse_id3_item, MENU_FUNC_CHECK_RETVAL, ID2P(LANG_MENU_SHOW_ID3_INFO),
- browse_id3_wrapper, NULL, NULL, Icon_NOICON);
+ browse_id3_wrapper, NULL, Icon_NOICON);
#ifdef HAVE_PITCHCONTROL
MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH),
- gui_syncpitchscreen_run, NULL, NULL, Icon_Audio);
+ gui_syncpitchscreen_run, NULL, Icon_Audio);
#endif
/* CONTEXT_[TREE|ID3DB] items */
@@ -1544,19 +1264,19 @@ static int clipboard_callback(int action,
struct gui_synclist *this_list);
MENUITEM_FUNCTION(rename_file_item, 0, ID2P(LANG_RENAME),
- rename_file, NULL, clipboard_callback, Icon_NOICON);
+ rename_file, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(clipboard_cut_item, 0, ID2P(LANG_CUT),
- clipboard_cut, NULL, clipboard_callback, Icon_NOICON);
+ clipboard_cut, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(clipboard_copy_item, 0, ID2P(LANG_COPY),
- clipboard_copy, NULL, clipboard_callback, Icon_NOICON);
+ clipboard_copy, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(clipboard_paste_item, 0, ID2P(LANG_PASTE),
- clipboard_paste, NULL, clipboard_callback, Icon_NOICON);
+ clipboard_paste, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(delete_file_item, 0, ID2P(LANG_DELETE),
- delete_file_dir, NULL, clipboard_callback, Icon_NOICON);
+ delete_file_dir, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(delete_dir_item, 0, ID2P(LANG_DELETE_DIR),
- delete_file_dir, NULL, clipboard_callback, Icon_NOICON);
+ delete_file_dir, clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(create_dir_item, 0, ID2P(LANG_CREATE_DIR),
- create_dir, NULL, clipboard_callback, Icon_NOICON);
+ create_dir, clipboard_callback, Icon_NOICON);
/* other items */
static bool list_viewers(void)
@@ -1567,32 +1287,69 @@ static bool list_viewers(void)
return false;
}
+#ifdef HAVE_TAGCACHE
+static bool prepare_database_sel(void *param)
+{
+ if (context == CONTEXT_ID3DB &&
+ (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
+ {
+ if (!strcmp(param, "properties"))
+ strmemccpy(selected_file_path, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER),
+ sizeof(selected_file_path));
+ else if (!tagtree_get_subentry_filename(selected_file_path, MAX_PATH))
+ {
+ onplay_result = ONPLAY_RELOAD_DIR;
+ return false;
+ }
+
+ selected_file = selected_file_path;
+ }
+ return true;
+}
+#endif
+
static bool onplay_load_plugin(void *param)
{
+#ifdef HAVE_TAGCACHE
+ if (!prepare_database_sel(param))
+ return false;
+#endif
int ret = filetype_load_plugin((const char*)param, selected_file);
if (ret == PLUGIN_USB_CONNECTED)
onplay_result = ONPLAY_RELOAD_DIR;
+ else if (ret == PLUGIN_GOTO_PLUGIN)
+ onplay_result = ONPLAY_PLUGIN;
+ else if (ret == PLUGIN_GOTO_WPS)
+ onplay_result = ONPLAY_START_PLAY;
return false;
}
MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH),
- list_viewers, NULL, clipboard_callback, Icon_NOICON);
-MENUITEM_FUNCTION(properties_item, MENU_FUNC_USEPARAM, ID2P(LANG_PROPERTIES),
+ list_viewers, clipboard_callback, Icon_NOICON);
+MENUITEM_FUNCTION_W_PARAM(properties_item, 0, ID2P(LANG_PROPERTIES),
onplay_load_plugin, (void *)"properties",
clipboard_callback, Icon_NOICON);
+MENUITEM_FUNCTION_W_PARAM(track_info_item, 0, ID2P(LANG_MENU_SHOW_ID3_INFO),
+ onplay_load_plugin, (void *)"properties",
+ clipboard_callback, Icon_NOICON);
+#ifdef HAVE_TAGCACHE
+MENUITEM_FUNCTION_W_PARAM(pictureflow_item, 0, ID2P(LANG_ONPLAY_PICTUREFLOW),
+ onplay_load_plugin, (void *)"pictureflow",
+ clipboard_callback, Icon_NOICON);
+#endif
static bool onplay_add_to_shortcuts(void)
{
shortcuts_add(SHORTCUT_BROWSER, selected_file);
return false;
}
MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
- onplay_add_to_shortcuts, NULL,
+ onplay_add_to_shortcuts,
clipboard_callback, Icon_NOICON);
#if LCD_DEPTH > 1
static bool set_backdrop(void)
{
- strlcpy(global_settings.backdrop_file, selected_file,
+ strmemccpy(global_settings.backdrop_file, selected_file,
sizeof(global_settings.backdrop_file));
settings_save();
skin_backdrop_load_setting();
@@ -1600,18 +1357,18 @@ static bool set_backdrop(void)
return true;
}
MENUITEM_FUNCTION(set_backdrop_item, 0, ID2P(LANG_SET_AS_BACKDROP),
- set_backdrop, NULL, clipboard_callback, Icon_NOICON);
+ set_backdrop, clipboard_callback, Icon_NOICON);
#endif
#ifdef HAVE_RECORDING
static bool set_recdir(void)
{
- strlcpy(global_settings.rec_directory, selected_file,
+ strmemccpy(global_settings.rec_directory, selected_file,
sizeof(global_settings.rec_directory));
settings_save();
return false;
}
-MENUITEM_FUNCTION(set_recdir_item, 0, ID2P(LANG_SET_AS_REC_DIR),
- set_recdir, NULL, clipboard_callback, Icon_Recording);
+MENUITEM_FUNCTION(set_recdir_item, 0, ID2P(LANG_RECORDING_DIR),
+ set_recdir, clipboard_callback, Icon_Recording);
#endif
static bool set_startdir(void)
{
@@ -1621,8 +1378,25 @@ static bool set_startdir(void)
settings_save();
return false;
}
-MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_SET_AS_START_DIR),
- set_startdir, NULL, clipboard_callback, Icon_file_view_menu);
+MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_START_DIR),
+ set_startdir, clipboard_callback, Icon_file_view_menu);
+
+static bool set_catalogdir(void)
+{
+ catalog_set_directory(selected_file);
+ settings_save();
+ return false;
+}
+MENUITEM_FUNCTION(set_catalogdir_item, 0, ID2P(LANG_PLAYLIST_DIR),
+ set_catalogdir, clipboard_callback, Icon_Playlist);
+
+MAKE_ONPLAYMENU(set_as_dir_menu, ID2P(LANG_SET_AS),
+ clipboard_callback, Icon_NOICON,
+ &set_catalogdir_item,
+#ifdef HAVE_RECORDING
+ &set_recdir_item,
+#endif
+ &set_startdir_item);
static int clipboard_callback(int action,
const struct menu_item_ex *this_item,
@@ -1644,9 +1418,8 @@ static int clipboard_callback(int action,
#ifdef HAVE_TAGCACHE
if (context == CONTEXT_ID3DB)
{
- if (((selected_file_attr & FILE_ATTR_MASK) ==
- FILE_ATTR_AUDIO) &&
- this_item == &properties_item)
+ if (this_item == &track_info_item ||
+ this_item == &pictureflow_item)
return action;
return ACTION_EXIT_MENUITEM;
}
@@ -1667,7 +1440,10 @@ static int clipboard_callback(int action,
if (this_item == &rename_file_item ||
this_item == &clipboard_cut_item ||
this_item == &clipboard_copy_item ||
- this_item == &properties_item ||
+ (this_item == &track_info_item &&
+ (selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) ||
+ (this_item == &properties_item &&
+ (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) ||
this_item == &add_to_faves_item)
{
return action;
@@ -1677,7 +1453,8 @@ static int clipboard_callback(int action,
/* only for directories */
if (this_item == &delete_dir_item ||
this_item == &set_startdir_item ||
- this_item == &set_catalogdir_item
+ this_item == &set_catalogdir_item ||
+ this_item == &set_as_dir_menu
#ifdef HAVE_RECORDING
|| this_item == &set_recdir_item
#endif
@@ -1732,7 +1509,7 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
);
MENUITEM_FUNCTION(view_playlist_item, 0, ID2P(LANG_VIEW),
- view_playlist, NULL,
+ view_playlist,
onplaymenu_callback, Icon_Playlist);
/* used when onplay() is not called in the CONTEXT_WPS context */
@@ -1741,14 +1518,14 @@ MAKE_ONPLAYMENU( tree_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
&view_playlist_item, &tree_playlist_menu, &cat_playlist_menu,
&rename_file_item, &clipboard_cut_item, &clipboard_copy_item,
&clipboard_paste_item, &delete_file_item, &delete_dir_item,
+ &list_viewers_item, &create_dir_item, &properties_item, &track_info_item,
+#ifdef HAVE_TAGCACHE
+ &pictureflow_item,
+#endif
#if LCD_DEPTH > 1
&set_backdrop_item,
#endif
- &list_viewers_item, &create_dir_item, &properties_item,
-#ifdef HAVE_RECORDING
- &set_recdir_item,
-#endif
- &set_startdir_item, &add_to_faves_item, &file_menu,
+ &add_to_faves_item, &set_as_dir_menu, &file_menu,
);
static int onplaymenu_callback(int action,
const struct menu_item_ex *this_item,
@@ -1782,17 +1559,24 @@ static int onplaymenu_callback(int action,
#ifdef HAVE_HOTKEY
/* direct function calls, no need for menu callbacks */
-static bool delete_item(void)
+static bool hotkey_delete_item(void)
{
#ifdef HAVE_MULTIVOLUME
/* no delete for volumes */
if (selected_file_attr & ATTR_VOLUME)
return false;
#endif
+
+#ifdef HAVE_TAGCACHE
+ if (context == CONTEXT_ID3DB &&
+ (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
+ return false;
+#endif
+
return delete_file_dir();
}
-static bool open_with(void)
+static bool hotkey_open_with(void)
{
/* only open files */
if (selected_file_attr & ATTR_DIRECTORY)
@@ -1804,116 +1588,146 @@ static bool open_with(void)
return list_viewers();
}
-static int playlist_insert_shuffled(void)
+static int hotkey_tree_pl_insert_shuffled(void)
{
if ((audio_status() & AUDIO_STATUS_PLAY) ||
(selected_file_attr & ATTR_DIRECTORY) ||
((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))
{
- playlist_insert_func((intptr_t*)PLAYLIST_INSERT_SHUFFLED);
- return ONPLAY_START_PLAY;
+ add_to_playlist(&addtopl_insert_shuf);
}
+ return ONPLAY_RELOAD_DIR;
+}
+
+static int hotkey_tree_run_plugin(void *param)
+{
+#ifdef HAVE_TAGCACHE
+ if (!prepare_database_sel(param))
+ return ONPLAY_RELOAD_DIR;
+#endif
+ if (filetype_load_plugin((const char*)param, selected_file) == PLUGIN_GOTO_WPS)
+ return ONPLAY_START_PLAY;
return ONPLAY_RELOAD_DIR;
}
-static void hotkey_run_plugin(void)
+static int hotkey_wps_run_plugin(void)
{
open_plugin_run(ID2P(LANG_HOTKEY_WPS));
+ return ONPLAY_OK;
}
-
-struct hotkey_assignment {
- int action; /* hotkey_action */
- int lang_id; /* Language ID */
- struct menu_func func; /* Function to run if this entry is selected */
- int return_code; /* What to return after the function is run */
-};
-
#define HOTKEY_FUNC(func, param) {{(void *)func}, param}
/* Any desired hotkey functions go here, in the enum in onplay.h,
and in the settings menu in settings_list.c. The order here
is not important. */
-static struct hotkey_assignment hotkey_items[] = {
- { HOTKEY_VIEW_PLAYLIST, LANG_VIEW_DYNAMIC_PLAYLIST,
- HOTKEY_FUNC(NULL, NULL),
- ONPLAY_PLAYLIST },
- { HOTKEY_SHOW_TRACK_INFO, LANG_MENU_SHOW_ID3_INFO,
- HOTKEY_FUNC(browse_id3, NULL),
- ONPLAY_RELOAD_DIR },
+static const struct hotkey_assignment hotkey_items[] = {
+ [0]{ .action = HOTKEY_OFF,
+ .lang_id = LANG_OFF,
+ .func = HOTKEY_FUNC(NULL,NULL),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
+ { .action = HOTKEY_VIEW_PLAYLIST,
+ .lang_id = LANG_VIEW_DYNAMIC_PLAYLIST,
+ .func = HOTKEY_FUNC(NULL, NULL),
+ .return_code = ONPLAY_PLAYLIST,
+ .flags = HOTKEY_FLAG_WPS },
+ { .action = HOTKEY_SHOW_TRACK_INFO,
+ .lang_id = LANG_MENU_SHOW_ID3_INFO,
+ .func = HOTKEY_FUNC(browse_id3_wrapper, NULL),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_WPS },
#ifdef HAVE_PITCHCONTROL
- { HOTKEY_PITCHSCREEN, LANG_PITCH,
- HOTKEY_FUNC(gui_syncpitchscreen_run, NULL),
- ONPLAY_RELOAD_DIR },
+ { .action = HOTKEY_PITCHSCREEN,
+ .lang_id = LANG_PITCH,
+ .func = HOTKEY_FUNC(gui_syncpitchscreen_run, NULL),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
+#endif
+ { .action = HOTKEY_OPEN_WITH,
+ .lang_id = LANG_ONPLAY_OPEN_WITH,
+ .func = HOTKEY_FUNC(hotkey_open_with, NULL),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
+ { .action = HOTKEY_DELETE,
+ .lang_id = LANG_DELETE,
+ .func = HOTKEY_FUNC(hotkey_delete_item, NULL),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
+ { .action = HOTKEY_INSERT,
+ .lang_id = LANG_ADD,
+ .func = HOTKEY_FUNC(add_to_playlist, (intptr_t*)&addtopl_insert),
+ .return_code = ONPLAY_RELOAD_DIR,
+ .flags = HOTKEY_FLAG_TREE },
+ { .action = HOTKEY_INSERT_SHUFFLED,
+ .lang_id = LANG_ADD_SHUFFLED,
+ .func = HOTKEY_FUNC(hotkey_tree_pl_insert_shuffled, NULL),
+ .return_code = ONPLAY_FUNC_RETURN,
+ .flags = HOTKEY_FLAG_TREE },
+ { .action = HOTKEY_PLUGIN,
+ .lang_id = LANG_OPEN_PLUGIN,
+ .func = HOTKEY_FUNC(hotkey_wps_run_plugin, NULL),
+ .return_code = ONPLAY_FUNC_RETURN,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
+ { .action = HOTKEY_BOOKMARK,
+ .lang_id = LANG_BOOKMARK_MENU_CREATE,
+ .func = HOTKEY_FUNC(bookmark_create_menu, NULL),
+ .return_code = ONPLAY_OK,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
+ { .action = HOTKEY_BOOKMARK_LIST,
+ .lang_id = LANG_BOOKMARK_MENU_LIST,
+ .func = HOTKEY_FUNC(bookmark_load_menu, NULL),
+ .return_code = ONPLAY_START_PLAY,
+ .flags = HOTKEY_FLAG_WPS },
+ { .action = HOTKEY_PROPERTIES,
+ .lang_id = LANG_PROPERTIES,
+ .func = HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"properties"),
+ .return_code = ONPLAY_FUNC_RETURN,
+ .flags = HOTKEY_FLAG_TREE },
+#ifdef HAVE_TAGCACHE
+ { .action = HOTKEY_PICTUREFLOW,
+ .lang_id = LANG_ONPLAY_PICTUREFLOW,
+ .func = HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"pictureflow"),
+ .return_code = ONPLAY_FUNC_RETURN,
+ .flags = HOTKEY_FLAG_TREE },
#endif
- { HOTKEY_OPEN_WITH, LANG_ONPLAY_OPEN_WITH,
- HOTKEY_FUNC(open_with, NULL),
- ONPLAY_RELOAD_DIR },
- { HOTKEY_DELETE, LANG_DELETE,
- HOTKEY_FUNC(delete_item, NULL),
- ONPLAY_RELOAD_DIR },
- { HOTKEY_INSERT, LANG_INSERT,
- HOTKEY_FUNC(playlist_insert_func, (intptr_t*)PLAYLIST_INSERT),
- ONPLAY_RELOAD_DIR },
- { HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
- HOTKEY_FUNC(playlist_insert_shuffled, NULL),
- ONPLAY_RELOAD_DIR },
- { HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
- HOTKEY_FUNC(hotkey_run_plugin, NULL),
- ONPLAY_OK },
- { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
- HOTKEY_FUNC(bookmark_create_menu, NULL),
- ONPLAY_OK },
};
-/* Return the language ID for this action */
-int get_hotkey_lang_id(int action)
+const struct hotkey_assignment *get_hotkey(int action)
{
- int i = ARRAYLEN(hotkey_items);
- while (i--)
+ for (size_t i = ARRAYLEN(hotkey_items) - 1; i < ARRAYLEN(hotkey_items); i--)
{
if (hotkey_items[i].action == action)
- return hotkey_items[i].lang_id;
+ return &hotkey_items[i];
}
-
- return LANG_OFF;
+ return &hotkey_items[0]; /* no valid hotkey set, return HOTKEY_OFF*/
}
/* Execute the hotkey function, if listed */
static int execute_hotkey(bool is_wps)
{
- int i = ARRAYLEN(hotkey_items);
- struct hotkey_assignment *this_item;
const int action = (is_wps ? global_settings.hotkey_wps :
- global_settings.hotkey_tree);
+ global_settings.hotkey_tree);
/* search assignment struct for a match for the hotkey setting */
- while (i--)
+ const struct hotkey_assignment *this_item = get_hotkey(action);
+
+ /* run the associated function (with optional param), if any */
+ const struct menu_func_param func = this_item->func;
+
+ int func_return = ONPLAY_RELOAD_DIR;
+ if (func.function != NULL)
{
- this_item = &hotkey_items[i];
- if (this_item->action == action)
- {
- /* run the associated function (with optional param), if any */
- const struct menu_func func = this_item->func;
- int func_return = ONPLAY_RELOAD_DIR;
- if (func.function != NULL)
- {
- if (func.param != NULL)
- func_return = (*func.function_w_param)(func.param);
- else
- func_return = (*func.function)();
- }
- /* return with the associated code */
- const int return_code = this_item->return_code;
- /* ONPLAY_OK here means to use the function return code */
- if (return_code == ONPLAY_OK)
- return func_return;
- return return_code;
- }
+ if (func.param != NULL)
+ func_return = (*func.function_w_param)(func.param);
+ else
+ func_return = (*func.function)();
}
+ const int return_code = this_item->return_code;
- /* no valid hotkey set, ignore hotkey */
- return ONPLAY_RELOAD_DIR;
+ if (return_code == ONPLAY_FUNC_RETURN)
+ return func_return; /* Use value returned by function */
+ return return_code; /* or return the associated value */
}
#endif /* HOTKEY */
@@ -1922,12 +1736,31 @@ int onplay(char* file, int attr, int from, bool hotkey)
const struct menu_item_ex *menu;
onplay_result = ONPLAY_OK;
context = from;
- if (file == NULL)
- selected_file = NULL;
- else
+ ctx_current_playlist_insert = NULL;
+ selected_file = NULL;
+#ifdef HAVE_TAGCACHE
+ if (context == CONTEXT_ID3DB &&
+ (attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
{
- strlcpy(selected_file_path, file, MAX_PATH);
- selected_file = selected_file_path;
+ ctx_add_to_playlist = tagtree_add_to_playlist;
+ if (file != NULL)
+ {
+ /* add a leading slash so that catalog_add_to_a_playlist
+ later prefills the name when creating a new playlist */
+ snprintf(selected_file_path, MAX_PATH, "/%s", file);
+ selected_file = selected_file_path;
+ }
+ }
+ else
+#endif
+ {
+ ctx_add_to_playlist = NULL;
+ if (file != NULL)
+ {
+ strmemccpy(selected_file_path, file, MAX_PATH);
+ selected_file = selected_file_path;
+ }
+
}
selected_file_attr = attr;
int menu_selection;
@@ -1944,7 +1777,9 @@ int onplay(char* file, int attr, int from, bool hotkey)
else
menu = &tree_onplay_menu;
menu_selection = do_menu(menu, NULL, NULL, false);
- pop_current_activity();
+
+ if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */
+ pop_current_activity(); /* popped already by menu item */
switch (menu_selection)
{
@@ -1961,3 +1796,9 @@ int onplay(char* file, int attr, int from, bool hotkey)
return onplay_result;
}
}
+
+int get_onplay_context(void)
+{
+ return context;
+}
+