rbutil: add the forgotten ui file from festival support.
[kugel-rb.git] / apps / playlist_viewer.c
blobaf07766997a797f69ad4b53580bf87478d64ce3a
1 /***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
11 * Copyright (C) 2003 Hardeep Sidhu
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 * Kevin Ferrare 2005/10/16
24 * multi-screen support, rewrote a lot of code
26 #include <string.h>
27 #include <sprintf.h>
28 #include "playlist.h"
29 #include "audio.h"
30 #include "screens.h"
31 #include "settings.h"
32 #include "icons.h"
33 #include "menu.h"
34 #include "plugin.h"
35 #include "keyboard.h"
36 #include "filetypes.h"
37 #include "onplay.h"
38 #include "talk.h"
39 #include "misc.h"
40 #include "action.h"
41 #include "debug.h"
42 #include "backlight.h"
44 #include "lang.h"
46 #include "playlist_viewer.h"
47 #include "playlist_catalog.h"
48 #include "icon.h"
49 #include "list.h"
50 #include "statusbar.h"
51 #include "splash.h"
52 #include "playlist_menu.h"
53 #include "action.h"
55 /* Maximum number of tracks we can have loaded at one time */
56 #define MAX_PLAYLIST_ENTRIES 200
58 /* The number of items between the selected one and the end/start of
59 * the buffer under which the buffer must reload */
60 #define MIN_BUFFER_MARGIN (screens[0].getnblines()+1)
62 /* Information about a specific track */
63 struct playlist_entry {
64 char *name; /* Formatted track name */
65 int index; /* Playlist index */
66 int display_index; /* Display index */
67 bool queued; /* Is track queued? */
68 bool skipped; /* Is track marked as bad? */
71 enum direction
73 FORWARD,
74 BACKWARD
77 struct playlist_buffer
79 char *name_buffer; /* Buffer used to store track names */
80 int buffer_size; /* Size of name buffer */
82 int first_index; /* Real index of first track loaded inside
83 the buffer */
85 enum direction direction; /* Direction of the buffer (if the buffer
86 was loaded BACKWARD, the last track in
87 the buffer has a real index < to the
88 real index of the the first track)*/
90 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
91 int num_loaded; /* Number of track entries loaded in buffer */
94 /* Global playlist viewer settings */
95 struct playlist_viewer {
96 struct playlist_info* playlist; /* playlist being viewed */
97 int num_tracks; /* Number of tracks in playlist */
98 int current_playing_track; /* Index of current playing track */
99 int selected_track; /* The selected track, relative (first is 0)*/
100 int move_track; /* Playlist index of track to move or -1 */
101 struct playlist_buffer buffer;
104 static struct playlist_viewer viewer;
106 /* Used when viewing playlists on disk */
107 static struct playlist_info temp_playlist;
109 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
110 int names_buffer_size);
111 static void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
112 enum direction direction);
113 static int playlist_entry_load(struct playlist_entry *entry, int index,
114 char* name_buffer, int remaining_size);
116 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
117 int index);
119 static bool playlist_viewer_init(struct playlist_viewer * viewer,
120 const char* filename, bool reload);
122 static void format_name(char* dest, const char* src);
123 static void format_line(const struct playlist_entry* track, char* str,
124 int len);
126 static bool update_playlist(bool force);
127 static int onplay_menu(int index);
128 static bool viewer_menu(void);
129 static int save_playlist_func(void);
131 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
132 int names_buffer_size)
134 pb->name_buffer=names_buffer;
135 pb->buffer_size=names_buffer_size;
136 pb->first_index=0;
137 pb->num_loaded=0;
141 * Loads the entries following 'index' in the playlist buffer
143 static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index,
144 enum direction direction)
146 int num_entries = viewer.num_tracks;
147 char* p = pb->name_buffer;
148 int remaining = pb->buffer_size;
149 int i;
151 pb->first_index = index;
152 if (num_entries > MAX_PLAYLIST_ENTRIES)
153 num_entries = MAX_PLAYLIST_ENTRIES;
155 for(i=0; i<num_entries; i++)
157 int len = playlist_entry_load(&(pb->tracks[i]), index, p, remaining);
158 if (len < 0)
160 /* Out of name buffer space */
161 num_entries = i;
162 break;
165 p += len;
166 remaining -= len;
168 if(direction==FORWARD)
169 index++;
170 else
171 index--;
172 index+=viewer.num_tracks;
173 index%=viewer.num_tracks;
175 pb->direction=direction;
176 pb->num_loaded = i;
179 static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
180 enum direction direction)
182 if(direction==FORWARD)
184 int min_start=viewer.selected_track-2*screens[0].getnblines();
185 while(min_start<0)
186 min_start+=viewer.num_tracks;
187 min_start %= viewer.num_tracks;
188 playlist_buffer_load_entries(pb, min_start, FORWARD);
190 else
192 int max_start=viewer.selected_track+2*screens[0].getnblines();
193 max_start%=viewer.num_tracks;
194 playlist_buffer_load_entries(pb, max_start, BACKWARD);
198 static int playlist_entry_load(struct playlist_entry *entry, int index,
199 char* name_buffer, int remaining_size)
201 struct playlist_track_info info;
202 int len;
204 /* Playlist viewer orders songs based on display index. We need to
205 convert to real playlist index to access track */
206 index = (index + playlist_get_first_index(viewer.playlist)) %
207 viewer.num_tracks;
208 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
209 return -1;
211 len = strlen(info.filename) + 1;
213 if (len <= remaining_size)
215 strcpy(name_buffer, info.filename);
217 entry->name = name_buffer;
218 entry->index = info.index;
219 entry->display_index = info.display_index;
220 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
221 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
222 return len;
224 return -1;
227 static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
229 int buffer_index;
230 if(pb->direction==FORWARD)
232 if(index>=pb->first_index)
233 buffer_index=index-pb->first_index;
234 else /* rotation : track0 in buffer + requested track */
235 buffer_index=(viewer.num_tracks-pb->first_index)+(index);
237 else
239 if(index<=pb->first_index)
240 buffer_index=pb->first_index-index;
241 else /* rotation : track0 in buffer + dist from the last track
242 to the requested track (num_tracks-requested track) */
243 buffer_index=(pb->first_index)+(viewer.num_tracks-index);
245 return(buffer_index);
248 #define distance(a, b) \
249 a>b? (a) - (b) : (b) - (a)
250 static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
251 int track_index)
253 if(pb->num_loaded==viewer.num_tracks)
254 return(false);
255 int selected_index=playlist_buffer_get_index(pb, track_index);
256 int first_buffer_index=playlist_buffer_get_index(pb, pb->first_index);
257 int distance_beginning=distance(selected_index, first_buffer_index);
258 if(distance_beginning<MIN_BUFFER_MARGIN)
259 return(true);
261 if(pb->num_loaded - distance_beginning < MIN_BUFFER_MARGIN)
262 return(true);
263 return(false);
266 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
267 int index)
269 int buffer_index=playlist_buffer_get_index(pb, index);
270 return(&(pb->tracks[buffer_index]));
273 /* Initialize the playlist viewer. */
274 static bool playlist_viewer_init(struct playlist_viewer * viewer,
275 const char* filename, bool reload)
277 char* buffer;
278 size_t buffer_size;
279 bool is_playing = audio_status() & (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE);
280 bool have_list = filename || is_playing;
281 if (!have_list && (global_status.resume_index != -1))
283 /* Try to restore the list from control file */
284 have_list = (playlist_resume() != -1);
286 if (!have_list && (playlist_amount() > 0))
288 /*If dynamic playlist still exists, view it anyway even
289 if playback has reached the end of the playlist */
290 have_list = true;
292 if (!have_list)
294 /* Nothing to view, exit */
295 splash(HZ, str(LANG_CATALOG_NO_PLAYLISTS));
296 return false;
299 buffer = plugin_get_buffer(&buffer_size);
300 if (!buffer)
301 return false;
303 if (!filename)
304 viewer->playlist = NULL;
305 else
307 /* Viewing playlist on disk */
308 const char *dir, *file;
309 char *temp_ptr;
310 char *index_buffer = NULL;
311 ssize_t index_buffer_size = 0;
313 viewer->playlist = &temp_playlist;
315 /* Separate directory from filename */
316 temp_ptr = strrchr(filename+1,'/');
317 if (temp_ptr)
319 *temp_ptr = 0;
320 dir = filename;
321 file = temp_ptr + 1;
323 else
325 dir = "/";
326 file = filename+1;
329 if (is_playing)
331 /* Something is playing, use half the plugin buffer for playlist
332 indices */
333 index_buffer_size = buffer_size / 2;
334 index_buffer = buffer;
337 playlist_create_ex(viewer->playlist, dir, file, index_buffer,
338 index_buffer_size, buffer+index_buffer_size,
339 buffer_size-index_buffer_size);
341 if (temp_ptr)
342 *temp_ptr = '/';
344 buffer += index_buffer_size;
345 buffer_size -= index_buffer_size;
347 playlist_buffer_init(&viewer->buffer, buffer, buffer_size );
349 viewer->move_track = -1;
351 if (!reload)
353 if (viewer->playlist)
354 viewer->selected_track = 0;
355 else
356 viewer->selected_track = playlist_get_display_index() - 1;
359 if (!update_playlist(true))
360 return false;
361 return true;
364 /* Format trackname for display purposes */
365 static void format_name(char* dest, const char* src)
367 switch (global_settings.playlist_viewer_track_display)
369 case 0:
370 default:
372 /* Only display the filename */
373 char* p = strrchr(src, '/');
375 strcpy(dest, p+1);
377 /* Remove the extension */
378 strrsplt(dest, '.');
380 break;
382 case 1:
383 /* Full path */
384 strcpy(dest, src);
385 break;
389 /* Format display line */
390 static void format_line(const struct playlist_entry* track, char* str,
391 int len)
393 char name[MAX_PATH];
394 char *skipped = "";
396 format_name(name, track->name);
398 if (track->skipped)
399 skipped = "(ERR) ";
401 if (global_settings.playlist_viewer_indices)
402 /* Display playlist index */
403 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
404 else
405 snprintf(str, len, "%s%s", skipped, name);
409 /* Update playlist in case something has changed or forced */
410 static bool update_playlist(bool force)
412 if (!viewer.playlist)
413 playlist_get_resume_info(&viewer.current_playing_track);
414 else
415 viewer.current_playing_track = -1;
416 int nb_tracks=playlist_amount_ex(viewer.playlist);
417 force=force || nb_tracks != viewer.num_tracks;
418 if (force)
420 /* Reload tracks */
421 viewer.num_tracks = nb_tracks;
422 if (viewer.num_tracks <= 0)
423 return false;
424 playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD);
425 if (viewer.buffer.num_loaded <= 0)
426 return false;
428 return true;
431 /* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
432 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
433 changed. */
434 static int onplay_menu(int index)
436 int result, ret = 0;
437 struct playlist_entry * current_track=
438 playlist_buffer_get_track(&viewer.buffer, index);
439 MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL,
440 ID2P(LANG_REMOVE), ID2P(LANG_MOVE),
441 ID2P(LANG_CATALOG_ADD_TO), ID2P(LANG_CATALOG_ADD_TO_NEW));
442 bool current = (current_track->index == viewer.current_playing_track);
444 result = do_menu(&menu_items, NULL, NULL, false);
445 if (result == MENU_ATTACHED_USB)
447 ret = -1;
449 else if (result >= 0)
451 /* Abort current move */
452 viewer.move_track = -1;
454 switch (result)
456 case 0:
457 /* delete track */
458 playlist_delete(viewer.playlist, current_track->index);
459 if (current)
461 if (playlist_amount_ex(viewer.playlist) <= 0)
462 audio_stop();
463 else
465 /* Start playing new track except if it's the lasttrack
466 track in the playlist and repeat mode is disabled */
467 current_track =
468 playlist_buffer_get_track(&viewer.buffer, index);
469 if (current_track->display_index!=viewer.num_tracks ||
470 global_settings.repeat_mode == REPEAT_ALL)
472 #if CONFIG_CODEC != SWCODEC
473 talk_buffer_steal(); /* will use the mp3 buffer */
474 #endif
475 audio_play(0);
476 viewer.current_playing_track = -1;
480 ret = 1;
481 break;
482 case 1:
483 /* move track */
484 viewer.move_track = current_track->index;
485 ret = 0;
486 break;
487 case 2: /* add to catalog */
488 case 3: /* add to a new one */
489 catalog_add_to_a_playlist(current_track->name,
490 FILE_ATTR_AUDIO,
491 result==3, NULL);
492 ret = 0;
493 break;
496 return ret;
499 /* Menu of viewer options. Invoked via F1(r) or Menu(p). */
500 MENUITEM_SETTING(show_icons, &global_settings.playlist_viewer_icons, NULL);
501 MENUITEM_SETTING(show_indices, &global_settings.playlist_viewer_indices, NULL);
502 MENUITEM_SETTING(track_display,
503 &global_settings.playlist_viewer_track_display, NULL);
504 MENUITEM_FUNCTION(save_playlist_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
505 save_playlist_func, 0, NULL, Icon_NOICON);
506 MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS),
507 NULL, Icon_Playlist,
508 &show_icons, &show_indices, &track_display, &save_playlist_item);
509 static bool viewer_menu(void)
511 return do_menu(&viewer_settings_menu, NULL, NULL, false) == MENU_ATTACHED_USB;
514 /* Save playlist to disk */
515 static int save_playlist_func(void)
517 save_playlist_screen(viewer.playlist);
518 return 0;
521 /* View current playlist */
522 bool playlist_viewer(void)
524 return playlist_viewer_ex(NULL);
527 static int get_track_num( struct playlist_viewer * local_viewer,
528 int selected_item )
530 if( local_viewer->move_track >= 0 )
532 if( local_viewer->selected_track == selected_item )
534 return local_viewer->move_track;
536 else if( local_viewer->selected_track > selected_item
537 && selected_item >= local_viewer->move_track )
539 return selected_item+1;
541 else if( local_viewer->selected_track < selected_item
542 && selected_item <= local_viewer->move_track )
544 return selected_item-1;
547 return selected_item;
550 static char *playlist_callback_name(int selected_item,
551 void *data,
552 char *buffer,
553 size_t buffer_len)
555 struct playlist_viewer * local_viewer = (struct playlist_viewer *)data;
557 int track_num = get_track_num(local_viewer, selected_item);
558 struct playlist_entry *track =
559 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
561 format_line(track, buffer, buffer_len);
563 return(buffer);
567 static int playlist_callback_icons(int selected_item, void *data)
569 struct playlist_viewer * local_viewer=(struct playlist_viewer *)data;
571 int track_num = get_track_num(local_viewer, selected_item);
572 struct playlist_entry *track=
573 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
575 if (track->index == local_viewer->current_playing_track)
577 /* Current playing track */
578 return Icon_Audio;
580 else if (track->index == local_viewer->move_track)
582 /* Track we are moving */
583 return Icon_Moving;
585 else if (track->queued)
587 /* Queued track */
588 return Icon_Queued;
590 else
591 return Icon_NOICON;
594 /* Main viewer function. Filename identifies playlist to be viewed. If NULL,
595 view current playlist. */
596 bool playlist_viewer_ex(const char* filename)
598 bool ret = false; /* return value */
599 bool exit=false; /* exit viewer */
600 int button;
601 struct gui_synclist playlist_lists;
602 if (!playlist_viewer_init(&viewer, filename, false))
603 goto exit;
605 gui_synclist_init(&playlist_lists, playlist_callback_name,
606 &viewer, false, 1, NULL);
607 gui_synclist_set_icon_callback(&playlist_lists,
608 global_settings.playlist_viewer_icons?
609 &playlist_callback_icons:NULL);
610 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
611 gui_synclist_select_item(&playlist_lists, viewer.selected_track);
612 gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
613 gui_synclist_draw(&playlist_lists);
614 while (!exit)
616 int track;
618 if (global_status.resume_index != -1 && !viewer.playlist)
619 playlist_get_resume_info(&track);
620 else
621 track = -1;
623 if (track != viewer.current_playing_track ||
624 playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
626 /* Playlist has changed (new track started?) */
627 if (!update_playlist(false))
628 goto exit;
629 /*Needed because update_playlist gives wrong value when
630 playing is stopped*/
631 viewer.current_playing_track = track;
632 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
633 /* Abort move on playlist change */
634 viewer.move_track = -1;
635 gui_synclist_draw(&playlist_lists);
638 /* Timeout so we can determine if play status has changed */
639 button = get_action(CONTEXT_TREE,HZ/2);
640 if( (gui_synclist_do_button(&playlist_lists, &button,LIST_WRAP_UNLESS_HELD)) )
642 viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists);
643 if(playlist_buffer_needs_reload(&viewer.buffer,
644 viewer.selected_track))
645 playlist_buffer_load_entries_screen(&viewer.buffer,
646 button==ACTION_STD_NEXT?
647 FORWARD
649 BACKWARD
651 gui_synclist_draw(&playlist_lists);
653 switch (button)
655 case ACTION_TREE_WPS:
656 case ACTION_STD_CANCEL:
658 if (viewer.move_track >= 0)
660 viewer.selected_track = viewer.move_track;
661 gui_synclist_select_item(&playlist_lists, viewer.move_track);
662 viewer.move_track = -1;
663 gui_synclist_draw(&playlist_lists);
665 else
666 exit = true;
667 break;
669 case ACTION_STD_OK:
671 struct playlist_entry * current_track =
672 playlist_buffer_get_track(&viewer.buffer,
673 viewer.selected_track);
674 if (viewer.move_track >= 0)
676 /* Move track */
677 int ret_val;
679 ret_val = playlist_move(viewer.playlist, viewer.move_track,
680 current_track->index);
681 if (ret_val < 0)
682 splashf(HZ, (unsigned char *)"%s %s", str(LANG_MOVE),
683 str(LANG_FAILED));
684 update_playlist(true);
685 viewer.move_track = -1;
687 else if (!viewer.playlist)
689 /* play new track */
690 playlist_start(current_track->index, 0);
691 update_playlist(false);
693 else
695 /* New playlist */
696 if (playlist_set_current(viewer.playlist) < 0)
697 goto exit;
699 playlist_start(current_track->index, 0);
701 /* Our playlist is now the current list */
702 if (!playlist_viewer_init(&viewer, NULL, true))
703 goto exit;
705 gui_synclist_draw(&playlist_lists);
707 break;
709 case ACTION_STD_CONTEXT:
711 /* ON+PLAY menu */
712 int ret_val;
714 ret_val = onplay_menu(viewer.selected_track);
716 if (ret_val < 0)
718 ret = true;
719 goto exit;
721 else if (ret > 0)
723 /* Playlist changed */
724 gui_synclist_del_item(&playlist_lists);
725 update_playlist(true);
726 if (viewer.num_tracks <= 0)
727 exit = true;
728 if(viewer.selected_track >= viewer.num_tracks)
729 viewer.selected_track = viewer.num_tracks-1;
731 gui_synclist_draw(&playlist_lists);
732 break;
734 case ACTION_STD_MENU:
735 if (viewer_menu())
737 ret = true;
738 goto exit;
740 gui_synclist_set_icon_callback(
741 &playlist_lists,
742 global_settings.playlist_viewer_icons?
743 &playlist_callback_icons:NULL
745 gui_synclist_draw(&playlist_lists);
746 break;
748 default:
749 if(default_event_handler(button) == SYS_USB_CONNECTED)
751 ret = true;
752 goto exit;
754 break;
758 exit:
759 if (viewer.playlist)
760 playlist_close(viewer.playlist);
761 return ret;
764 static char *playlist_search_callback_name(int selected_item, void * data,
765 char *buffer, size_t buffer_len)
767 (void)buffer_len; /* this should probably be used */
768 int *found_indicies = (int*)data;
769 static struct playlist_track_info track;
770 playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track);
771 format_name(buffer, track.filename);
772 return(buffer);
775 bool search_playlist(void)
777 char search_str[32] = "";
778 bool ret = false, exit = false;
779 int i, playlist_count;
780 int found_indicies[MAX_PLAYLIST_ENTRIES];
781 int found_indicies_count = 0, last_found_count = -1;
782 int button;
783 struct gui_synclist playlist_lists;
784 struct playlist_track_info track;
786 if (!playlist_viewer_init(&viewer, 0, false))
787 return ret;
788 if (kbd_input(search_str, sizeof(search_str)) == -1)
789 return ret;
790 lcd_clear_display();
791 playlist_count = playlist_amount_ex(viewer.playlist);
793 cpu_boost(true);
795 for (i=0; (i<playlist_count)&&(found_indicies_count<MAX_PLAYLIST_ENTRIES); i++)
797 if (found_indicies_count != last_found_count)
799 splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), found_indicies_count,
800 str(LANG_OFF_ABORT));
801 last_found_count = found_indicies_count;
804 if (action_userabort(TIMEOUT_NOBLOCK))
805 break;
807 playlist_get_track_info(viewer.playlist, i, &track);
809 if (strcasestr(track.filename,search_str))
810 found_indicies[found_indicies_count++] = track.index;
812 yield();
815 cpu_boost(false);
817 if (!found_indicies_count)
819 return ret;
821 backlight_on();
823 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
824 found_indicies, false, 1, NULL);
825 gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON);
826 gui_synclist_set_icon_callback(&playlist_lists, NULL);
827 gui_synclist_set_nb_items(&playlist_lists, found_indicies_count);
828 gui_synclist_select_item(&playlist_lists, 0);
829 gui_synclist_draw(&playlist_lists);
830 while (!exit)
832 button = get_action(CONTEXT_LIST, HZ/4);
833 if (gui_synclist_do_button(&playlist_lists, &button, LIST_WRAP_UNLESS_HELD))
834 continue;
835 switch (button)
837 case ACTION_STD_CANCEL:
838 exit = true;
839 break;
841 case ACTION_STD_OK:
842 playlist_start(
843 found_indicies[gui_synclist_get_sel_pos(&playlist_lists)]
844 ,0);
845 exit = 1;
846 break;
848 default:
849 if(default_event_handler(button) == SYS_USB_CONNECTED)
851 ret = true;
852 exit = true;
854 break;
857 return ret;