mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Allow for specifiying a per-mount metadata interval for shoutcast style streams
svn path=/icecast/trunk/icecast/; revision=9233
This commit is contained in:
parent
22aa8719e2
commit
6d48d6c4f9
@ -335,6 +335,7 @@ If you are relaying a Shoutcast stream, you need to specify this indicator to al
|
|||||||
<no-yp>1</no-yp>
|
<no-yp>1</no-yp>
|
||||||
<hidden>1</hidden>
|
<hidden>1</hidden>
|
||||||
<burst-size>65536</burst-size>
|
<burst-size>65536</burst-size>
|
||||||
|
<mp3-metadata-interval>4096</mp3-metadata-interval>
|
||||||
<authentication type="htpasswd">
|
<authentication type="htpasswd">
|
||||||
<option name="filename" value="myauth"/>
|
<option name="filename" value="myauth"/>
|
||||||
<option name="allow_duplicate_users" value="0"/>
|
<option name="allow_duplicate_users" value="0"/>
|
||||||
@ -392,6 +393,13 @@ to a local relay instead
|
|||||||
This optional setting allows for providing a burst size which overrides the default burst size
|
This optional setting allows for providing a burst size which overrides the default burst size
|
||||||
as defined in limits. The value is in bytes.
|
as defined in limits. The value is in bytes.
|
||||||
</div>
|
</div>
|
||||||
|
<h4>mp3-metadata-interval</h4>
|
||||||
|
<div class="indentedbox">
|
||||||
|
This optional setting specifies what interval, in bytes, there is between metadata updates within
|
||||||
|
shoutcast compatible streams. This only applies to new listeners connecting on this mountpoint,
|
||||||
|
not existing listeners falling back to this mountpoint. The default is either the hardcoded
|
||||||
|
server default or the value passed from a relay.
|
||||||
|
</div>
|
||||||
<h4>hidden</h4>
|
<h4>hidden</h4>
|
||||||
<div class="indentedbox">
|
<div class="indentedbox">
|
||||||
Enable this to prevent this mount from being shown on the xsl pages. This is mainly
|
Enable this to prevent this mount from being shown on the xsl pages. This is mainly
|
||||||
|
20
src/admin.c
20
src/admin.c
@ -34,7 +34,6 @@
|
|||||||
#include "xslt.h"
|
#include "xslt.h"
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "format_mp3.h"
|
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
@ -920,34 +919,31 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
|
|||||||
{
|
{
|
||||||
char *action;
|
char *action;
|
||||||
char *value;
|
char *value;
|
||||||
mp3_state *state;
|
|
||||||
|
|
||||||
DEBUG0("Got shoutcast metadata update request");
|
DEBUG0("Got shoutcast metadata update request");
|
||||||
|
|
||||||
COMMAND_REQUIRE(client, "mode", action);
|
COMMAND_REQUIRE(client, "mode", action);
|
||||||
COMMAND_REQUIRE(client, "song", value);
|
COMMAND_REQUIRE(client, "song", value);
|
||||||
|
|
||||||
if (source->format->type == FORMAT_TYPE_OGG) {
|
|
||||||
client_send_400 (client, "Cannot update metadata on vorbis streams");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (action, "updinfo") != 0)
|
if (strcmp (action, "updinfo") != 0)
|
||||||
{
|
{
|
||||||
client_send_400 (client, "No such action");
|
client_send_400 (client, "No such action");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = source->format->_state;
|
if (source->format && source->format->set_tag)
|
||||||
|
{
|
||||||
mp3_set_tag (source->format, "title", value);
|
source->format->set_tag (source->format, "title", value);
|
||||||
|
|
||||||
DEBUG2("Metadata on mountpoint %s changed to \"%s\"",
|
DEBUG2("Metadata on mountpoint %s changed to \"%s\"",
|
||||||
source->mount, value);
|
source->mount, value);
|
||||||
|
|
||||||
|
|
||||||
html_success(client, "Metadata update successful");
|
html_success(client, "Metadata update successful");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client_send_400 (client, "mountpoint will not accept URL updates");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void command_stats(client_t *client, int response) {
|
static void command_stats(client_t *client, int response) {
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
|
@ -521,6 +521,7 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
/* default <mount> settings */
|
/* default <mount> settings */
|
||||||
mount->max_listeners = -1;
|
mount->max_listeners = -1;
|
||||||
mount->burst_size = -1;
|
mount->burst_size = -1;
|
||||||
|
mount->mp3_meta_interval = -1;
|
||||||
mount->next = NULL;
|
mount->next = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -552,6 +553,11 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
mount->max_listeners = atoi(tmp);
|
mount->max_listeners = atoi(tmp);
|
||||||
if(tmp) xmlFree(tmp);
|
if(tmp) xmlFree(tmp);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(node->name, "mp3-metadata-interval") == 0) {
|
||||||
|
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
|
mount->mp3_meta_interval = atoi(tmp);
|
||||||
|
if(tmp) xmlFree(tmp);
|
||||||
|
}
|
||||||
else if (strcmp(node->name, "fallback-override") == 0) {
|
else if (strcmp(node->name, "fallback-override") == 0) {
|
||||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
mount->fallback_override = atoi(tmp);
|
mount->fallback_override = atoi(tmp);
|
||||||
|
@ -60,6 +60,7 @@ typedef struct _mount_proxy {
|
|||||||
int no_yp; /* Do we prevent YP on this mount */
|
int no_yp; /* Do we prevent YP on this mount */
|
||||||
int hidden; /* Do we list this on the xsl pages */
|
int hidden; /* Do we list this on the xsl pages */
|
||||||
unsigned int source_timeout; /* source timeout in seconds */
|
unsigned int source_timeout; /* source timeout in seconds */
|
||||||
|
int mp3_meta_interval; /* outgoing per-stream metadata interval */
|
||||||
|
|
||||||
char *auth_type; /* Authentication type */
|
char *auth_type; /* Authentication type */
|
||||||
char *cluster_password;
|
char *cluster_password;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "httpp/httpp.h"
|
#include "httpp/httpp.h"
|
||||||
|
|
||||||
struct source_tag;
|
struct source_tag;
|
||||||
|
struct _mount_proxy;
|
||||||
|
|
||||||
typedef enum _format_type_tag
|
typedef enum _format_type_tag
|
||||||
{
|
{
|
||||||
@ -48,6 +49,7 @@ typedef struct _format_plugin_tag
|
|||||||
struct source_tag *source, client_t *client);
|
struct source_tag *source, client_t *client);
|
||||||
void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
|
void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
|
||||||
void (*free_plugin)(struct _format_plugin_tag *self);
|
void (*free_plugin)(struct _format_plugin_tag *self);
|
||||||
|
void (*apply_settings)(client_t *client, struct _format_plugin_tag *format, struct _mount_proxy *mount);
|
||||||
|
|
||||||
/* for internal state management */
|
/* for internal state management */
|
||||||
void *_state;
|
void *_state;
|
||||||
|
@ -63,6 +63,8 @@ static int format_mp3_write_buf_to_client(format_plugin_t *self, client_t *clien
|
|||||||
static void format_mp3_send_headers(format_plugin_t *self,
|
static void format_mp3_send_headers(format_plugin_t *self,
|
||||||
source_t *source, client_t *client);
|
source_t *source, client_t *client);
|
||||||
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
|
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(client_t *client, format_plugin_t *format, mount_proxy *mount);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -90,6 +92,7 @@ int format_mp3_get_plugin (source_t *source)
|
|||||||
plugin->client_send_headers = format_mp3_send_headers;
|
plugin->client_send_headers = format_mp3_send_headers;
|
||||||
plugin->free_plugin = format_mp3_free_plugin;
|
plugin->free_plugin = format_mp3_free_plugin;
|
||||||
plugin->set_tag = mp3_set_tag;
|
plugin->set_tag = mp3_set_tag;
|
||||||
|
plugin->apply_settings = format_mp3_apply_settings;
|
||||||
|
|
||||||
plugin->contenttype = httpp_getvar (source->parser, "content-type");
|
plugin->contenttype = httpp_getvar (source->parser, "content-type");
|
||||||
if (plugin->contenttype == NULL) {
|
if (plugin->contenttype == NULL) {
|
||||||
@ -115,6 +118,7 @@ int format_mp3_get_plugin (source_t *source)
|
|||||||
{
|
{
|
||||||
state->offset = 0;
|
state->offset = 0;
|
||||||
plugin->get_buffer = mp3_get_filter_meta;
|
plugin->get_buffer = mp3_get_filter_meta;
|
||||||
|
state->interval = state->inline_metadata_interval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source->format = plugin;
|
source->format = plugin;
|
||||||
@ -124,7 +128,7 @@ int format_mp3_get_plugin (source_t *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value)
|
static void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value)
|
||||||
{
|
{
|
||||||
mp3_state *source_mp3 = plugin->_state;
|
mp3_state *source_mp3 = plugin->_state;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
@ -193,10 +197,31 @@ static void filter_shoutcast_metadata (source_t *source, char *metadata, unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void format_mp3_apply_settings (client_t *client, format_plugin_t *format, mount_proxy *mount)
|
||||||
|
{
|
||||||
|
mp3_state *source_mp3 = format->_state;
|
||||||
|
|
||||||
|
if (mount->mp3_meta_interval <= 0)
|
||||||
|
{
|
||||||
|
char *metadata = httpp_getvar (client->parser, "icy-metaint");
|
||||||
|
source_mp3->interval = -1;
|
||||||
|
if (metadata)
|
||||||
|
{
|
||||||
|
int interval = atoi (metadata);
|
||||||
|
if (interval > 0)
|
||||||
|
source_mp3->interval = interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
source_mp3->interval = mount->mp3_meta_interval;
|
||||||
|
DEBUG2 ("mp3 interval %d, %d", mount->mp3_meta_interval, source_mp3->interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* called from the source thread when the metadata has been updated.
|
/* called from the source thread when the metadata has been updated.
|
||||||
* The artist title are checked and made ready for clients to send
|
* The artist title are checked and made ready for clients to send
|
||||||
*/
|
*/
|
||||||
void mp3_set_title (source_t *source)
|
static void mp3_set_title (source_t *source)
|
||||||
{
|
{
|
||||||
const char meta[] = "StreamTitle='";
|
const char meta[] = "StreamTitle='";
|
||||||
int size;
|
int size;
|
||||||
|
@ -36,6 +36,5 @@ typedef struct {
|
|||||||
} mp3_state;
|
} mp3_state;
|
||||||
|
|
||||||
int format_mp3_get_plugin(struct source_tag *src);
|
int format_mp3_get_plugin(struct source_tag *src);
|
||||||
void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value);
|
|
||||||
|
|
||||||
#endif /* __FORMAT_MP3_H__ */
|
#endif /* __FORMAT_MP3_H__ */
|
||||||
|
@ -912,6 +912,8 @@ void source_apply_mount (source_t *source, mount_proxy *mountinfo)
|
|||||||
if (mountinfo->burst_size > -1)
|
if (mountinfo->burst_size > -1)
|
||||||
source->burst_size = mountinfo->burst_size;
|
source->burst_size = mountinfo->burst_size;
|
||||||
DEBUG1 ("amount to burst on client connect set to %u", source->burst_size);
|
DEBUG1 ("amount to burst on client connect set to %u", source->burst_size);
|
||||||
|
if (source->format && source->format->apply_settings)
|
||||||
|
source->format->apply_settings (source->client, source->format, mountinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user