Commit c7aa89cf authored by Jack Moffitt's avatar Jack Moffitt

Two things:

1) vorbis tags (ARTIST and TITLE) now appear in the stats.  Oddsock did
the first cut of this.

2) stats bug fixed.  if a stats value was NULL a segfault occurred.
strdup(NULL) is fun!

svn path=/trunk/icecast/; revision=3024
parent 0512d524
......@@ -15,13 +15,14 @@
#include "format_vorbis.h"
format_plugin_t *format_get_plugin(format_type_t type)
format_plugin_t *format_get_plugin(format_type_t type, char *mount)
{
format_plugin_t *plugin;
switch (type) {
case FORMAT_TYPE_VORBIS:
plugin = format_vorbis_get_plugin();
if (plugin) plugin->mount = mount;
break;
default:
plugin = NULL;
......
......@@ -16,6 +16,9 @@ typedef struct _format_plugin_tag
{
format_type_t type;
/* we need to know the mount to report statistics */
char *mount;
/* set this is the data format has a header that
** we must send before regular data
*/
......@@ -29,7 +32,7 @@ typedef struct _format_plugin_tag
void *_state;
} format_plugin_t;
format_plugin_t *format_get_plugin(format_type_t type);
format_plugin_t *format_get_plugin(format_type_t type, char *mount);
#endif /* __FORMAT_H__ */
......
......@@ -18,10 +18,15 @@
typedef struct _vstate_tag
{
ogg_sync_state oy;
ogg_stream_state os;
vorbis_info vi;
vorbis_comment vc;
ogg_page og;
unsigned long serialno;
int header;
refbuf_t *headbuf[10];
int packets;
} vstate_t;
void format_vorbis_free_plugin(format_plugin_t *self);
......@@ -58,6 +63,9 @@ void format_vorbis_free_plugin(format_plugin_t *self)
/* free state memory */
ogg_sync_clear(&state->oy);
ogg_stream_clear(&state->os);
vorbis_comment_clear(&state->vc);
vorbis_info_clear(&state->vi);
for (i = 0; i < 10; i++) {
if (state->headbuf[i]) {
......@@ -76,7 +84,9 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
{
char *buffer;
refbuf_t *refbuf;
int i;
int i, result;
ogg_packet op;
char *tag;
vstate_t *state = (vstate_t *)self->_state;
if (data) {
......@@ -95,28 +105,67 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
if (state->serialno != ogg_page_serialno(&state->og)) {
/* this is a new logical bitstream */
state->header = 0;
state->packets = 0;
/* release old headers, stream state, vorbis data */
for (i = 0; i < 10; i++) {
if (state->headbuf[i]) {
refbuf_release(state->headbuf[i]);
state->headbuf[i] = NULL;
}
}
state->serialno = ogg_page_serialno(&state->og);
ogg_stream_init(&state->os, state->serialno);
vorbis_info_init(&state->vi);
vorbis_comment_init(&state->vc);
}
if (state->header >= 0) {
if (ogg_page_granulepos(&state->og) == 0) {
state->header++;
} else {
state->header = 0;
/* we're done caching headers */
state->header = -1;
/* put known comments in the stats */
tag = vorbis_comment_query(&state->vc, "TITLE", 0);
if (tag) stats_event_args(self->mount, "title", tag);
else stats_event_args(self->mount, "title", "unknown");
tag = vorbis_comment_query(&state->vc, "ARTIST", 0);
if (tag) stats_event_args(self->mount, "artist", tag);
else stats_event_args(self->mount, "artist", "unknown");
/* don't need these now */
ogg_stream_clear(&state->os);
vorbis_comment_clear(&state->vc);
vorbis_info_clear(&state->vi);
}
}
/* cache first three pages */
if (state->header) {
/* cache header pages */
if (state->header > 0) {
refbuf_addref(refbuf);
state->headbuf[state->header - 1] = refbuf;
if (state->packets >= 0 && state->packets < 2) {
ogg_stream_pagein(&state->os, &state->og);
while (state->packets < 2) {
result = ogg_stream_packetout(&state->os, &op);
if (result == 0) break; /* need more data */
if (result < 0) {
state->packets = -1;
break;
}
state->packets++;
if (vorbis_synthesis_headerin(&state->vi, &state->vc, &op) < 0) {
state->packets = -1;
break;
}
}
}
}
}
......
......@@ -41,10 +41,10 @@ source_t *source_create(connection_t *con, http_parser_t *parser, const char *mo
source_t *src;
src = (source_t *)malloc(sizeof(source_t));
src->format = format_get_plugin(type);
src->mount = (char *)strdup(mount);
src->format = format_get_plugin(type, src->mount);
src->con = con;
src->parser = parser;
src->mount = (char *)strdup(mount);
src->client_tree = avl_tree_new(_compare_clients, NULL);
src->pending_tree = avl_tree_new(_compare_clients, NULL);
......@@ -110,6 +110,7 @@ void *source_main(void *arg)
int ret, timeout;
client_t *client;
avl_node *client_node;
char *s;
refbuf_t *refbuf, *abuf;
int data_done;
......@@ -134,6 +135,14 @@ void *source_main(void *arg)
/* start off the statistics */
stats_event(source->mount, "listeners", "0");
if ((s = httpp_getvar(source->parser, "ice-name")))
stats_event(source->mount, "name", s);
if ((s = httpp_getvar(source->parser, "ice-url")))
stats_event(source->mount, "url", s);
if ((s = httpp_getvar(source->parser, "ice-bitrate")))
stats_event(source->mount, "bitrate", s);
if ((s = httpp_getvar(source->parser, "ice-description")))
stats_event(source->mount, "description", s);
while (global.running == ICE_RUNNING) {
refbuf = source->format->get_buffer(source->format, NULL, 0);
......
......@@ -286,7 +286,10 @@ static stats_event_t *_copy_event(stats_event_t *event)
else
copy->source = NULL;
copy->name = (char *)strdup(event->name);
copy->value = (char *)strdup(event->value);
if (event->value)
copy->value = (char *)strdup(event->value);
else
copy->value = NULL;
copy->next = NULL;
return copy;
......@@ -480,7 +483,7 @@ static int _send_event_to_client(stats_event_t *event, connection_t *con)
int ret;
/* send data to the client!!!! */
ret = sock_write(con->sock, "EVENT %s %s %s\n", (event->source != NULL) ? event->source : "global", event->name, event->value);
ret = sock_write(con->sock, "EVENT %s %s %s\n", (event->source != NULL) ? event->source : "global", event->name, event->value ? event->value : "null");
return (ret == -1) ? 0 : 1;
}
......
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