Oops.
[kugel-rb.git] / apps / playlist_viewer.c
blob961d2cdf12b5fe9e847a92674e0da9e7c301f93e
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 "splash.h"
51 #include "playlist_menu.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].getnblines()+1)
60 /* Information about a specific track */
61 struct playlist_entry {
62 char *name; /* Formatted track name */
63 int index; /* Playlist index */
64 int display_index; /* Display index */
65 bool queued; /* Is track queued? */
66 bool skipped; /* Is track marked as bad? */
69 enum direction
71 FORWARD,
72 BACKWARD
75 struct playlist_buffer
77 char *name_buffer; /* Buffer used to store track names */
78 int buffer_size; /* Size of name buffer */
80 int first_index; /* Real index of first track loaded inside
81 the buffer */
83 enum direction direction; /* Direction of the buffer (if the buffer
84 was loaded BACKWARD, the last track in
85 the buffer has a real index < to the
86 real index of the the first track)*/
88 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
89 int num_loaded; /* Number of track entries loaded in buffer */
92 /* Global playlist viewer settings */
93 struct playlist_viewer {
94 struct playlist_info* playlist; /* playlist being viewed */
95 int num_tracks; /* Number of tracks in playlist */
96 int current_playing_track; /* Index of current playing track */
97 int selected_track; /* The selected track, relative (first is 0)*/
98 int move_track; /* Playlist index of track to move or -1 */
99 struct playlist_buffer buffer;
102 static struct playlist_viewer viewer;
104 /* Used when viewing playlists on disk */
105 static struct playlist_info temp_playlist;
107 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
108 int names_buffer_size);
109 static void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
110 enum direction direction);
111 static int playlist_entry_load(struct playlist_entry *entry, int index,
112 char* name_buffer, int remaining_size);
114 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
115 int index);
117 static bool playlist_viewer_init(struct playlist_viewer * viewer,
118 const char* filename, bool reload);
120 static void format_name(char* dest, const char* src);
121 static void format_line(const struct playlist_entry* track, char* str,
122 int len);
124 static bool update_playlist(bool force);
125 static int onplay_menu(int index);
126 static bool viewer_menu(void);
127 static int save_playlist_func(void);
129 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
130 int names_buffer_size)
132 pb->name_buffer=names_buffer;
133 pb->buffer_size=names_buffer_size;
134 pb->first_index=0;
135 pb->num_loaded=0;
139 * Loads the entries following 'index' in the playlist buffer
141 static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index,
142 enum direction direction)
144 int num_entries = viewer.num_tracks;
145 char* p = pb->name_buffer;
146 int remaining = pb->buffer_size;
147 int i;
149 pb->first_index = index;
150 if (num_entries > MAX_PLAYLIST_ENTRIES)
151 num_entries = MAX_PLAYLIST_ENTRIES;
153 for(i=0; i<num_entries; i++)
155 int len = playlist_entry_load(&(pb->tracks[i]), index, p, remaining);
156 if (len < 0)
158 /* Out of name buffer space */
159 num_entries = i;
160 break;
163 p += len;
164 remaining -= len;
166 if(direction==FORWARD)
167 index++;
168 else
169 index--;
170 index+=viewer.num_tracks;
171 index%=viewer.num_tracks;
173 pb->direction=direction;
174 pb->num_loaded = i;
177 static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
178 enum direction direction)
180 if(direction==FORWARD)
182 int min_start=viewer.selected_track-2*screens[0].getnblines();
183 while(min_start<0)
184 min_start+=viewer.num_tracks;
185 min_start %= viewer.num_tracks;
186 playlist_buffer_load_entries(pb, min_start, FORWARD);
188 else
190 int max_start=viewer.selected_track+2*screens[0].getnblines();
191 max_start%=viewer.num_tracks;
192 playlist_buffer_load_entries(pb, max_start, BACKWARD);
196 static int playlist_entry_load(struct playlist_entry *entry, int index,
197 char* name_buffer, int remaining_size)
199 struct playlist_track_info info;
200 int len;
202 /* Playlist viewer orders songs based on display index. We need to
203 convert to real playlist index to access track */
204 index = (index + playlist_get_first_index(viewer.playlist)) %
205 viewer.num_tracks;
206 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
207 return -1;
209 len = strlen(info.filename) + 1;
211 if (len <= remaining_size)
213 strcpy(name_buffer, info.filename);
215 entry->name = name_buffer;
216 entry->index = info.index;
217 entry->display_index = info.display_index;
218 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
219 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
220 return len;
222 return -1;
225 static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
227 int buffer_index;
228 if(pb->direction==FORWARD)
230 if(index>=pb->first_index)
231 buffer_index=index-pb->first_index;
232 else /* rotation : track0 in buffer + requested track */
233 buffer_index=(viewer.num_tracks-pb->first_index)+(index);
235 else
237 if(index<=pb->first_index)
238 buffer_index=pb->first_index-index;
239 else /* rotation : track0 in buffer + dist from the last track
240 to the requested track (num_tracks-requested track) */
241 buffer_index=(pb->first_index)+(viewer.num_tracks-index);
243 return(buffer_index);
246 #define distance(a, b) \
247 a>b? (a) - (b) : (b) - (a)
248 static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
249 int track_index)
251 if(pb->num_loaded==viewer.num_tracks)
252 return(false);
253 int selected_index=playlist_buffer_get_index(pb, track_index);
254 int first_buffer_index=playlist_buffer_get_index(pb, pb->first_index);
255 int distance_beginning=distance(selected_index, first_buffer_index);
256 if(distance_beginning<MIN_BUFFER_MARGIN)
257 return(true);
259 if(pb->num_loaded - distance_beginning < MIN_BUFFER_MARGIN)
260 return(true);
261 return(false);
264 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
265 int index)
267 int buffer_index=playlist_buffer_get_index(pb, index);
268 return(&(pb->tracks[buffer_index]));
271 /* Initialize the playlist viewer. */
272 static bool playlist_viewer_init(struct playlist_viewer * viewer,
273 const char* filename, bool reload)
275 char* buffer;
276 size_t buffer_size;
277 bool is_playing = audio_status() & (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE);
278 bool have_list = filename || is_playing;
279 if (!have_list && (global_status.resume_index != -1))
281 /* Try to restore the list from control file */
282 have_list = (playlist_resume() != -1);
284 if (!have_list && (playlist_amount() > 0))
286 /*If dynamic playlist still exists, view it anyway even
287 if playback has reached the end of the playlist */
288 have_list = true;
290 if (!have_list)
292 /* Nothing to view, exit */
293 splash(HZ, str(LANG_CATALOG_NO_PLAYLISTS));
294 return false;
297 buffer = plugin_get_buffer(&buffer_size);
298 if (!buffer)
299 return false;
301 if (!filename)
302 viewer->playlist = NULL;
303 else
305 /* Viewing playlist on disk */
306 const char *dir, *file;
307 char *temp_ptr;
308 char *index_buffer = NULL;
309 ssize_t index_buffer_size = 0;
311 viewer->playlist = &temp_playlist;
313 /* Separate directory from filename */
314 temp_ptr = strrchr(filename+1,'/');
315 if (temp_ptr)
317 *temp_ptr = 0;
318 dir = filename;
319 file = temp_ptr + 1;
321 else
323 dir = "/";
324 file = filename+1;
327 if (is_playing)
329 /* Something is playing, use half the plugin buffer for playlist
330 indices */
331 index_buffer_size = buffer_size / 2;
332 index_buffer = buffer;
335 playlist_create_ex(viewer->playlist, dir, file, index_buffer,
336 index_buffer_size, buffer+index_buffer_size,
337 buffer_size-index_buffer_size);
339 if (temp_ptr)
340 *temp_ptr = '/';
342 buffer += index_buffer_size;
343 buffer_size -= index_buffer_size;
345 playlist_buffer_init(&viewer->buffer, buffer, buffer_size );
347 viewer->move_track = -1;
349 if (!reload)
351 if (viewer->playlist)
352 viewer->selected_track = 0;
353 else
354 viewer->selected_track = playlist_get_display_index() - 1;
357 if (!update_playlist(true))
358 return false;
359 return true;
362 /* Format trackname for display purposes */
363 static void format_name(char* dest, const char* src)
365 switch (global_settings.playlist_viewer_track_display)
367 case 0:
368 default:
370 /* Only display the filename */
371 char* p = strrchr(src, '/');
373 strcpy(dest, p+1);
375 /* Remove the extension */
376 strrsplt(dest, '.');
378 break;
380 case 1:
381 /* Full path */
382 strcpy(dest, src);
383 break;
387 /* Format display line */
388 static void format_line(const struct playlist_entry* track, char* str,
389 int len)
391 char name[MAX_PATH];
392 char *skipped = "";
394 format_name(name, track->name);
396 if (track->skipped)
397 skipped = "(ERR) ";
399 if (global_settings.playlist_viewer_indices)
400 /* Display playlist index */
401 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
402 else
403 snprintf(str, len, "%s%s", skipped, name);
407 /* Update playlist in case something has changed or forced */
408 static bool update_playlist(bool force)
410 if (!viewer.playlist)
411 playlist_get_resume_info(&viewer.current_playing_track);
412 else
413 viewer.current_playing_track = -1;
414 int nb_tracks=playlist_amount_ex(viewer.playlist);
415 force=force || nb_tracks != viewer.num_tracks;
416 if (force)
418 /* Reload tracks */
419 viewer.num_tracks = nb_tracks;
420 if (viewer.num_tracks <= 0)
421 return false;
422 playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD);
423 if (viewer.buffer.num_loaded <= 0)
424 return false;
426 return true;
429 /* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
430 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
431 changed. */
432 static int onplay_menu(int index)
434 int result, ret = 0;
435 struct playlist_entry * current_track=
436 playlist_buffer_get_track(&viewer.buffer, index);
437 MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL,
438 ID2P(LANG_REMOVE), ID2P(LANG_MOVE),
439 ID2P(LANG_CATALOG_ADD_TO), ID2P(LANG_CATALOG_ADD_TO_NEW));
440 bool current = (current_track->index == viewer.current_playing_track);
442 result = do_menu(&menu_items, NULL, NULL, false);
443 if (result == MENU_ATTACHED_USB)
445 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 #if CONFIG_CODEC != SWCODEC
471 talk_buffer_steal(); /* will use the mp3 buffer */
472 #endif
473 audio_play(0);
474 viewer.current_playing_track = -1;
478 ret = 1;
479 break;
480 case 1:
481 /* move track */
482 viewer.move_track = current_track->index;
483 ret = 0;
484 break;
485 case 2: /* add to catalog */
486 case 3: /* add to a new one */
487 catalog_add_to_a_playlist(current_track->name,
488 FILE_ATTR_AUDIO,
489 result==3, NULL);
490 ret = 0;
491 break;
494 return ret;
497 /* Menu of viewer options. Invoked via F1(r) or Menu(p). */
498 MENUITEM_SETTING(show_icons, &global_settings.playlist_viewer_icons, NULL);
499 MENUITEM_SETTING(show_indices, &global_settings.playlist_viewer_indices, NULL);
500 MENUITEM_SETTING(track_display,
501 &global_settings.playlist_viewer_track_display, NULL);
502 MENUITEM_FUNCTION(save_playlist_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
503 save_playlist_func, 0, NULL, Icon_NOICON);
504 MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS),
505 NULL, Icon_Playlist,
506 &show_icons, &show_indices, &track_display, &save_playlist_item);
507 static bool viewer_menu(void)
509 return do_menu(&viewer_settings_menu, NULL, NULL, false) == MENU_ATTACHED_USB;
512 /* Save playlist to disk */
513 static int save_playlist_func(void)
515 save_playlist_screen(viewer.playlist);
516 return 0;
519 /* View current playlist */
520 bool playlist_viewer(void)
522 return playlist_viewer_ex(NULL);
525 static int get_track_num( struct playlist_viewer * local_viewer,
526 int selected_item )
528 if( local_viewer->move_track >= 0 )
530 if( local_viewer->selected_track == selected_item )
532 return local_viewer->move_track;
534 else if( local_viewer->selected_track > selected_item
535 && selected_item >= local_viewer->move_track )
537 return selected_item+1;
539 else if( local_viewer->selected_track < selected_item
540 && selected_item <= local_viewer->move_track )
542 return selected_item-1;
545 return selected_item;
548 static char *playlist_callback_name(int selected_item,
549 void *data,
550 char *buffer,
551 size_t buffer_len)
553 struct playlist_viewer * local_viewer = (struct playlist_viewer *)data;
555 int track_num = get_track_num(local_viewer, selected_item);
556 struct playlist_entry *track =
557 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
559 format_line(track, buffer, buffer_len);
561 return(buffer);
565 static int playlist_callback_icons(int selected_item, void *data)
567 struct playlist_viewer * local_viewer=(struct playlist_viewer *)data;
569 int track_num = get_track_num(local_viewer, selected_item);
570 struct playlist_entry *track=
571 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
573 if (track->index == local_viewer->current_playing_track)
575 /* Current playing track */
576 return Icon_Audio;
578 else if (track->index == local_viewer->move_track)
580 /* Track we are moving */
581 return Icon_Moving;
583 else if (track->queued)
585 /* Queued track */
586 return Icon_Queued;
588 else
589 return Icon_NOICON;
592 /* Main viewer function. Filename identifies playlist to be viewed. If NULL,
593 view current playlist. */
594 bool playlist_viewer_ex(const char* filename)
596 bool ret = false; /* return value */
597 bool exit=false; /* exit viewer */
598 int button;
599 struct gui_synclist playlist_lists;
600 if (!playlist_viewer_init(&viewer, filename, false))
601 goto exit;
603 gui_synclist_init(&playlist_lists, playlist_callback_name,
604 &viewer, false, 1, NULL);
605 gui_synclist_set_icon_callback(&playlist_lists,
606 global_settings.playlist_viewer_icons?
607 &playlist_callback_icons:NULL);
608 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
609 gui_synclist_select_item(&playlist_lists, viewer.selected_track);
610 gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
611 gui_synclist_draw(&playlist_lists);
612 while (!exit)
614 int track;
616 if (global_status.resume_index != -1 && !viewer.playlist)
617 playlist_get_resume_info(&track);
618 else
619 track = -1;
621 if (track != viewer.current_playing_track ||
622 playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
624 /* Playlist has changed (new track started?) */
625 if (!update_playlist(false))
626 goto exit;
627 /*Needed because update_playlist gives wrong value when
628 playing is stopped*/
629 viewer.current_playing_track = track;
630 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
631 /* Abort move on playlist change */
632 viewer.move_track = -1;
633 gui_synclist_draw(&playlist_lists);
636 /* Timeout so we can determine if play status has changed */
637 button = get_action(CONTEXT_TREE,HZ/2);
638 if( (gui_synclist_do_button(&playlist_lists, &button,LIST_WRAP_UNLESS_HELD)) )
640 viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists);
641 if(playlist_buffer_needs_reload(&viewer.buffer,
642 viewer.selected_track))
643 playlist_buffer_load_entries_screen(&viewer.buffer,
644 button==ACTION_STD_NEXT?
645 FORWARD
647 BACKWARD
649 gui_synclist_draw(&playlist_lists);
651 switch (button)
653 case ACTION_TREE_WPS:
654 case ACTION_STD_CANCEL:
656 if (viewer.move_track >= 0)
658 viewer.selected_track = viewer.move_track;
659 gui_synclist_select_item(&playlist_lists, viewer.move_track);
660 viewer.move_track = -1;
661 gui_synclist_draw(&playlist_lists);
663 else
664 exit = true;
665 break;
667 case ACTION_STD_OK:
669 struct playlist_entry * current_track =
670 playlist_buffer_get_track(&viewer.buffer,
671 viewer.selected_track);
672 if (viewer.move_track >= 0)
674 /* Move track */
675 int ret_val;
677 ret_val = playlist_move(viewer.playlist, viewer.move_track,
678 current_track->index);
679 if (ret_val < 0)
680 splashf(HZ, (unsigned char *)"%s %s", str(LANG_MOVE),
681 str(LANG_FAILED));
682 update_playlist(true);
683 viewer.move_track = -1;
685 else if (!viewer.playlist)
687 /* play new track */
688 playlist_start(current_track->index, 0);
689 update_playlist(false);
691 else
693 /* New playlist */
694 if (playlist_set_current(viewer.playlist) < 0)
695 goto exit;
697 playlist_start(current_track->index, 0);
699 /* Our playlist is now the current list */
700 if (!playlist_viewer_init(&viewer, NULL, true))
701 goto exit;
703 gui_synclist_draw(&playlist_lists);
705 break;
707 case ACTION_STD_CONTEXT:
709 /* ON+PLAY menu */
710 int ret_val;
712 ret_val = onplay_menu(viewer.selected_track);
714 if (ret_val < 0)
716 ret = true;
717 goto exit;
719 else if (ret > 0)
721 /* Playlist changed */
722 gui_synclist_del_item(&playlist_lists);
723 update_playlist(true);
724 if (viewer.num_tracks <= 0)
725 exit = true;
726 if(viewer.selected_track >= viewer.num_tracks)
727 viewer.selected_track = viewer.num_tracks-1;
729 gui_synclist_draw(&playlist_lists);
730 break;
732 case ACTION_STD_MENU:
733 if (viewer_menu())
735 ret = true;
736 goto exit;
738 gui_synclist_set_icon_callback(
739 &playlist_lists,
740 global_settings.playlist_viewer_icons?
741 &playlist_callback_icons:NULL
743 gui_synclist_draw(&playlist_lists);
744 break;
746 default:
747 if(default_event_handler(button) == SYS_USB_CONNECTED)
749 ret = true;
750 goto exit;
752 break;
756 exit:
757 if (viewer.playlist)
758 playlist_close(viewer.playlist);
759 return ret;
762 static char *playlist_search_callback_name(int selected_item, void * data,
763 char *buffer, size_t buffer_len)
765 (void)buffer_len; /* this should probably be used */
766 int *found_indicies = (int*)data;
767 static struct playlist_track_info track;
768 playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track);
769 format_name(buffer, track.filename);
770 return(buffer);
773 bool search_playlist(void)
775 char search_str[32] = "";
776 bool ret = false, exit = false;
777 int i, playlist_count;
778 int found_indicies[MAX_PLAYLIST_ENTRIES];
779 int found_indicies_count = 0, last_found_count = -1;
780 int button;
781 struct gui_synclist playlist_lists;
782 struct playlist_track_info track;
784 if (!playlist_viewer_init(&viewer, 0, false))
785 return ret;
786 if (kbd_input(search_str, sizeof(search_str)) == -1)
787 return ret;
788 lcd_clear_display();
789 playlist_count = playlist_amount_ex(viewer.playlist);
791 cpu_boost(true);
793 for (i=0; (i<playlist_count)&&(found_indicies_count<MAX_PLAYLIST_ENTRIES); i++)
795 if (found_indicies_count != last_found_count)
797 splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), found_indicies_count,
798 str(LANG_OFF_ABORT));
799 last_found_count = found_indicies_count;
802 if (action_userabort(TIMEOUT_NOBLOCK))
803 break;
805 playlist_get_track_info(viewer.playlist, i, &track);
807 if (strcasestr(track.filename,search_str))
808 found_indicies[found_indicies_count++] = track.index;
810 yield();
813 cpu_boost(false);
815 if (!found_indicies_count)
817 return ret;
819 backlight_on();
821 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
822 found_indicies, false, 1, NULL);
823 gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON);
824 gui_synclist_set_icon_callback(&playlist_lists, NULL);
825 gui_synclist_set_nb_items(&playlist_lists, found_indicies_count);
826 gui_synclist_select_item(&playlist_lists, 0);
827 gui_synclist_draw(&playlist_lists);
828 while (!exit)
830 button = get_action(CONTEXT_LIST, HZ/4);
831 if (gui_synclist_do_button(&playlist_lists, &button, LIST_WRAP_UNLESS_HELD))
832 continue;
833 switch (button)
835 case ACTION_STD_CANCEL:
836 exit = true;
837 break;
839 case ACTION_STD_OK:
840 playlist_start(
841 found_indicies[gui_synclist_get_sel_pos(&playlist_lists)]
842 ,0);
843 exit = 1;
844 break;
846 default:
847 if(default_event_handler(button) == SYS_USB_CONNECTED)
849 ret = true;
850 exit = true;
852 break;
855 return ret;