From f99a24f8b3ab1d0fa0cc56432b766a5c1ae85fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 10 Jul 2015 11:53:24 +0300 Subject: [PATCH] playsink: Require the streamvolume interface on the sink when using the sink's volume/mute properties If the sink has properties named volume and mute, we have no idea about their meaning. The streamvolume interface standardizes the meaning. In the case of osxaudiosink for example, the current volume property has a range of 0.0 to 1.0, but we need 0.0 to 10.0 or similar. Also osxaudiosink has no mute property. As such, the volume element should be used here instead. https://bugzilla.gnome.org/show_bug.cgi?id=752156 --- gst/playback/gstplaysink.c | 117 ++++++++++++++----------------------- 1 file changed, 43 insertions(+), 74 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index e7ae9f8c6d..aa43111a69 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -105,7 +105,6 @@ typedef struct GstElement *volume; /* element with the volume property */ gboolean sink_volume; /* if the volume was provided by the sink */ gulong notify_volume_id; - GstElement *mute; /* element with the mute property */ gulong notify_mute_id; GstElement *sink; GstElement *ts_offset; @@ -730,7 +729,7 @@ disconnect_audio_chain (GstPlayAudioChain * chain, GstPlaySink * playsink) if (chain->notify_volume_id) g_signal_handler_disconnect (chain->volume, chain->notify_volume_id); if (chain->notify_mute_id) - g_signal_handler_disconnect (chain->mute, chain->notify_mute_id); + g_signal_handler_disconnect (chain->volume, chain->notify_mute_id); chain->notify_volume_id = chain->notify_mute_id = 0; } } @@ -1148,12 +1147,10 @@ gst_play_sink_set_volume (GstPlaySink * playsink, gdouble volume) playsink->volume = volume; chain = (GstPlayAudioChain *) playsink->audiochain; if (chain && chain->volume) { - GST_LOG_OBJECT (playsink, "elements: volume=%" GST_PTR_FORMAT ", mute=%" - GST_PTR_FORMAT "; new volume=%.03f, mute=%d", chain->volume, - chain->mute, volume, playsink->mute); - /* if there is a mute element or we are not muted, set the volume */ - if (chain->mute || !playsink->mute) - g_object_set (chain->volume, "volume", volume, NULL); + GST_LOG_OBJECT (playsink, + "elements: volume=%" GST_PTR_FORMAT "; new volume=%.03f, mute=%d", + chain->volume, volume, playsink->mute); + g_object_set (chain->volume, "volume", volume, NULL); } else { GST_LOG_OBJECT (playsink, "no volume element"); playsink->volume_changed = TRUE; @@ -1171,10 +1168,8 @@ gst_play_sink_get_volume (GstPlaySink * playsink) chain = (GstPlayAudioChain *) playsink->audiochain; result = playsink->volume; if (chain && chain->volume) { - if (chain->mute || !playsink->mute) { - g_object_get (chain->volume, "volume", &result, NULL); - playsink->volume = result; - } + g_object_get (chain->volume, "volume", &result, NULL); + playsink->volume = result; } GST_PLAY_SINK_UNLOCK (playsink); @@ -1189,16 +1184,8 @@ gst_play_sink_set_mute (GstPlaySink * playsink, gboolean mute) GST_PLAY_SINK_LOCK (playsink); playsink->mute = mute; chain = (GstPlayAudioChain *) playsink->audiochain; - if (chain) { - if (chain->mute) { - g_object_set (chain->mute, "mute", mute, NULL); - } else if (chain->volume) { - if (mute) - g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL); - else - g_object_set (chain->volume, "volume", (gdouble) playsink->volume, - NULL); - } + if (chain && chain->volume) { + g_object_set (chain->volume, "mute", mute, NULL); } else { playsink->mute_changed = TRUE; } @@ -1213,8 +1200,8 @@ gst_play_sink_get_mute (GstPlaySink * playsink) GST_PLAY_SINK_LOCK (playsink); chain = (GstPlayAudioChain *) playsink->audiochain; - if (chain && chain->mute) { - g_object_get (chain->mute, "mute", &result, NULL); + if (chain && chain->volume) { + g_object_get (chain->volume, "mute", &result, NULL); playsink->mute = result; } else { result = playsink->mute; @@ -2767,11 +2754,16 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset", G_TYPE_INT64)); - /* check if the sink, or something within the sink, has the volume property. - * If it does we don't need to add a volume element. */ - elem = - gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", - G_TYPE_DOUBLE); + /* check if the sink, or something within the sink, implements the + * streamvolume interface. If it does we don't need to add a volume element. */ + if (GST_IS_BIN (chain->sink)) + elem = + gst_bin_get_by_interface (GST_BIN_CAST (chain->sink), + GST_TYPE_STREAM_VOLUME); + else if (GST_IS_STREAM_VOLUME (chain->sink)) + elem = gst_object_ref (chain->sink); + else + elem = NULL; chain->notify_volume_id = chain->notify_mute_id = 0; if (elem) { chain->volume = elem; @@ -2782,29 +2774,15 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) GST_DEBUG_OBJECT (playsink, "the sink has a volume property"); have_volume = TRUE; chain->sink_volume = TRUE; - /* if the sink also has a mute property we can use this as well. We'll only - * use the mute property if there is a volume property. We can simulate the - * mute with the volume otherwise. */ - chain->mute = - gst_play_sink_find_property_sinks (playsink, chain->sink, "mute", - G_TYPE_BOOLEAN); - if (chain->mute) { - GST_DEBUG_OBJECT (playsink, "the sink has a mute property"); - chain->notify_mute_id = g_signal_connect (chain->mute, "notify::mute", - G_CALLBACK (notify_mute_cb), playsink); - } + chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute", + G_CALLBACK (notify_mute_cb), playsink); /* use the sink to control the volume and mute */ if (playsink->volume_changed) { g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); playsink->volume_changed = FALSE; } if (playsink->mute_changed) { - if (chain->mute) { - g_object_set (chain->mute, "mute", playsink->mute, NULL); - } else { - if (playsink->mute) - g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL); - } + g_object_set (chain->volume, "mute", playsink->mute, NULL); playsink->mute_changed = FALSE; } } else { @@ -2848,14 +2826,13 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) G_CALLBACK (notify_volume_cb), playsink); /* volume also has the mute property */ - chain->mute = chain->volume; - chain->notify_mute_id = g_signal_connect (chain->mute, "notify::mute", + chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute", G_CALLBACK (notify_mute_cb), playsink); /* configure with the latest volume and mute */ g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); - g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL); + g_object_set (G_OBJECT (chain->volume), "mute", playsink->mute, NULL); } } } @@ -2980,11 +2957,16 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw) /* Disconnect signals */ disconnect_audio_chain (chain, playsink); - /* check if the sink, or something within the sink, has the volume property. - * If it does we don't need to add a volume element. */ - elem = - gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", - G_TYPE_DOUBLE); + /* check if the sink, or something within the sink, implements the + * streamvolume interface. If it does we don't need to add a volume element. */ + if (GST_IS_BIN (chain->sink)) + elem = + gst_bin_get_by_interface (GST_BIN_CAST (chain->sink), + GST_TYPE_STREAM_VOLUME); + else if (GST_IS_STREAM_VOLUME (chain->sink)) + elem = gst_object_ref (chain->sink); + else + elem = NULL; if (elem) { chain->volume = elem; @@ -2998,19 +2980,10 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw) chain->notify_volume_id = g_signal_connect (chain->volume, "notify::volume", G_CALLBACK (notify_volume_cb), playsink); - /* if the sink also has a mute property we can use this as well. We'll only - * use the mute property if there is a volume property. We can simulate the - * mute with the volume otherwise. */ - chain->mute = - gst_play_sink_find_property_sinks (playsink, chain->sink, "mute", - G_TYPE_BOOLEAN); - if (chain->mute) { - GST_DEBUG_OBJECT (playsink, "the sink has a mute property"); - chain->notify_mute_id = g_signal_connect (chain->mute, "notify::mute", - G_CALLBACK (notify_mute_cb), playsink); - g_object_set (chain->mute, "mute", playsink->mute, NULL); - playsink->mute_changed = FALSE; - } + chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute", + G_CALLBACK (notify_mute_cb), playsink); + g_object_set (chain->volume, "mute", playsink->mute, NULL); + playsink->mute_changed = FALSE; g_object_set (chain->conv, "use-volume", FALSE, NULL); } else if (conv) { @@ -3021,18 +2994,17 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw) if (conv->volume && (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME)) { chain->volume = conv->volume; - chain->mute = chain->volume; chain->notify_volume_id = g_signal_connect (chain->volume, "notify::volume", G_CALLBACK (notify_volume_cb), playsink); - chain->notify_mute_id = g_signal_connect (chain->mute, "notify::mute", + chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute", G_CALLBACK (notify_mute_cb), playsink); /* configure with the latest volume and mute */ g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); - g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL); + g_object_set (G_OBJECT (chain->volume), "mute", playsink->mute, NULL); } GST_DEBUG_OBJECT (playsink, "reusing existing volume element"); @@ -3501,7 +3473,6 @@ gst_play_sink_do_reconfigure (GstPlaySink * playsink) activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); disconnect_audio_chain (playsink->audiochain, playsink); playsink->audiochain->volume = NULL; - playsink->audiochain->mute = NULL; if (playsink->audiochain->ts_offset) gst_object_unref (playsink->audiochain->ts_offset); playsink->audiochain->ts_offset = NULL; @@ -3610,7 +3581,6 @@ gst_play_sink_do_reconfigure (GstPlaySink * playsink) if (playsink->audiochain->sink_volume) { disconnect_audio_chain (playsink->audiochain, playsink); playsink->audiochain->volume = NULL; - playsink->audiochain->mute = NULL; if (playsink->audiochain->ts_offset) gst_object_unref (playsink->audiochain->ts_offset); playsink->audiochain->ts_offset = NULL; @@ -4813,11 +4783,10 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition) /* fall through */ case GST_STATE_CHANGE_READY_TO_NULL: if (playsink->audiochain && playsink->audiochain->sink_volume) { - /* remove our links to the mute and volume elements when they were + /* remove our links to the volume elements when they were * provided by a sink */ disconnect_audio_chain (playsink->audiochain, playsink); playsink->audiochain->volume = NULL; - playsink->audiochain->mute = NULL; } if (playsink->audiochain && playsink->audiochain->ts_offset) {