int http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) { trace ("reading %d bytes of metadata\n", size); trace ("%s\n", meta); const char *e = meta + size; const char strtitle[] = "StreamTitle='"; char title[256] = ""; while (meta < e) { if (!memcmp (meta, strtitle, sizeof (strtitle)-1)) { trace ("extracting streamtitle\n"); meta += sizeof (strtitle)-1; const char *substr_end = meta; while (substr_end < e-1 && (*substr_end != '\'' || *(substr_end+1) != ';')) { substr_end++; } if (substr_end >= e) { return -1; // end of string not found } int s = substr_end - meta; s = min (sizeof (title)-1, s); memcpy (title, meta, s); title[s] = 0; trace ("got stream title: %s\n", title); if (fp->track) { char *tit = strstr (title, " - "); if (tit) { *tit = 0; tit += 3; vfs_curl_set_meta (fp->track, "artist", title); vfs_curl_set_meta (fp->track, "title", tit); } else { vfs_curl_set_meta (fp->track, "title", title); } ddb_playlist_t *plt = deadbeef->plt_get_curr (); if (plt) { deadbeef->plt_modified (plt); deadbeef->plt_unref (plt); } deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, 0, 0); } return 0; } while (meta < e && *meta != ';') { meta++; } if (meta < e) { meta++; } } return -1; }
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 *p = ptr; const uint8_t *end = p + size*nmemb; uint8_t key[256]; uint8_t value[256]; int refresh_playlist = 0; if (fp->length == 0) { fp->length = -1; } while (p < end) { if (p <= end - 4) { if (!memcmp (p, "\r\n\r\n", 4)) { p += 4; return size * nmemb - (size_t)(p-(const uint8_t *)ptr); } } // skip linebreaks while (p < end && (*p == 0x0d || *p == 0x0a)) { p++; } 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")) { if (fp->content_type) { free (fp->content_type); } fp->content_type = strdup (value); } else if (!strcasecmp (key, "Content-Length")) { fp->length = atoi (value); } else if (!strcasecmp (key, "icy-name")) { if (fp->track) { vfs_curl_set_meta (fp->track, "album", value); refresh_playlist = 1; } } else if (!strcasecmp (key, "icy-genre")) { if (fp->track) { vfs_curl_set_meta (fp->track, "genre", value); refresh_playlist = 1; } } else if (!strcasecmp (key, "icy-metaint")) { //printf ("icy-metaint: %d\n", atoi (value)); fp->icy_metaint = atoi (value); fp->wait_meta = fp->icy_metaint; } } ddb_playlist_t *plt = deadbeef->plt_get_curr (); if (plt) { deadbeef->plt_modified (plt); deadbeef->plt_unref (plt); } if (refresh_playlist) { deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, 0, 0); } if (!fp->icyheader) { fp->gotsomeheader = 1; } return size * nmemb; }
int http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) { trace ("reading %d bytes of metadata\n", size); trace ("%s\n", meta); const char *e = meta + size; const char strtitle[] = "StreamTitle='"; char title[256] = ""; while (meta < e) { if (!memcmp (meta, strtitle, sizeof (strtitle)-1)) { trace ("extracting streamtitle\n"); meta += sizeof (strtitle)-1; const char *substr_end = meta; while (substr_end < e-1 && (*substr_end != '\'' || *(substr_end+1) != ';')) { substr_end++; } if (substr_end >= e) { return -1; // end of string not found } int s = substr_end - meta; s = min (sizeof (title)-1, s); memcpy (title, meta, s); title[s] = 0; trace ("got stream title: %s\n", title); if (fp->track) { int songstarted = 0; char *tit = strstr (title, " - "); deadbeef->pl_lock (); if (tit) { *tit = 0; tit += 3; const char *orig_title = deadbeef->pl_find_meta (fp->track, "title"); const char *orig_artist = deadbeef->pl_find_meta (fp->track, "artist"); if (!orig_title || strcasecmp (orig_title, tit)) { vfs_curl_set_meta (fp->track, "title", tit); songstarted = 1; } if (!orig_artist || strcasecmp (orig_artist, title)) { vfs_curl_set_meta (fp->track, "artist", title); songstarted = 1; } } else { const char *orig_title = deadbeef->pl_find_meta (fp->track, "title"); if (!orig_title || strcasecmp (orig_title, title)) { vfs_curl_set_meta (fp->track, "title", title); songstarted = 1; } } deadbeef->pl_unlock (); ddb_playlist_t *plt = deadbeef->plt_get_curr (); if (plt) { deadbeef->plt_modified (plt); deadbeef->plt_unref (plt); } deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, 0, 0); if (songstarted) { ddb_event_track_t *ev = (ddb_event_track_t *)deadbeef->event_alloc (DB_EV_SONGSTARTED); ev->track = fp->track; if (ev->track) { deadbeef->pl_item_ref (ev->track); } deadbeef->event_send ((ddb_event_t *)ev, 0, 0); } } return 0; } while (meta < e && *meta != ';') { meta++; } if (meta < e) { meta++; } } return -1; }
int http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) { trace ("reading %d bytes of metadata\n", size); trace ("%s\n", meta); const char *e = meta + size; const char strtitle[] = "StreamTitle='"; char title[256] = ""; while (meta < e) { if (!memcmp (meta, strtitle, sizeof (strtitle)-1)) { trace ("extracting streamtitle\n"); meta += sizeof (strtitle)-1; const char *substr_end = meta; while (substr_end < e-1 && (*substr_end != '\'' || *(substr_end+1) != ';')) { substr_end++; } if (substr_end >= e) { return -1; // end of string not found } int s = substr_end - meta; s = min (sizeof (title)-1, s); memcpy (title, meta, s); title[s] = 0; trace ("got stream title: %s\n", title); if (fp->track) { int songstarted = 0; char *tit = strstr (title, " - "); deadbeef->pl_lock (); int emulate_trackchange = deadbeef->conf_get_int ("vfs_curl.emulate_trackchange", 0); // create dummy track with previous meta DB_playItem_t *from = NULL; if (emulate_trackchange) { from = deadbeef->pl_item_alloc (); deadbeef->pl_items_copy_junk (fp->track, from, from); } if (tit) { *tit = 0; tit += 3; const char *orig_title = deadbeef->pl_find_meta (fp->track, "title"); const char *orig_artist = deadbeef->pl_find_meta (fp->track, "artist"); if (!orig_title || strcasecmp (orig_title, tit)) { vfs_curl_set_meta (fp->track, "title", tit); songstarted = 1; } if (!orig_artist || strcasecmp (orig_artist, title)) { vfs_curl_set_meta (fp->track, "artist", title); songstarted = 1; } } else { const char *orig_title = deadbeef->pl_find_meta (fp->track, "title"); if (!orig_title || strcasecmp (orig_title, title)) { deadbeef->pl_delete_meta (fp->track, "artist"); vfs_curl_set_meta (fp->track, "title", title); songstarted = 1; } } deadbeef->pl_unlock (); ddb_playlist_t *plt = deadbeef->plt_get_curr (); if (plt) { deadbeef->plt_modified (plt); deadbeef->plt_unref (plt); } deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); if (songstarted) { float playpos = deadbeef->streamer_get_playpos (); if (emulate_trackchange) { ddb_event_trackchange_t *ev = (ddb_event_trackchange_t *)deadbeef->event_alloc (DB_EV_SONGCHANGED); ev->from = from; ev->to = fp->track; ev->playtime = playpos - fp->prev_playtime; ev->started_timestamp = fp->started_timestamp; deadbeef->pl_item_ref (ev->from); deadbeef->pl_item_ref (ev->to); deadbeef->event_send ((ddb_event_t *)ev, 0, 0); } ddb_event_track_t *ev = (ddb_event_track_t *)deadbeef->event_alloc (DB_EV_SONGSTARTED); ev->track = fp->track; fp->started_timestamp = time(NULL); ev->started_timestamp = fp->started_timestamp; if (ev->track) { deadbeef->pl_item_ref (ev->track); } deadbeef->event_send ((ddb_event_t *)ev, 0, 0); fp->prev_playtime = playpos; } if (from) { deadbeef->pl_item_unref (from); from = NULL; } } return 0; } while (meta < e && *meta != ';') { meta++; } if (meta < e) { meta++; } } return -1; }