Small improvements to the just committed midiplay.tex in wording and spelling. Thanks...
[kugel-rb.git] / apps / playlist_viewer.c
blobb910ca449bd34887634bf05d7a5ce073f4c83862
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 "filetypes.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 "playlist_catalog.h"
47 #include "icon.h"
48 #include "list.h"
49 #include "statusbar.h"
50 #include "splash.h"
51 #include "playlist_menu.h"
52 #include "action.h"
54 /* Maximum number of tracks we can have loaded at one time */
55 #define MAX_PLAYLIST_ENTRIES 200
57 /* The number of items between the selected one and the end/start of
58 * the buffer under which the buffer must reload */
59 #define MIN_BUFFER_MARGIN (screens[0].nb_lines+1)
61 /* Information about a specific track */
62 struct playlist_entry {
63 char *name; /* Formatted track name */
64 int index; /* Playlist index */
65 int display_index; /* Display index */
66 bool queued; /* Is track queued? */
67 bool skipped; /* Is track marked as bad? */
70 enum direction
72 FORWARD,
73 BACKWARD
76 struct playlist_buffer
78 char *name_buffer; /* Buffer used to store track names */
79 int buffer_size; /* Size of name buffer */
81 int first_index; /* Real index of first track loaded inside
82 the buffer */
84 enum direction direction; /* Direction of the buffer (if the buffer
85 was loaded BACKWARD, the last track in
86 the buffer has a real index < to the
87 real index of the the first track)*/
89 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
90 int num_loaded; /* Number of track entries loaded in buffer */
93 /* Global playlist viewer settings */
94 struct playlist_viewer {
95 struct playlist_info* playlist; /* playlist being viewed */
96 int num_tracks; /* Number of tracks in playlist */
97 int current_playing_track; /* Index of current playing track */
98 int selected_track; /* The selected track, relative (first is 0)*/
99 int move_track; /* Playlist index of track to move or -1 */
100 struct playlist_buffer buffer;
103 static struct playlist_viewer viewer;
105 /* Used when viewing playlists on disk */
106 static struct playlist_info temp_playlist;
108 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
109 int names_buffer_size);
110 static void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
111 enum direction direction);
112 static int playlist_entry_load(struct playlist_entry *entry, int index,
113 char* name_buffer, int remaining_size);
115 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
116 int index);
118 static bool playlist_viewer_init(struct playlist_viewer * viewer,
119 const char* filename, bool reload);
121 static void format_name(char* dest, const char* src);
122 static void format_line(const struct playlist_entry* track, char* str,
123 int len);
125 static bool update_playlist(bool force);
126 static int onplay_menu(int index);
127 static bool viewer_menu(void);
128 static int save_playlist_func(void);
130 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
131 int names_buffer_size)
133 pb->name_buffer=names_buffer;
134 pb->buffer_size=names_buffer_size;
135 pb->first_index=0;
136 pb->num_loaded=0;
140 * Loads the entries following 'index' in the playlist buffer
142 static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index,
143 enum direction direction)
145 int num_entries = viewer.num_tracks;
146 char* p = pb->name_buffer;
147 int remaining = pb->buffer_size;
148 int i;
150 pb->first_index = index;
151 if (num_entries > MAX_PLAYLIST_ENTRIES)
152 num_entries = MAX_PLAYLIST_ENTRIES;
154 for(i=0; i<num_entries; i++)
156 int len = playlist_entry_load(&(pb->tracks[i]), index, p, remaining);
157 if (len < 0)
159 /* Out of name buffer space */
160 num_entries = i;
161 break;
164 p += len;
165 remaining -= len;
167 if(direction==FORWARD)
168 index++;
169 else
170 index--;
171 index+=viewer.num_tracks;
172 index%=viewer.num_tracks;
174 pb->direction=direction;
175 pb->num_loaded = i;
178 static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
179 enum direction direction)
181 if(direction==FORWARD)
183 int min_start=viewer.selected_track-2*screens[0].nb_lines;
184 while(min_start<0)
185 min_start+=viewer.num_tracks;
186 min_start %= viewer.num_tracks;
187 playlist_buffer_load_entries(pb, min_start, FORWARD);
189 else
191 int max_start=viewer.selected_track+2*screens[0].nb_lines;
192 max_start%=viewer.num_tracks;
193 playlist_buffer_load_entries(pb, max_start, BACKWARD);
197 static int playlist_entry_load(struct playlist_entry *entry, int index,
198 char* name_buffer, int remaining_size)
200 struct playlist_track_info info;
201 int len;
203 /* Playlist viewer orders songs based on display index. We need to
204 convert to real playlist index to access track */
205 index = (index + playlist_get_first_index(viewer.playlist)) %
206 viewer.num_tracks;
207 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
208 return -1;
210 len = strlen(info.filename) + 1;
212 if (len <= remaining_size)
214 strcpy(name_buffer, info.filename);
216 entry->name = name_buffer;
217 entry->index = info.index;
218 entry->display_index = info.display_index;
219 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
220 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
221 return len;
223 return -1;
226 static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
228 int buffer_index;
229 if(pb->direction==FORWARD)
231 if(index>=pb->first_index)
232 buffer_index=index-pb->first_index;
233 else /* rotation : track0 in buffer + requested track */
234 buffer_index=(viewer.num_tracks-pb->first_index)+(index);
236 else
238 if(index<=pb->first_index)
239 buffer_index=pb->first_index-index;
240 else /* rotation : track0 in buffer + dist from the last track
241 to the requested track (num_tracks-requested track) */
242 buffer_index=(pb->first_index)+(viewer.num_tracks-index);
244 return(buffer_index);
247 #define distance(a, b) \
248 a>b? (a) - (b) : (b) - (a)
249 static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
250 int track_index)
252 if(pb->num_loaded==viewer.num_tracks)
253 return(false);
254 int selected_index=playlist_buffer_get_index(pb, track_index);
255 int first_buffer_index=playlist_buffer_get_index(pb, pb->first_index);
256 int distance_beginning=distance(selected_index, first_buffer_index);
257 if(distance_beginning<MIN_BUFFER_MARGIN)
258 return(true);
260 if(pb->num_loaded - distance_beginning < MIN_BUFFER_MARGIN)
261 return(true);
262 return(false);
265 static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
266 int index)
268 int buffer_index=playlist_buffer_get_index(pb, index);
269 return(&(pb->tracks[buffer_index]));
272 /* Initialize the playlist viewer. */
273 static bool playlist_viewer_init(struct playlist_viewer * viewer,
274 const char* filename, bool reload)
276 char* buffer;
277 size_t buffer_size;
278 bool is_playing = audio_status() & (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE);
279 bool have_list = filename || is_playing;
280 if (!have_list && (global_status.resume_index != -1))
282 /* Try to restore the list from control file */
283 have_list = (playlist_resume() != -1);
285 if (!have_list && (playlist_amount() > 0))
287 /*If dynamic playlist still exists, view it anyway even
288 if playback has reached the end of the playlist */
289 have_list = true;
291 if (!have_list)
293 /* Nothing to view, exit */
294 gui_syncsplash(HZ, str(LANG_CATALOG_NO_PLAYLISTS));
295 return false;
298 buffer = plugin_get_buffer(&buffer_size);
299 if (!buffer)
300 return false;
302 if (!filename)
303 viewer->playlist = NULL;
304 else
306 /* Viewing playlist on disk */
307 const char *dir, *file;
308 char *temp_ptr;
309 char *index_buffer = NULL;
310 ssize_t index_buffer_size = 0;
312 viewer->playlist = &temp_playlist;
314 /* Separate directory from filename */
315 temp_ptr = strrchr(filename+1,'/');
316 if (temp_ptr)
318 *temp_ptr = 0;
319 dir = filename;
320 file = temp_ptr + 1;
322 else
324 dir = "/";
325 file = filename+1;
328 if (is_playing)
330 /* Something is playing, use half the plugin buffer for playlist
331 indices */
332 index_buffer_size = buffer_size / 2;
333 index_buffer = buffer;
336 playlist_create_ex(viewer->playlist, dir, file, index_buffer,
337 index_buffer_size, buffer+index_buffer_size,
338 buffer_size-index_buffer_size);
340 if (temp_ptr)
341 *temp_ptr = '/';
343 buffer += index_buffer_size;
344 buffer_size -= index_buffer_size;
346 playlist_buffer_init(&viewer->buffer, buffer, buffer_size );
348 viewer->move_track = -1;
350 if (!reload)
352 if (viewer->playlist)
353 viewer->selected_track = 0;
354 else
355 viewer->selected_track = playlist_get_display_index() - 1;
358 if (!update_playlist(true))
359 return false;
360 return true;
363 /* Format trackname for display purposes */
364 static void format_name(char* dest, const char* src)
366 switch (global_settings.playlist_viewer_track_display)
368 case 0:
369 default:
371 /* Only display the filename */
372 char* p = strrchr(src, '/');
374 strcpy(dest, p+1);
376 /* Remove the extension */
377 strrsplt(dest, '.');
379 break;
381 case 1:
382 /* Full path */
383 strcpy(dest, src);
384 break;
388 /* Format display line */
389 static void format_line(const struct playlist_entry* track, char* str,
390 int len)
392 char name[MAX_PATH];
393 char *skipped = "";
395 format_name(name, track->name);
397 if (track->skipped)
398 skipped = "(ERR) ";
400 if (global_settings.playlist_viewer_indices)
401 /* Display playlist index */
402 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
403 else
404 snprintf(str, len, "%s%s", skipped, name);
408 /* Update playlist in case something has changed or forced */
409 static bool update_playlist(bool force)
411 if (!viewer.playlist)
412 playlist_get_resume_info(&viewer.current_playing_track);
413 else
414 viewer.current_playing_track = -1;
415 int nb_tracks=playlist_amount_ex(viewer.playlist);
416 force=force || nb_tracks != viewer.num_tracks;
417 if (force)
419 /* Reload tracks */
420 viewer.num_tracks = nb_tracks;
421 if (viewer.num_tracks <= 0)
422 return false;
423 playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD);
424 if (viewer.buffer.num_loaded <= 0)
425 return false;
427 return true;
430 /* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
431 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
432 changed. */
433 static int onplay_menu(int index)
435 int result, ret = 0;
436 struct playlist_entry * current_track=
437 playlist_buffer_get_track(&viewer.buffer, index);
438 MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL,
439 ID2P(LANG_REMOVE), ID2P(LANG_MOVE),
440 ID2P(LANG_CATALOG_ADD_TO), ID2P(LANG_CATALOG_ADD_TO_NEW));
441 bool current = (current_track->index == viewer.current_playing_track);
443 result = do_menu(&menu_items, NULL, NULL, false);
444 if (result == MENU_ATTACHED_USB)
446 ret = -1;
448 else if (result >= 0)
450 /* Abort current move */
451 viewer.move_track = -1;
453 switch (result)
455 case 0:
456 /* delete track */
457 playlist_delete(viewer.playlist, current_track->index);
458 if (current)
460 if (playlist_amount_ex(viewer.playlist) <= 0)
461 audio_stop();
462 else
464 /* Start playing new track except if it's the lasttrack
465 track in the playlist and repeat mode is disabled */
466 current_track =
467 playlist_buffer_get_track(&viewer.buffer, index);
468 if (current_track->display_index!=viewer.num_tracks ||
469 global_settings.repeat_mode == REPEAT_ALL)
471 #if CONFIG_CODEC != SWCODEC
472 talk_buffer_steal(); /* will use the mp3 buffer */
473 #endif
474 audio_play(0);
475 viewer.current_playing_track = -1;
479 ret = 1;
480 break;
481 case 1:
482 /* move track */
483 viewer.move_track = current_track->index;
484 ret = 0;
485 break;
486 case 2: /* add to catalog */
487 case 3: /* add to a new one */
488 catalog_add_to_a_playlist(current_track->name,
489 FILE_ATTR_AUDIO,
490 result==3, NULL);
491 ret = 0;
492 break;
495 return ret;
498 /* Menu of viewer options. Invoked via F1(r) or Menu(p). */
499 MENUITEM_SETTING(show_icons, &global_settings.playlist_viewer_icons, NULL);
500 MENUITEM_SETTING(show_indices, &global_settings.playlist_viewer_indices, NULL);
501 MENUITEM_SETTING(track_display,
502 &global_settings.playlist_viewer_track_display, NULL);
503 MENUITEM_FUNCTION(save_playlist_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
504 save_playlist_func, 0, NULL, Icon_NOICON);
505 MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS),
506 NULL, Icon_Playlist,
507 &show_icons, &show_indices, &track_display, &save_playlist_item);
508 static bool viewer_menu(void)
510 return do_menu(&viewer_settings_menu, NULL, NULL, false) == MENU_ATTACHED_USB;
513 /* Save playlist to disk */
514 static int save_playlist_func(void)
516 save_playlist_screen(viewer.playlist);
517 return 0;
520 /* View current playlist */
521 bool playlist_viewer(void)
523 return playlist_viewer_ex(NULL);
526 static int get_track_num( struct playlist_viewer * local_viewer,
527 int selected_item )
529 if( local_viewer->move_track >= 0 )
531 if( local_viewer->selected_track == selected_item )
533 return local_viewer->move_track;
535 else if( local_viewer->selected_track > selected_item
536 && selected_item >= local_viewer->move_track )
538 return selected_item+1;
540 else if( local_viewer->selected_track < selected_item
541 && selected_item <= local_viewer->move_track )
543 return selected_item-1;
546 return selected_item;
549 static char *playlist_callback_name(int selected_item,
550 void *data,
551 char *buffer,
552 size_t buffer_len)
554 struct playlist_viewer * local_viewer = (struct playlist_viewer *)data;
556 int track_num = get_track_num(local_viewer, selected_item);
557 struct playlist_entry *track =
558 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
560 format_line(track, buffer, buffer_len);
562 return(buffer);
566 static int playlist_callback_icons(int selected_item, void *data)
568 struct playlist_viewer * local_viewer=(struct playlist_viewer *)data;
570 int track_num = get_track_num(local_viewer, selected_item);
571 struct playlist_entry *track=
572 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
574 if (track->index == local_viewer->current_playing_track)
576 /* Current playing track */
577 return Icon_Audio;
579 else if (track->index == local_viewer->move_track)
581 /* Track we are moving */
582 return Icon_Moving;
584 else if (track->queued)
586 /* Queued track */
587 return Icon_Queued;
589 else
590 return Icon_NOICON;
593 /* Main viewer function. Filename identifies playlist to be viewed. If NULL,
594 view current playlist. */
595 bool playlist_viewer_ex(const char* filename)
597 bool ret = false; /* return value */
598 bool exit=false; /* exit viewer */
599 int button;
600 struct gui_synclist playlist_lists;
601 if (!playlist_viewer_init(&viewer, filename, false))
602 goto exit;
604 gui_synclist_init(&playlist_lists, playlist_callback_name,
605 &viewer, false, 1, NULL);
606 gui_synclist_set_icon_callback(&playlist_lists,
607 global_settings.playlist_viewer_icons?
608 &playlist_callback_icons:NULL);
609 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
610 gui_synclist_select_item(&playlist_lists, viewer.selected_track);
611 gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
612 gui_synclist_draw(&playlist_lists);
613 while (!exit)
615 int track;
617 if (global_status.resume_index != -1 && !viewer.playlist)
618 playlist_get_resume_info(&track);
619 else
620 track = -1;
622 if (track != viewer.current_playing_track ||
623 playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
625 /* Playlist has changed (new track started?) */
626 if (!update_playlist(false))
627 goto exit;
628 /*Needed because update_playlist gives wrong value when
629 playing is stopped*/
630 viewer.current_playing_track = track;
631 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
632 /* Abort move on playlist change */
633 viewer.move_track = -1;
634 gui_synclist_draw(&playlist_lists);
637 /* Timeout so we can determine if play status has changed */
638 button = get_action(CONTEXT_TREE,HZ/2);
639 if( (gui_synclist_do_button(&playlist_lists, &button,LIST_WRAP_UNLESS_HELD)) )
641 viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists);
642 if(playlist_buffer_needs_reload(&viewer.buffer,
643 viewer.selected_track))
644 playlist_buffer_load_entries_screen(&viewer.buffer,
645 button==ACTION_STD_NEXT?
646 FORWARD
648 BACKWARD
650 gui_synclist_draw(&playlist_lists);
652 switch (button)
654 case ACTION_TREE_WPS:
655 case ACTION_STD_CANCEL:
657 if (viewer.move_track >= 0)
659 viewer.selected_track = viewer.move_track;
660 gui_synclist_select_item(&playlist_lists, viewer.move_track);
661 viewer.move_track = -1;
662 gui_synclist_draw(&playlist_lists);
664 else
665 exit = true;
666 break;
668 case ACTION_STD_OK:
670 struct playlist_entry * current_track =
671 playlist_buffer_get_track(&viewer.buffer,
672 viewer.selected_track);
673 if (viewer.move_track >= 0)
675 /* Move track */
676 int ret_val;
678 ret_val = playlist_move(viewer.playlist, viewer.move_track,
679 current_track->index);
680 if (ret_val < 0)
681 gui_syncsplash(HZ, (unsigned char *)"%s %s",
682 str(LANG_MOVE), str(LANG_FAILED));
683 update_playlist(true);
684 viewer.move_track = -1;
686 else if (!viewer.playlist)
688 /* play new track */
689 playlist_start(current_track->index, 0);
690 update_playlist(false);
692 else
694 /* New playlist */
695 if (playlist_set_current(viewer.playlist) < 0)
696 goto exit;
698 playlist_start(current_track->index, 0);
700 /* Our playlist is now the current list */
701 if (!playlist_viewer_init(&viewer, NULL, true))
702 goto exit;
704 gui_synclist_draw(&playlist_lists);
706 break;
708 case ACTION_STD_CONTEXT:
710 /* ON+PLAY menu */
711 int ret_val;
713 ret_val = onplay_menu(viewer.selected_track);
715 if (ret_val < 0)
717 ret = true;
718 goto exit;
720 else if (ret > 0)
722 /* Playlist changed */
723 gui_synclist_del_item(&playlist_lists);
724 update_playlist(true);
725 if (viewer.num_tracks <= 0)
726 exit = true;
727 if(viewer.selected_track >= viewer.num_tracks)
728 viewer.selected_track = viewer.num_tracks-1;
730 gui_synclist_draw(&playlist_lists);
731 break;
733 case ACTION_STD_MENU:
734 if (viewer_menu())
736 ret = true;
737 goto exit;
739 gui_synclist_set_icon_callback(
740 &playlist_lists,
741 global_settings.playlist_viewer_icons?
742 &playlist_callback_icons:NULL
744 gui_synclist_draw(&playlist_lists);
745 break;
747 case ACTION_NONE:
748 gui_syncstatusbar_draw(&statusbars, false);
749 break;
751 default:
752 if(default_event_handler(button) == SYS_USB_CONNECTED)
754 ret = true;
755 goto exit;
757 break;
761 exit:
762 if (viewer.playlist)
763 playlist_close(viewer.playlist);
764 return ret;
767 static char *playlist_search_callback_name(int selected_item, void * data,
768 char *buffer, size_t buffer_len)
770 (void)buffer_len; /* this should probably be used */
771 int *found_indicies = (int*)data;
772 static struct playlist_track_info track;
773 playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track);
774 format_name(buffer, track.filename);
775 return(buffer);
778 bool search_playlist(void)
780 char search_str[32] = "";
781 bool ret = false, exit = false;
782 int i, playlist_count;
783 int found_indicies[MAX_PLAYLIST_ENTRIES],found_indicies_count = 0;
784 int button;
785 struct gui_synclist playlist_lists;
786 struct playlist_track_info track;
788 if (!playlist_viewer_init(&viewer, 0, false))
789 return ret;
790 if (kbd_input(search_str,sizeof(search_str)) == -1)
791 return ret;
792 lcd_clear_display();
793 playlist_count = playlist_amount_ex(viewer.playlist);
794 for (i=0;(i<playlist_count)&&(found_indicies_count<MAX_PLAYLIST_ENTRIES);i++)
796 gui_syncsplash(0, str(LANG_PLAYLIST_SEARCH_MSG),found_indicies_count,
797 str(LANG_OFF_ABORT));
798 if (action_userabort(TIMEOUT_NOBLOCK))
800 if (!found_indicies_count)
801 return ret;
802 break;
804 playlist_get_track_info(viewer.playlist,i,&track);
805 if (strcasestr(track.filename,search_str))
807 found_indicies[found_indicies_count++] = track.index;
810 if (!found_indicies_count)
812 return ret;
814 backlight_on();
815 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
816 found_indicies, false, 1, NULL);
817 gui_synclist_set_icon_callback(&playlist_lists, NULL);
818 gui_synclist_set_nb_items(&playlist_lists, found_indicies_count);
819 gui_synclist_select_item(&playlist_lists, 0);
820 gui_synclist_draw(&playlist_lists);
821 while (!exit)
823 button = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
824 if (gui_synclist_do_button(&playlist_lists, &button, LIST_WRAP_UNLESS_HELD))
825 continue;
826 switch (button)
828 case ACTION_STD_CANCEL:
829 exit = true;
830 break;
832 case ACTION_STD_OK:
833 playlist_start(
834 found_indicies[gui_synclist_get_sel_pos(&playlist_lists)]
835 ,0);
836 exit = 1;
837 break;
838 case ACTION_NONE:
839 break;
840 default:
841 if(default_event_handler(button) == SYS_USB_CONNECTED)
843 ret = true;
844 exit = true;
846 break;
849 return ret;