mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-02-02 15:07:36 -05:00
mp3 metadata work (incomplete)
svn path=/trunk/icecast/; revision=4177
This commit is contained in:
parent
5890aa4f4b
commit
40444f4178
@ -6,6 +6,8 @@
|
||||
#ifndef __CLIENT_H__
|
||||
#define __CLIENT_H__
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
typedef struct _client_tag
|
||||
{
|
||||
/* the clients connection */
|
||||
|
@ -31,12 +31,11 @@
|
||||
#include "refbuf.h"
|
||||
#include "client.h"
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
#include "logging.h"
|
||||
#include "xslt.h"
|
||||
#include "fserve.h"
|
||||
|
||||
#include "source.h"
|
||||
#include "format.h"
|
||||
|
||||
#define CATMODULE "connection"
|
||||
|
||||
@ -482,8 +481,6 @@ static void _handle_get_request(connection_t *con,
|
||||
{
|
||||
char *fullpath;
|
||||
client_t *client;
|
||||
avl_node *node;
|
||||
http_var_t *var;
|
||||
int bytes;
|
||||
struct stat statbuf;
|
||||
source_t *source;
|
||||
@ -636,26 +633,10 @@ static void _handle_get_request(connection_t *con,
|
||||
global.clients++;
|
||||
global_unlock();
|
||||
|
||||
client->respcode = 200;
|
||||
bytes = sock_write(client->con->sock,
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: %s\r\n",
|
||||
format_get_mimetype(source->format->type));
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
/* iterate through source http headers and send to client */
|
||||
avl_tree_rlock(source->parser->vars);
|
||||
node = avl_get_first(source->parser->vars);
|
||||
while (node) {
|
||||
var = (http_var_t *)node->key;
|
||||
if (strcasecmp(var->name, "ice-password") &&
|
||||
!strncasecmp("ice-", var->name, 4)) {
|
||||
bytes = sock_write(client->con->sock,
|
||||
"%s: %s\r\n", var->name, var->value);
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
}
|
||||
node = avl_get_next(node);
|
||||
}
|
||||
avl_tree_unlock(source->parser->vars);
|
||||
client->format_data = source->format->create_client_data(
|
||||
source->format, source, client);
|
||||
|
||||
source->format->client_send_headers(source->format, source, client);
|
||||
|
||||
bytes = sock_write(client->con->sock, "\r\n");
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
|
25
src/format.c
25
src/format.c
@ -11,6 +11,7 @@
|
||||
#include "connection.h"
|
||||
#include "refbuf.h"
|
||||
|
||||
#include "source.h"
|
||||
#include "format.h"
|
||||
|
||||
#include "format_vorbis.h"
|
||||
@ -84,3 +85,27 @@ int format_generic_write_buf_to_client(format_plugin_t *format,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void format_send_general_headers(format_plugin_t *format,
|
||||
source_t *source, client_t *client)
|
||||
{
|
||||
http_var_t *var;
|
||||
avl_node *node;
|
||||
int bytes;
|
||||
|
||||
/* iterate through source http headers and send to client */
|
||||
avl_tree_rlock(source->parser->vars);
|
||||
node = avl_get_first(source->parser->vars);
|
||||
while (node) {
|
||||
var = (http_var_t *)node->key;
|
||||
if (strcasecmp(var->name, "ice-password") &&
|
||||
(!strncasecmp("ice-", var->name, 4) ||
|
||||
!strncasecmp("icy-", var->name, 4))) {
|
||||
bytes = sock_write(client->con->sock,
|
||||
"%s: %s\r\n", var->name, var->value);
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
}
|
||||
node = avl_get_next(node);
|
||||
}
|
||||
avl_tree_unlock(source->parser->vars);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "client.h"
|
||||
#include "refbuf.h"
|
||||
|
||||
struct source_tag;
|
||||
|
||||
typedef enum _format_type_tag
|
||||
{
|
||||
FORMAT_TYPE_VORBIS,
|
||||
@ -34,7 +36,10 @@ typedef struct _format_plugin_tag
|
||||
refbuf_queue_t *(*get_predata)(struct _format_plugin_tag *self);
|
||||
int (*write_buf_to_client)(struct _format_plugin_tag *format,
|
||||
client_t *client, unsigned char *buf, int len);
|
||||
void *(*create_client_data)(struct _format_plugin_tag *format);
|
||||
void *(*create_client_data)(struct _format_plugin_tag *format,
|
||||
struct source_tag *source, client_t *client);
|
||||
void (*client_send_headers)(struct _format_plugin_tag *format,
|
||||
struct source_tag *source, client_t *client);
|
||||
|
||||
void (*free_plugin)(struct _format_plugin_tag *self);
|
||||
|
||||
@ -48,6 +53,8 @@ format_plugin_t *format_get_plugin(format_type_t type, char *mount);
|
||||
|
||||
int format_generic_write_buf_to_client(format_plugin_t *format,
|
||||
client_t *client, unsigned char *buf, int len);
|
||||
void format_send_general_headers(format_plugin_t *format,
|
||||
struct source_tag *source, client_t *client);
|
||||
|
||||
#endif /* __FORMAT_H__ */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* format_mp3.c
|
||||
**
|
||||
** format plugin for mp3 (no metadata)
|
||||
** format plugin for mp3
|
||||
**
|
||||
*/
|
||||
|
||||
@ -9,15 +9,38 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "refbuf.h"
|
||||
#include "source.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
#include "httpp/httpp.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include "format_mp3.h"
|
||||
|
||||
#define CATMODULE "format-mp3"
|
||||
|
||||
#define ICY_METADATA_INTERVAL 16000
|
||||
|
||||
static void format_mp3_free_plugin(format_plugin_t *self);
|
||||
static int format_mp3_get_buffer(format_plugin_t *self, char *data,
|
||||
unsigned long len, refbuf_t **buffer);
|
||||
static refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self);
|
||||
static void *format_mp3_create_client_data(format_plugin_t *self);
|
||||
static void *format_mp3_create_client_data(format_plugin_t *self,
|
||||
source_t *source, client_t *client);
|
||||
static int format_mp3_write_buf_to_client(format_plugin_t *self,
|
||||
client_t *client, unsigned char *buf, int len);
|
||||
static void format_mp3_send_headers(format_plugin_t *self,
|
||||
source_t *source, client_t *client);
|
||||
|
||||
typedef struct {
|
||||
int interval;
|
||||
int offset;
|
||||
int metadata;
|
||||
} mp3_client_data;
|
||||
|
||||
format_plugin_t *format_mp3_get_plugin(void)
|
||||
{
|
||||
@ -29,23 +52,44 @@ format_plugin_t *format_mp3_get_plugin(void)
|
||||
plugin->has_predata = 0;
|
||||
plugin->get_buffer = format_mp3_get_buffer;
|
||||
plugin->get_predata = format_mp3_get_predata;
|
||||
plugin->write_buf_to_client = format_generic_write_buf_to_client;
|
||||
plugin->write_buf_to_client = format_mp3_write_buf_to_client;
|
||||
plugin->create_client_data = format_mp3_create_client_data;
|
||||
plugin->client_send_headers = format_mp3_send_headers;
|
||||
plugin->free_plugin = format_mp3_free_plugin;
|
||||
plugin->format_description = "MP3 audio";
|
||||
|
||||
plugin->_state = NULL;
|
||||
plugin->_state = calloc(1, sizeof(mp3_state));
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void format_mp3_free_plugin(format_plugin_t *self)
|
||||
static int format_mp3_write_buf_to_client(format_plugin_t *self,
|
||||
client_t *client, unsigned char *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sock_write_bytes(client->con->sock, buf, len);
|
||||
|
||||
if(ret < 0) {
|
||||
if(sock_recoverable(ret)) {
|
||||
DEBUG1("Client had recoverable error %ld", ret);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
client->con->sent_bytes += ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void format_mp3_free_plugin(format_plugin_t *self)
|
||||
{
|
||||
/* free the plugin instance */
|
||||
free(self);
|
||||
}
|
||||
|
||||
int format_mp3_get_buffer(format_plugin_t *self, char *data, unsigned long len, refbuf_t **buffer)
|
||||
static int format_mp3_get_buffer(format_plugin_t *self, char *data,
|
||||
unsigned long len, refbuf_t **buffer)
|
||||
{
|
||||
refbuf_t *refbuf;
|
||||
if(!data) {
|
||||
@ -60,13 +104,50 @@ int format_mp3_get_buffer(format_plugin_t *self, char *data, unsigned long len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self)
|
||||
static refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *format_mp3_create_client_data(format_plugin_t *self) {
|
||||
return NULL;
|
||||
static void *format_mp3_create_client_data(format_plugin_t *self,
|
||||
source_t *source, client_t *client)
|
||||
{
|
||||
mp3_client_data *data = calloc(1,sizeof(mp3_client_data));
|
||||
char *metadata;
|
||||
|
||||
data->interval = ICY_METADATA_INTERVAL;
|
||||
data->offset = 0;
|
||||
|
||||
metadata = httpp_getvar(source->parser, "icy-metadata");
|
||||
if(metadata)
|
||||
data->metadata = atoi(metadata)>0?1:0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void format_mp3_send_headers(format_plugin_t *self,
|
||||
source_t *source, client_t *client)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
client->respcode = 200;
|
||||
bytes = sock_write(client->con->sock,
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: %s\r\n",
|
||||
format_get_mimetype(source->format->type));
|
||||
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
|
||||
format_send_general_headers(self, source, client);
|
||||
|
||||
if(0 && ((mp3_client_data *)(client->format_data))->metadata) {
|
||||
int bytes = sock_write(client->con->sock, "icy-metaint: %d\r\n",
|
||||
ICY_METADATA_INTERVAL);
|
||||
if(bytes > 0)
|
||||
client->con->sent_bytes += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,6 +6,11 @@
|
||||
#ifndef __FORMAT_MP3_H__
|
||||
#define __FORMAT_MP3_H__
|
||||
|
||||
typedef struct {
|
||||
char *metadata;
|
||||
int metadata_age;
|
||||
} mp3_state;
|
||||
|
||||
format_plugin_t *format_mp3_get_plugin(void);
|
||||
|
||||
#endif /* __FORMAT_MP3_H__ */
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
#include "refbuf.h"
|
||||
#include "source.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
@ -40,7 +42,10 @@ static void format_vorbis_free_plugin(format_plugin_t *self);
|
||||
static int format_vorbis_get_buffer(format_plugin_t *self, char *data,
|
||||
unsigned long len, refbuf_t **buffer);
|
||||
static refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self);
|
||||
static void *format_vorbis_create_client_data(format_plugin_t *self);
|
||||
static void *format_vorbis_create_client_data(format_plugin_t *self,
|
||||
source_t *source, client_t *client);
|
||||
static void format_vorbis_send_headers(format_plugin_t *self,
|
||||
source_t *source, client_t *client);
|
||||
|
||||
format_plugin_t *format_vorbis_get_plugin(void)
|
||||
{
|
||||
@ -55,6 +60,7 @@ format_plugin_t *format_vorbis_get_plugin(void)
|
||||
plugin->get_predata = format_vorbis_get_predata;
|
||||
plugin->write_buf_to_client = format_generic_write_buf_to_client;
|
||||
plugin->create_client_data = format_vorbis_create_client_data;
|
||||
plugin->client_send_headers = format_vorbis_send_headers;
|
||||
plugin->free_plugin = format_vorbis_free_plugin;
|
||||
plugin->format_description = "Ogg Vorbis";
|
||||
|
||||
@ -218,8 +224,26 @@ refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self)
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void *format_vorbis_create_client_data(format_plugin_t *self) {
|
||||
static void *format_vorbis_create_client_data(format_plugin_t *self,
|
||||
source_t *source, client_t *client)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void format_vorbis_send_headers(format_plugin_t *self,
|
||||
source_t *source, client_t *client)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
client->respcode = 200;
|
||||
bytes = sock_write(client->con->sock,
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: %s\r\n",
|
||||
format_get_mimetype(source->format->type));
|
||||
|
||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
||||
|
||||
format_send_general_headers(self, source, client);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include "httpp.h"
|
||||
#include "connection.h"
|
||||
#include "refbuf.h"
|
||||
#include "format.h"
|
||||
#include "client.h"
|
||||
#include "source.h"
|
||||
#include "format.h"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
@ -37,10 +37,9 @@
|
||||
#include "refbuf.h"
|
||||
#include "client.h"
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include "source.h"
|
||||
#include "format.h"
|
||||
|
||||
#define CATMODULE "slave"
|
||||
|
||||
|
@ -23,13 +23,12 @@
|
||||
#include "refbuf.h"
|
||||
#include "client.h"
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
#include "log.h"
|
||||
#include "logging.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "source.h"
|
||||
#include "format.h"
|
||||
|
||||
#undef CATMODULE
|
||||
#define CATMODULE "source"
|
||||
@ -325,8 +324,6 @@ void *source_main(void *arg)
|
||||
*/
|
||||
if (source->format->has_predata) {
|
||||
client = (client_t *)client_node->key;
|
||||
client->format_data = source->format->create_client_data(
|
||||
source->format);
|
||||
client->queue = source->format->get_predata(source->format);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef __SOURCE_H__
|
||||
#define __SOURCE_H__
|
||||
|
||||
#include "format.h"
|
||||
|
||||
typedef struct source_tag
|
||||
{
|
||||
client_t *client;
|
||||
@ -8,7 +10,7 @@ typedef struct source_tag
|
||||
http_parser_t *parser;
|
||||
|
||||
char *mount;
|
||||
format_plugin_t *format;
|
||||
struct _format_plugin_tag *format;
|
||||
|
||||
avl_tree *client_tree;
|
||||
avl_tree *pending_tree;
|
||||
|
Loading…
x
Reference in New Issue
Block a user