mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Feature: Added support to send vorbis comments
This commit is contained in:
parent
7965610b26
commit
dbffcb6dc0
@ -19,6 +19,7 @@
|
|||||||
#include <igloo/error.h>
|
#include <igloo/error.h>
|
||||||
#include <igloo/ro.h>
|
#include <igloo/ro.h>
|
||||||
#include <igloo/sp.h>
|
#include <igloo/sp.h>
|
||||||
|
#include <igloo/cs.h>
|
||||||
#include <igloo/uuid.h>
|
#include <igloo/uuid.h>
|
||||||
|
|
||||||
#include "common/thread/thread.h"
|
#include "common/thread/thread.h"
|
||||||
@ -33,7 +34,9 @@
|
|||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "source.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "format_mp3.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#define CATMODULE "event-stream"
|
#define CATMODULE "event-stream"
|
||||||
|
|
||||||
@ -44,10 +47,12 @@ struct event_stream_event_tag {
|
|||||||
|
|
||||||
const char * uuid;
|
const char * uuid;
|
||||||
const char * mount;
|
const char * mount;
|
||||||
|
const char * source_instance_uuid;
|
||||||
const char * rendered;
|
const char * rendered;
|
||||||
size_t rendered_length;
|
size_t rendered_length;
|
||||||
|
|
||||||
event_t *event;
|
event_t *event;
|
||||||
|
vorbis_comment *vc;
|
||||||
|
|
||||||
event_stream_event_t *next;
|
event_stream_event_t *next;
|
||||||
};
|
};
|
||||||
@ -95,6 +100,8 @@ static void event_stream_event_free(igloo_ro_t self)
|
|||||||
{
|
{
|
||||||
event_stream_event_t *event = igloo_ro_to_type(self, event_stream_event_t);
|
event_stream_event_t *event = igloo_ro_to_type(self, event_stream_event_t);
|
||||||
igloo_sp_unref(&(event->uuid), igloo_instance);
|
igloo_sp_unref(&(event->uuid), igloo_instance);
|
||||||
|
igloo_sp_unref(&(event->mount), igloo_instance);
|
||||||
|
igloo_sp_unref(&(event->source_instance_uuid), igloo_instance);
|
||||||
igloo_sp_unref(&(event->rendered), igloo_instance);
|
igloo_sp_unref(&(event->rendered), igloo_instance);
|
||||||
igloo_ro_unref(&(event->event));
|
igloo_ro_unref(&(event->event));
|
||||||
igloo_ro_unref(&(event->next));
|
igloo_ro_unref(&(event->next));
|
||||||
@ -255,6 +262,12 @@ void event_stream_add_client(client_t *client)
|
|||||||
fserve_add_client_callback(client, event_stream_add_client_inner, NULL);
|
fserve_add_client_callback(client, event_stream_add_client_inner, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void event_stream_set_source(event_stream_event_t *event, source_t *source)
|
||||||
|
{
|
||||||
|
igloo_sp_replace(source->mount, &(event->mount), igloo_instance);
|
||||||
|
igloo_sp_replace(source->instance_uuid, &(event->source_instance_uuid), igloo_instance);
|
||||||
|
}
|
||||||
|
|
||||||
void event_stream_emit_event(event_t *event)
|
void event_stream_emit_event(event_t *event)
|
||||||
{
|
{
|
||||||
event_stream_event_t *el = event_stream_event_new();
|
event_stream_event_t *el = event_stream_event_new();
|
||||||
@ -267,6 +280,22 @@ void event_stream_emit_event(event_t *event)
|
|||||||
event_stream_queue(el);
|
event_stream_queue(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void event_stream_emit_vc(source_t *source, vorbis_comment *vc)
|
||||||
|
{
|
||||||
|
event_stream_event_t *el = event_stream_event_new();
|
||||||
|
if (!el)
|
||||||
|
return;
|
||||||
|
|
||||||
|
event_stream_set_source(el, source);
|
||||||
|
|
||||||
|
/* we only have a temp reference to vc, so we set it, render, and then unset before we queue. */
|
||||||
|
el->vc = vc;
|
||||||
|
event_stream_event_render(el);
|
||||||
|
el->vc = NULL;
|
||||||
|
|
||||||
|
event_stream_queue(el);
|
||||||
|
}
|
||||||
|
|
||||||
static void event_stream_send_to_client(client_t *client)
|
static void event_stream_send_to_client(client_t *client)
|
||||||
{
|
{
|
||||||
event_stream_clientstate_t *state = client->format_data;
|
event_stream_clientstate_t *state = client->format_data;
|
||||||
@ -393,6 +422,8 @@ static void event_stream_event_render(event_stream_event_t *event)
|
|||||||
string_renderer_t * renderer;
|
string_renderer_t * renderer;
|
||||||
json_renderer_t *json;
|
json_renderer_t *json;
|
||||||
char *body;
|
char *body;
|
||||||
|
bool has_type = false;
|
||||||
|
bool has_crude = false;
|
||||||
|
|
||||||
if (event->rendered)
|
if (event->rendered)
|
||||||
return;
|
return;
|
||||||
@ -409,6 +440,9 @@ static void event_stream_event_render(event_stream_event_t *event)
|
|||||||
if (event->event) {
|
if (event->event) {
|
||||||
event_t *uevent = event->event;
|
event_t *uevent = event->event;
|
||||||
|
|
||||||
|
has_type = true;
|
||||||
|
has_crude = true;
|
||||||
|
|
||||||
json_renderer_write_key(json, "type", JSON_RENDERER_FLAGS_NONE);
|
json_renderer_write_key(json, "type", JSON_RENDERER_FLAGS_NONE);
|
||||||
json_renderer_write_string(json, "event", JSON_RENDERER_FLAGS_NONE);
|
json_renderer_write_string(json, "event", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
|
||||||
@ -450,6 +484,111 @@ static void event_stream_event_render(event_stream_event_t *event)
|
|||||||
json_renderer_write_key(json, "mount", JSON_RENDERER_FLAGS_NONE);
|
json_renderer_write_key(json, "mount", JSON_RENDERER_FLAGS_NONE);
|
||||||
json_renderer_write_string(json, event->mount, JSON_RENDERER_FLAGS_NONE);
|
json_renderer_write_string(json, event->mount, JSON_RENDERER_FLAGS_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->vc) {
|
||||||
|
if (!has_type) {
|
||||||
|
json_renderer_write_key(json, "type", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
json_renderer_write_string(json, "vc", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
has_type = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_renderer_write_key(json, "vc", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
json_renderer_begin(json, JSON_ELEMENT_TYPE_OBJECT);
|
||||||
|
{
|
||||||
|
/* ok, this part is tricky, we first need to figure out all the keys.
|
||||||
|
* we however cheat here by assuming a few things.
|
||||||
|
* TODO: Fix this.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
char name[64];
|
||||||
|
size_t count;
|
||||||
|
} keys[64];
|
||||||
|
memset(keys, 0, sizeof(keys));
|
||||||
|
|
||||||
|
/* it is an int in libvorbis, not a size_t */
|
||||||
|
for (int i = 0; i < event->vc->comments; i++) {
|
||||||
|
const char *comment = event->vc->user_comments[i];
|
||||||
|
const char *keyend = strchr(comment, '=');
|
||||||
|
bool found = false;
|
||||||
|
size_t keylen;
|
||||||
|
|
||||||
|
if (!keyend)
|
||||||
|
continue;
|
||||||
|
keylen = keyend - comment;
|
||||||
|
if (keylen >= sizeof(keys->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < (sizeof(keys)/sizeof(*keys)); j++) {
|
||||||
|
char *name = keys[j].name;
|
||||||
|
|
||||||
|
if (*name) {
|
||||||
|
if (strncasecmp(comment, name, keylen) == 0) {
|
||||||
|
found = true;
|
||||||
|
keys[j].count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < (sizeof(keys)/sizeof(*keys)); j++) {
|
||||||
|
char *name = keys[j].name;
|
||||||
|
|
||||||
|
if (!*name) {
|
||||||
|
memcpy(name, comment, keylen);
|
||||||
|
name[keylen] = 0;
|
||||||
|
keys[j].count = 1;
|
||||||
|
igloo_cs_to_upper(name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have a list of all keys... */
|
||||||
|
for (size_t j = 0; j < (sizeof(keys)/sizeof(*keys)); j++) {
|
||||||
|
const char *name = keys[j].name;
|
||||||
|
if (!*name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
json_renderer_write_key(json, name, JSON_RENDERER_FLAGS_NONE);
|
||||||
|
json_renderer_begin(json, JSON_ELEMENT_TYPE_ARRAY);
|
||||||
|
for (size_t i = 0; i < keys[j].count; i++) {
|
||||||
|
const char *value = vorbis_comment_query(event->vc, name, i);
|
||||||
|
json_renderer_write_string(json, value, JSON_RENDERER_FLAGS_NONE);
|
||||||
|
}
|
||||||
|
json_renderer_end(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json_renderer_end(json);
|
||||||
|
|
||||||
|
if (!has_crude) {
|
||||||
|
has_crude = true;
|
||||||
|
json_renderer_write_key(json, "crude", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
json_renderer_begin(json, JSON_ELEMENT_TYPE_OBJECT);
|
||||||
|
{
|
||||||
|
static const char * display_title_keys[] = {"TITLE", MP3_METADATA_TITLE};
|
||||||
|
const char *display_title = NULL;
|
||||||
|
for (size_t i = 0; i < (sizeof(display_title_keys)/sizeof(*display_title_keys)); i++) {
|
||||||
|
display_title = vorbis_comment_query(event->vc, display_title_keys[i], 0);
|
||||||
|
if (display_title)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
json_renderer_write_key(json, "display-title", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
if (display_title) {
|
||||||
|
json_renderer_write_string(json, display_title, JSON_RENDERER_FLAGS_NONE);
|
||||||
|
} else {
|
||||||
|
json_renderer_write_null(json);
|
||||||
|
}
|
||||||
|
if (event->source_instance_uuid) {
|
||||||
|
json_renderer_write_key(json, "source-instance", JSON_RENDERER_FLAGS_NONE);
|
||||||
|
json_renderer_write_string(json, event->source_instance_uuid, JSON_RENDERER_FLAGS_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json_renderer_end(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
json_renderer_end(json);
|
json_renderer_end(json);
|
||||||
|
|
||||||
body = json_renderer_finish(&json);
|
body = json_renderer_finish(&json);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef __EVENT_STREAM_H__
|
#ifndef __EVENT_STREAM_H__
|
||||||
#define __EVENT_STREAM_H__
|
#define __EVENT_STREAM_H__
|
||||||
|
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
|
||||||
#include "icecasttypes.h"
|
#include "icecasttypes.h"
|
||||||
|
|
||||||
igloo_RO_FORWARD_TYPE(event_stream_event_t);
|
igloo_RO_FORWARD_TYPE(event_stream_event_t);
|
||||||
@ -18,5 +20,6 @@ void event_stream_shutdown(void);
|
|||||||
|
|
||||||
void event_stream_add_client(client_t *client);
|
void event_stream_add_client(client_t *client);
|
||||||
void event_stream_emit_event(event_t *event);
|
void event_stream_emit_event(event_t *event);
|
||||||
|
void event_stream_emit_vc(source_t *source, vorbis_comment *vc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "source.h"
|
#include "source.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "event_stream.h"
|
||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
@ -206,6 +207,7 @@ static void filter_shoutcast_metadata (source_t *source, char *metadata, unsigne
|
|||||||
yp_touch (source->mount);
|
yp_touch (source->mount);
|
||||||
free (p);
|
free (p);
|
||||||
playlist_push_track(source->history, &source->format->vc);
|
playlist_push_track(source->history, &source->format->vc);
|
||||||
|
event_stream_emit_vc(source, &source->format->vc);
|
||||||
}
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
#include "event_stream.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "format_ogg.h"
|
#include "format_ogg.h"
|
||||||
@ -332,6 +333,7 @@ static void update_comments(source_t *source)
|
|||||||
stats_event (source->mount, "display-title", title);
|
stats_event (source->mount, "display-title", title);
|
||||||
|
|
||||||
playlist_push_track(source->history, &source->format->vc);
|
playlist_push_track(source->history, &source->format->vc);
|
||||||
|
event_stream_emit_vc(source, &source->format->vc);
|
||||||
|
|
||||||
codec = ogg_info->codecs;
|
codec = ogg_info->codecs;
|
||||||
while (codec)
|
while (codec)
|
||||||
|
Loading…
Reference in New Issue
Block a user