Commit 0ac03fde authored by Philipp Schafft's avatar Philipp Schafft Committed by Philipp Schafft
Browse files

Feature: Added support for setting format and usage

parent de5569da
......@@ -56,6 +56,22 @@ extern "C" {
/* backward-compatibility alias */
#define SHOUT_FORMAT_VORBIS SHOUT_FORMAT_OGG
/* Usages */
#define SHOUT_USAGE_AUDIO (0x0001U) /* Audio substreams*/
#define SHOUT_USAGE_VISUAL (0x0002U) /* Picture/Video substreams (most often combined with SHOUT_USAGE_AUDIO) */
#define SHOUT_USAGE_TEXT (0x0004U) /* Text substreams that are not subtitles */
#define SHOUT_USAGE_SUBTITLE (0x0008U) /* Subtitle substreams */
#define SHOUT_USAGE_LIGHT (0x0010U) /* Light control substreams */
#define SHOUT_USAGE_UI (0x0020U) /* User interface data, such as DVD menus or buttons */
#define SHOUT_USAGE_METADATA (0x0040U) /* Substreams that include metadata for the stream */
#define SHOUT_USAGE_APPLICATION (0x0080U) /* Application specific data substreams */
#define SHOUT_USAGE_CONTROL (0x0100U) /* Substreams that control the infrastructure */
#define SHOUT_USAGE_COMPLEX (0x0200U) /* Substreams that are themself a mixture of other types */
#define SHOUT_USAGE_OTHER (0x0400U) /* Substream of types not listed here */
#define SHOUT_USAGE_UNKNOWN (0x0800U) /* The stream MAY contain additional substreams of unknown nature */
#define SHOUT_USAGE_3D (0x1000U) /* The Stream contains information for 3D playback */
#define SHOUT_USAGE_4D (0x2000U) /* The Stream contains information for 4D/XD playback */
#define SHOUT_PROTOCOL_HTTP ( 0)
#define SHOUT_PROTOCOL_XAUDIOCAST ( 1) /* Deprecated. May be removed in future versions. Do not use. */
#define SHOUT_PROTOCOL_ICY ( 2)
......@@ -214,6 +230,9 @@ unsigned int shout_get_public(shout_t *self);
int shout_set_format(shout_t *self, unsigned int format);
unsigned int shout_get_format(shout_t *self);
int shout_set_content_format(shout_t *self, unsigned int format, unsigned int usage, const char *codecs);
int shout_get_content_format(shout_t *self, unsigned int *format, unsigned int *usage, const char **codecs);
/* takes a SHOUT_PROTOCOL_xxxxx argument */
int shout_set_protocol(shout_t *self, unsigned int protocol);
unsigned int shout_get_protocol(shout_t *self);
......
......@@ -91,27 +91,10 @@ static shout_connection_return_state_t shout_create_http_request_source(shout_t
const char *mimetype;
char *mount = NULL;
switch (self->format) {
case SHOUT_FORMAT_OGG:
mimetype = "application/ogg";
break;
case SHOUT_FORMAT_MP3:
mimetype = "audio/mpeg";
break;
case SHOUT_FORMAT_WEBM:
mimetype = "video/webm";
break;
case SHOUT_FORMAT_WEBMAUDIO:
mimetype = "audio/webm";
break;
default:
shout_connection_set_error(connection, SHOUTERR_INSANE);
return SHOUT_RS_ERROR;
break;
mimetype = shout_get_mimetype_from_self(self);
if (!mimetype) {
shout_connection_set_error(connection, SHOUTERR_INSANE);
return SHOUT_RS_ERROR;
}
/* this is lazy code that relies on the only error from queue_* being
......
......@@ -131,6 +131,7 @@ shout_t *shout_new(void)
self->port = LIBSHOUT_DEFAULT_PORT;
self->format = LIBSHOUT_DEFAULT_FORMAT;
self->usage = LIBSHOUT_DEFAULT_USAGE;
self->protocol = LIBSHOUT_DEFAULT_PROTOCOL;
return self;
......@@ -811,22 +812,142 @@ int shout_set_format(shout_t *self, unsigned int format)
if (self->connection)
return self->error = SHOUTERR_CONNECTED;
if (format != SHOUT_FORMAT_OGG && format != SHOUT_FORMAT_MP3 &&
format != SHOUT_FORMAT_WEBM && format != SHOUT_FORMAT_WEBMAUDIO) {
switch (format) {
case SHOUT_FORMAT_OGG:
return shout_set_content_format(self, SHOUT_FORMAT_OGG, SHOUT_USAGE_UNKNOWN, NULL);
break;
case SHOUT_FORMAT_MP3:
return shout_set_content_format(self, SHOUT_FORMAT_MP3, SHOUT_USAGE_AUDIO, NULL);
break;
case SHOUT_FORMAT_WEBM:
return shout_set_content_format(self, SHOUT_FORMAT_WEBM, SHOUT_USAGE_AUDIO|SHOUT_USAGE_VISUAL, NULL);
break;
case SHOUT_FORMAT_WEBMAUDIO:
return shout_set_content_format(self, SHOUT_FORMAT_WEBM, SHOUT_USAGE_AUDIO, NULL);
break;
}
return self->error = SHOUTERR_UNSUPPORTED;
}
unsigned int shout_get_format(shout_t* self)
{
if (!self)
return 0;
if (self->format == SHOUT_FORMAT_WEBM && self->usage == SHOUT_USAGE_AUDIO) {
return SHOUT_FORMAT_WEBMAUDIO;
}
return self->format;
}
static inline unsigned int remove_bits(unsigned int value, unsigned int to_remove)
{
value |= to_remove;
value -= to_remove;
return value;
}
static inline int is_audio(unsigned int usage)
{
if (!(usage & SHOUT_USAGE_AUDIO))
return 0;
if (remove_bits(usage, SHOUT_USAGE_AUDIO|SHOUT_USAGE_SUBTITLE))
return 0;
return 1;
}
static inline int is_video(unsigned int usage)
{
if (!(usage & SHOUT_USAGE_VISUAL))
return 0;
if (remove_bits(usage, SHOUT_USAGE_VISUAL|SHOUT_USAGE_AUDIO|SHOUT_USAGE_SUBTITLE|SHOUT_USAGE_3D|SHOUT_USAGE_4D))
return 0;
return 1;
}
static const char *shout_get_mimetype(unsigned int format, unsigned int usage, const char *codecs)
{
if (codecs)
return NULL;
switch (format) {
case SHOUT_FORMAT_OGG:
if (is_audio(usage)) {
return "audio/ogg";
} else if (is_video(usage)) {
return "video/ogg";
} else {
return "application/ogg";
}
break;
case SHOUT_FORMAT_MP3:
/* MP3 *ONLY* support Audio. So all other values are outright invalid */
if (usage == SHOUT_USAGE_AUDIO) {
return "audio/mpeg";
}
break;
case SHOUT_FORMAT_WEBM:
if (is_audio(usage)) {
return "audio/webm";
} else if (is_video(usage)) {
return "video/webm";
}
break;
}
return NULL;
}
const char *shout_get_mimetype_from_self(shout_t *self)
{
return shout_get_mimetype(self->format, self->usage, NULL);
}
int shout_set_content_format(shout_t *self, unsigned int format, unsigned int usage, const char *codecs)
{
if (!self)
return SHOUTERR_INSANE;
if (self->connection)
return self->error = SHOUTERR_CONNECTED;
if (codecs) {
return self->error = SHOUTERR_UNSUPPORTED;
}
if (!shout_get_mimetype(format, usage, codecs)) {
return self->error = SHOUTERR_UNSUPPORTED;
}
self->format = format;
self->usage = usage;
return self->error = SHOUTERR_SUCCESS;
}
unsigned int shout_get_format(shout_t* self)
int shout_get_content_format(shout_t *self, unsigned int *format, unsigned int *usage, const char **codecs)
{
if (!self)
return 0;
return SHOUTERR_INSANE;
return self->format;
if (format)
*format = self->format;
if (usage)
*usage = self->usage;
if (codecs)
*codecs = NULL;
return self->error = SHOUTERR_SUCCESS;
}
int shout_set_protocol(shout_t *self, unsigned int protocol)
......
......@@ -48,6 +48,7 @@
#define LIBSHOUT_DEFAULT_HOST "localhost"
#define LIBSHOUT_DEFAULT_PORT 8000
#define LIBSHOUT_DEFAULT_FORMAT SHOUT_FORMAT_OGG
#define LIBSHOUT_DEFAULT_USAGE SHOUT_USAGE_UNKNOWN
#define LIBSHOUT_DEFAULT_PROTOCOL SHOUT_PROTOCOL_HTTP
#define LIBSHOUT_DEFAULT_USER "source"
#define LIBSHOUT_DEFAULT_USERAGENT "libshout/" VERSION
......@@ -214,6 +215,7 @@ struct shout {
unsigned int protocol;
/* type of data being sent */
unsigned int format;
unsigned int usage;
/* audio encoding parameters */
util_dict *audio_info;
......@@ -263,6 +265,8 @@ struct shout {
};
/* helper functions */
const char *shout_get_mimetype_from_self(shout_t *self);
int shout_queue_data(shout_queue_t *queue, const unsigned char *data, size_t len);
int shout_queue_str(shout_connection_t *self, const char *str);
int shout_queue_printf(shout_connection_t *self, const char *fmt, ...);
......
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