Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / playlist_viewer.c
blob7c73b2bad921947efab970f2a8225c77247d2eab
1 /***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
11 * Copyright (C) 2003 Hardeep Sidhu
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
21 * Kevin Ferrare 2005/10/16
22 * multi-screen support, rewrote a lot of code
24 #include <string.h>
25 #include <sprintf.h>
26 #include "playlist.h"
27 #include "audio.h"
28 #include "screens.h"
29 #include "status.h"
30 #include "settings.h"
31 #include "icons.h"
32 #include "menu.h"
33 #include "plugin.h"
34 #include "keyboard.h"
35 #include "tree.h"
36 #include "onplay.h"
37 #include "talk.h"
38 #include "misc.h"
39 #include "action.h"
40 #include "debug.h"
41 #include "backlight.h"
43 #include "lang.h"
45 #include "playlist_viewer.h"
46 #include "icon.h"
47 #include "list.h"
48 #include "statusbar.h"
49 #include "splash.h"
50 #include "playlist_menu.h"
51 #include "action.h"
53 /* Maximum number of tracks we can have loaded at one time */
54 #define MAX_PLAYLIST_ENTRIES 200
56 /* The number of items between the selected one and the end/start of
57 * the buffer under which the buffer must reload */
58 #define MIN_BUFFER_MARGIN (screens[0].nb_lines+1)
60 /* Default playlist name for saving */
61 #define DEFAULT_VIEWER_PLAYLIST_NAME "/viewer.m3u"
64 /* Information about a specific track */
65 struct playlist_entry {
66 char *name; /* Formatted track name */
67 int index; /* Playlist index */
68 int display_index; /* Display index */
69 bool queued; /* Is track queued? */
70 bool skipped; /* Is track marked as bad? */
73 enum direction
75 FORWARD,
76 BACKWARD
79 struct playlist_buffer
81 char *name_buffer; /* Buffer used to store track names */
82 int buffer_size; /* Size of name buffer */
84 int first_index; /* Real index of first track loaded inside
85 the buffer */
87 enum direction direction; /* Direction of the buffer (if the buffer
88 was loaded BACKWARD, the last track in
89 the buffer has a real index < to the
90 real index of the the first track)*/
92 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
93 int num_loaded; /* Number of track entries loaded in buffer */
96 /* Global playlist viewer settings */
97 struct playlist_viewer {
98 struct playlist_info* playlist; /* playlist being viewed */
99 int num_tracks; /* Number of tracks in playlist */
100 int current_playing_track; /* Index of current playing track */
101 int selected_track; /* The selected track, relative (first is 0)*/
102 int move_track; /* Playlist index of track to move or -1 */
103 struct playlist_buffer buffer;
106 static struct playlist_viewer viewer;
108 /* Used when viewing playlists on disk */
109 static struct playlist_info temp_playlist;
111 void playlist_buffer_init(struct playlist_buffer * pb, char * names_buffer,
112 int names_buffer_size);
113 void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
114 enum direction direction);
115 int playlist_entry_load(struct playlist_entry *entry, int index,
116 char* name_buffer, int remaining_size);
118 struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer * pb,
119 int index);
121 static bool playlist_viewer_init(struct playlist_viewer * viewer,
122 char* filename, bool reload);
124 static void format_name(char* dest, const char* src);
125 static void format_line(const struct playlist_entry* track, char* str,
126 int len);
128 static bool update_playlist(bool force);
129 static int onplay_menu(int index);
130 static bool viewer_menu(void);
131 static bool show_icons(void);
132 static bool show_indices(void);
133 static bool track_display(void);
134 static bool save_playlist(void);
136 void playlist_buffer_init(struct playlist_buffer * pb, char * names_buffer,
137 int names_buffer_size)
139 pb->name_buffer=names_buffer;
140 pb->buffer_size=names_buffer_size;
141 pb->first_index=0;
142 pb->num_loaded=0;
146 * Loads the entries following 'index' in the playlist buffer
148 void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
149 enum direction direction)
151 int num_entries = viewer.num_tracks;
152 char* p = pb->name_buffer;
153 int remaining = pb->buffer_size;
154 int i;
156 pb->first_index = index;
157 if (num_entries > MAX_PLAYLIST_ENTRIES)
158 num_entries = MAX_PLAYLIST_ENTRIES;
160 for(i=0; i<num_entries; i++)
162 int len = playlist_entry_load(&(pb->tracks[i]), index, p, remaining);
163 if (len < 0)
165 /* Out of name buffer space */
166 num_entries = i;
167 break;
170 p += len;
171 remaining -= len;
173 if(direction==FORWARD)
174 index++;
175 else
176 index--;
177 index+=viewer.num_tracks;
178 index%=viewer.num_tracks;
180 pb->direction=direction;
181 pb->num_loaded = i;
184 void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
185 enum direction direction)
187 if(direction==FORWARD)
189 int min_start=viewer.selected_track-2*screens[0].nb_lines;
190 while(min_start<0)
191 min_start+=viewer.num_tracks;
192 min_start %= viewer.num_tracks;
193 playlist_buffer_load_entries(pb, min_start, FORWARD);
195 else
197 int max_start=viewer.selected_track+2*screens[0].nb_lines;
198 max_start%=viewer.num_tracks;
199 playlist_buffer_load_entries(pb, max_start, BACKWARD);
203 int playlist_entry_load(struct playlist_entry *entry, int index,
204 char* name_buffer, int remaining_size)
206 struct playlist_track_info info;
207 int len;
209 /* Playlist viewer orders songs based on display index. We need to
210 convert to real playlist index to access track */
211 index = (index + playlist_get_first_index(viewer.playlist)) %
212 viewer.num_tracks;
213 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
214 return -1;
216 len = strlen(info.filename) + 1;
218 if (len <= remaining_size)
220 strcpy(name_buffer, info.filename);
222 entry->name = name_buffer;
223 entry->index = info.index;
224 entry->display_index = info.display_index;
225 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
226 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
227 return len;
229 return -1;
232 int playlist_buffer_get_index(struct playlist_buffer * pb, int index )
234 int buffer_index;
235 if(pb->direction==FORWARD)
237 if(index>=pb->first_index)
238 buffer_index=index-pb->first_index;
239 else /* rotation : track0 in buffer + requested track */
240 buffer_index=(viewer.num_tracks-pb->first_index)+(index);
242 else
244 if(index<=pb->first_index)
245 buffer_index=pb->first_index-index;
246 else /* rotation : track0 in buffer + dist from the last track
247 to the requested track (num_tracks-requested track) */
248 buffer_index=(pb->first_index)+(viewer.num_tracks-index);
250 return(buffer_index);
253 #define distance(a, b) \
254 a>b? (a) - (b) : (b) - (a)
255 bool playlist_buffer_needs_reload(struct playlist_buffer* pb, int track_index)
257 if(pb->num_loaded==viewer.num_tracks)
258 return(false);
259 int selected_index=playlist_buffer_get_index(pb, track_index);
260 int first_buffer_index=playlist_buffer_get_index(pb, pb->first_index);
261 int distance_beginning=distance(selected_index, first_buffer_index);
262 if(distance_beginning<MIN_BUFFER_MARGIN)
263 return(true);
265 if(pb->num_loaded - distance_beginning < MIN_BUFFER_MARGIN)
266 return(true);
267 return(false);
270 struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer * pb,
271 int index)
273 int buffer_index=playlist_buffer_get_index(pb, index);
274 return(&(pb->tracks[buffer_index]));
277 /* Initialize the playlist viewer. */
278 static bool playlist_viewer_init(struct playlist_viewer * viewer,
279 char* filename, bool reload)
281 char* buffer;
282 int buffer_size;
283 bool is_playing = audio_status() & AUDIO_STATUS_PLAY;
285 if (!filename && !is_playing)
286 /* Nothing is playing, exit */
287 return false;
289 buffer = plugin_get_buffer(&buffer_size);
290 if (!buffer)
291 return false;
293 if (!filename)
294 viewer->playlist = NULL;
295 else
297 /* Viewing playlist on disk */
298 char *dir, *file, *temp_ptr;
299 char *index_buffer = NULL;
300 int index_buffer_size = 0;
302 viewer->playlist = &temp_playlist;
304 /* Separate directory from filename */
305 temp_ptr = strrchr(filename+1,'/');
306 if (temp_ptr)
308 *temp_ptr = 0;
309 dir = filename;
310 file = temp_ptr + 1;
312 else
314 dir = "/";
315 file = filename+1;
318 if (is_playing)
320 /* Something is playing, use half the plugin buffer for playlist
321 indices */
322 index_buffer_size = buffer_size / 2;
323 index_buffer = buffer;
326 playlist_create_ex(viewer->playlist, dir, file, index_buffer,
327 index_buffer_size, buffer+index_buffer_size,
328 buffer_size-index_buffer_size);
330 if (temp_ptr)
331 *temp_ptr = '/';
333 buffer += index_buffer_size;
334 buffer_size -= index_buffer_size;
336 playlist_buffer_init(&viewer->buffer, buffer, buffer_size );
338 viewer->move_track = -1;
340 if (!reload)
342 if (viewer->playlist)
343 viewer->selected_track = 0;
344 else
345 viewer->selected_track = playlist_get_display_index() - 1;
348 if (!update_playlist(true))
349 return false;
350 return true;
353 /* Format trackname for display purposes */
354 static void format_name(char* dest, const char* src)
356 switch (global_settings.playlist_viewer_track_display)
358 case 0:
359 default:
361 /* Only display the filename */
362 char* p = strrchr(src, '/');
364 strcpy(dest, p+1);
366 /* Remove the extension */
367 char* q = strrchr(dest, '.');
369 if (q != NULL)
370 *q = '\0';
372 break;
374 case 1:
375 /* Full path */
376 strcpy(dest, src);
377 break;
381 /* Format display line */
382 static void format_line(const struct playlist_entry* track, char* str,
383 int len)
385 char name[MAX_PATH];
386 char *skipped = "";
388 format_name(name, track->name);
390 if (track->skipped)
391 skipped = "(ERR) ";
393 if (global_settings.playlist_viewer_indices)
394 /* Display playlist index */
395 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
396 else
397 snprintf(str, len, "%s%s", skipped, name);
401 /* Update playlist in case something has changed or forced */
402 static bool update_playlist(bool force)
404 if (!viewer.playlist)
405 playlist_get_resume_info(&viewer.current_playing_track);
406 else
407 viewer.current_playing_track = -1;
408 int nb_tracks=playlist_amount_ex(viewer.playlist);
409 force=force || nb_tracks != viewer.num_tracks;
410 if (force)
412 /* Reload tracks */
413 viewer.num_tracks = nb_tracks;
414 if (viewer.num_tracks <= 0)
415 return false;
416 playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD);
417 if (viewer.buffer.num_loaded <= 0)
418 return false;
420 return true;
423 /* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
424 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
425 changed. */
426 static int onplay_menu(int index)
428 struct menu_item items[3]; /* increase this if you add entries! */
429 int m, i=0, result, ret = 0;
430 struct playlist_entry * current_track=
431 playlist_buffer_get_track(&viewer.buffer, index);
432 bool current = (current_track->index == viewer.current_playing_track);
434 items[i].desc = ID2P(LANG_REMOVE);
435 i++;
437 items[i].desc = ID2P(LANG_MOVE);
438 i++;
440 items[i].desc = ID2P(LANG_FILE_OPTIONS);
441 i++;
443 m = menu_init(items, i, NULL, NULL, NULL, NULL);
444 result = menu_show(m);
445 if (result == MENU_ATTACHED_USB)
446 ret = -1;
447 else if (result >= 0)
449 /* Abort current move */
450 viewer.move_track = -1;
452 switch (result)
454 case 0:
455 /* delete track */
456 playlist_delete(viewer.playlist, current_track->index);
457 if (current)
459 if (playlist_amount_ex(viewer.playlist) <= 0)
460 audio_stop();
461 else
463 /* Start playing new track except if it's the lasttrack
464 track in the playlist and repeat mode is disabled */
465 current_track =
466 playlist_buffer_get_track(&viewer.buffer, index);
467 if (current_track->display_index!=viewer.num_tracks ||
468 global_settings.repeat_mode == REPEAT_ALL)
470 talk_buffer_steal(); /* will use the mp3 buffer */
471 audio_play(0);
472 viewer.current_playing_track = -1;
476 ret = 1;
477 break;
478 case 1:
479 /* move track */
480 viewer.move_track = current_track->index;
481 ret = 0;
482 break;
483 case 2:
485 onplay(current_track->name, TREE_ATTR_MPA, CONTEXT_TREE);
487 if (!viewer.playlist)
488 ret = 1;
489 else
490 ret = 0;
491 break;
495 menu_exit(m);
496 return ret;
499 /* Menu of viewer options. Invoked via F1(r) or Menu(p). */
500 static bool viewer_menu(void)
502 int m;
503 bool result;
505 static const struct menu_item items[] = {
506 { ID2P(LANG_SHOW_ICONS), show_icons },
507 { ID2P(LANG_SHOW_INDICES), show_indices },
508 { ID2P(LANG_TRACK_DISPLAY), track_display },
509 { ID2P(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist },
512 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
513 NULL, NULL, NULL );
514 result = menu_run(m);
515 menu_exit(m);
517 settings_save();
519 return result;
522 /* Show icons in viewer? */
523 static bool show_icons(void)
525 return set_bool((char *)str(LANG_SHOW_ICONS),
526 &global_settings.playlist_viewer_icons);
529 /* Show indices of tracks? */
530 static bool show_indices(void)
532 return set_bool((char *)str(LANG_SHOW_INDICES),
533 &global_settings.playlist_viewer_indices);
536 /* How to display a track */
537 static bool track_display(void)
539 static const struct opt_items names[] = {
540 { STR(LANG_DISPLAY_TRACK_NAME_ONLY) },
541 { STR(LANG_DISPLAY_FULL_PATH) }
544 return set_option((char *)str(LANG_TRACK_DISPLAY),
545 &global_settings.playlist_viewer_track_display, INT, names, 2,
546 NULL);
549 /* Save playlist to disk */
550 static bool save_playlist(void)
552 save_playlist_screen(viewer.playlist);
553 return false;
556 /* View current playlist */
557 bool playlist_viewer(void)
559 return playlist_viewer_ex(NULL);
562 char * playlist_callback_name(int selected_item, void * data, char *buffer)
564 struct playlist_viewer * local_viewer = (struct playlist_viewer *)data;
565 struct playlist_entry *track=
566 playlist_buffer_get_track(&(local_viewer->buffer), selected_item);
567 format_line(track, buffer, MAX_PATH);
568 return(buffer);
572 void playlist_callback_icons(int selected_item, void * data, ICON * icon)
574 struct playlist_viewer * local_viewer=(struct playlist_viewer *)data;
575 struct playlist_entry *track=
576 playlist_buffer_get_track(&(local_viewer->buffer), selected_item);
577 if (track->index == local_viewer->current_playing_track)
579 /* Current playing track */
580 #ifdef HAVE_LCD_BITMAP
581 *icon=bitmap_icons_6x8[Icon_Audio];
582 #else
583 *icon=Icon_Audio;
584 #endif
586 else if (track->index == local_viewer->move_track)
588 /* Track we are moving */
589 #ifdef HAVE_LCD_BITMAP
590 *icon=bitmap_icons_6x8[Icon_Moving];
591 #else
592 *icon=Icon_Moving;
593 #endif
595 else if (track->queued)
597 /* Queued track */
598 #ifdef HAVE_LCD_BITMAP
599 *icon=bitmap_icons_6x8[Icon_Queued];
600 #else
601 *icon=Icon_Queued;
602 #endif
604 else
605 #ifdef HAVE_LCD_BITMAP
606 *icon=0;
607 #else
608 *icon=-1;
609 #endif
612 /* Main viewer function. Filename identifies playlist to be viewed. If NULL,
613 view current playlist. */
614 bool playlist_viewer_ex(char* filename)
616 bool ret = false; /* return value */
617 bool exit=false; /* exit viewer */
618 int button;
619 struct gui_synclist playlist_lists;
620 if (!playlist_viewer_init(&viewer, filename, false))
621 goto exit;
623 gui_synclist_init(&playlist_lists, playlist_callback_name, &viewer, false, 1);
624 gui_synclist_set_icon_callback(&playlist_lists,
625 global_settings.playlist_viewer_icons?
626 &playlist_callback_icons:NULL);
627 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
628 gui_synclist_select_item(&playlist_lists, viewer.selected_track);
629 gui_synclist_draw(&playlist_lists);
630 while (!exit)
632 int track;
633 if (!viewer.playlist && !(audio_status() & AUDIO_STATUS_PLAY))
635 /* Play has stopped */
636 #ifdef HAVE_LCD_CHARCELLS
637 gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_PLAYER));
638 #else
639 gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_RECORDER));
640 #endif
641 goto exit;
644 if (viewer.move_track != -1)
645 gui_synclist_flash(&playlist_lists);
647 if (!viewer.playlist)
648 playlist_get_resume_info(&track);
649 else
650 track = -1;
652 if (track != viewer.current_playing_track ||
653 playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
655 /* Playlist has changed (new track started?) */
656 if (!update_playlist(false))
657 goto exit;
658 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
659 /* Abort move on playlist change */
660 viewer.move_track = -1;
661 gui_synclist_draw(&playlist_lists);
664 /* Timeout so we can determine if play status has changed */
665 button = get_action(CONTEXT_TREE,HZ/2);
666 int list_action;
667 if( (list_action=gui_synclist_do_button(&playlist_lists, button))!=0 )
669 viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists);
670 if(playlist_buffer_needs_reload(&viewer.buffer,
671 viewer.selected_track))
672 playlist_buffer_load_entries_screen(&viewer.buffer,
673 list_action==ACTION_STD_NEXT?
674 FORWARD
676 BACKWARD
679 switch (button)
681 case ACTION_STD_CANCEL:
682 exit = true;
683 break;
684 case ACTION_STD_OK:
686 struct playlist_entry * current_track =
687 playlist_buffer_get_track(&viewer.buffer,
688 viewer.selected_track);
689 if (viewer.move_track >= 0)
691 /* Move track */
692 int ret;
694 ret = playlist_move(viewer.playlist, viewer.move_track,
695 current_track->index);
696 if (ret < 0)
697 gui_syncsplash(HZ, true, str(LANG_MOVE_FAILED));
699 update_playlist(true);
700 viewer.move_track = -1;
702 else if (!viewer.playlist)
704 /* play new track */
705 playlist_start(current_track->index, 0);
706 update_playlist(false);
708 else
710 /* New playlist */
711 if (playlist_set_current(viewer.playlist) < 0)
712 goto exit;
714 playlist_start(current_track->index, 0);
716 /* Our playlist is now the current list */
717 if (!playlist_viewer_init(&viewer, NULL, true))
718 goto exit;
720 gui_synclist_draw(&playlist_lists);
722 break;
724 case ACTION_STD_CONTEXT:
726 /* ON+PLAY menu */
727 int ret;
729 ret = onplay_menu(viewer.selected_track);
731 if (ret < 0)
733 ret = true;
734 goto exit;
736 else if (ret > 0)
738 /* Playlist changed */
739 gui_synclist_del_item(&playlist_lists);
740 update_playlist(true);
741 if (viewer.num_tracks <= 0)
742 exit = true;
744 gui_synclist_draw(&playlist_lists);
745 break;
747 case ACTION_STD_MENU:
748 if (viewer_menu())
750 ret = true;
751 goto exit;
753 gui_synclist_set_icon_callback(
754 &playlist_lists,
755 global_settings.playlist_viewer_icons?
756 &playlist_callback_icons:NULL
758 gui_synclist_draw(&playlist_lists);
759 break;
761 case ACTION_NONE:
762 gui_syncstatusbar_draw(&statusbars, false);
763 break;
765 default:
766 if(default_event_handler(button) == SYS_USB_CONNECTED)
768 ret = true;
769 goto exit;
771 break;
775 exit:
776 if (viewer.playlist)
777 playlist_close(viewer.playlist);
778 action_signalscreenchange();
779 return ret;
781 char * playlist_search_callback_name(int selected_item, void * data, char *buffer)
783 int *found_indicies = (int*)data;
784 static struct playlist_track_info track;
785 playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track);
786 format_name(buffer,track.filename);
787 return(buffer);
791 void playlist_search_callback_icons(int selected_item, void * data, ICON * icon)
793 (void)selected_item;
794 (void)data;
795 #ifdef HAVE_LCD_BITMAP
796 *icon=0;
797 #else
798 *icon=-1;
799 #endif
801 bool search_playlist(void)
803 char search_str[32] = "";
804 bool ret = false, exit = false;
805 int i, playlist_count;
806 int found_indicies[MAX_PLAYLIST_ENTRIES],found_indicies_count = 0;
807 int button;
808 struct gui_synclist playlist_lists;
809 struct playlist_track_info track;
811 if (!playlist_viewer_init(&viewer, 0, false))
812 return ret;
813 if (kbd_input(search_str,sizeof(search_str)) == -1)
814 return ret;
815 lcd_clear_display();
816 playlist_count = playlist_amount_ex(viewer.playlist);
817 for (i=0;(i<playlist_count)&&(found_indicies_count<MAX_PLAYLIST_ENTRIES);i++)
819 gui_syncsplash(0, true, str(LANG_PLAYLIST_SEARCH_MSG),found_indicies_count,
820 #if CONFIG_KEYPAD == PLAYER_PAD
821 str(LANG_STOP_ABORT)
822 #else
823 str(LANG_OFF_ABORT)
824 #endif
826 if (action_userabort(TIMEOUT_NOBLOCK))
827 return ret;
828 playlist_get_track_info(viewer.playlist,i,&track);
829 if (strcasestr(track.filename,search_str))
831 found_indicies[found_indicies_count++] = track.index;
834 if (!found_indicies_count)
836 return ret;
838 backlight_on();
839 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
840 found_indicies, false, 1);
841 gui_synclist_set_icon_callback(&playlist_lists,
842 global_settings.playlist_viewer_icons?
843 &playlist_search_callback_icons:NULL);
844 gui_synclist_set_nb_items(&playlist_lists, found_indicies_count);
845 gui_synclist_select_item(&playlist_lists, 0);
846 gui_synclist_draw(&playlist_lists);
847 while (!exit)
849 button = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
850 if (gui_synclist_do_button(&playlist_lists, button))
851 continue;
852 switch (button)
854 case ACTION_STD_CANCEL:
855 exit = true;
856 break;
858 case ACTION_STD_OK:
859 playlist_start(
860 found_indicies[gui_synclist_get_sel_pos(&playlist_lists)]
861 ,0);
862 exit = 1;
863 break;
864 case ACTION_NONE:
865 break;
866 default:
867 if(default_event_handler(button) == SYS_USB_CONNECTED)
869 ret = true;
870 exit = true;
872 break;
875 action_signalscreenchange();
876 return ret;