/* drawer function for the GUI_EVENT_REDRAW callback */ void tree_drawlists(void) { /* band-aid to fix the bar/list redrawing properly after leaving a plugin */ send_event(GUI_EVENT_THEME_CHANGED, NULL); /* end bandaid */ gui_synclist_draw(&tree_lists); }
void browse_cuesheet(struct cuesheet *cue) { struct gui_synclist lists; int action; bool done = false; int sel; char title[MAX_PATH]; char cuepath[MAX_PATH]; struct mp3entry *id3 = audio_current_track(); snprintf(title, MAX_PATH, "%s: %s", cue->performer, cue->title); gui_synclist_init(&lists, list_get_name_cb, cue, false, 2, NULL); gui_synclist_set_nb_items(&lists, 2*cue->track_count); gui_synclist_set_title(&lists, title, 0); if (id3) { gui_synclist_select_item(&lists, 2*cue_find_current_track(cue, id3->elapsed)); } while (!done) { gui_synclist_draw(&lists); action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK); if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD)) continue; switch (action) { case ACTION_STD_OK: id3 = audio_current_track(); if (id3 && *id3->path && strcmp(id3->path, "No file!")) { look_for_cuesheet_file(id3->path, cuepath); if (id3->cuesheet && !strcmp(cue->path, cuepath)) { sel = gui_synclist_get_sel_pos(&lists); seek(cue->tracks[sel/2].offset); } } break; case ACTION_STD_CANCEL: done = true; } } }
/* ------------------------------------------------------------------------*/ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume, char** selected_bookmark) { struct bookmark_list* bookmarks; struct gui_synclist list; int item = 0; int action; size_t size; bool exit = false; bool refresh = true; int ret = BOOKMARK_FAIL; bookmarks = plugin_get_buffer(&size); bookmarks->buffer_size = size; bookmarks->show_dont_resume = show_dont_resume; bookmarks->filename = bookmark_file_name; bookmarks->start = 0; bookmarks->show_playlist_name = strcmp(bookmark_file_name, RECENT_BOOKMARK_FILE) == 0; gui_synclist_init(&list, &get_bookmark_info, (void*) bookmarks, false, 2, NULL); if(global_settings.talk_menu) gui_synclist_set_voice_callback(&list, bookmark_list_voice_cb); gui_synclist_set_title(&list, str(LANG_BOOKMARK_SELECT_BOOKMARK), Icon_Bookmark); while (!exit) { if (refresh) { int count = get_bookmark_count(bookmark_file_name); bookmarks->total_count = count; if (bookmarks->total_count < 1) { /* No more bookmarks, delete file and exit */ splash(HZ, ID2P(LANG_BOOKMARK_LOAD_EMPTY)); remove(bookmark_file_name); *selected_bookmark = NULL; return BOOKMARK_FAIL; } if (bookmarks->show_dont_resume) { count++; item++; } gui_synclist_set_nb_items(&list, count * 2); if (item >= count) { /* Selected item has been deleted */ item = count - 1; gui_synclist_select_item(&list, item * 2); } buffer_bookmarks(bookmarks, bookmarks->start); gui_synclist_draw(&list); cond_talk_ids_fq(VOICE_EXT_BMARK); gui_synclist_speak_item(&list); refresh = false; } list_do_action(CONTEXT_BOOKMARKSCREEN, HZ / 2, &list, &action, LIST_WRAP_UNLESS_HELD); item = gui_synclist_get_sel_pos(&list) / 2; if (bookmarks->show_dont_resume) { item--; } if (action == ACTION_STD_CONTEXT) { MENUITEM_STRINGLIST(menu_items, ID2P(LANG_BOOKMARK_CONTEXT_MENU), NULL, ID2P(LANG_BOOKMARK_CONTEXT_RESUME), ID2P(LANG_BOOKMARK_CONTEXT_DELETE)); static const int menu_actions[] = { ACTION_STD_OK, ACTION_BMS_DELETE }; int selection = do_menu(&menu_items, NULL, NULL, false); refresh = true; if (selection >= 0 && selection <= (int) (sizeof(menu_actions) / sizeof(menu_actions[0]))) { action = menu_actions[selection]; } } switch (action) { case ACTION_STD_OK: if (item >= 0) { talk_shutup(); *selected_bookmark = bookmarks->items[item - bookmarks->start]; return BOOKMARK_SUCCESS; } exit = true; ret = BOOKMARK_SUCCESS; break; case ACTION_TREE_WPS: case ACTION_STD_CANCEL: exit = true; break; case ACTION_BMS_DELETE: if (item >= 0) { const char *lines[]={ ID2P(LANG_REALLY_DELETE) }; const char *yes_lines[]={ ID2P(LANG_DELETING) }; const struct text_message message={lines, 1}; const struct text_message yes_message={yes_lines, 1}; if(gui_syncyesno_run(&message, &yes_message, NULL)==YESNO_YES) { delete_bookmark(bookmark_file_name, item); bookmarks->reload = true; } refresh = true; } break; default: if (default_event_handler(action) == SYS_USB_CONNECTED) { ret = BOOKMARK_USB_CONNECTED; exit = true; } break; } } talk_shutup(); *selected_bookmark = NULL; return ret; }
/* main loop, handles key events */ static int dirbrowse(void) { int numentries=0; char buf[MAX_PATH]; int button, oldbutton; bool reload_root = false; int lastfilter = *tc.dirfilter; bool lastsortcase = global_settings.sort_case; bool exit_func = false; char* currdir = tc.currdir; /* just a shortcut */ #ifdef HAVE_TAGCACHE bool id3db = *tc.dirfilter == SHOW_ID3DB; if (id3db) curr_context=CONTEXT_ID3DB; else #endif curr_context=CONTEXT_TREE; if (tc.selected_item < 0) tc.selected_item = 0; #ifdef HAVE_TAGCACHE tc.firstpos = 0; lasttable = -1; lastextra = -1; lastfirstpos = 0; #endif start_wps = false; numentries = update_dir(); reload_dir = false; if (numentries == -1) return GO_TO_PREVIOUS; /* currdir is not a directory */ if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0) { splash(HZ*2, ID2P(LANG_NO_FILES)); return GO_TO_PREVIOUS; /* No files found for rockbox_browse() */ } gui_synclist_draw(&tree_lists); while(1) { bool restore = false; if (tc.dirlevel < 0) tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */ button = get_action(CONTEXT_TREE, list_do_action_timeout(&tree_lists, HZ/2)); oldbutton = button; gui_synclist_do_button(&tree_lists, &button,LIST_WRAP_UNLESS_HELD); tc.selected_item = gui_synclist_get_sel_pos(&tree_lists); switch ( button ) { case ACTION_STD_OK: /* nothing to do if no files to display */ if ( numentries == 0 ) break; short attr = tree_get_entry_at(&tc, tc.selected_item)->attr; if ((tc.browse->flags & BROWSE_SELECTONLY) && !(attr & ATTR_DIRECTORY)) { tc.browse->flags |= BROWSE_SELECTED; get_current_file(tc.browse->buf, tc.browse->bufsize); return GO_TO_PREVIOUS; } #ifdef HAVE_TAGCACHE switch (id3db?tagtree_enter(&tc):ft_enter(&tc)) #else switch (ft_enter(&tc)) #endif { case GO_TO_FILEBROWSER: reload_dir = true; break; case GO_TO_WPS: return GO_TO_WPS; #if CONFIG_TUNER case GO_TO_FM: return GO_TO_FM; #endif case GO_TO_ROOT: exit_func = true; break; default: break; } restore = true; break; case ACTION_STD_CANCEL: if (*tc.dirfilter > NUM_FILTER_MODES && tc.dirlevel < 1) { exit_func = true; break; } if ((*tc.dirfilter == SHOW_ID3DB && tc.dirlevel == 0) || ((*tc.dirfilter != SHOW_ID3DB && !strcmp(currdir,"/")))) { #ifdef HAVE_LCD_BITMAP /* charcell doesnt have ACTION_TREE_PGLEFT so this isnt needed */ if (oldbutton == ACTION_TREE_PGLEFT) break; else #endif return GO_TO_ROOT; } #ifdef HAVE_TAGCACHE if (id3db) tagtree_exit(&tc); else #endif if (ft_exit(&tc) == 3) exit_func = true; restore = true; break; case ACTION_TREE_STOP: if (list_stop_handler()) restore = true; break; case ACTION_STD_MENU: return GO_TO_ROOT; break; #ifdef HAVE_RECORDING case ACTION_STD_REC: return GO_TO_RECSCREEN; #endif case ACTION_TREE_WPS: return GO_TO_PREVIOUS_MUSIC; break; #ifdef HAVE_QUICKSCREEN case ACTION_STD_QUICKSCREEN: /* don't enter f2 from plugin browser */ if (*tc.dirfilter < NUM_FILTER_MODES) { if (quick_screen_quick(button)) reload_dir = true; restore = true; } break; #endif #ifdef BUTTON_F3 case ACTION_F3: /* don't enter f3 from plugin browser */ if (*tc.dirfilter < NUM_FILTER_MODES) { if (quick_screen_f3(ACTION_F3)) reload_dir = true; restore = true; } break; #endif #ifdef HAVE_HOTKEY case ACTION_TREE_HOTKEY: if (!global_settings.hotkey_tree) break; /* fall through */ #endif case ACTION_STD_CONTEXT: { bool hotkey = button == ACTION_TREE_HOTKEY; int onplay_result; int attr = 0; if (tc.browse->flags & BROWSE_NO_CONTEXT_MENU) break; if(!numentries) onplay_result = onplay(NULL, 0, curr_context, hotkey); else { #ifdef HAVE_TAGCACHE if (id3db) { if (tagtree_get_attr(&tc) == FILE_ATTR_AUDIO) { attr = FILE_ATTR_AUDIO; tagtree_get_filename(&tc, buf, sizeof(buf)); } else attr = ATTR_DIRECTORY; } else #endif { struct entry *entry = tree_get_entry_at(&tc, tc.selected_item); attr = entry->attr; if (currdir[1]) /* Not in / */ snprintf(buf, sizeof buf, "%s/%s", currdir, entry->name); else /* In / */ snprintf(buf, sizeof buf, "/%s", entry->name); } onplay_result = onplay(buf, attr, curr_context, hotkey); } switch (onplay_result) { case ONPLAY_MAINMENU: return GO_TO_ROOT; case ONPLAY_OK: restore = true; break; case ONPLAY_RELOAD_DIR: reload_dir = true; break; case ONPLAY_START_PLAY: return GO_TO_WPS; break; } break; } #ifdef HAVE_HOTSWAP case SYS_FS_CHANGED: #ifdef HAVE_TAGCACHE if (!id3db) #endif reload_dir = true; /* The 'dir no longer valid' situation will be caught later * by checking the showdir() result. */ break; #endif default: if (default_event_handler(button) == SYS_USB_CONNECTED) { if(*tc.dirfilter > NUM_FILTER_MODES) /* leave sub-browsers after usb, doing otherwise might be confusing to the user */ exit_func = true; else reload_dir = true; } break; } if (start_wps) return GO_TO_WPS; if (button && !IS_SYSEVENT(button)) { storage_spin(); } check_rescan: /* do we need to rescan dir? */ if (reload_dir || reload_root || lastfilter != *tc.dirfilter || lastsortcase != global_settings.sort_case) { if (reload_root) { strcpy(currdir, "/"); tc.dirlevel = 0; #ifdef HAVE_TAGCACHE tc.currtable = 0; tc.currextra = 0; lasttable = -1; lastextra = -1; #endif reload_root = false; } if (!reload_dir) { gui_synclist_select_item(&tree_lists, 0); gui_synclist_draw(&tree_lists); tc.selected_item = 0; lastdir[0] = 0; } lastfilter = *tc.dirfilter; lastsortcase = global_settings.sort_case; restore = true; } if (exit_func) return GO_TO_PREVIOUS; if (restore || reload_dir) { /* restore display */ numentries = update_dir(); reload_dir = false; if (currdir[1] && (numentries < 0)) { /* not in root and reload failed */ reload_root = true; /* try root */ goto check_rescan; } } } return true; }
/* * Called when a new dir is loaded (for example when returning from other apps ...) * also completely redraws the tree */ static int update_dir(void) { bool changed = false; #ifdef HAVE_TAGCACHE bool id3db = *tc.dirfilter == SHOW_ID3DB; /* Checks for changes */ if (id3db) { if (tc.currtable != lasttable || tc.currextra != lastextra || tc.firstpos != lastfirstpos || reload_dir) { if (tagtree_load(&tc) < 0) return -1; lasttable = tc.currtable; lastextra = tc.currextra; lastfirstpos = tc.firstpos; changed = true; } } else #endif { /* if the tc.currdir has been changed, reload it ...*/ if (strncmp(tc.currdir, lastdir, sizeof(lastdir)) || reload_dir) { if (ft_load(&tc, NULL) < 0) return -1; strcpy(lastdir, tc.currdir); changed = true; } } /* if selected item is undefined */ if (tc.selected_item == -1) { /* use lastfile to determine the selected item */ tc.selected_item = tree_get_file_position(lastfile); /* If the file doesn't exists, select the first one (default) */ if(tc.selected_item < 0) tc.selected_item = 0; changed = true; } if (changed) { if( #ifdef HAVE_TAGCACHE !id3db && #endif tc.dirfull ) { splash(HZ, ID2P(LANG_SHOWDIR_BUFFER_FULL)); } } #ifdef HAVE_TAGCACHE if (id3db) { #ifdef HAVE_LCD_BITMAP if (global_settings.show_path_in_browser == SHOW_PATH_FULL || global_settings.show_path_in_browser == SHOW_PATH_CURRENT) { gui_synclist_set_title(&tree_lists, tagtree_get_title(&tc), filetype_get_icon(ATTR_DIRECTORY)); } else { /* Must clear the title as the list is reused */ gui_synclist_set_title(&tree_lists, NULL, NOICON); } #endif } else #endif { #ifdef HAVE_LCD_BITMAP if (tc.browse && tc.browse->title) { int icon = tc.browse->icon; if (icon == NOICON) icon = filetype_get_icon(ATTR_DIRECTORY); gui_synclist_set_title(&tree_lists, tc.browse->title, icon); } else if (global_settings.show_path_in_browser == SHOW_PATH_FULL) { gui_synclist_set_title(&tree_lists, tc.currdir, filetype_get_icon(ATTR_DIRECTORY)); } else if (global_settings.show_path_in_browser == SHOW_PATH_CURRENT) { char *title = strrchr(tc.currdir, '/') + 1; if (*title == '\0') { /* Display "Files" for the root dir */ gui_synclist_set_title(&tree_lists, str(LANG_DIR_BROWSER), filetype_get_icon(ATTR_DIRECTORY)); } else gui_synclist_set_title(&tree_lists, title, filetype_get_icon(ATTR_DIRECTORY)); } else { /* Must clear the title as the list is reused */ gui_synclist_set_title(&tree_lists, NULL, NOICON); } #endif } gui_synclist_set_nb_items(&tree_lists, tc.filesindir); gui_synclist_set_icon_callback(&tree_lists, global_settings.show_icons?tree_get_fileicon:NULL); if( tc.selected_item >= tc.filesindir) tc.selected_item=tc.filesindir-1; gui_synclist_select_item(&tree_lists, tc.selected_item); #ifdef HAVE_BUTTONBAR if (global_settings.buttonbar) { if (*tc.dirfilter < NUM_FILTER_MODES) gui_buttonbar_set(&tree_buttonbar, str(LANG_SYSFONT_DIRBROWSE_F1), str(LANG_SYSFONT_DIRBROWSE_F2), str(LANG_SYSFONT_DIRBROWSE_F3)); else gui_buttonbar_set(&tree_buttonbar, "<<<", "", ""); gui_buttonbar_draw(&tree_buttonbar); } #endif gui_synclist_draw(&tree_lists); gui_synclist_speak_item(&tree_lists); return tc.filesindir; }
bool option_screen(const struct settings_list *setting, struct viewport parent[NB_SCREENS], bool use_temp_var, unsigned char* option_title) { int action; bool done = false; struct gui_synclist lists; int oldvalue, nb_items = 0, selected = 0, temp_var; int *variable; bool allow_wrap = setting->flags & F_NO_WRAP ? false : true; int var_type = setting->flags&F_T_MASK; void (*function)(int) = NULL; char *title; if (var_type == F_T_INT || var_type == F_T_UINT) { variable = use_temp_var ? &temp_var: (int*)setting->setting; temp_var = oldvalue = *(int*)setting->setting; } else if (var_type == F_T_BOOL) { /* bools always use the temp variable... if use_temp_var is false it will be copied to setting->setting every change */ variable = &temp_var; temp_var = oldvalue = *(bool*)setting->setting?1:0; } else return false; /* only int/bools can go here */ gui_synclist_init(&lists, value_setting_get_name_cb, (void*)setting, false, 1, parent); if (setting->lang_id == -1) title = (char*)setting->cfg_vals; else title = P2STR(option_title); gui_synclist_set_title(&lists, title, Icon_Questionmark); gui_synclist_set_icon_callback(&lists, NULL); if(global_settings.talk_menu) gui_synclist_set_voice_callback(&lists, option_talk); val_to_selection(setting, oldvalue, &nb_items, &selected, &function); gui_synclist_set_nb_items(&lists, nb_items); gui_synclist_select_item(&lists, selected); gui_synclist_limit_scroll(&lists, true); gui_synclist_draw(&lists); /* talk the item */ gui_synclist_speak_item(&lists); while (!done) { if (list_do_action(CONTEXT_LIST, HZ, /* HZ so the status bar redraws */ &lists, &action, allow_wrap? LIST_WRAP_UNLESS_HELD: LIST_WRAP_OFF)) { /* setting changed */ selected = gui_synclist_get_sel_pos(&lists); *variable = selection_to_val(setting, selected); if (var_type == F_T_BOOL && !use_temp_var) *(bool*)setting->setting = (*variable==1); } else if (action == ACTION_NONE) continue; else if (action == ACTION_STD_CANCEL) { /* setting canceled, restore old value if changed */ if (*variable != oldvalue) { *variable = oldvalue; if (var_type == F_T_BOOL && !use_temp_var) *(bool*)setting->setting = (oldvalue==1); splash(HZ/2, ID2P(LANG_CANCEL)); } done = true; } else if (action == ACTION_STD_CONTEXT) { /* reset setting to default */ reset_setting(setting, variable); if (var_type == F_T_BOOL && !use_temp_var) *(bool*)setting->setting = (*variable==1); val_to_selection(setting, *variable, &nb_items, &selected, &function); gui_synclist_select_item(&lists, selected); gui_synclist_draw(&lists); gui_synclist_speak_item(&lists); } else if (action == ACTION_STD_OK) { /* setting accepted, store now if it used a temp var */ if (use_temp_var) { if (var_type == F_T_INT || var_type == F_T_UINT) *(int*)setting->setting = *variable; else *(bool*)setting->setting = (*variable==1); } settings_save(); done = true; } else if(default_event_handler(action) == SYS_USB_CONNECTED) return true; /* callback */ if ( function ) function(*variable); /* if the volume is changing we need to let the skins know */ if (function == sound_get_fn(SOUND_VOLUME)) global_status.last_volume_change = current_tick; } return false; }
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; }