summaryrefslogtreecommitdiff
path: root/apps/playlist_viewer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playlist_viewer.c')
-rw-r--r--apps/playlist_viewer.c400
1 files changed, 321 insertions, 79 deletions
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 00da973..20ac6c0 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -28,6 +28,9 @@
#include "icons.h"
#include "menu.h"
#include "plugin.h"
+#include "keyboard.h"
+#include "tree.h"
+#include "onplay.h"
#ifdef HAVE_LCD_BITMAP
#include "widgets.h"
@@ -35,6 +38,8 @@
#include "lang.h"
+#include "playlist_viewer.h"
+
/* Defines for LCD display purposes. Taken from tree.c */
#ifdef HAVE_LCD_BITMAP
#define CURSOR_X (global_settings.scrollbar && \
@@ -46,7 +51,9 @@
#define MARGIN_X ((global_settings.scrollbar && \
viewer.num_tracks > viewer.num_display_lines ? \
- SCROLLBAR_WIDTH : 0) + CURSOR_WIDTH + ICON_WIDTH)
+ SCROLLBAR_WIDTH : 0) + CURSOR_WIDTH + \
+ (global_settings.playlist_viewer_icons ? \
+ ICON_WIDTH : 0))
#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
#define LINE_X 0
@@ -67,11 +74,15 @@
/* Maximum number of tracks we can have loaded at one time */
#define MAX_PLAYLIST_ENTRIES 200
+/* Default playlist name for saving */
+#define DEFAULT_PLAYLIST_NAME "/viewer.m3u"
+
/* Index of track on display line _pos */
#define INDEX(_pos) (viewer.first_display_index - viewer.first_index + (_pos))
/* Global playlist viewer settings */
struct playlist_viewer_info {
+ struct playlist_info* playlist; /* playlist being viewed */
char *name_buffer; /* Buffer used to store track names */
int buffer_size; /* Size of name buffer */
@@ -103,15 +114,19 @@ struct playlist_entry {
static struct playlist_viewer_info viewer;
static struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
+/* Used when viewing playlists on disk */
+static struct playlist_info temp_playlist;
+
#ifdef HAVE_LCD_BITMAP
extern unsigned char bitmap_icons_6x8[LastIcon][6];
#endif
-static bool initialize(void);
+static bool initialize(char* filename, bool reload);
static void load_playlist_entries(int start_index);
static void load_playlist_entries_r(int end_index);
static int load_entry(int index, int pos, char* p, int size);
static void format_name(char* dest, char* src);
+static void format_line(struct playlist_entry* track, char* str, int len);
static void display_playlist(void);
static void update_display_line(int line, bool scroll);
static void scroll_display(int lines);
@@ -120,18 +135,74 @@ static bool update_playlist(bool force);
#ifdef BUTTON_ON
static int onplay_menu(int index);
#endif
-
-/* Initialize the playlist viewer */
-static bool initialize(void)
+static bool viewer_menu(void);
+static bool show_icons(void);
+static bool show_indices(void);
+static bool track_display(void);
+static bool save_playlist(void);
+
+/* Initialize the playlist viewer. */
+static bool initialize(char* filename, bool reload)
{
- if (!(mpeg_status() & MPEG_STATUS_PLAY))
+ char* buffer;
+ int buffer_size;
+ bool is_playing = mpeg_status() & MPEG_STATUS_PLAY;
+
+ if (!filename && !is_playing)
/* Nothing is playing, exit */
return false;
- viewer.name_buffer = plugin_get_buffer(&viewer.buffer_size);
- if (!viewer.name_buffer)
+ buffer = plugin_get_buffer(&buffer_size);
+ if (!buffer)
return false;
+ if (!filename)
+ viewer.playlist = NULL;
+ else
+ {
+ /* Viewing playlist on disk */
+ char *dir, *file, *temp_ptr;
+ char *index_buffer = NULL;
+ int index_buffer_size = 0;
+
+ viewer.playlist = &temp_playlist;
+
+ /* Separate directory from filename */
+ temp_ptr = strrchr(filename+1,'/');
+ if (temp_ptr)
+ {
+ *temp_ptr = 0;
+ dir = filename;
+ file = temp_ptr + 1;
+ }
+ else
+ {
+ dir = "/";
+ file = filename+1;
+ }
+
+ if (is_playing)
+ {
+ /* Something is playing, use half the plugin buffer for playlist
+ indices */
+ index_buffer_size = buffer_size / 2;
+ index_buffer = buffer;
+ }
+
+ playlist_create_ex(viewer.playlist, dir, file, index_buffer,
+ index_buffer_size, buffer+index_buffer_size,
+ buffer_size-index_buffer_size);
+
+ if (temp_ptr)
+ *temp_ptr = '/';
+
+ buffer += index_buffer_size;
+ buffer_size -= index_buffer_size;
+ }
+
+ viewer.name_buffer = buffer;
+ viewer.buffer_size = buffer_size;
+
#ifdef HAVE_LCD_BITMAP
{
char icon_chars[] = "MQ"; /* characters used as icons */
@@ -166,12 +237,20 @@ static bool initialize(void)
viewer.line_height = 1;
#endif
- viewer.cursor_pos = 0;
viewer.move_track = -1;
- /* Start displaying at current playing track */
- viewer.first_display_index = playlist_get_display_index() - 1;
- update_first_index();
+ if (!reload)
+ {
+ viewer.cursor_pos = 0;
+
+ if (!viewer.playlist)
+ /* Start displaying at current playing track */
+ viewer.first_display_index = playlist_get_display_index() - 1;
+ else
+ viewer.first_display_index = 0;
+
+ update_first_index();
+ }
if (!update_playlist(true))
return false;
@@ -287,21 +366,19 @@ static int load_entry(int index, int pos, char* p, int size)
struct playlist_track_info info;
int len;
int result = 0;
- char name[MAX_PATH];
/* Playlist viewer orders songs based on display index. We need to
convert to real playlist index to access track */
- index = (index + playlist_get_first_index()) % viewer.num_tracks;
- if (playlist_get_track_info(index, &info) < 0)
+ index = (index + playlist_get_first_index(viewer.playlist)) %
+ viewer.num_tracks;
+ if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
return -1;
- format_name(name, info.filename);
-
- len = strlen(name) + 1;
+ len = strlen(info.filename) + 1;
if (len <= size)
{
- strcpy(p, name);
+ strcpy(p, info.filename);
tracks[pos].name = p;
tracks[pos].index = info.index;
@@ -319,18 +396,46 @@ static int load_entry(int index, int pos, char* p, int size)
/* Format trackname for display purposes */
static void format_name(char* dest, char* src)
{
- char* p = strrchr(src, '/');
- int len;
+ switch (global_settings.playlist_viewer_track_display)
+ {
+ case 0:
+ default:
+ {
+ /* Only display the mp3 filename */
+ char* p = strrchr(src, '/');
+ int len;
+
+ strcpy(dest, p+1);
+ len = strlen(dest);
+
+ /* Remove the extension */
+ if (!strcasecmp(&dest[len-4], ".mp3") ||
+ !strcasecmp(&dest[len-4], ".mp2") ||
+ !strcasecmp(&dest[len-4], ".mpa"))
+ dest[len-4] = '\0';
+
+ break;
+ }
+ case 1:
+ /* Full path */
+ strcpy(dest, src);
+ break;
+ }
+}
+
+/* Format display line */
+static void format_line(struct playlist_entry* track, char* str, int len)
+{
+ char name[MAX_PATH];
- /* Only display the mp3 filename */
- strcpy(dest, p+1);
- len = strlen(dest);
+ format_name(name, track->name);
+
+ if (global_settings.playlist_viewer_indices)
+ /* Display playlist index */
+ snprintf(str, len, "%d. %s", track->display_index, name);
+ else
+ snprintf(str, len, "%s", name);
- /* Remove the extension */
- if (!strcasecmp(&dest[len-4], ".mp3") ||
- !strcasecmp(&dest[len-4], ".mp2") ||
- !strcasecmp(&dest[len-4], ".mpa"))
- dest[len-4] = '\0';
}
/* Display tracks on screen */
@@ -349,41 +454,44 @@ static void display_playlist(void)
for (i=0; i<=num_display_tracks; i++)
{
- /* Icons */
- if (tracks[INDEX(i)].index == viewer.current_playing_track)
+ if (global_settings.playlist_viewer_icons)
{
- /* Current playing track */
+ /* Icons */
+ if (tracks[INDEX(i)].index == viewer.current_playing_track)
+ {
+ /* Current playing track */
#ifdef HAVE_LCD_BITMAP
- int offset=0;
- if ( viewer.line_height > 8 )
- offset = (viewer.line_height - 8) / 2;
- lcd_bitmap(bitmap_icons_6x8[File],
- CURSOR_X * 6 + CURSOR_WIDTH,
- MARGIN_Y+(i*viewer.line_height) + offset,
- 6, 8, true);
+ int offset=0;
+ if ( viewer.line_height > 8 )
+ offset = (viewer.line_height - 8) / 2;
+ lcd_bitmap(bitmap_icons_6x8[File],
+ CURSOR_X * 6 + CURSOR_WIDTH,
+ MARGIN_Y+(i*viewer.line_height) + offset,
+ 6, 8, true);
#else
- lcd_putc(LINE_X-1, i, File);
+ lcd_putc(LINE_X-1, i, File);
#endif
- }
- else if (tracks[INDEX(i)].index == viewer.move_track)
- {
- /* Track we are moving */
+ }
+ else if (tracks[INDEX(i)].index == viewer.move_track)
+ {
+ /* Track we are moving */
#ifdef HAVE_LCD_BITMAP
- lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
- MARGIN_Y+(i*viewer.line_height), "M");
+ lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
+ MARGIN_Y+(i*viewer.line_height), "M");
#else
- lcd_putc(LINE_X-1, i, 'M');
+ lcd_putc(LINE_X-1, i, 'M');
#endif
- }
- else if (tracks[INDEX(i)].queued)
- {
- /* Queued track */
+ }
+ else if (tracks[INDEX(i)].queued)
+ {
+ /* Queued track */
#ifdef HAVE_LCD_BITMAP
- lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
- MARGIN_Y+(i*viewer.line_height), "Q");
+ lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
+ MARGIN_Y+(i*viewer.line_height), "Q");
#else
- lcd_putc(LINE_X-1, i, 'Q');
+ lcd_putc(LINE_X-1, i, 'Q');
#endif
+ }
}
update_display_line(i, false);
@@ -494,10 +602,8 @@ static void update_display_line(int line, bool scroll)
{
char str[MAX_PATH + 16];
- snprintf(str, sizeof(str), "%d. %s",
- tracks[INDEX(line)].display_index,
- tracks[INDEX(line)].name);
-
+ format_line(&tracks[INDEX(line)], str, sizeof(str));
+
if (scroll)
{
#ifdef HAVE_LCD_BITMAP
@@ -516,7 +622,7 @@ static void update_display_line(int line, bool scroll)
static void update_first_index(void)
{
/* viewer.num_tracks may be invalid at this point */
- int num_tracks = playlist_amount();
+ int num_tracks = playlist_amount_ex(viewer.playlist);
if ((num_tracks - viewer.first_display_index) < viewer.num_display_lines)
{
@@ -535,14 +641,17 @@ static void update_first_index(void)
/* Update playlist in case something has changed or forced */
static bool update_playlist(bool force)
{
- playlist_get_resume_info(&viewer.current_playing_track);
+ if (!viewer.playlist)
+ playlist_get_resume_info(&viewer.current_playing_track);
+ else
+ viewer.current_playing_track = -1;
- if (force || playlist_amount() != viewer.num_tracks)
+ if (force || playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
{
int index;
/* Reload tracks */
- viewer.num_tracks = playlist_amount();
+ viewer.num_tracks = playlist_amount_ex(viewer.playlist);
if (viewer.num_tracks < 0)
return false;
@@ -571,16 +680,19 @@ static bool update_playlist(bool force)
changed. */
static int onplay_menu(int index)
{
- struct menu_items menu[2]; /* increase this if you add entries! */
+ struct menu_items menu[3]; /* increase this if you add entries! */
int m, i=0, result, ret = 0;
bool current = (tracks[index].index == viewer.current_playing_track);
- menu[i].desc = str(LANG_DELETE);
+ menu[i].desc = str(LANG_REMOVE);
i++;
menu[i].desc = str(LANG_MOVE);
i++;
+ menu[i].desc = str(LANG_FILE_OPTIONS);
+ i++;
+
m = menu_init(menu, i);
result = menu_show(m);
if (result == MENU_ATTACHED_USB)
@@ -597,7 +709,7 @@ static int onplay_menu(int index)
if (current)
mpeg_stop();
- playlist_delete(tracks[index].index);
+ playlist_delete(viewer.playlist, tracks[index].index);
if (current)
{
@@ -618,6 +730,17 @@ static int onplay_menu(int index)
viewer.move_track = tracks[index].index;
ret = 0;
break;
+ case 2:
+ {
+ onplay(tracks[index].name, TREE_ATTR_MPA);
+
+ if (!viewer.playlist)
+ ret = 1;
+ else
+ ret = 0;
+
+ break;
+ }
}
}
@@ -627,17 +750,91 @@ static int onplay_menu(int index)
}
#endif
-/* Main viewer function */
+/* Menu of viewer options. Invoked via F1(r) or Menu(p). */
+static bool viewer_menu(void)
+{
+ int m;
+ bool result;
+
+ struct menu_items items[] = {
+ { str(LANG_SHOW_ICONS), show_icons },
+ { str(LANG_SHOW_INDICES), show_indices },
+ { str(LANG_TRACK_DISPLAY), track_display },
+ { str(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist },
+ };
+
+ m=menu_init( items, sizeof(items) / sizeof(*items) );
+ result = menu_run(m);
+ menu_exit(m);
+
+ settings_save();
+
+ return result;
+}
+
+/* Show icons in viewer? */
+static bool show_icons(void)
+{
+ return set_bool(str(LANG_SHOW_ICONS),
+ &global_settings.playlist_viewer_icons);
+}
+
+/* Show indices of tracks? */
+static bool show_indices(void)
+{
+ return set_bool(str(LANG_SHOW_INDICES),
+ &global_settings.playlist_viewer_indices);
+}
+
+/* How to display a track */
+static bool track_display(void)
+{
+ char* names[] = {
+ str(LANG_DISPLAY_TRACK_NAME_ONLY),
+ str(LANG_DISPLAY_FULL_PATH)
+ };
+
+ return set_option(str(LANG_TRACK_DISPLAY),
+ &global_settings.playlist_viewer_track_display, INT, names, 2, NULL);
+}
+
+/* Save playlist to disk */
+static bool save_playlist(void)
+{
+ char filename[MAX_PATH+1];
+
+ strncpy(filename, DEFAULT_PLAYLIST_NAME, sizeof(filename));
+
+ if (!kbd_input(filename, sizeof(filename)))
+ {
+ playlist_save(viewer.playlist, filename);
+
+ /* reload in case playlist was saved to cwd */
+ reload_directory();
+ }
+
+ return false;
+}
+
+/* View current playlist */
bool playlist_viewer(void)
{
+ return playlist_viewer_ex(NULL);
+}
+
+/* Main viewer function. Filename identifies playlist to be viewed. If NULL,
+ view current playlist. */
+bool playlist_viewer_ex(char* filename)
+{
+ bool ret = false; /* return value */
bool exit=false; /* exit viewer */
bool update=true; /* update display */
bool cursor_on=true; /* used for flashing cursor */
int old_cursor_pos; /* last cursor position */
int button;
- if (!initialize())
- return false;
+ if (!initialize(filename, false))
+ goto exit;
old_cursor_pos = viewer.cursor_pos;
@@ -648,7 +845,7 @@ bool playlist_viewer(void)
/* Timeout so we can determine if play status has changed */
button = button_get_w_tmo(HZ/2);
- if (!(mpeg_status() & MPEG_STATUS_PLAY))
+ if (!viewer.playlist && !(mpeg_status() & MPEG_STATUS_PLAY))
{
/* Play has stopped */
#ifdef HAVE_LCD_CHARCELLS
@@ -657,7 +854,7 @@ bool playlist_viewer(void)
splash(HZ, true, str(LANG_END_PLAYLIST_RECORDER));
#endif
status_set_playmode(STATUS_STOP);
- return false;;
+ goto exit;
}
if (viewer.move_track != -1 || !cursor_on)
@@ -685,10 +882,13 @@ bool playlist_viewer(void)
#endif
}
- playlist_get_resume_info(&track);
+ if (!viewer.playlist)
+ playlist_get_resume_info(&track);
+ else
+ track = -1;
if (track != viewer.current_playing_track ||
- playlist_amount() != viewer.num_tracks)
+ playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
{
/* Playlist has changed (new track started?) */
update_first_index();
@@ -769,7 +969,7 @@ bool playlist_viewer(void)
/* Move track */
int ret;
- ret = playlist_move(viewer.move_track,
+ ret = playlist_move(viewer.playlist, viewer.move_track,
tracks[INDEX(viewer.cursor_pos)].index);
if (ret < 0)
splash(HZ, true, str(LANG_MOVE_FAILED));
@@ -777,7 +977,7 @@ bool playlist_viewer(void)
update_playlist(true);
viewer.move_track = -1;
}
- else
+ else if (!viewer.playlist)
{
/* Stop current track and play new track */
mpeg_stop();
@@ -785,6 +985,22 @@ bool playlist_viewer(void)
status_set_playmode(STATUS_PLAY);
update_playlist(false);
}
+ else
+ {
+ /* Play track from playlist on disk */
+ mpeg_stop();
+
+ /* New playlist */
+ if (playlist_set_current(viewer.playlist) < 0)
+ goto exit;
+
+ playlist_start(tracks[INDEX(viewer.cursor_pos)].index, 0);
+ status_set_playmode(STATUS_PLAY);
+
+ /* Our playlist is now the current list */
+ if (!initialize(NULL, true))
+ goto exit;
+ }
display_playlist();
update = true;
@@ -799,13 +1015,15 @@ bool playlist_viewer(void)
ret = onplay_menu(INDEX(viewer.cursor_pos));
if (ret < 0)
- /* USB attached */
- return true;
+ {
+ ret = true;
+ goto exit;
+ }
else if (ret > 0)
{
/* Playlist changed */
update_first_index();
- update_playlist(true);
+ update_playlist(false);
if (viewer.num_tracks <= 0)
exit = true;
}
@@ -816,9 +1034,30 @@ bool playlist_viewer(void)
break;
}
#endif /* BUTTON_ON */
+#ifdef HAVE_RECORDER_KEYPAD
+ case BUTTON_F1:
+#else
+ case BUTTON_MENU:
+#endif
+ if (viewer_menu())
+ {
+ ret = true;
+ goto exit;
+ }
+
+ display_playlist();
+ update = true;
+ break;
+
case SYS_USB_CONNECTED:
usb_screen();
- return true;
+ ret = true;
+ goto exit;
+ break;
+
+ case BUTTON_NONE:
+ status_draw(false);
+ break;
}
if (update && !exit)
@@ -852,5 +1091,8 @@ bool playlist_viewer(void)
}
}
- return false;
+exit:
+ if (viewer.playlist)
+ playlist_close(viewer.playlist);
+ return ret;
}