1 /***************************************************************************
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
37 #ifdef HAVE_LCD_BITMAP
43 #include "playlist_viewer.h"
45 /* Defines for LCD display purposes. Taken from tree.c */
46 #ifdef HAVE_LCD_BITMAP
47 #define CURSOR_X (global_settings.scrollbar && \
48 viewer.num_tracks>viewer.num_display_lines?1:0)
50 #define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)
52 #define ICON_WIDTH ((viewer.char_width > 6) ? viewer.char_width : 6)
54 #define MARGIN_X ((global_settings.scrollbar && \
55 viewer.num_tracks > viewer.num_display_lines ? \
56 SCROLLBAR_WIDTH : 0) + CURSOR_WIDTH + \
57 (global_settings.playlist_viewer_icons ? \
59 #define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
62 #define LINE_Y (global_settings.statusbar ? 1 : 0)
65 #define SCROLLBAR_Y lcd_getymargin()
66 #define SCROLLBAR_WIDTH 6
76 /* Maximum number of tracks we can have loaded at one time */
77 #define MAX_PLAYLIST_ENTRIES 200
79 /* Default playlist name for saving */
80 #define DEFAULT_PLAYLIST_NAME "/viewer.m3u"
82 /* Index of track on display line _pos */
83 #define INDEX(_pos) (viewer.first_display_index - viewer.first_index + (_pos))
85 /* Global playlist viewer settings */
86 struct playlist_viewer_info
{
87 struct playlist_info
* playlist
; /* playlist being viewed */
88 char *name_buffer
; /* Buffer used to store track names */
89 int buffer_size
; /* Size of name buffer */
91 int num_display_lines
; /* Number of lines on lcd */
92 int line_height
; /* Height (in pixels) of display line */
93 int char_width
; /* Width (in pixels) of a character */
95 int num_tracks
; /* Number of tracks in playlist */
96 int current_playing_track
; /* Index of current playing track */
98 int num_loaded
; /* Number of track entries loaded in viewer */
99 int first_index
; /* Index of first loaded track */
100 int last_index
; /* Index of last loaded track */
101 int first_display_index
; /* Index of first track on display */
102 int last_display_index
; /* Index of last track on display */
103 int cursor_pos
; /* Line number of cursor */
105 int move_track
; /* Playlist index of track to move or -1 */
108 /* Information about a specific track */
109 struct playlist_entry
{
110 char *name
; /* Formatted track name */
111 int index
; /* Playlist index */
112 int display_index
; /* Display index */
113 bool queued
; /* Is track queued? */
116 static struct playlist_viewer_info viewer
;
117 static struct playlist_entry tracks
[MAX_PLAYLIST_ENTRIES
];
119 /* Used when viewing playlists on disk */
120 static struct playlist_info temp_playlist
;
122 static bool initialize(char* filename
, bool reload
);
123 static void load_playlist_entries(int start_index
);
124 static void load_playlist_entries_r(int end_index
);
125 static int load_entry(int index
, int pos
, char* p
, int size
);
126 static void format_name(char* dest
, const char* src
);
127 static void format_line(const struct playlist_entry
* track
, char* str
, int len
);
128 static void display_playlist(void);
129 static void update_display_line(int line
, bool scroll
);
130 static void scroll_display(int lines
);
131 static void update_first_index(void);
132 static bool update_playlist(bool force
);
133 static int onplay_menu(int index
);
134 static bool viewer_menu(void);
135 static bool show_icons(void);
136 static bool show_indices(void);
137 static bool track_display(void);
138 static bool save_playlist(void);
140 /* Initialize the playlist viewer. */
141 static bool initialize(char* filename
, bool reload
)
145 bool is_playing
= mpeg_status() & MPEG_STATUS_PLAY
;
147 if (!filename
&& !is_playing
)
148 /* Nothing is playing, exit */
151 buffer
= plugin_get_buffer(&buffer_size
);
156 viewer
.playlist
= NULL
;
159 /* Viewing playlist on disk */
160 char *dir
, *file
, *temp_ptr
;
161 char *index_buffer
= NULL
;
162 int index_buffer_size
= 0;
164 viewer
.playlist
= &temp_playlist
;
166 /* Separate directory from filename */
167 temp_ptr
= strrchr(filename
+1,'/');
182 /* Something is playing, use half the plugin buffer for playlist
184 index_buffer_size
= buffer_size
/ 2;
185 index_buffer
= buffer
;
188 playlist_create_ex(viewer
.playlist
, dir
, file
, index_buffer
,
189 index_buffer_size
, buffer
+index_buffer_size
,
190 buffer_size
-index_buffer_size
);
195 buffer
+= index_buffer_size
;
196 buffer_size
-= index_buffer_size
;
199 viewer
.name_buffer
= buffer
;
200 viewer
.buffer_size
= buffer_size
;
202 #ifdef HAVE_LCD_BITMAP
204 char icon_chars
[] = "MQ"; /* characters used as icons */
207 viewer
.char_width
= 0;
208 viewer
.line_height
= 0;
210 /* Use icon characters to calculate largest possible width/height so
211 that we set proper margins */
212 for (i
=0; i
<sizeof(icon_chars
); i
++)
217 snprintf(str
, sizeof(str
), "%c", icon_chars
[i
]);
218 lcd_getstringsize(str
, &w
, &h
);
220 if (w
> viewer
.char_width
)
221 viewer
.char_width
= w
;
223 if (h
> viewer
.line_height
)
225 viewer
.line_height
= h
;
226 viewer
.num_display_lines
= (LCD_HEIGHT
- MARGIN_Y
)/h
;
231 viewer
.num_display_lines
= 2;
232 viewer
.char_width
= 1;
233 viewer
.line_height
= 1;
236 viewer
.move_track
= -1;
240 viewer
.cursor_pos
= 0;
242 if (!viewer
.playlist
)
243 /* Start displaying at current playing track */
244 viewer
.first_display_index
= playlist_get_display_index() - 1;
246 viewer
.first_display_index
= 0;
248 update_first_index();
251 if (!update_playlist(true))
257 /* Load tracks starting at start_index */
258 static void load_playlist_entries(int start_index
)
260 int num_entries
= viewer
.num_tracks
- start_index
;
261 char* p
= viewer
.name_buffer
;
262 int remaining
= viewer
.buffer_size
;
265 viewer
.first_index
= start_index
;
267 if (num_entries
> MAX_PLAYLIST_ENTRIES
)
268 num_entries
= MAX_PLAYLIST_ENTRIES
;
270 for(i
=0; i
<num_entries
; i
++, start_index
++)
272 int len
= load_entry(start_index
, i
, p
, remaining
);
275 /* Out of name buffer space */
284 viewer
.num_loaded
= num_entries
;
285 viewer
.last_index
= viewer
.first_index
+ (viewer
.num_loaded
- 1);
288 /* Load tracks in reverse, ending at end_index */
289 static void load_playlist_entries_r(int end_index
)
291 int num_entries
= end_index
;
292 char* p
= viewer
.name_buffer
;
293 int remaining
= viewer
.buffer_size
;
296 viewer
.last_index
= end_index
;
298 if (num_entries
>= MAX_PLAYLIST_ENTRIES
)
299 num_entries
= MAX_PLAYLIST_ENTRIES
-1;
301 for(i
=num_entries
; i
>=0; i
--, end_index
--)
303 int len
= load_entry(end_index
, i
, p
, remaining
);
308 /* Out of name buffer space */
311 /* Shift loaded tracks up such that first track is index 0 */
312 for (j
=0; j
<num_entries
; j
++, i
++)
314 tracks
[j
].name
= tracks
[i
].name
;
315 tracks
[j
].index
= tracks
[i
].index
;
316 tracks
[j
].display_index
= tracks
[i
].display_index
;
317 tracks
[j
].queued
= tracks
[i
].queued
;
327 viewer
.first_index
= viewer
.last_index
- num_entries
;
330 if (!viewer
.first_index
&&
331 num_entries
< viewer
.num_tracks
&&
332 num_entries
< MAX_PLAYLIST_ENTRIES
)
334 /* Lets see if we can load more data at the end of the list */
335 int max
= viewer
.num_tracks
;
336 if (max
> MAX_PLAYLIST_ENTRIES
)
337 max
= MAX_PLAYLIST_ENTRIES
;
339 for (i
= num_entries
; i
<max
; i
++)
341 int len
= load_entry(num_entries
, num_entries
, p
, remaining
);
343 /* Out of name buffer space */
354 viewer
.num_loaded
= num_entries
;
357 /* Load track at playlist index. pos is the position in the tracks array and
358 p is a pointer to the name buffer (max size), Returns -1 if buffer is
360 static int load_entry(int index
, int pos
, char* p
, int size
)
362 struct playlist_track_info info
;
366 /* Playlist viewer orders songs based on display index. We need to
367 convert to real playlist index to access track */
368 index
= (index
+ playlist_get_first_index(viewer
.playlist
)) %
370 if (playlist_get_track_info(viewer
.playlist
, index
, &info
) < 0)
373 len
= strlen(info
.filename
) + 1;
377 strcpy(p
, info
.filename
);
379 tracks
[pos
].name
= p
;
380 tracks
[pos
].index
= info
.index
;
381 tracks
[pos
].display_index
= info
.display_index
;
382 tracks
[pos
].queued
= info
.attr
& PLAYLIST_ATTR_QUEUED
;
392 /* Format trackname for display purposes */
393 static void format_name(char* dest
, const char* src
)
395 switch (global_settings
.playlist_viewer_track_display
)
400 /* Only display the mp3 filename */
401 char* p
= strrchr(src
, '/');
407 /* Remove the extension */
408 if (!strcasecmp(&dest
[len
-4], ".mp3") ||
409 !strcasecmp(&dest
[len
-4], ".mp2") ||
410 !strcasecmp(&dest
[len
-4], ".mpa"))
422 /* Format display line */
423 static void format_line(const struct playlist_entry
* track
, char* str
, int len
)
427 format_name(name
, track
->name
);
429 if (global_settings
.playlist_viewer_indices
)
430 /* Display playlist index */
431 snprintf(str
, len
, "%d. %s", track
->display_index
, name
);
433 snprintf(str
, len
, "%s", name
);
437 /* Display tracks on screen */
438 static void display_playlist(void)
441 int num_display_tracks
=
442 viewer
.last_display_index
- viewer
.first_display_index
;
446 #ifdef HAVE_LCD_BITMAP
447 lcd_setmargins(MARGIN_X
, MARGIN_Y
);
448 lcd_setfont(FONT_UI
);
451 for (i
=0; i
<=num_display_tracks
; i
++)
453 if (global_settings
.playlist_viewer_icons
)
456 if (tracks
[INDEX(i
)].index
== viewer
.current_playing_track
)
458 /* Current playing track */
459 #ifdef HAVE_LCD_BITMAP
461 if ( viewer
.line_height
> 8 )
462 offset
= (viewer
.line_height
- 8) / 2;
463 lcd_bitmap(bitmap_icons_6x8
[File
],
464 CURSOR_X
* 6 + CURSOR_WIDTH
,
465 MARGIN_Y
+(i
*viewer
.line_height
) + offset
,
468 lcd_putc(LINE_X
-1, i
, File
);
471 else if (tracks
[INDEX(i
)].index
== viewer
.move_track
)
473 /* Track we are moving */
474 #ifdef HAVE_LCD_BITMAP
475 lcd_putsxy(CURSOR_X
* 6 + CURSOR_WIDTH
,
476 MARGIN_Y
+(i
*viewer
.line_height
), "M");
478 lcd_putc(LINE_X
-1, i
, 'M');
481 else if (tracks
[INDEX(i
)].queued
)
484 #ifdef HAVE_LCD_BITMAP
485 lcd_putsxy(CURSOR_X
* 6 + CURSOR_WIDTH
,
486 MARGIN_Y
+(i
*viewer
.line_height
), "Q");
488 lcd_putc(LINE_X
-1, i
, 'Q');
493 update_display_line(i
, false);
496 #ifdef HAVE_LCD_BITMAP
497 if (global_settings
.scrollbar
&&
498 (viewer
.num_tracks
> viewer
.num_display_lines
))
499 scrollbar(SCROLLBAR_X
, SCROLLBAR_Y
, SCROLLBAR_WIDTH
- 1,
500 LCD_HEIGHT
- SCROLLBAR_Y
, viewer
.num_tracks
-1,
501 viewer
.first_display_index
, viewer
.last_display_index
,
505 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, true);
509 /* Scroll cursor or display by num lines */
510 static void scroll_display(int lines
)
512 int new_index
= viewer
.first_display_index
+ viewer
.cursor_pos
+ lines
;
513 bool pagescroll
= false;
516 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, false);
518 if (lines
> 1 || lines
< -1)
523 /* Wrap around if not pageup */
528 new_index
+= viewer
.num_tracks
;
529 viewer
.cursor_pos
= viewer
.num_display_lines
-1;
533 else if (new_index
>= viewer
.num_tracks
)
535 /* Wrap around if not pagedown */
537 new_index
= viewer
.num_tracks
- 1;
540 new_index
-= viewer
.num_tracks
;
541 viewer
.cursor_pos
= 0;
546 if (new_index
>= viewer
.first_display_index
&&
547 new_index
<= viewer
.last_display_index
)
549 /* Just update the cursor */
550 viewer
.cursor_pos
= new_index
- viewer
.first_display_index
;
554 /* New track is outside of display */
556 viewer
.first_display_index
= new_index
;
558 viewer
.first_display_index
= viewer
.first_display_index
+ lines
;
560 if (viewer
.first_display_index
< 0)
561 viewer
.first_display_index
= 0;
563 viewer
.last_display_index
=
564 viewer
.first_display_index
+ (viewer
.num_display_lines
- 1);
565 if (viewer
.last_display_index
>= viewer
.num_tracks
)
567 /* display as many tracks as possible on screen */
568 if (viewer
.first_display_index
> 0)
570 viewer
.first_display_index
-=
571 (viewer
.last_display_index
- viewer
.num_tracks
+ 1);
572 if (viewer
.first_display_index
< 0)
573 viewer
.first_display_index
= 0;
576 viewer
.last_display_index
= viewer
.num_tracks
- 1;
579 if (viewer
.cursor_pos
>
580 (viewer
.last_display_index
- viewer
.first_display_index
))
582 viewer
.last_display_index
- viewer
.first_display_index
;
584 /* Load more data if needed */
585 if (viewer
.first_display_index
< viewer
.first_index
)
586 load_playlist_entries_r(viewer
.last_display_index
);
587 else if (viewer
.last_display_index
> viewer
.last_index
)
588 load_playlist_entries(viewer
.first_display_index
);
593 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, true);
596 /* Update lcd line. Scroll line if requested */
597 static void update_display_line(int line
, bool scroll
)
599 char str
[MAX_PATH
+ 16];
601 format_line(&tracks
[INDEX(line
)], str
, sizeof(str
));
605 #ifdef HAVE_LCD_BITMAP
606 if (global_settings
.invert_cursor
)
607 lcd_puts_scroll_style(LINE_X
, line
, str
, STYLE_INVERT
);
610 lcd_puts_scroll(LINE_X
, line
, str
);
613 lcd_puts(LINE_X
, line
, str
);
616 /* Update first index, if necessary, to put as much as possible on the
618 static void update_first_index(void)
620 /* viewer.num_tracks may be invalid at this point */
621 int num_tracks
= playlist_amount_ex(viewer
.playlist
);
623 if ((num_tracks
- viewer
.first_display_index
) < viewer
.num_display_lines
)
625 /* Try to display as much as possible */
626 int old_index
= viewer
.first_display_index
;
628 viewer
.first_display_index
= num_tracks
- viewer
.num_display_lines
;
629 if (viewer
.first_display_index
< 0)
630 viewer
.first_display_index
= 0;
632 /* Cursor should still point at current track */
633 viewer
.cursor_pos
+= old_index
- viewer
.first_display_index
;
637 /* Update playlist in case something has changed or forced */
638 static bool update_playlist(bool force
)
640 if (!viewer
.playlist
)
641 playlist_get_resume_info(&viewer
.current_playing_track
);
643 viewer
.current_playing_track
= -1;
645 if (force
|| playlist_amount_ex(viewer
.playlist
) != viewer
.num_tracks
)
650 viewer
.num_tracks
= playlist_amount_ex(viewer
.playlist
);
651 if (viewer
.num_tracks
< 0)
654 index
= viewer
.first_display_index
;
656 load_playlist_entries(index
);
658 if (viewer
.num_loaded
<= 0)
661 viewer
.first_display_index
= viewer
.first_index
;
662 viewer
.last_display_index
=
663 viewer
.first_index
+ viewer
.num_display_lines
- 1;
664 if (viewer
.last_display_index
>= viewer
.num_tracks
)
665 viewer
.last_display_index
= viewer
.num_tracks
- 1;
673 /* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
674 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
676 static int onplay_menu(int index
)
678 struct menu_item items
[3]; /* increase this if you add entries! */
679 int m
, i
=0, result
, ret
= 0;
680 bool current
= (tracks
[index
].index
== viewer
.current_playing_track
);
682 items
[i
].desc
= ID2P(LANG_REMOVE
);
685 items
[i
].desc
= ID2P(LANG_MOVE
);
688 items
[i
].desc
= ID2P(LANG_FILE_OPTIONS
);
691 m
= menu_init(items
, i
, NULL
, NULL
, NULL
, NULL
);
692 result
= menu_show(m
);
693 if (result
== MENU_ATTACHED_USB
)
695 else if (result
>= 0)
697 /* Abort current move */
698 viewer
.move_track
= -1;
707 playlist_delete(viewer
.playlist
, tracks
[index
].index
);
711 /* Start playing new track except if it's the last track
712 in the playlist and repeat mode is disabled */
713 if (tracks
[index
].display_index
!= viewer
.num_tracks
||
714 global_settings
.repeat_mode
== REPEAT_ALL
)
716 talk_buffer_steal(); /* will use the mp3 buffer */
718 viewer
.current_playing_track
= -1;
726 viewer
.move_track
= tracks
[index
].index
;
731 onplay(tracks
[index
].name
, TREE_ATTR_MPA
);
733 if (!viewer
.playlist
)
748 /* Menu of viewer options. Invoked via F1(r) or Menu(p). */
749 static bool viewer_menu(void)
754 static const struct menu_item items
[] = {
755 { ID2P(LANG_SHOW_ICONS
), show_icons
},
756 { ID2P(LANG_SHOW_INDICES
), show_indices
},
757 { ID2P(LANG_TRACK_DISPLAY
), track_display
},
758 { ID2P(LANG_SAVE_DYNAMIC_PLAYLIST
), save_playlist
},
761 m
=menu_init( items
, sizeof(items
) / sizeof(*items
), NULL
,
763 result
= menu_run(m
);
771 /* Show icons in viewer? */
772 static bool show_icons(void)
774 return set_bool(str(LANG_SHOW_ICONS
),
775 &global_settings
.playlist_viewer_icons
);
778 /* Show indices of tracks? */
779 static bool show_indices(void)
781 return set_bool(str(LANG_SHOW_INDICES
),
782 &global_settings
.playlist_viewer_indices
);
785 /* How to display a track */
786 static bool track_display(void)
788 static const struct opt_items names
[] = {
789 { STR(LANG_DISPLAY_TRACK_NAME_ONLY
) },
790 { STR(LANG_DISPLAY_FULL_PATH
) }
793 return set_option(str(LANG_TRACK_DISPLAY
),
794 &global_settings
.playlist_viewer_track_display
, INT
, names
, 2, NULL
);
797 /* Save playlist to disk */
798 static bool save_playlist(void)
800 char filename
[MAX_PATH
+1];
802 strncpy(filename
, DEFAULT_PLAYLIST_NAME
, sizeof(filename
));
804 if (!kbd_input(filename
, sizeof(filename
)))
806 playlist_save(viewer
.playlist
, filename
);
808 /* reload in case playlist was saved to cwd */
815 /* View current playlist */
816 bool playlist_viewer(void)
818 return playlist_viewer_ex(NULL
);
821 /* Main viewer function. Filename identifies playlist to be viewed. If NULL,
822 view current playlist. */
823 bool playlist_viewer_ex(char* filename
)
825 bool ret
= false; /* return value */
826 bool exit
=false; /* exit viewer */
827 bool update
=true; /* update display */
828 bool cursor_on
=true; /* used for flashing cursor */
829 int old_cursor_pos
; /* last cursor position */
830 int button
, lastbutton
= BUTTON_NONE
;
832 if (!initialize(filename
, false))
835 old_cursor_pos
= viewer
.cursor_pos
;
841 if (!viewer
.playlist
&& !(mpeg_status() & MPEG_STATUS_PLAY
))
843 /* Play has stopped */
844 #ifdef HAVE_LCD_CHARCELLS
845 splash(HZ
, true, str(LANG_END_PLAYLIST_PLAYER
));
847 splash(HZ
, true, str(LANG_END_PLAYLIST_RECORDER
));
852 if (viewer
.move_track
!= -1 || !cursor_on
)
854 /* Flash cursor to identify that we are moving a track */
855 cursor_on
= !cursor_on
;
856 #ifdef HAVE_LCD_BITMAP
857 if (global_settings
.invert_cursor
)
860 MARGIN_X
, MARGIN_Y
+(viewer
.cursor_pos
*viewer
.line_height
),
861 LCD_WIDTH
, viewer
.line_height
);
862 lcd_invertscroll(LINE_X
, viewer
.cursor_pos
);
865 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
,
869 0, MARGIN_Y
+ (viewer
.cursor_pos
* viewer
.line_height
),
870 LCD_WIDTH
, viewer
.line_height
);
872 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, cursor_on
);
877 if (!viewer
.playlist
)
878 playlist_get_resume_info(&track
);
882 if (track
!= viewer
.current_playing_track
||
883 playlist_amount_ex(viewer
.playlist
) != viewer
.num_tracks
)
885 /* Playlist has changed (new track started?) */
886 update_first_index();
887 if (!update_playlist(false))
892 /* Abort move on playlist change */
893 viewer
.move_track
= -1;
896 /* Timeout so we can determine if play status has changed */
897 button
= button_get_w_tmo(HZ
/2);
909 case TREE_PREV
| BUTTON_REPEAT
:
915 case TREE_NEXT
| BUTTON_REPEAT
:
922 case TREE_PGUP
| BUTTON_REPEAT
:
924 scroll_display(-viewer
.num_display_lines
);
929 case TREE_PGDN
| BUTTON_REPEAT
:
931 scroll_display(viewer
.num_display_lines
);
938 if (lastbutton
!= TREE_RUN_PRE
)
941 if (viewer
.move_track
>= 0)
946 ret
= playlist_move(viewer
.playlist
, viewer
.move_track
,
947 tracks
[INDEX(viewer
.cursor_pos
)].index
);
949 splash(HZ
, true, str(LANG_MOVE_FAILED
));
951 update_playlist(true);
952 viewer
.move_track
= -1;
954 else if (!viewer
.playlist
)
956 /* Stop current track and play new track */
958 playlist_start(tracks
[INDEX(viewer
.cursor_pos
)].index
, 0);
959 update_playlist(false);
963 /* Play track from playlist on disk */
967 if (playlist_set_current(viewer
.playlist
) < 0)
970 playlist_start(tracks
[INDEX(viewer
.cursor_pos
)].index
, 0);
972 /* Our playlist is now the current list */
973 if (!initialize(NULL
, true))
989 ret
= onplay_menu(INDEX(viewer
.cursor_pos
));
998 /* Playlist changed */
999 update_first_index();
1000 update_playlist(false);
1001 if (viewer
.num_tracks
<= 0)
1027 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
1035 if (update
&& !exit
)
1039 if (viewer
.cursor_pos
>
1040 (viewer
.last_display_index
- viewer
.first_display_index
))
1042 /* Cursor position is invalid */
1043 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, false);
1045 viewer
.last_display_index
- viewer
.first_display_index
;
1046 put_cursorxy(CURSOR_X
, CURSOR_Y
+ viewer
.cursor_pos
, true);
1049 if (viewer
.cursor_pos
!= old_cursor_pos
&&
1051 (viewer
.last_display_index
- viewer
.first_display_index
))
1052 /* Stop scrolling previous line */
1053 update_display_line(old_cursor_pos
, false);
1055 /* Scroll line at new cursor position */
1056 update_display_line(viewer
.cursor_pos
, true);
1060 old_cursor_pos
= viewer
.cursor_pos
;
1064 lastbutton
= button
;
1068 if (viewer
.playlist
)
1069 playlist_close(viewer
.playlist
);