summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2006-05-08 23:34:10 +0000
committerLennart Poettering <lennart@poettering.net>2006-05-08 23:34:10 +0000
commiteff37b9e21e47b8a16a5fc4477589b21508720e4 (patch)
tree934b6bdceef480d14a85acb2ce18a58e1ce4c747
parentf8f641889aafafa817c9c03def299945cd23c018 (diff)
* use streamed tagging metadata to name the playback stream in polypaudio
* minor cleanups git-svn-id: file:///home/lennart/svn/public/gst-pulse/trunk@15 bb39ca4e-bce3-0310-b5d4-eea78a553289
-rw-r--r--src/polypsink.c111
-rw-r--r--src/polypsink.h2
2 files changed, 98 insertions, 15 deletions
diff --git a/src/polypsink.c b/src/polypsink.c
index 96c0c9f..d9e7b5f 100644
--- a/src/polypsink.c
+++ b/src/polypsink.c
@@ -23,12 +23,15 @@
#include "config.h"
#endif
-#include <pthread.h>
#include <string.h>
#include <stdio.h>
+#include <gst/base/gstbasesink.h>
+#include <gst/gsttaglist.h>
+
#include "polypsink.h"
+
GST_DEBUG_CATEGORY_EXTERN(polyp_debug);
#define GST_CAT_DEFAULT polyp_debug
@@ -46,6 +49,7 @@ static void gst_polypsink_destroy_context(GstPolypSink *polypsink);
static void gst_polypsink_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_polypsink_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void gst_polypsink_finalize(GObject *object);
+static void gst_polypsink_dispose(GObject *object);
static gboolean gst_polypsink_open(GstAudioSink *asink);
static gboolean gst_polypsink_close(GstAudioSink *asink);
@@ -57,6 +61,8 @@ static guint gst_polypsink_write(GstAudioSink *asink, gpointer data, guint lengt
static guint gst_polypsink_delay(GstAudioSink *asink);
static void gst_polypsink_reset(GstAudioSink *asink);
+static gboolean gst_polypsink_event(GstBaseSink *sink, GstEvent *event);
+
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
# define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
#else
@@ -109,7 +115,7 @@ static void gst_polypsink_base_init(gpointer g_class) {
"Lennart Poettering");
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
-
+
gst_element_class_set_details(element_class, &details);
gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&pad_template));
}
@@ -119,14 +125,17 @@ static void gst_polypsink_class_init(
gpointer class_data) {
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
-// GstElementClass *gstelement_class = GST_ELEMENT_CLASS(g_class);
+ GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS(g_class);
GstAudioSinkClass *gstaudiosink_class = GST_AUDIO_SINK_CLASS(g_class);
parent_class = g_type_class_peek_parent(g_class);
- gobject_class->set_property = gst_polypsink_set_property;
- gobject_class->get_property = gst_polypsink_get_property;
- gobject_class->finalize = gst_polypsink_finalize;
+ gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_polypsink_dispose);
+ gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_polypsink_finalize);
+ gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_polypsink_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_polypsink_get_property);
+ gstbasesink_class->event = GST_DEBUG_FUNCPTR(gst_polypsink_event);
+
gstaudiosink_class->open = GST_DEBUG_FUNCPTR(gst_polypsink_open);
gstaudiosink_class->close = GST_DEBUG_FUNCPTR(gst_polypsink_close);
gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR(gst_polypsink_prepare);
@@ -153,7 +162,7 @@ static void gst_polypsink_init(
GstPolypSink *polypsink = GST_POLYPSINK(instance);
int e;
- polypsink->server = polypsink->device = NULL;
+ polypsink->server = polypsink->device = polypsink->stream_name = NULL;
polypsink->context = NULL;
polypsink->stream = NULL;
@@ -171,6 +180,9 @@ static void gst_polypsink_destroy_stream(GstPolypSink* polypsink) {
pa_stream_unref(polypsink->stream);
polypsink->stream = NULL;
}
+
+ g_free(polypsink->stream_name);
+ polypsink->stream_name = NULL;
}
static void gst_polypsink_destroy_context(GstPolypSink* polypsink) {
@@ -193,12 +205,17 @@ static void gst_polypsink_finalize(GObject * object) {
g_free(polypsink->server);
g_free(polypsink->device);
+ g_free(polypsink->stream_name);
pa_threaded_mainloop_free(polypsink->mainloop);
G_OBJECT_CLASS(parent_class)->finalize(object);
}
+static void gst_polypsink_dispose(GObject * object) {
+ G_OBJECT_CLASS(parent_class)->dispose(object);
+}
+
static void gst_polypsink_set_property(
GObject * object,
guint prop_id,
@@ -377,7 +394,7 @@ static gboolean gst_polypsink_prepare(GstAudioSink *asink, GstRingBufferSpec *sp
goto unlock_and_fail;
}
- if (!(polypsink->stream = pa_stream_new(polypsink->context, "the stream", &polypsink->sample_spec, NULL))) {
+ if (!(polypsink->stream = pa_stream_new(polypsink->context, polypsink->stream_name ? polypsink->stream_name : "Playback Stream", &polypsink->sample_spec, NULL))) {
GST_ELEMENT_ERROR(polypsink, RESOURCE, FAILED, ("Failed to create stream: %s", pa_strerror(pa_context_errno(polypsink->context))), (NULL));
goto unlock_and_fail;
}
@@ -463,8 +480,6 @@ static guint gst_polypsink_write(GstAudioSink *asink, gpointer data, guint lengt
pa_threaded_mainloop_unlock(polypsink->mainloop);
- GST_WARNING("Write");
-
return l;
unlock_and_fail:
@@ -491,8 +506,6 @@ static guint gst_polypsink_delay(GstAudioSink *asink) {
t = 0;
}
- GST_WARNING("Latency %0.3f ms", (double) t / 1000);
-
pa_threaded_mainloop_unlock(polypsink->mainloop);
return (guint) ((t * polypsink->sample_spec.rate) / 1000000LL);
@@ -530,8 +543,6 @@ static void gst_polypsink_reset(GstAudioSink *asink) {
pa_threaded_mainloop_wait(polypsink->mainloop);
}
- GST_WARNING("Reset");
-
if (!polypsink->operation_success) {
GST_ELEMENT_ERROR(polypsink, RESOURCE, FAILED, ("Flush failed: %s", pa_strerror(pa_context_errno(polypsink->context))), (NULL));
goto unlock_and_fail;
@@ -547,6 +558,78 @@ unlock_and_fail:
pa_threaded_mainloop_unlock(polypsink->mainloop);
}
+static void gst_polypsink_change_title(GstPolypSink *polypsink, const gchar *t) {
+ pa_operation *o = NULL;
+
+ pa_threaded_mainloop_lock(polypsink->mainloop);
+
+ g_free(polypsink->stream_name);
+ polypsink->stream_name = g_strdup(t);
+
+ if (!(polypsink)->context || pa_context_get_state((polypsink)->context) != PA_CONTEXT_READY ||
+ !(polypsink)->stream || pa_stream_get_state((polypsink)->stream) != PA_STREAM_READY) {
+ goto unlock_and_fail;
+ }
+
+ if (!(o = pa_stream_set_name(polypsink->stream, polypsink->stream_name, NULL, polypsink))) {
+ GST_ELEMENT_ERROR(polypsink, RESOURCE, FAILED, ("pa_stream_set_name() failed: %s", pa_strerror(pa_context_errno(polypsink->context))), (NULL));
+ goto unlock_and_fail;
+ }
+
+ /* We're not interested if this operation failed or not */
+
+unlock_and_fail:
+
+ if (o)
+ pa_operation_unref(o);
+
+ pa_threaded_mainloop_unlock(polypsink->mainloop);
+}
+
+static gboolean gst_polypsink_event(GstBaseSink *sink, GstEvent *event) {
+ GstPolypSink *polypsink = GST_POLYPSINK(sink);
+
+ switch (GST_EVENT_TYPE(event)) {
+ case GST_EVENT_TAG: {
+ gchar *title = NULL, *artist = NULL, *location = NULL, *description = NULL, *t = NULL, *buf = NULL;
+ GstTagList *l;
+
+ gst_event_parse_tag(event, &l);
+
+ gst_tag_list_get_string(l, GST_TAG_TITLE, &title);
+ gst_tag_list_get_string(l, GST_TAG_ARTIST, &artist);
+ gst_tag_list_get_string(l, GST_TAG_LOCATION, &location);
+ gst_tag_list_get_string(l, GST_TAG_DESCRIPTION, &description);
+
+ gst_tag_list_free(l);
+
+ if (title && artist)
+ t = buf = g_strdup_printf("'%s' by '%s'", title, artist);
+ else if (title)
+ t = title;
+ else if (description)
+ t = description;
+ else if (location)
+ t = location;
+
+ if (t)
+ gst_polypsink_change_title(polypsink, t);
+
+ g_free(title);
+ g_free(artist);
+ g_free(location);
+ g_free(description);
+ g_free(buf);
+
+ break;
+ }
+ default:
+ ;
+ }
+
+ return GST_BASE_SINK_CLASS(parent_class)->event(sink, event);
+}
+
GType gst_polypsink_get_type(void) {
static GType polypsink_type = 0;
diff --git a/src/polypsink.h b/src/polypsink.h
index 4b9a76b..e5e98d0 100644
--- a/src/polypsink.h
+++ b/src/polypsink.h
@@ -47,7 +47,7 @@ typedef struct _GstPolypSinkClass GstPolypSinkClass;
struct _GstPolypSink {
GstAudioSink sink;
- gchar *server, *device;
+ gchar *server, *device, *stream_name;
pa_threaded_mainloop *mainloop;