summaryrefslogtreecommitdiff
path: root/playlist.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-11-04 21:10:40 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-11-04 21:10:40 +0100
commit35bc2a7710d11fff5c4f4dcd4b4c83f8649fdf1b (patch)
treeb0a6ae57b5a7d80792587cb98d4e722d62290dc9 /playlist.c
parent8201a459bf2c2703a48552f0b5ae23511074490b (diff)
improved icy protocol support; initial m3u support
Diffstat (limited to 'playlist.c')
-rw-r--r--playlist.c133
1 files changed, 101 insertions, 32 deletions
diff --git a/playlist.c b/playlist.c
index 911da45d..97ed441d 100644
--- a/playlist.c
+++ b/playlist.c
@@ -63,7 +63,14 @@ pl_free (void) {
}
static const uint8_t *
-pl_str_skipspaces (const uint8_t *p) {
+pl_str_skipspaces (const uint8_t *p, const uint8_t *end) {
+ while (p < end && *p <= ' ') {
+ p++;
+ }
+ return p;
+}
+static const uint8_t *
+pl_cue_skipspaces (const uint8_t *p) {
while (*p && *p <= ' ') {
p++;
}
@@ -86,7 +93,7 @@ pl_get_qvalue_from_cue (const uint8_t *p, int sz, char *out) {
return;
}
p++;
- p = pl_str_skipspaces (p);
+ p = pl_cue_skipspaces (p);
while (*p && *p != '"' && sz > 1) {
sz--;
*out++ = *p++;
@@ -265,7 +272,7 @@ pl_insert_cue_from_buffer (playItem_t *after, const char *fname, const uint8_t *
str[p-buffer] = 0;
buffersize -= p-buffer;
buffer = p;
- p = pl_str_skipspaces (str);
+ p = pl_cue_skipspaces (str);
if (!strncmp (p, "PERFORMER ", 10)) {
pl_get_qvalue_from_cue (p + 10, sizeof (performer), performer);
// printf ("got performer: %s\n", performer);
@@ -353,14 +360,70 @@ pl_insert_cue (playItem_t *after, const char *fname, struct DB_decoder_s *decode
}
playItem_t *
-pl_insert_m3u (playItem_t *after, const char *fname) {
- return NULL;
+pl_insert_m3u (playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) {
+ // skip all empty lines and comments
+ DB_FILE *fp = vfs_fopen (fname);
+ if (!fp) {
+ trace ("failed to open file %s\n", fname);
+ return NULL;
+ }
+ int sz = vfs_fgetlength (fp);
+ if (sz > 1024*1024) {
+ vfs_fclose (fp);
+ trace ("file %s is too large to be a playlist\n", fname);
+ return NULL;
+ }
+ if (sz < 30) {
+ vfs_fclose (fp);
+ trace ("file %s is too small to be a playlist\n", fname);
+ return NULL;
+ }
+ vfs_rewind (fp);
+ uint8_t buffer[sz];
+ vfs_fread (buffer, 1, sz, fp);
+ vfs_fclose (fp);
+ const uint8_t *p = buffer;
+ const uint8_t *end = buffer+sz;
+ while (p < end) {
+ p = pl_str_skipspaces (p, end);
+ if (p >= end) {
+ break;
+ }
+ if (*p == '#') {
+ while (p < end && *p >= 0x20) {
+ p++;
+ }
+ if (p >= end) {
+ break;
+ }
+ continue;
+ }
+ const uint8_t *e = p;
+ while (e < end && *e >= 0x20) {
+ e++;
+ }
+ int n = e-p;
+ uint8_t nm[n+1];
+ memcpy (nm, p, n);
+ nm[n] = 0;
+ playItem_t *it = pl_insert_file (after, nm, pabort, cb, user_data);
+ if (it) {
+ after = it;
+ }
+ if (pabort && *pabort) {
+ return after;
+ }
+ if (p >= end) {
+ break;
+ }
+ }
+ return after;
}
// that has to be opened with vfs functions to allow loading from http, as
// referenced from M3U.
playItem_t *
-pl_insert_pls (playItem_t *after, const char *fname) {
+pl_insert_pls (playItem_t *after, const char *fname, int *pabort, int (*cb)(playItem_t *it, void *data), void *user_data) {
DB_FILE *fp = vfs_fopen (fname);
if (!fp) {
trace ("failed to open file %s\n", fname);
@@ -389,7 +452,7 @@ pl_insert_pls (playItem_t *after, const char *fname) {
return NULL;
}
p += 10;
- p = pl_str_skipspaces (p);
+ p = pl_str_skipspaces (p, end);
if (p >= end) {
trace ("file %s finished before numberofentries had been read\n", fname);
return NULL;
@@ -403,7 +466,7 @@ pl_insert_pls (playItem_t *after, const char *fname) {
while (p < end && *p > 0x20) {
p++;
}
- p = pl_str_skipspaces (p);
+ p = pl_str_skipspaces (p, end);
// fetch all tracks
char url[1024] = "";
char title[1024] = "";
@@ -437,7 +500,7 @@ pl_insert_pls (playItem_t *after, const char *fname) {
url[n] = 0;
trace ("url: %s\n", url);
p = ++e;
- p = pl_str_skipspaces (p);
+ p = pl_str_skipspaces (p, end);
if (strncasecmp (p, "title", 5)) {
break;
}
@@ -459,7 +522,7 @@ pl_insert_pls (playItem_t *after, const char *fname) {
title[n] = 0;
trace ("title: %s\n", title);
p = ++e;
- p = pl_str_skipspaces (p);
+ p = pl_str_skipspaces (p, end);
if (strncasecmp (p, "length", 6)) {
break;
}
@@ -481,13 +544,15 @@ pl_insert_pls (playItem_t *after, const char *fname) {
length[n] = 0;
trace ("length: %s\n", length);
// add track
- playItem_t *it = pl_item_alloc ();
- it->decoder = NULL;
- it->fname = strdup (url);
- it->filetype = "content";
- pl_set_item_duration (it, atoi (length));
- pl_add_meta (it, "title", title);
- after = pl_insert_item (after, it);
+ playItem_t *it = pl_insert_file (after, url, pabort, cb, user_data);
+ if (it) {
+ after = it;
+ pl_set_item_duration (it, atoi (length));
+ pl_add_meta (it, "title", title);
+ }
+ if (pabort && *pabort) {
+ return after;
+ }
}
return after;
}
@@ -498,6 +563,25 @@ pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(pla
return NULL;
}
+ // detect decoder
+ const char *eol = fname + strlen (fname) - 1;
+ while (eol > fname && *eol != '.') {
+ eol--;
+ }
+ eol++;
+
+ // detect pls/m3u files
+ // they must be handled before checking for http://,
+ // so that remote playlist files referenced from other playlist files could
+ // be loaded correctly
+ if (!memcmp (eol, "m3u", 4)) {
+ return pl_insert_m3u (after, fname, pabort, cb, user_data);
+ }
+ else if (!memcmp (eol, "pls", 4)) {
+
+ return pl_insert_pls (after, fname, pabort, cb, user_data);
+ }
+
// add all posible streams as special-case:
// set decoder to NULL, and filetype to "content"
// streamer is responsible to determine content type on 1st access and
@@ -528,21 +612,6 @@ pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(pla
fname += 7;
}
- // detect decoder
- const char *eol = fname + strlen (fname) - 1;
- while (eol > fname && *eol != '.') {
- eol--;
- }
- eol++;
-
- // detect pls/m3u files
- if (!memcmp (eol, "m3u", 4)) {
- return pl_insert_m3u (after, fname);
- }
- else if (!memcmp (eol, "pls", 4)) {
- return pl_insert_pls (after, fname);
- }
-
DB_decoder_t **decoders = plug_get_decoder_list ();
// match by decoder
for (int i = 0; decoders[i]; i++) {