mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-09-29 04:25:55 -04:00
add intro file handling
svn path=/icecast/branches/kh/icecast/; revision=8189
This commit is contained in:
parent
f2f292cfaa
commit
0d0a87ea84
@ -100,6 +100,7 @@
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-when-full>1</fallback-when-full>
|
||||
<hidden>1</hidden>
|
||||
<intro>/path/to/stream-intro.ogg</intro>
|
||||
<no-yp>1</no-yp>
|
||||
<authentication type="htpasswd">
|
||||
<option name="filename" value="myauth"/>
|
||||
|
@ -330,6 +330,7 @@ An on-demand relay will only retrieve the stream if there are listeners connecte
|
||||
<password>hackmemore</password>
|
||||
<max-listeners>1</max-listeners>
|
||||
<dump-file>/tmp/dump-example1.ogg</dump-file>
|
||||
<intro>/path/to/intro.ogg</intro>
|
||||
<fallback-mount>/example2.ogg</fallback-mount>
|
||||
<fallback-override>1</fallback-override>
|
||||
<burst-size>65536</burst-size>
|
||||
@ -363,6 +364,12 @@ An optional value which will set the maximum number of listeners that can be att
|
||||
<div class="indentedbox">
|
||||
An optional value which will set the filename which will be a dump of the stream coming through on this mountpoint.
|
||||
</div>
|
||||
<h4>intro</h4>
|
||||
<div class="indentedbox">
|
||||
An optional value which will specify the file those contents will be sent to new listeners when they
|
||||
connect but before the normal stream is sent. Make sure the format of the file specified matches the
|
||||
streaming format.
|
||||
</div>
|
||||
<h4>fallback-mount</h4>
|
||||
<div class="indentedbox">
|
||||
This optional value specifies a mountpoint that clients are automatically moved to if the source
|
||||
|
@ -183,6 +183,7 @@ void config_clear(ice_config_t *c)
|
||||
xmlFree(mount->username);
|
||||
xmlFree(mount->password);
|
||||
xmlFree(mount->dumpfile);
|
||||
xmlFree(mount->intro_filename);
|
||||
xmlFree(mount->on_connect);
|
||||
xmlFree(mount->on_disconnect);
|
||||
xmlFree(mount->fallback_mount);
|
||||
@ -551,6 +552,10 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
|
||||
mount->dumpfile = (char *)xmlNodeListGetString(
|
||||
doc, node->xmlChildrenNode, 1);
|
||||
}
|
||||
else if (strcmp(node->name, "intro") == 0) {
|
||||
mount->intro_filename = (char *)xmlNodeListGetString(
|
||||
doc, node->xmlChildrenNode, 1);
|
||||
}
|
||||
else if (strcmp(node->name, "fallback-mount") == 0) {
|
||||
mount->fallback_mount = (char *)xmlNodeListGetString(
|
||||
doc, node->xmlChildrenNode, 1);
|
||||
|
@ -47,6 +47,7 @@ typedef struct _mount_proxy {
|
||||
|
||||
char *dumpfile; /* Filename to dump this stream to (will be appended). NULL
|
||||
to not dump. */
|
||||
char *intro_filename; /* Send contents of file to client before the stream */
|
||||
int fallback_when_full; /* switch new listener to fallback source
|
||||
when max listeners reached */
|
||||
int max_listeners; /* Max listeners for this mountpoint only. -1 to not
|
||||
|
@ -40,6 +40,9 @@ typedef struct _client_tag
|
||||
/* auth completed, 0 not yet, 1 passed, 2 failed */
|
||||
int authenticated;
|
||||
|
||||
/* is client getting intro data */
|
||||
long intro_offset;
|
||||
|
||||
/* where in the queue the client is */
|
||||
refbuf_t *refbuf;
|
||||
|
||||
|
53
src/format.c
53
src/format.c
@ -98,6 +98,48 @@ int format_get_plugin(format_type_t type, source_t *source)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int get_intro_data (FILE *intro, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = client->refbuf;
|
||||
int bytes;
|
||||
|
||||
if (intro == NULL || fseek (intro, client->intro_offset, SEEK_SET) < 0)
|
||||
return 0;
|
||||
bytes = fread (refbuf->data, 1, 4096, intro);
|
||||
if (bytes == 0)
|
||||
{
|
||||
client->intro_offset = 0;
|
||||
return 0;
|
||||
}
|
||||
refbuf->len = bytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* wrapper for the per-format write to client routine. Here we populate
|
||||
* the refbuf before calling it
|
||||
*/
|
||||
static int format_intro_write_to_client (source_t *source, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = client->refbuf;
|
||||
|
||||
if (client->pos == refbuf->len)
|
||||
{
|
||||
if (get_intro_data (source->intro_file, client) == 0)
|
||||
{
|
||||
client_set_queue (client, source->stream_data_tail);
|
||||
client->write_to_client = source->format->write_buf_to_client;
|
||||
return 0;
|
||||
}
|
||||
client->pos = 0;
|
||||
client->intro_offset += refbuf->len;
|
||||
}
|
||||
|
||||
return source->format->write_buf_to_client (source, client);
|
||||
}
|
||||
|
||||
|
||||
int format_http_write_to_client (source_t *source, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = client->refbuf;
|
||||
@ -131,8 +173,19 @@ int format_http_write_to_client (source_t *source, client_t *client)
|
||||
if (ret > 0)
|
||||
client->pos += ret;
|
||||
if (client->pos == refbuf->len)
|
||||
{
|
||||
if (source->intro_file)
|
||||
{
|
||||
/* client should be sent an intro file */
|
||||
client->write_to_client = format_intro_write_to_client;
|
||||
client->intro_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
client_set_queue (client, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ typedef struct _format_plugin_tag
|
||||
char *format_description;
|
||||
|
||||
refbuf_t *(*get_buffer)(struct source_tag *);
|
||||
int (*write_buf_to_client)(struct source_tag *format, client_t *client);
|
||||
int (*write_buf_to_client)(struct source_tag *source, client_t *client);
|
||||
void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
|
||||
int (*create_client_data)(struct source_tag *source, client_t *client);
|
||||
void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
|
||||
|
@ -59,7 +59,7 @@ static refbuf_t *mp3_get_no_meta (source_t *source);
|
||||
|
||||
static int format_mp3_create_client_data (source_t *source, client_t *client);
|
||||
static void free_mp3_client_data (client_t *client);
|
||||
static int format_mp3_write_buf_to_client(source_t *self, client_t *client);
|
||||
static int format_mp3_write_buf_to_client(source_t *source, client_t *client);
|
||||
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
|
||||
static void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value);
|
||||
static void format_mp3_apply_settings(struct source_tag *source, struct _mount_proxy *mount);
|
||||
@ -296,7 +296,7 @@ static int send_mp3_metadata (client_t *client, refbuf_t *associated)
|
||||
/* Handler for writing mp3 data to a client, taking into account whether
|
||||
* client has requested shoutcast style metadata updates
|
||||
*/
|
||||
static int format_mp3_write_buf_to_client (source_t *self, client_t *client)
|
||||
static int format_mp3_write_buf_to_client (source_t *source, client_t *client)
|
||||
{
|
||||
int ret, written = 0;
|
||||
mp3_client_data *client_mp3 = client->format_data;
|
||||
|
@ -509,7 +509,7 @@ static void free_ogg_client_data (client_t *client);
|
||||
|
||||
static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf);
|
||||
static refbuf_t *ogg_get_buffer (source_t *source);
|
||||
static int write_buf_to_client (source_t *self, client_t *client);
|
||||
static int write_buf_to_client (source_t *source, client_t *client);
|
||||
|
||||
|
||||
static void free_ogg_codecs (ogg_state_t *ogg_info)
|
||||
@ -802,7 +802,7 @@ static int send_ogg_headers (client_t *client, refbuf_t *headers)
|
||||
}
|
||||
|
||||
|
||||
static int write_buf_to_client (source_t *self, client_t *client)
|
||||
static int write_buf_to_client (source_t *source, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = client->refbuf;
|
||||
char *buf;
|
||||
|
@ -98,7 +98,7 @@ static void free_vorbis_client_data (client_t *client);
|
||||
|
||||
static void write_vorbis_to_file (struct source_tag *source, refbuf_t *refbuf);
|
||||
static refbuf_t *vorbis_get_buffer (source_t *source);
|
||||
static int vorbis_write_buf_to_client (source_t *self, client_t *client);
|
||||
static int vorbis_write_buf_to_client (source_t *source, client_t *client);
|
||||
static void vorbis_set_tag (format_plugin_t *plugin, char *tag, char *value);
|
||||
|
||||
|
||||
@ -751,7 +751,7 @@ static int send_vorbis_headers (client_t *client, refbuf_t *headers)
|
||||
}
|
||||
|
||||
|
||||
static int vorbis_write_buf_to_client (source_t *self, client_t *client)
|
||||
static int vorbis_write_buf_to_client (source_t *source, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = client->refbuf;
|
||||
char *buf;
|
||||
|
26
src/source.c
26
src/source.c
@ -264,6 +264,12 @@ void source_clear_source (source_t *source)
|
||||
free(source->dumpfilename);
|
||||
source->dumpfilename = NULL;
|
||||
|
||||
if (source->intro_file)
|
||||
{
|
||||
fclose (source->intro_file);
|
||||
source->intro_file = NULL;
|
||||
}
|
||||
|
||||
free (source->on_connect);
|
||||
source->on_connect = NULL;
|
||||
|
||||
@ -562,6 +568,7 @@ static void process_listeners (source_t *source, int fast_clients_only, int dele
|
||||
static void get_next_buffer (source_t *source)
|
||||
{
|
||||
refbuf_t *refbuf = NULL;
|
||||
int no_delay_count = 0;
|
||||
|
||||
while (global.running == ICE_RUNNING && source->running)
|
||||
{
|
||||
@ -569,8 +576,18 @@ static void get_next_buffer (source_t *source)
|
||||
time_t current = time(NULL);
|
||||
int delay = 200;
|
||||
|
||||
/* service fast clients but jump out once in a while to check on
|
||||
* normal clients */
|
||||
if (no_delay_count < 10)
|
||||
{
|
||||
if (source->active_clients != source->first_normal_client)
|
||||
{
|
||||
delay = 0;
|
||||
no_delay_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
thread_mutex_unlock (&source->lock);
|
||||
|
||||
@ -1175,6 +1192,15 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
|
||||
free (source->dumpfilename);
|
||||
source->dumpfilename = strdup (mountinfo->dumpfile);
|
||||
}
|
||||
if (source->intro_file)
|
||||
fclose (source->intro_file);
|
||||
if (mountinfo->intro_filename)
|
||||
{
|
||||
source->intro_file = fopen (mountinfo->intro_filename, "rb");
|
||||
if (source->intro_file == NULL)
|
||||
WARN2 ("Cannot open intro file \"%s\": %s",
|
||||
mountinfo->intro_filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (mountinfo->queue_size_limit)
|
||||
source->queue_size_limit = mountinfo->queue_size_limit;
|
||||
|
@ -85,6 +85,8 @@ typedef struct source_tag
|
||||
refbuf_t *stream_data;
|
||||
refbuf_t *stream_data_tail;
|
||||
|
||||
FILE *intro_file;
|
||||
|
||||
} source_t;
|
||||
|
||||
source_t *source_reserve (const char *mount);
|
||||
|
Loading…
Reference in New Issue
Block a user