diff options
Diffstat (limited to 'src/pulsesink.c')
-rw-r--r-- | src/pulsesink.c | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/src/pulsesink.c b/src/pulsesink.c index 04b10be..295811e 100644 --- a/src/pulsesink.c +++ b/src/pulsesink.c @@ -2,17 +2,17 @@ /*** This file is part of gst-pulse. - + gst-pulse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + gst-pulse is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with gst-pulse; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -82,7 +82,7 @@ static void gst_pulsesink_base_init(gpointer g_class) { "depth = (int) 16, " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 16 ];" - + "audio/x-raw-int, " "signed = (boolean) FALSE, " "width = (int) 8, " @@ -105,7 +105,7 @@ static void gst_pulsesink_base_init(gpointer g_class) { "channels = (int) [ 1, 16 ]" ) ); - + static const GstElementDetails details = GST_ELEMENT_DETAILS( "PulseAudio Audio Sink", @@ -114,7 +114,7 @@ static void gst_pulsesink_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)); } @@ -122,19 +122,19 @@ static void gst_pulsesink_base_init(gpointer g_class) { static void gst_pulsesink_class_init( gpointer g_class, gpointer class_data) { - + GObjectClass *gobject_class = G_OBJECT_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->dispose = GST_DEBUG_FUNCPTR(gst_pulsesink_dispose); gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_pulsesink_finalize); gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_pulsesink_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_pulsesink_get_property); gstbasesink_class->event = GST_DEBUG_FUNCPTR(gst_pulsesink_event); - + gstaudiosink_class->open = GST_DEBUG_FUNCPTR(gst_pulsesink_open); gstaudiosink_class->close = GST_DEBUG_FUNCPTR(gst_pulsesink_close); gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR(gst_pulsesink_prepare); @@ -142,7 +142,7 @@ static void gst_pulsesink_class_init( gstaudiosink_class->write = GST_DEBUG_FUNCPTR(gst_pulsesink_write); gstaudiosink_class->delay = GST_DEBUG_FUNCPTR(gst_pulsesink_delay); gstaudiosink_class->reset = GST_DEBUG_FUNCPTR(gst_pulsesink_reset); - + /* Overwrite GObject fields */ g_object_class_install_property( gobject_class, @@ -157,12 +157,12 @@ static void gst_pulsesink_class_init( static void gst_pulsesink_init( GTypeInstance * instance, gpointer g_class) { - + GstPulseSink *pulsesink = GST_PULSESINK(instance); int e; pulsesink->server = pulsesink->device = pulsesink->stream_name = NULL; - + pulsesink->context = NULL; pulsesink->stream = NULL; @@ -219,7 +219,7 @@ static void gst_pulsesink_set_property( GObject * object, guint prop_id, const GValue * value, - GParamSpec * pspec) { + GParamSpec * pspec) { GstPulseSink *pulsesink = GST_PULSESINK(object); switch (prop_id) { @@ -244,7 +244,7 @@ static void gst_pulsesink_get_property( guint prop_id, GValue * value, GParamSpec * pspec) { - + GstPulseSink *pulsesink = GST_PULSESINK(object); switch(prop_id) { @@ -321,7 +321,7 @@ static gboolean gst_pulsesink_open(GstAudioSink *asink) { } pa_context_set_state_callback(pulsesink->context, gst_pulsesink_context_state_cb, pulsesink); - + if (pa_context_connect(pulsesink->context, pulsesink->server, 0, NULL) < 0) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("Failed to connect: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; @@ -340,7 +340,7 @@ static gboolean gst_pulsesink_open(GstAudioSink *asink) { return TRUE; unlock_and_fail: - + pa_threaded_mainloop_unlock(pulsesink->mainloop); g_free(name); return FALSE; @@ -359,7 +359,7 @@ static gboolean gst_pulsesink_close(GstAudioSink *asink) { static gboolean gst_pulsesink_prepare(GstAudioSink *asink, GstRingBufferSpec *spec) { pa_buffer_attr buf_attr; pa_channel_map channel_map; - + GstPulseSink *pulsesink = GST_PULSESINK(asink); if (!gst_pulse_fill_sample_spec(spec, &pulsesink->sample_spec)) { @@ -373,7 +373,7 @@ static gboolean gst_pulsesink_prepare(GstAudioSink *asink, GstRingBufferSpec *sp GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("Bad context state: %s", pulsesink->context ? pa_strerror(pa_context_errno(pulsesink->context)) : NULL), (NULL)); goto unlock_and_fail; } - + if (!(pulsesink->stream = pa_stream_new(pulsesink->context, pulsesink->stream_name ? pulsesink->stream_name : "Playback Stream", &pulsesink->sample_spec, gst_pulse_gst_to_channel_map(&channel_map,spec)))) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("Failed to create stream: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; @@ -386,8 +386,9 @@ static gboolean gst_pulsesink_prepare(GstAudioSink *asink, GstRingBufferSpec *sp memset(&buf_attr, 0, sizeof(buf_attr)); buf_attr.tlength = spec->segtotal*spec->segsize; buf_attr.maxlength = buf_attr.tlength*2; - buf_attr.prebuf = buf_attr.minreq = spec->segsize; - + buf_attr.prebuf = buf_attr.tlength*2; + buf_attr.minreq = spec->segsize; + if (pa_stream_connect_playback(pulsesink->stream, pulsesink->device, &buf_attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_NOT_MONOTONOUS, NULL, NULL) < 0) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("Failed to connect stream: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; @@ -405,11 +406,11 @@ static gboolean gst_pulsesink_prepare(GstAudioSink *asink, GstRingBufferSpec *sp spec->bytes_per_sample = pa_frame_size(&pulsesink->sample_spec); memset(spec->silence_sample, 0, spec->bytes_per_sample); - + return TRUE; unlock_and_fail: - + pa_threaded_mainloop_unlock(pulsesink->mainloop); return FALSE; } @@ -434,15 +435,15 @@ if (!(pulsesink)->context || pa_context_get_state((pulsesink)->context) != PA_CO static guint gst_pulsesink_write(GstAudioSink *asink, gpointer data, guint length) { GstPulseSink *pulsesink = GST_PULSESINK(asink); size_t sum = 0; - + pa_threaded_mainloop_lock(pulsesink->mainloop); while (length > 0) { size_t l; - + for (;;) { CHECK_DEAD_GOTO(pulsesink, unlock_and_fail); - + if ((l = pa_stream_writable_size(pulsesink->stream)) == (size_t) -1) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; @@ -450,13 +451,13 @@ static guint gst_pulsesink_write(GstAudioSink *asink, gpointer data, guint lengt if (l > 0) break; - + pa_threaded_mainloop_wait(pulsesink->mainloop); } if (l > length) l = length; - + if (pa_stream_write(pulsesink->stream, data, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; @@ -471,9 +472,9 @@ static guint gst_pulsesink_write(GstAudioSink *asink, gpointer data, guint lengt pa_threaded_mainloop_unlock(pulsesink->mainloop); return sum; - + unlock_and_fail: - + pa_threaded_mainloop_unlock(pulsesink->mainloop); return 0; } @@ -486,7 +487,7 @@ static guint gst_pulsesink_delay(GstAudioSink *asink) { for (;;) { CHECK_DEAD_GOTO(pulsesink, unlock_and_fail); - + if (pa_stream_get_latency(pulsesink->stream, &t, NULL) >= 0) break; @@ -503,7 +504,7 @@ static guint gst_pulsesink_delay(GstAudioSink *asink) { return gst_util_uint64_scale_int (t, pulsesink->sample_spec.rate, 1000000LL); unlock_and_fail: - + pa_threaded_mainloop_unlock(pulsesink->mainloop); return 0; } @@ -518,7 +519,7 @@ static void gst_pulsesink_success_cb(pa_stream *s, int success, void *userdata) static void gst_pulsesink_reset(GstAudioSink *asink) { GstPulseSink *pulsesink = GST_PULSESINK(asink); pa_operation *o = NULL; - + pa_threaded_mainloop_lock(pulsesink->mainloop); CHECK_DEAD_GOTO(pulsesink, unlock_and_fail); @@ -531,7 +532,7 @@ static void gst_pulsesink_reset(GstAudioSink *asink) { pulsesink->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(pulsesink, unlock_and_fail); - + pa_threaded_mainloop_wait(pulsesink->mainloop); } @@ -539,27 +540,27 @@ static void gst_pulsesink_reset(GstAudioSink *asink) { GST_ELEMENT_ERROR(pulsesink, RESOURCE, FAILED, ("Flush failed: %s", pa_strerror(pa_context_errno(pulsesink->context))), (NULL)); goto unlock_and_fail; } - + unlock_and_fail: if (o) { pa_operation_cancel(o); pa_operation_unref(o); } - + pa_threaded_mainloop_unlock(pulsesink->mainloop); } static void gst_pulsesink_change_title(GstPulseSink *pulsesink, const gchar *t) { pa_operation *o = NULL; - + pa_threaded_mainloop_lock(pulsesink->mainloop); g_free(pulsesink->stream_name); pulsesink->stream_name = g_strdup(t); - - if (!(pulsesink)->context || pa_context_get_state((pulsesink)->context) != PA_CONTEXT_READY || - !(pulsesink)->stream || pa_stream_get_state((pulsesink)->stream) != PA_STREAM_READY) { + + if (!(pulsesink)->context || pa_context_get_state((pulsesink)->context) != PA_CONTEXT_READY || + !(pulsesink)->stream || pa_stream_get_state((pulsesink)->stream) != PA_STREAM_READY) { goto unlock_and_fail; } @@ -585,7 +586,7 @@ static gboolean gst_pulsesink_event(GstBaseSink *sink, GstEvent *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); @@ -604,25 +605,25 @@ static gboolean gst_pulsesink_event(GstBaseSink *sink, GstEvent *event) { if (t) gst_pulsesink_change_title(pulsesink, 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_pulsesink_get_type(void) { static GType pulsesink_type = 0; - + if (!pulsesink_type) { static const GTypeInfo pulsesink_info = { |