From 7fb6ad6d4c477daf4a51bb7edb24088c43455f42 Mon Sep 17 00:00:00 2001 From: Sebastian Dröge Date: Fri, 11 Sep 2009 16:09:40 +0200 Subject: pulsesink: Implement mute property --- ext/pulse/pulsesink.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++- ext/pulse/pulsesink.h | 2 + 2 files changed, 140 insertions(+), 2 deletions(-) (limited to 'ext') diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c index 2ce538a1..b6a00be0 100644 --- a/ext/pulse/pulsesink.c +++ b/ext/pulse/pulsesink.c @@ -62,6 +62,7 @@ GST_DEBUG_CATEGORY_EXTERN (pulse_debug); #define DEFAULT_DEVICE NULL #define DEFAULT_DEVICE_NAME NULL #define DEFAULT_VOLUME 1.0 +#define DEFAULT_MUTE FALSE #define MAX_VOLUME 10.0 enum @@ -71,6 +72,7 @@ enum PROP_DEVICE, PROP_DEVICE_NAME, PROP_VOLUME, + PROP_MUTE, PROP_LAST }; @@ -651,6 +653,11 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) #endif PA_STREAM_START_CORKED; +#if HAVE_PULSE_0_9_12 + if (psink->mute_set && psink->mute) + flags |= PA_STREAM_START_MUTED; +#endif + /* we always start corked (see flags above) */ pbuf->corked = TRUE; @@ -1081,8 +1088,10 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample, psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf)); /* FIXME post message rather than using a signal (as mixer interface) */ - if (g_atomic_int_compare_and_exchange (&psink->notify, 1, 0)) + if (g_atomic_int_compare_and_exchange (&psink->notify, 1, 0)) { g_object_notify (G_OBJECT (psink), "volume"); + g_object_notify (G_OBJECT (psink), "mute"); + } /* make sure the ringbuffer is started */ if (G_UNLIKELY (g_atomic_int_get (&buf->state) != @@ -1472,6 +1481,11 @@ gst_pulsesink_class_init (GstPulseSinkClass * klass) g_param_spec_double ("volume", "Volume", "Volume of this stream, 1.0=100%", 0.0, MAX_VOLUME, DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", + "Mute state of this stream", DEFAULT_MUTE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); #endif } @@ -1529,6 +1543,9 @@ gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass) pulsesink->volume = 1.0; pulsesink->volume_set = FALSE; + pulsesink->mute = FALSE; + pulsesink->mute_set = FALSE; + pulsesink->notify = 0; /* needed for conditional execution */ @@ -1635,6 +1652,61 @@ volume_failed: } } +static void +gst_pulsesink_set_mute (GstPulseSink * psink, gboolean mute) +{ + pa_operation *o = NULL; + GstPulseRingBuffer *pbuf; + uint32_t idx; + + pa_threaded_mainloop_lock (psink->mainloop); + + GST_DEBUG_OBJECT (psink, "setting mute state to %d", mute); + + psink->mute = mute; + psink->mute_set = TRUE; + + pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer); + if (pbuf == NULL || pbuf->stream == NULL) + goto no_buffer; + + if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX) + goto no_index; + + if (!(o = pa_context_set_sink_input_mute (pbuf->context, idx, + mute, NULL, NULL))) + goto mute_failed; + + /* We don't really care about the result of this call */ +unlock: + + if (o) + pa_operation_unref (o); + + pa_threaded_mainloop_unlock (psink->mainloop); + + return; + + /* ERRORS */ +no_buffer: + { + GST_DEBUG_OBJECT (psink, "we have no ringbuffer"); + goto unlock; + } +no_index: + { + GST_DEBUG_OBJECT (psink, "we don't have a stream index"); + goto unlock; + } +mute_failed: + { + GST_ELEMENT_ERROR (psink, RESOURCE, FAILED, + ("pa_stream_set_sink_input_mute() failed: %s", + pa_strerror (pa_context_errno (pbuf->context))), (NULL)); + goto unlock; + } +} + static void gst_pulsesink_sink_input_info_cb (pa_context * c, const pa_sink_input_info * i, int eol, void *userdata) @@ -1654,8 +1726,10 @@ gst_pulsesink_sink_input_info_cb (pa_context * c, const pa_sink_input_info * i, /* If the index doesn't match our current stream, * it implies we just recreated the stream (caps change) */ - if (i->index == pa_stream_get_index (pbuf->stream)) + if (i->index == pa_stream_get_index (pbuf->stream)) { psink->volume = pa_sw_volume_to_linear (pa_cvolume_max (&i->volume)); + psink->mute = i->mute; + } done: pa_threaded_mainloop_signal (psink->mainloop, 0); @@ -1721,6 +1795,62 @@ info_failed: goto unlock; } } + +static gboolean +gst_pulsesink_get_mute (GstPulseSink * psink) +{ + GstPulseRingBuffer *pbuf; + pa_operation *o = NULL; + uint32_t idx; + gboolean mute; + + pa_threaded_mainloop_lock (psink->mainloop); + + pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer); + if (pbuf == NULL || pbuf->stream == NULL) + goto no_buffer; + + if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX) + goto no_index; + + if (!(o = pa_context_get_sink_input_info (pbuf->context, idx, + gst_pulsesink_sink_input_info_cb, pbuf))) + goto info_failed; + + while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) { + pa_threaded_mainloop_wait (psink->mainloop); + if (gst_pulsering_is_dead (psink, pbuf)) + goto unlock; + } + +unlock: + if (o) + pa_operation_unref (o); + + mute = psink->mute; + pa_threaded_mainloop_unlock (psink->mainloop); + + return mute; + + /* ERRORS */ +no_buffer: + { + GST_DEBUG_OBJECT (psink, "we have no ringbuffer"); + goto unlock; + } +no_index: + { + GST_DEBUG_OBJECT (psink, "we don't have a stream index"); + goto unlock; + } +info_failed: + { + GST_ELEMENT_ERROR (psink, RESOURCE, FAILED, + ("pa_context_get_sink_input_info() failed: %s", + pa_strerror (pa_context_errno (pbuf->context))), (NULL)); + goto unlock; + } +} #endif static void @@ -1816,6 +1946,9 @@ gst_pulsesink_set_property (GObject * object, case PROP_VOLUME: gst_pulsesink_set_volume (pulsesink, g_value_get_double (value)); break; + case PROP_MUTE: + gst_pulsesink_set_mute (pulsesink, g_value_get_boolean (value)); + break; #endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1844,6 +1977,9 @@ gst_pulsesink_get_property (GObject * object, case PROP_VOLUME: g_value_set_double (value, gst_pulsesink_get_volume (pulsesink)); break; + case PROP_MUTE: + g_value_set_boolean (value, gst_pulsesink_get_mute (pulsesink)); + break; #endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/ext/pulse/pulsesink.h b/ext/pulse/pulsesink.h index 6120609c..c7ff2e87 100644 --- a/ext/pulse/pulsesink.h +++ b/ext/pulse/pulsesink.h @@ -61,6 +61,8 @@ struct _GstPulseSink gdouble volume; gboolean volume_set; + gboolean mute; + gboolean mute_set; gint notify; const gchar *pa_version; -- cgit