summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-11-06 21:12:38 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-11-06 21:12:38 +0100
commit39b8fe4b2c864247e0004d2a8c0ca55bab0fdf32 (patch)
tree6a5a4daf957a6522ba7342c6ca376b2722768fcb
parent63a606b4592acacf7adb76587c3177b0676d3886 (diff)
rewrote icy header parser
shoutcast title is being read from icy headers
-rw-r--r--deadbeef.h4
-rw-r--r--plugins.c2
-rw-r--r--plugins/mpgmad/mpgmad.c14
-rw-r--r--plugins/vfs_curl/vfs_curl.c137
-rw-r--r--vfs.c15
-rw-r--r--vfs.h2
6 files changed, 160 insertions, 14 deletions
diff --git a/deadbeef.h b/deadbeef.h
index b9cc4c5e..51f512dc 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -236,6 +236,8 @@ typedef struct {
void (*rewind) (DB_FILE *stream);
int64_t (*fgetlength) (DB_FILE *stream);
const char *(*fget_content_type) (DB_FILE *stream);
+ const char *(*fget_content_name) (DB_FILE *stream);
+ const char *(*fget_content_genre) (DB_FILE *stream);
// message passing
int (*sendmessage) (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2);
// configuration access
@@ -393,6 +395,8 @@ typedef struct DB_vfs_s {
void (*rewind) (DB_FILE *stream);
int64_t (*getlength)(DB_FILE *stream);
const char * (*get_content_type) (DB_FILE *stream);
+ const char * (*get_content_name) (DB_FILE *stream);
+ const char * (*get_content_genre) (DB_FILE *stream);
const char **scheme_names; // NULL-terminated list of supported schemes, e.g. {"http", "ftp", NULL}
unsigned streaming : 1;
} DB_vfs_t;
diff --git a/plugins.c b/plugins.c
index 53604178..3ed508e5 100644
--- a/plugins.c
+++ b/plugins.c
@@ -111,6 +111,8 @@ static DB_functions_t deadbeef_api = {
.rewind = vfs_rewind,
.fgetlength = vfs_fgetlength,
.fget_content_type = vfs_get_content_type,
+ .fget_content_name = vfs_get_content_name,
+ .fget_content_genre = vfs_get_content_genre,
// message passing
.sendmessage = messagepump_push,
// configuration access
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 21d3b8fb..8e54b6c8 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -498,6 +498,8 @@ cmp3_init (DB_playItem_t *it) {
}
else {
int len = deadbeef->fgetlength (buffer.file);
+ const char *name = deadbeef->fget_content_name (buffer.file);
+ const char *genre = deadbeef->fget_content_genre (buffer.file);
if (len > 0) {
deadbeef->pl_delete_all_meta (it);
int v2err = deadbeef->junk_read_id3v2 (it, buffer.file);
@@ -506,6 +508,18 @@ cmp3_init (DB_playItem_t *it) {
deadbeef->fseek (buffer.file, 0, SEEK_SET);
}
}
+ else {
+ deadbeef->pl_delete_all_meta (it);
+ if (name) {
+ deadbeef->pl_add_meta (it, "title", name);
+ }
+ else {
+ deadbeef->pl_add_meta (it, "title", NULL);
+ }
+ if (genre) {
+ deadbeef->pl_add_meta (it, "genre", genre);
+ }
+ }
int res = cmp3_scan_stream (&buffer, 0);
if (res < 0) {
trace ("mpgmad: cmp3_init: initial cmp3_scan_stream failed\n");
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index e467692e..1ac15c93 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -58,6 +58,8 @@ typedef struct {
int icyheader;
int nheaderpackets;
char *content_type;
+ char *content_name;
+ char *content_genre;
uint8_t status;
} HTTP_FILE;
@@ -170,28 +172,91 @@ http_size_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
return size * nmemb;
}
+static const uint8_t *
+parse_header (const uint8_t *p, const uint8_t *e, uint8_t *key, int keysize, uint8_t *value, int valuesize) {
+ int sz; // will hold lenght of extracted string
+ const uint8_t *v; // pointer to current character
+ keysize--;
+ valuesize--;
+ *key = 0;
+ *value = 0;
+ v = p;
+ // find :
+ while (v < e && *v != 0x0d && *v != 0x0a && *v != ':') {
+ v++;
+ }
+ if (*v != ':') {
+ // skip linebreaks
+ while (v < e && (*v == 0x0d || *v == 0x0a)) {
+ v++;
+ }
+ return v;
+ }
+ // copy key
+ sz = v-p;
+ sz = min (keysize, sz);
+ memcpy (key, p, sz);
+ key[sz] = 0;
+
+ // skip whitespace
+ v++;
+ while (v < e && (*v == 0x20 || *v == 0x08)) {
+ v++;
+ }
+ if (*v == 0x0d || *v == 0x0a) {
+ // skip linebreaks
+ while (v < e && (*v == 0x0d || *v == 0x0a)) {
+ v++;
+ }
+ return v;
+ }
+ p = v;
+
+ // find linebreak
+ while (v < e && *v != 0x0d || *v == 0x0a) {
+ v++;
+ }
+
+ // copy value
+ sz = v-p;
+ sz = min (valuesize, sz);
+ memcpy (value, p, sz);
+ value[sz] = 0;
+
+ // skip linebreaks
+ while (v < e && (*v == 0x0d || *v == 0x0a)) {
+ v++;
+ }
+ return v;
+}
+
static size_t
http_content_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
trace ("http_content_header_handler\n");
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
const uint8_t c_type_str[] ="Content-Type:";
- const uint8_t *cl = strcasestr (ptr, c_type_str);
- if (cl) {
- fp->gotheader = 1;
- cl += sizeof (c_type_str)-1;
- while (*cl <= 0x20) {
- cl++;
+ const uint8_t icy_name_str[] ="icy-name:";
+ const uint8_t icy_genre_str[] ="icy-genre:";
+ const uint8_t *p = ptr;
+ const uint8_t *end = p + size*nmemb;
+ uint8_t key[256];
+ uint8_t value[256];
+ while (p < end) {
+ p = parse_header (p, end, key, sizeof (key), value, sizeof (value));
+ trace ("%skey=%s value=%s\n", fp->icyheader ? "[icy] " : "", key, value);
+ if (!strcasecmp (key, "Content-Type")) {
+ fp->content_type = strdup (value);
+ }
+ else if (!strcasecmp (key, "icy-name")) {
+ fp->content_name = strdup (value);
}
- const uint8_t *p = (const uint8_t *)cl;
- while (*p >= 0x20) {
- p++;
+ else if (!strcasecmp (key, "icy-genre")) {
+ fp->content_genre = strdup (value);
}
- int len = (const uint8_t *)p-cl;
- char str[len+1];
- strncpy (str, cl, len);
- str[len] = 0;
- fp->content_type = strdup (str);
+ }
+ if (!fp->icyheader) {
+ fp->gotheader = 1;
}
return size * nmemb;
}
@@ -300,6 +365,12 @@ http_close (DB_FILE *stream) {
if (fp->content_type) {
free (fp->content_type);
}
+ if (fp->content_name) {
+ free (fp->content_name);
+ }
+ if (fp->content_genre) {
+ free (fp->content_genre);
+ }
if (fp->url) {
free (fp->url);
}
@@ -476,6 +547,42 @@ http_get_content_type (DB_FILE *stream) {
return fp->content_type;
}
+static const char *
+http_get_content_name (DB_FILE *stream) {
+ trace ("http_get_content_name\n");
+ assert (stream);
+ HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->gotheader) {
+ return fp->content_name;
+ }
+ if (!fp->tid) {
+ http_start_streamer (fp);
+ }
+ trace ("http_get_content_name waiting for response...\n");
+ while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader) {
+ usleep (3000);
+ }
+ return fp->content_name;
+}
+
+static const char *
+http_get_content_genre (DB_FILE *stream) {
+ trace ("http_get_content_genre\n");
+ assert (stream);
+ HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->gotheader) {
+ return fp->content_genre;
+ }
+ if (!fp->tid) {
+ http_start_streamer (fp);
+ }
+ trace ("http_get_content_genre waiting for response...\n");
+ while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader) {
+ usleep (3000);
+ }
+ return fp->content_genre;
+}
+
static const char *scheme_names[] = { "http://", "ftp://", NULL };
// standard stdio vfs
@@ -497,6 +604,8 @@ static DB_vfs_t plugin = {
.rewind = http_rewind,
.getlength = http_getlength,
.get_content_type = http_get_content_type,
+ .get_content_name = http_get_content_name,
+ .get_content_genre = http_get_content_type,
.scheme_names = scheme_names,
.streaming = 1
};
diff --git a/vfs.c b/vfs.c
index 7e6f64ee..2c038fac 100644
--- a/vfs.c
+++ b/vfs.c
@@ -84,3 +84,18 @@ const char *
vfs_get_content_type (DB_FILE *stream) {
return stream->vfs->get_content_type (stream);
}
+
+const char *
+vfs_get_content_name (DB_FILE *stream) {
+ if (stream->vfs->get_content_name) {
+ return stream->vfs->get_content_name (stream);
+ }
+ return NULL;
+}
+const char *
+vfs_get_content_genre (DB_FILE *stream) {
+ if (stream->vfs->get_content_genre) {
+ return stream->vfs->get_content_genre (stream);
+ }
+ return NULL;
+}
diff --git a/vfs.h b/vfs.h
index 6bb7afd7..599e63e4 100644
--- a/vfs.h
+++ b/vfs.h
@@ -30,5 +30,7 @@ int64_t vfs_ftell (DB_FILE *stream);
void vfs_rewind (DB_FILE *stream);
int64_t vfs_fgetlength (DB_FILE *stream);
const char *vfs_get_content_type (DB_FILE *stream);
+const char *vfs_get_content_name (DB_FILE *stream);
+const char *vfs_get_content_genre (DB_FILE *stream);
#endif // __VFS_H