Commit 9e118ca7 authored by Karl Heyes's avatar Karl Heyes

explicitly flag up a metadata update after they have been set. Could of led to

a non-crash type race between artist and title fields updating.  Also allow
passing a url setting, mapping to StreamURL in the icy metadata block, but do
not override any existing inline setting.

svn path=/icecast/trunk/icecast/; revision=15622
parent e6dfee63
...@@ -941,6 +941,8 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -941,6 +941,8 @@ static void command_metadata(client_t *client, source_t *source,
source->mount, artist, title); source->mount, artist, title);
} }
} }
/* updates are now done, let them be pushed into the stream */
plugin->set_tag (plugin, NULL, NULL, NULL);
} }
else else
{ {
...@@ -983,6 +985,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source) ...@@ -983,6 +985,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
if (same_ip && source->format && source->format->set_tag) if (same_ip && source->format && source->format->set_tag)
{ {
source->format->set_tag (source->format, "title", value, NULL); source->format->set_tag (source->format, "title", value, NULL);
source->format->set_tag (source->format, NULL, NULL, NULL);
DEBUG2("Metadata on mountpoint %s changed to \"%s\"", DEBUG2("Metadata on mountpoint %s changed to \"%s\"",
source->mount, value); source->mount, value);
......
...@@ -127,37 +127,39 @@ int format_mp3_get_plugin (source_t *source) ...@@ -127,37 +127,39 @@ int format_mp3_get_plugin (source_t *source)
static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset) static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset)
{ {
mp3_state *source_mp3 = plugin->_state; mp3_state *source_mp3 = plugin->_state;
unsigned int len; char *value = NULL;
const char meta[] = "StreamTitle='";
int size = sizeof (meta) + 1;
char *value;
if (tag==NULL || in_value == NULL)
return;
/* protect against multiple updaters */ /* protect against multiple updaters */
thread_mutex_lock (&source_mp3->url_lock); thread_mutex_lock (&source_mp3->url_lock);
value = util_conv_string (in_value, charset, plugin->charset); if (tag==NULL)
if (value == NULL) {
value = strdup (in_value); source_mp3->update_metadata = 1;
thread_mutex_unlock (&source_mp3->url_lock);
return;
}
len = strlen (value)+1; if (in_value)
size += len; {
value = util_conv_string (in_value, charset, plugin->charset);
if (value == NULL)
value = strdup (in_value);
}
if (strcmp (tag, "title") == 0 || strcmp (tag, "song") == 0) if (strcmp (tag, "title") == 0 || strcmp (tag, "song") == 0)
{ {
free (source_mp3->url_title); free (source_mp3->url_title);
free (source_mp3->url_artist);
source_mp3->url_artist = NULL;
source_mp3->url_title = value; source_mp3->url_title = value;
source_mp3->update_metadata = 1;
} }
else if (strcmp (tag, "artist") == 0) else if (strcmp (tag, "artist") == 0)
{ {
free (source_mp3->url_artist); free (source_mp3->url_artist);
source_mp3->url_artist = value; source_mp3->url_artist = value;
source_mp3->update_metadata = 1; }
else if (strcmp (tag, "url") == 0)
{
free (source_mp3->url);
source_mp3->url = value;
} }
else else
free (value); free (value);
...@@ -234,11 +236,12 @@ static void format_mp3_apply_settings (client_t *client, format_plugin_t *format ...@@ -234,11 +236,12 @@ static void format_mp3_apply_settings (client_t *client, format_plugin_t *format
*/ */
static void mp3_set_title (source_t *source) static void mp3_set_title (source_t *source)
{ {
const char meta[] = "StreamTitle='"; const char streamtitle[] = "StreamTitle='";
int size; const char streamurl[] = "StreamUrl='";
size_t size;
unsigned char len_byte; unsigned char len_byte;
refbuf_t *p; refbuf_t *p;
unsigned int len = sizeof(meta) + 2; /* the StreamTitle, quotes, ; and null */ unsigned int len = sizeof(streamtitle) + 2; /* the StreamTitle, quotes, ; and null */
mp3_state *source_mp3 = source->format->_state; mp3_state *source_mp3 = source->format->_state;
/* make sure the url data does not disappear from under us */ /* make sure the url data does not disappear from under us */
...@@ -251,6 +254,14 @@ static void mp3_set_title (source_t *source) ...@@ -251,6 +254,14 @@ static void mp3_set_title (source_t *source)
len += strlen (source_mp3->url_title); len += strlen (source_mp3->url_title);
if (source_mp3->url_artist && source_mp3->url_title) if (source_mp3->url_artist && source_mp3->url_title)
len += 3; len += 3;
if (source_mp3->inline_url)
{
char *end = strstr (source_mp3->inline_url, "';");
if (end)
len += end - source_mp3->inline_url+2;
}
else if (source_mp3->url)
len += strlen (source_mp3->url) + strlen (streamurl) + 2;
#define MAX_META_LEN 255*16 #define MAX_META_LEN 255*16
if (len > MAX_META_LEN) if (len > MAX_META_LEN)
{ {
...@@ -268,14 +279,29 @@ static void mp3_set_title (source_t *source) ...@@ -268,14 +279,29 @@ static void mp3_set_title (source_t *source)
if (p) if (p)
{ {
mp3_state *source_mp3 = source->format->_state; mp3_state *source_mp3 = source->format->_state;
int r;
memset (p->data, '\0', size); memset (p->data, '\0', size);
if (source_mp3->url_artist && source_mp3->url_title) if (source_mp3->url_artist && source_mp3->url_title)
snprintf (p->data, size, "%c%s%s - %s';", len_byte, meta, r = snprintf (p->data, size, "%c%s%s - %s';", len_byte, streamtitle,
source_mp3->url_artist, source_mp3->url_title); source_mp3->url_artist, source_mp3->url_title);
else else
snprintf (p->data, size, "%c%s%s';", len_byte, meta, r = snprintf (p->data, size, "%c%s%s';", len_byte, streamtitle,
source_mp3->url_title); source_mp3->url_title);
if (r > 0)
{
if (source_mp3->inline_url)
{
char *end = strstr (source_mp3->inline_url, "';");
int urllen = size;
if (end) urllen = end - source_mp3->inline_url + 2;
if (size-r > urllen)
snprintf (p->data+r, size-r, "StreamUrl='%s';", source_mp3->inline_url+11);
}
else if (source_mp3->url)
snprintf (p->data+r, size-r, "StreamUrl='%s';", source_mp3->url);
}
DEBUG1 ("shoutcast metadata block setup with %s", p->data+1);
filter_shoutcast_metadata (source, p->data, size); filter_shoutcast_metadata (source, p->data, size);
refbuf_release (source_mp3->metadata); refbuf_release (source_mp3->metadata);
...@@ -289,7 +315,7 @@ static void mp3_set_title (source_t *source) ...@@ -289,7 +315,7 @@ static void mp3_set_title (source_t *source)
* which is 0 or greater. Check the client in_metadata value afterwards * which is 0 or greater. Check the client in_metadata value afterwards
* to see if all metadata has been sent * to see if all metadata has been sent
*/ */
static int send_mp3_metadata (client_t *client, refbuf_t *associated) static int send_stream_metadata (client_t *client, refbuf_t *associated)
{ {
int ret = 0; int ret = 0;
char *metadata; char *metadata;
...@@ -355,7 +381,7 @@ static int format_mp3_write_buf_to_client(client_t *client) ...@@ -355,7 +381,7 @@ static int format_mp3_write_buf_to_client(client_t *client)
if (client_mp3->in_metadata) if (client_mp3->in_metadata)
{ {
refbuf_t *associated = refbuf->associated; refbuf_t *associated = refbuf->associated;
ret = send_mp3_metadata (client, associated); ret = send_stream_metadata (client, associated);
if (client_mp3->in_metadata) if (client_mp3->in_metadata)
break; break;
...@@ -367,7 +393,7 @@ static int format_mp3_write_buf_to_client(client_t *client) ...@@ -367,7 +393,7 @@ static int format_mp3_write_buf_to_client(client_t *client)
unsigned int remaining = client_mp3->interval - unsigned int remaining = client_mp3->interval -
client_mp3->since_meta_block; client_mp3->since_meta_block;
/* sending the metadata block */ /* leading up to sending the metadata block */
if (remaining <= len) if (remaining <= len)
{ {
/* send any mp3 before the metadata block */ /* send any mp3 before the metadata block */
...@@ -384,11 +410,10 @@ static int format_mp3_write_buf_to_client(client_t *client) ...@@ -384,11 +410,10 @@ static int format_mp3_write_buf_to_client(client_t *client)
break; break;
written += ret; written += ret;
} }
ret = send_mp3_metadata (client, refbuf->associated); ret = send_stream_metadata (client, refbuf->associated);
if (client_mp3->in_metadata) if (client_mp3->in_metadata)
break; break;
written += ret; written += ret;
/* change buf and len */
buf += remaining; buf += remaining;
len -= remaining; len -= remaining;
/* limit how much mp3 we send if using small intervals */ /* limit how much mp3 we send if using small intervals */
...@@ -602,6 +627,7 @@ static refbuf_t *mp3_get_filter_meta (source_t *source) ...@@ -602,6 +627,7 @@ static refbuf_t *mp3_get_filter_meta (source_t *source)
source_mp3->build_metadata_len); source_mp3->build_metadata_len);
refbuf_release (source_mp3->metadata); refbuf_release (source_mp3->metadata);
source_mp3->metadata = meta; source_mp3->metadata = meta;
source_mp3->inline_url = strstr (meta->data+1, "StreamUrl='");
} }
else else
{ {
...@@ -633,7 +659,7 @@ static int format_mp3_create_client_data(source_t *source, client_t *client) ...@@ -633,7 +659,7 @@ static int format_mp3_create_client_data(source_t *source, client_t *client)
{ {
mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data)); mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data));
mp3_state *source_mp3 = source->format->_state; mp3_state *source_mp3 = source->format->_state;
const char *metadata; const char *metadata;
/* the +-2 is for overwriting the last set of \r\n */ /* the +-2 is for overwriting the last set of \r\n */
unsigned remaining = 4096 - client->refbuf->len + 2; unsigned remaining = 4096 - client->refbuf->len + 2;
char *ptr = client->refbuf->data + client->refbuf->len - 2; char *ptr = client->refbuf->data + client->refbuf->len - 2;
......
...@@ -25,11 +25,13 @@ typedef struct { ...@@ -25,11 +25,13 @@ typedef struct {
int interval; int interval;
char *url_artist; char *url_artist;
char *url_title; char *url_title;
char *url;
char *inline_url;
int update_metadata; int update_metadata;
refbuf_t *metadata; refbuf_t *metadata;
refbuf_t *read_data; refbuf_t *read_data;
unsigned int read_count; int read_count;
mutex_t url_lock; mutex_t url_lock;
unsigned build_metadata_len; unsigned build_metadata_len;
......
...@@ -421,7 +421,6 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char ...@@ -421,7 +421,6 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char
ogg_state_t *ogg_info = plugin->_state; ogg_state_t *ogg_info = plugin->_state;
ogg_codec_t *codec = ogg_info->codecs; ogg_codec_t *codec = ogg_info->codecs;
vorbis_codec_t *source_vorbis; vorbis_codec_t *source_vorbis;
int change = 0;
char *value; char *value;
/* avoid updating if multiple codecs in use */ /* avoid updating if multiple codecs in use */
...@@ -430,6 +429,13 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char ...@@ -430,6 +429,13 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char
else else
return; return;
if (tag == NULL)
{
source_vorbis->stream_notify = 1;
source_vorbis->rebuild_comment = 1;
return;
}
value = util_conv_string (in_value, charset, "UTF-8"); value = util_conv_string (in_value, charset, "UTF-8");
if (value == NULL) if (value == NULL)
value = strdup (in_value); value = strdup (in_value);
...@@ -438,26 +444,16 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char ...@@ -438,26 +444,16 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char
{ {
free (ogg_info->artist); free (ogg_info->artist);
ogg_info->artist = value; ogg_info->artist = value;
change = 1;
} }
else if (strcmp (tag, "title") == 0) else if (strcmp (tag, "title") == 0)
{ {
free (ogg_info->title); free (ogg_info->title);
ogg_info->title = value; ogg_info->title = value;
change = 1;
} }
else if (strcmp (tag, "song") == 0) else if (strcmp (tag, "song") == 0)
{ {
free (ogg_info->artist);
free (ogg_info->title); free (ogg_info->title);
ogg_info->artist = NULL;
ogg_info->title = value; ogg_info->title = value;
change = 1;
}
if (change)
{
source_vorbis->stream_notify = 1;
source_vorbis->rebuild_comment = 1;
} }
else else
free (value); free (value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment