Index: apps/playlist.c
===================================================================
--- apps/playlist.c (revision 14452)
+++ apps/playlist.c (working copy)
@@ -250,6 +250,26 @@
}
/*
+ * check if there is extm3u header
+ */
+static int check_for_extm3u(struct playlist_info* playlist)
+{
+ char header[7];
+ int fd;
+
+ fd = open(playlist->filename, O_RDONLY);
+ if(fd < 0)
+ return -1; /* failed */
+
+ if (read(fd,header,sizeof(header)) < 0)
+ return -1;
+
+ playlist->is_extm3u = (strncmp(header,"#EXTM3U",7) == 0);
+
+ return 0;
+}
+
+/*
* Initialize a new playlist for viewing/editing/playing. dir is the
* directory where the playlist is located and file is the filename.
*/
@@ -269,6 +289,9 @@
}
update_playlist_filename(playlist, dir, file);
+
+ if (file)
+ check_for_extm3u(playlist);
if (playlist->control_fd >= 0)
{
@@ -1365,6 +1388,69 @@
return (format_track_path(buf, tmp_buf, buf_length, max, dir_buf));
}
+/* fill in track title and song length to according extm3u comments
+* should not call if playlist->is_extm3u is false
+* a typical extm3u line: header time title
+* #EXTINF:111,example title */
+static int get_extm3u_info(struct playlist_info* playlist, int seek,
+ char *title_buf, int title_buf_size,
+ int *length)
+{
+ /* header + time can take up 13 characters for a 3 hour song */
+ int tmp_buf_size = MIN(seek - 1,title_buf_size +13);
+ int offset = MAX(0,seek - tmp_buf_size - 2);
+ char tmp_buf[MAX_PATH*2 + 13];
+
+ if(-1 == playlist->fd)
+ playlist->fd = open(playlist->filename, O_RDONLY);
+ if(playlist->fd < 0)
+ return -1; /* failed */
+
+ /* read the lines before seek to find extm3u comments */
+ if (lseek(playlist->fd, offset, SEEK_SET) != offset)
+ return -1;
+ else
+ {
+ if (read(playlist->fd, tmp_buf, tmp_buf_size) < 0)
+ return -1;
+
+ /* Can skip 8 chars because a valid extm3u line
+ * should have more than 8 chars*/
+ int i = tmp_buf_size - 8;
+ int j = tmp_buf_size - 1;
+
+ /* locate the start of extm3u comment line*/
+ while (i > 0 && (tmp_buf[i] != '\n') && (tmp_buf[i] != '\r'))
+ i--;
+
+ if (strncmp(&tmp_buf[++i],"#EXTINF:",8) != 0)
+ return -1; /*line too long or no comment*/
+
+ i += 8; /*skip the header*/
+ *length = atoi(&tmp_buf[i]);
+
+ if (*length == 0)
+ return -1; /*cannot retrieve song length*/
+
+ /*skip the time part*/
+ while (i < tmp_buf_size && tmp_buf[i] != ',')
+ i++;
+
+ if (tmp_buf[i] != ',' || i == j)
+ return -1; /*no title or not proper format*/
+
+ /*kill white spaces and new lines*/
+ while(j > i && (tmp_buf[j] == ' ' || tmp_buf[j] == '\t' ||
+ tmp_buf[j] == '\n' || tmp_buf[j] == '\r'))
+ j--;
+
+ tmp_buf[j+1] = '\0';
+
+ strncpy(title_buf,&tmp_buf[i+1],title_buf_size);
+ }
+ return 0;
+}
+
static int get_next_directory(char *dir){
return get_next_dir(dir,true,false);
}
@@ -3334,7 +3420,17 @@
if (get_filename(playlist, index, seek, control_file, info->filename,
sizeof(info->filename)) < 0)
return -1;
-
+
+ /* check info->has_extm3u so that if caller to this function
+ * explicitly asked for no extm3u info, extm3u info is not parsed */
+ if (info->has_extm3u && playlist->is_extm3u)
+ {
+ info->has_extm3u = !(get_extm3u_info(playlist, seek, info->title,
+ sizeof(info->title), &(info->length)) < 0);
+ }
+ else
+ info->has_extm3u = false;
+
info->attr = 0;
if (control_file)
Index: apps/playlist.h
===================================================================
--- apps/playlist.h (revision 14452)
+++ apps/playlist.h (working copy)
@@ -71,6 +71,7 @@
char filename[MAX_PATH]; /* path name of m3u playlist on disk */
char control_filename[MAX_PATH]; /* full path of control file */
bool utf8; /* playlist is in .m3u8 format */
+ bool is_extm3u; /*playlist contains extm3u infomation */
int fd; /* descriptor of the open playlist file */
int control_fd; /* descriptor of the open control file */
bool control_created; /* has control file been created? */
@@ -109,6 +110,11 @@
int attr; /* playlist attributes for track */
int index; /* index of track in playlist */
int display_index; /* index of track for display */
+ bool has_extm3u; /* Does it have extm3u information? */
+
+ /* used if extm3u information is present in playlist */
+ unsigned int length; /* song length in seconds */
+ char title[MAX_PATH*2]; /* track title */
};
/* Exported functions only for current playlist. */
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 14452)
+++ apps/lang/english.lang (working copy)
@@ -11122,3 +11122,31 @@
rtc: "oh"
+
+ id: LANG_DISPLAY_TRACK_TITLE_ONLY
+ desc: track display options
+ user:
+
+ *: "EXTM3U title only"
+
+
+ *: "EXTM3U title only"
+
+
+ *: "title only"
+
+
+
+ id: LANG_DISPLAY_TRACK_TITLE_TIME
+ desc: track display options
+ user:
+
+ *: "EXTM3U title and time"
+
+
+ *: "EXTM3U title and time"
+
+
+ *: "title and time"
+
+
\ No newline at end of file
Index: apps/playlist_viewer.c
===================================================================
--- apps/playlist_viewer.c (revision 14452)
+++ apps/playlist_viewer.c (working copy)
@@ -65,6 +65,11 @@
int display_index; /* Display index */
bool queued; /* Is track queued? */
bool skipped; /* Is track marked as bad? */
+ bool has_extm3u; /* Does it have extm3u information? */
+
+ /* used if extm3u information is present in playlist */
+ unsigned int length; /* song length in seconds */
+ char* title; /* track title */
};
enum direction
@@ -118,7 +123,8 @@
static bool playlist_viewer_init(struct playlist_viewer * viewer,
char* filename, bool reload);
-static void format_name(char* dest, const char* src);
+static void format_name(char* dest, const char* name,
+ int len, unsigned int track_length);
static void format_line(const struct playlist_entry* track, char* str,
int len);
@@ -199,25 +205,51 @@
{
struct playlist_track_info info;
int len;
-
+
+ /* Explicitly disable loading extm3u if not needed for display*/
+ switch (global_settings.playlist_viewer_track_display)
+ {
+ case 2:
+ case 3:
+ info.has_extm3u = true;
+ break;
+ default:
+ info.has_extm3u = false;
+ break;
+ }
+
/* 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.playlist)) %
viewer.num_tracks;
if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
return -1;
+
+ if (info.has_extm3u)
+ len = strlen(info.title) + 1;
+ else
+ len = strlen(info.filename) + 1;
- len = strlen(info.filename) + 1;
-
if (len <= remaining_size)
{
- strcpy(name_buffer, info.filename);
-
+ if (info.has_extm3u)
+ {
+ entry->has_extm3u = true;
+ entry->length = info.length;
+ strcpy(name_buffer, info.title);
+ }
+ else
+ {
+ entry->has_extm3u = false;
+ strcpy(name_buffer, info.filename);
+ }
+
entry->name = name_buffer;
entry->index = info.index;
entry->display_index = info.display_index;
entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
+
return len;
}
return -1;
@@ -352,18 +384,42 @@
return true;
}
-/* Format trackname for display purposes */
-static void format_name(char* dest, const char* src)
+/* Format name for display purposes */
+static void format_name(char* dest, const char* name,
+ int len, unsigned int track_length)
{
switch (global_settings.playlist_viewer_track_display)
{
+ case 3:
+ {
+ /* track title and time; fall through if no extm3u info
+ * (i.e. track_length is not 0) */
+ if (track_length)
+ {
+ snprintf(dest,len,"%s (%02d:%02d)",name,
+ track_length / 60, track_length %60);
+ break;
+ }
+ }
+ case 2:
+ {
+ /* track title only; fall through if no extm3u info*/
+ if (track_length)
+ {
+ strcpy(dest, name);
+ break;
+ }
+ }
case 0:
default:
{
/* Only display the filename */
- char* p = strrchr(src, '/');
+ char* p = strrchr(name, '/');
- strcpy(dest, p+1);
+ if (p != NULL)
+ strcpy(dest, p+1);
+ else
+ strcpy(dest, name);
/* Remove the extension */
char* q = strrchr(dest, '.');
@@ -374,9 +430,11 @@
break;
}
case 1:
- /* Full path */
- strcpy(dest, src);
+ {
+ /* Full path or extm3u title only; no formatting needed*/
+ strcpy(dest, name);
break;
+ }
}
}
@@ -384,11 +442,11 @@
static void format_line(const struct playlist_entry* track, char* str,
int len)
{
- char name[MAX_PATH];
+ char name[MAX_PATH*2];
char *skipped = "";
+ format_name(name, track->name, len, (track->has_extm3u) ?
+ track->length : 0);
- format_name(name, track->name);
-
if (track->skipped)
skipped = "(ERR) ";
@@ -523,7 +581,8 @@
struct playlist_viewer * local_viewer = (struct playlist_viewer *)data;
struct playlist_entry *track=
playlist_buffer_get_track(&(local_viewer->buffer), selected_item);
- format_line(track, buffer, MAX_PATH);
+
+ format_line(track, buffer, MAX_PATH*2);
return(buffer);
}
@@ -684,11 +743,25 @@
break;
}
case ACTION_STD_MENU:
+ {
+ int old_view_setting = global_settings.playlist_viewer_track_display;
+
if (viewer_menu())
{
ret = true;
goto exit;
}
+
+ if (old_view_setting != global_settings.playlist_viewer_track_display)
+ {
+ /* playlist needs update when view mode changes because probably
+ * not all needed information is present */
+
+ update_playlist(true);
+ if (viewer.num_tracks <= 0)
+ exit = true;
+ }
+
gui_synclist_set_icon_callback(
&playlist_lists,
global_settings.playlist_viewer_icons?
@@ -696,7 +769,7 @@
);
gui_synclist_draw(&playlist_lists);
break;
-
+ }
case ACTION_NONE:
gui_syncstatusbar_draw(&statusbars, false);
break;
@@ -721,8 +794,10 @@
{
int *found_indicies = (int*)data;
static struct playlist_track_info track;
+ /* Explicitly ask for no extm3u info */
+ track.has_extm3u = false;
playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track);
- format_name(buffer,track.filename);
+ format_name(buffer,track.filename,MAX_PATH*2,0);
return(buffer);
}
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 14452)
+++ apps/settings_list.c (working copy)
@@ -663,8 +663,11 @@
OFFON_SETTING(0,playlist_viewer_indices,LANG_SHOW_INDICES,true,
"playlist viewer indices",NULL),
CHOICE_SETTING(0, playlist_viewer_track_display, LANG_TRACK_DISPLAY, 0,
- "playlist viewer track display","track name,full path", NULL, 2,
- ID2P(LANG_DISPLAY_TRACK_NAME_ONLY), ID2P(LANG_DISPLAY_FULL_PATH)),
+ "playlist viewer track display",
+ "track name,full path,title,title with time", NULL, 4,
+ ID2P(LANG_DISPLAY_TRACK_NAME_ONLY), ID2P(LANG_DISPLAY_FULL_PATH),
+ ID2P(LANG_DISPLAY_TRACK_TITLE_ONLY),
+ ID2P(LANG_DISPLAY_TRACK_TITLE_TIME)),
CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_OFF,
"recursive directory insert", off_on_ask, NULL , 3 ,
ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)),