/* Update playlist in case something has changed or forced */ static bool update_playlist(bool force) { if (!viewer.playlist) playlist_get_resume_info(&viewer.current_playing_track); else viewer.current_playing_track = -1; int nb_tracks = playlist_amount_ex(viewer.playlist); force = force || nb_tracks != viewer.num_tracks; if (force) { /* Reload tracks */ viewer.num_tracks = nb_tracks; if (viewer.num_tracks <= 0) { global_status.resume_index = -1; global_status.resume_offset = -1; return false; } playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD); if (viewer.buffer.num_loaded <= 0) { global_status.resume_index = -1; global_status.resume_offset = -1; return false; } } return true; }
int playlist_amount(void) { return playlist_amount_ex(NULL); }
bool search_playlist(void) { char search_str[32] = ""; bool ret = false, exit = false; int i, playlist_count; int found_indicies[MAX_PLAYLIST_ENTRIES]; int found_indicies_count = 0, last_found_count = -1; int button; struct gui_synclist playlist_lists; struct playlist_track_info track; if (!playlist_viewer_init(&viewer, 0, false)) return ret; if (kbd_input(search_str, sizeof(search_str)) < 0) return ret; lcd_clear_display(); playlist_count = playlist_amount_ex(viewer.playlist); cpu_boost(true); for (i = 0; i < playlist_count && found_indicies_count < MAX_PLAYLIST_ENTRIES; i++) { if (found_indicies_count != last_found_count) { splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), found_indicies_count, str(LANG_OFF_ABORT)); last_found_count = found_indicies_count; } if (action_userabort(TIMEOUT_NOBLOCK)) break; playlist_get_track_info(viewer.playlist, i, &track); if (strcasestr(track.filename,search_str)) found_indicies[found_indicies_count++] = track.index; yield(); } cpu_boost(false); if (!found_indicies_count) { return ret; } backlight_on(); gui_synclist_init(&playlist_lists, playlist_search_callback_name, found_indicies, false, 1, NULL); gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON); gui_synclist_set_icon_callback(&playlist_lists, NULL); gui_synclist_set_nb_items(&playlist_lists, found_indicies_count); gui_synclist_select_item(&playlist_lists, 0); gui_synclist_draw(&playlist_lists); while (!exit) { if (list_do_action(CONTEXT_LIST, HZ/4, &playlist_lists, &button, LIST_WRAP_UNLESS_HELD)) continue; switch (button) { case ACTION_STD_CANCEL: exit = true; break; case ACTION_STD_OK: { int sel = gui_synclist_get_sel_pos(&playlist_lists); playlist_start(found_indicies[sel], 0); exit = 1; } break; default: if (default_event_handler(button) == SYS_USB_CONNECTED) { ret = true; exit = true; } break; } } return ret; }
/* Main viewer function. Filename identifies playlist to be viewed. If NULL, view current playlist. */ enum playlist_viewer_result playlist_viewer_ex(const char* filename) { enum playlist_viewer_result ret = PLAYLIST_VIEWER_OK; bool exit = false; /* exit viewer */ int button; bool dirty = false; struct gui_synclist playlist_lists; if (!playlist_viewer_init(&viewer, filename, false)) goto exit; push_current_activity(ACTIVITY_PLAYLISTVIEWER); gui_synclist_init(&playlist_lists, playlist_callback_name, &viewer, false, 1, NULL); gui_synclist_set_voice_callback(&playlist_lists, playlist_callback_voice); gui_synclist_set_icon_callback(&playlist_lists, global_settings.playlist_viewer_icons? &playlist_callback_icons:NULL); gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks); gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist); gui_synclist_select_item(&playlist_lists, viewer.selected_track); gui_synclist_draw(&playlist_lists); gui_synclist_speak_item(&playlist_lists); while (!exit) { int track; if (global_status.resume_index != -1 && !viewer.playlist) playlist_get_resume_info(&track); else track = -1; if (track != viewer.current_playing_track || playlist_amount_ex(viewer.playlist) != viewer.num_tracks) { /* Playlist has changed (new track started?) */ if (!update_playlist(false)) goto exit; /*Needed because update_playlist gives wrong value when playing is stopped*/ viewer.current_playing_track = track; gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks); gui_synclist_draw(&playlist_lists); } /* Timeout so we can determine if play status has changed */ bool res = list_do_action(CONTEXT_TREE, HZ/2, &playlist_lists, &button, LIST_WRAP_UNLESS_HELD); /* during moving, another redraw is going to be needed, * since viewer.selected_track is updated too late (after the first draw) * drawing the moving item needs it */ viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists); if (res) { bool reload = playlist_buffer_needs_reload(&viewer.buffer, viewer.selected_track); if (reload) playlist_buffer_load_entries_screen(&viewer.buffer, button == ACTION_STD_NEXT ? FORWARD : BACKWARD); if (reload || viewer.moving_track >= 0) gui_synclist_draw(&playlist_lists); } switch (button) { case ACTION_TREE_WPS: case ACTION_STD_CANCEL: { if (viewer.moving_track >= 0) { viewer.selected_track = viewer.moving_track; gui_synclist_select_item(&playlist_lists, viewer.moving_track); viewer.moving_track = -1; viewer.moving_playlist_index = -1; gui_synclist_draw(&playlist_lists); } else { exit = true; ret = PLAYLIST_VIEWER_CANCEL; } break; } case ACTION_STD_OK: { struct playlist_entry * current_track = playlist_buffer_get_track(&viewer.buffer, viewer.selected_track); if (viewer.moving_track >= 0) { /* Move track */ int ret_val; ret_val = playlist_move(viewer.playlist, viewer.moving_playlist_index, current_track->index); if (ret_val < 0) splashf(HZ, (unsigned char *)"%s %s", str(LANG_MOVE), str(LANG_FAILED)); update_playlist(true); viewer.moving_track = -1; viewer.moving_playlist_index = -1; dirty = true; } else if (!viewer.playlist) { /* play new track */ if (!global_settings.party_mode) { playlist_start(current_track->index, 0); update_playlist(false); } } else if (!global_settings.party_mode) { int start_index = current_track->index; if (!warn_on_pl_erase()) { gui_synclist_draw(&playlist_lists); break; } /* New playlist */ if (playlist_set_current(viewer.playlist) < 0) goto exit; if (global_settings.playlist_shuffle) start_index = playlist_shuffle(current_tick, start_index); playlist_start(start_index, 0); /* Our playlist is now the current list */ if (!playlist_viewer_init(&viewer, NULL, true)) goto exit; exit = true; } gui_synclist_draw(&playlist_lists); break; } case ACTION_STD_CONTEXT: { /* ON+PLAY menu */ int ret_val; ret_val = onplay_menu(viewer.selected_track); if (ret_val < 0) { ret = PLAYLIST_VIEWER_USB; goto exit; } else if (ret_val > 0) { /* Playlist changed */ gui_synclist_del_item(&playlist_lists); update_playlist(true); if (viewer.num_tracks <= 0) exit = true; if (viewer.selected_track >= viewer.num_tracks) viewer.selected_track = viewer.num_tracks-1; dirty = true; } gui_synclist_draw(&playlist_lists); break; } case ACTION_STD_MENU: ret = PLAYLIST_VIEWER_MAINMENU; goto exit; default: if(default_event_handler(button) == SYS_USB_CONNECTED) { ret = PLAYLIST_VIEWER_USB; goto exit; } break; } } exit: pop_current_activity(); if (viewer.playlist) { if(dirty && yesno_pop(ID2P(LANG_SAVE_CHANGES))) save_playlist_screen(viewer.playlist); playlist_close(viewer.playlist); } return ret; }
/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen. Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist changed. */ static int onplay_menu(int index) { int result, ret = 0; struct playlist_entry * current_track = playlist_buffer_get_track(&viewer.buffer, index); MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL, ID2P(LANG_CURRENT_PLAYLIST), ID2P(LANG_CATALOG), ID2P(LANG_REMOVE), ID2P(LANG_MOVE), ID2P(LANG_SHUFFLE), ID2P(LANG_SAVE_DYNAMIC_PLAYLIST)); bool current = (current_track->index == viewer.current_playing_track); result = do_menu(&menu_items, NULL, NULL, false); if (result == MENU_ATTACHED_USB) { ret = -1; } else if (result >= 0) { /* Abort current move */ viewer.moving_track = -1; viewer.moving_playlist_index = -1; switch (result) { case 0: /* playlist */ onplay_show_playlist_menu(current_track->name); ret = 0; break; case 1: /* add to catalog */ onplay_show_playlist_cat_menu(current_track->name); ret = 0; break; case 2: /* delete track */ playlist_delete(viewer.playlist, current_track->index); if (current) { if (playlist_amount_ex(viewer.playlist) <= 0) audio_stop(); else { /* Start playing new track except if it's the lasttrack track in the playlist and repeat mode is disabled */ current_track = playlist_buffer_get_track(&viewer.buffer, index); if (current_track->display_index!=viewer.num_tracks || global_settings.repeat_mode == REPEAT_ALL) { audio_play(0); viewer.current_playing_track = -1; } } } ret = 1; break; case 3: /* move track */ viewer.moving_track = index; viewer.moving_playlist_index = current_track->index; ret = 0; break; case 4: /* shuffle */ playlist_randomise(viewer.playlist, current_tick, false); ret = 1; break; case 5: /* save playlist */ save_playlist_screen(viewer.playlist); ret = 0; break; } } return ret; }
/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen. Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist changed. */ static int onplay_menu(int index) { int result, ret = 0; struct playlist_entry * current_track= playlist_buffer_get_track(&viewer.buffer, index); MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL, ID2P(LANG_REMOVE), ID2P(LANG_MOVE), ID2P(LANG_CATALOG_ADD_TO), ID2P(LANG_CATALOG_ADD_TO_NEW), ID2P(LANG_PLAYLISTVIEWER_SETTINGS)); bool current = (current_track->index == viewer.current_playing_track); result = do_menu(&menu_items, NULL, NULL, false); if (result == MENU_ATTACHED_USB) { ret = -1; } else if (result >= 0) { /* Abort current move */ viewer.moving_track = -1; viewer.moving_playlist_index = -1; switch (result) { case 0: /* delete track */ playlist_delete(viewer.playlist, current_track->index); if (current) { if (playlist_amount_ex(viewer.playlist) <= 0) audio_stop(); else { /* Start playing new track except if it's the lasttrack track in the playlist and repeat mode is disabled */ current_track = playlist_buffer_get_track(&viewer.buffer, index); if (current_track->display_index!=viewer.num_tracks || global_settings.repeat_mode == REPEAT_ALL) { #if CONFIG_CODEC != SWCODEC talk_buffer_steal(); /* will use the mp3 buffer */ #endif audio_play(0); viewer.current_playing_track = -1; } } } ret = 1; break; case 1: /* move track */ viewer.moving_track = index; viewer.moving_playlist_index = current_track->index; ret = 0; break; case 2: /* add to catalog */ case 3: /* add to a new one */ catalog_add_to_a_playlist(current_track->name, FILE_ATTR_AUDIO, result==3, NULL); ret = 0; break; case 4: /* playlist viewer settings */ /* true on usb connect */ ret = viewer_menu() ? -1 : 0; break; } } return ret; }