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
This commit is contained in:
Sebastian Dröge 2015-07-10 11:53:24 +03:00
parent 8be88f0364
commit f99a24f8b3

View file

@ -105,7 +105,6 @@ typedef struct
GstElement *volume; /* element with the volume property */ GstElement *volume; /* element with the volume property */
gboolean sink_volume; /* if the volume was provided by the sink */ gboolean sink_volume; /* if the volume was provided by the sink */
gulong notify_volume_id; gulong notify_volume_id;
GstElement *mute; /* element with the mute property */
gulong notify_mute_id; gulong notify_mute_id;
GstElement *sink; GstElement *sink;
GstElement *ts_offset; GstElement *ts_offset;
@ -730,7 +729,7 @@ disconnect_audio_chain (GstPlayAudioChain * chain, GstPlaySink * playsink)
if (chain->notify_volume_id) if (chain->notify_volume_id)
g_signal_handler_disconnect (chain->volume, chain->notify_volume_id); g_signal_handler_disconnect (chain->volume, chain->notify_volume_id);
if (chain->notify_mute_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; 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; playsink->volume = volume;
chain = (GstPlayAudioChain *) playsink->audiochain; chain = (GstPlayAudioChain *) playsink->audiochain;
if (chain && chain->volume) { if (chain && chain->volume) {
GST_LOG_OBJECT (playsink, "elements: volume=%" GST_PTR_FORMAT ", mute=%" GST_LOG_OBJECT (playsink,
GST_PTR_FORMAT "; new volume=%.03f, mute=%d", chain->volume, "elements: volume=%" GST_PTR_FORMAT "; new volume=%.03f, mute=%d",
chain->mute, volume, playsink->mute); chain->volume, volume, playsink->mute);
/* if there is a mute element or we are not muted, set the volume */ g_object_set (chain->volume, "volume", volume, NULL);
if (chain->mute || !playsink->mute)
g_object_set (chain->volume, "volume", volume, NULL);
} else { } else {
GST_LOG_OBJECT (playsink, "no volume element"); GST_LOG_OBJECT (playsink, "no volume element");
playsink->volume_changed = TRUE; playsink->volume_changed = TRUE;
@ -1171,10 +1168,8 @@ gst_play_sink_get_volume (GstPlaySink * playsink)
chain = (GstPlayAudioChain *) playsink->audiochain; chain = (GstPlayAudioChain *) playsink->audiochain;
result = playsink->volume; result = playsink->volume;
if (chain && chain->volume) { if (chain && chain->volume) {
if (chain->mute || !playsink->mute) { g_object_get (chain->volume, "volume", &result, NULL);
g_object_get (chain->volume, "volume", &result, NULL); playsink->volume = result;
playsink->volume = result;
}
} }
GST_PLAY_SINK_UNLOCK (playsink); GST_PLAY_SINK_UNLOCK (playsink);
@ -1189,16 +1184,8 @@ gst_play_sink_set_mute (GstPlaySink * playsink, gboolean mute)
GST_PLAY_SINK_LOCK (playsink); GST_PLAY_SINK_LOCK (playsink);
playsink->mute = mute; playsink->mute = mute;
chain = (GstPlayAudioChain *) playsink->audiochain; chain = (GstPlayAudioChain *) playsink->audiochain;
if (chain) { if (chain && chain->volume) {
if (chain->mute) { g_object_set (chain->volume, "mute", mute, NULL);
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);
}
} else { } else {
playsink->mute_changed = TRUE; playsink->mute_changed = TRUE;
} }
@ -1213,8 +1200,8 @@ gst_play_sink_get_mute (GstPlaySink * playsink)
GST_PLAY_SINK_LOCK (playsink); GST_PLAY_SINK_LOCK (playsink);
chain = (GstPlayAudioChain *) playsink->audiochain; chain = (GstPlayAudioChain *) playsink->audiochain;
if (chain && chain->mute) { if (chain && chain->volume) {
g_object_get (chain->mute, "mute", &result, NULL); g_object_get (chain->volume, "mute", &result, NULL);
playsink->mute = result; playsink->mute = result;
} else { } else {
result = playsink->mute; 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", gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset",
G_TYPE_INT64)); G_TYPE_INT64));
/* check if the sink, or something within the sink, has the volume property. /* check if the sink, or something within the sink, implements the
* If it does we don't need to add a volume element. */ * streamvolume interface. If it does we don't need to add a volume element. */
elem = if (GST_IS_BIN (chain->sink))
gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", elem =
G_TYPE_DOUBLE); 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; chain->notify_volume_id = chain->notify_mute_id = 0;
if (elem) { if (elem) {
chain->volume = 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"); GST_DEBUG_OBJECT (playsink, "the sink has a volume property");
have_volume = TRUE; have_volume = TRUE;
chain->sink_volume = TRUE; chain->sink_volume = TRUE;
/* if the sink also has a mute property we can use this as well. We'll only chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute",
* use the mute property if there is a volume property. We can simulate the G_CALLBACK (notify_mute_cb), playsink);
* 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);
}
/* use the sink to control the volume and mute */ /* use the sink to control the volume and mute */
if (playsink->volume_changed) { if (playsink->volume_changed) {
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
playsink->volume_changed = FALSE; playsink->volume_changed = FALSE;
} }
if (playsink->mute_changed) { if (playsink->mute_changed) {
if (chain->mute) { g_object_set (chain->volume, "mute", playsink->mute, NULL);
g_object_set (chain->mute, "mute", playsink->mute, NULL);
} else {
if (playsink->mute)
g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL);
}
playsink->mute_changed = FALSE; playsink->mute_changed = FALSE;
} }
} else { } else {
@ -2848,14 +2826,13 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
G_CALLBACK (notify_volume_cb), playsink); G_CALLBACK (notify_volume_cb), playsink);
/* volume also has the mute property */ /* volume also has the mute property */
chain->mute = chain->volume; chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute",
chain->notify_mute_id = g_signal_connect (chain->mute, "notify::mute",
G_CALLBACK (notify_mute_cb), playsink); G_CALLBACK (notify_mute_cb), playsink);
/* configure with the latest volume and mute */ /* configure with the latest volume and mute */
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume,
NULL); 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 signals */
disconnect_audio_chain (chain, playsink); disconnect_audio_chain (chain, playsink);
/* check if the sink, or something within the sink, has the volume property. /* check if the sink, or something within the sink, implements the
* If it does we don't need to add a volume element. */ * streamvolume interface. If it does we don't need to add a volume element. */
elem = if (GST_IS_BIN (chain->sink))
gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", elem =
G_TYPE_DOUBLE); 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) { if (elem) {
chain->volume = 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", chain->notify_volume_id = g_signal_connect (chain->volume, "notify::volume",
G_CALLBACK (notify_volume_cb), playsink); G_CALLBACK (notify_volume_cb), playsink);
/* if the sink also has a mute property we can use this as well. We'll only chain->notify_mute_id = g_signal_connect (chain->volume, "notify::mute",
* use the mute property if there is a volume property. We can simulate the G_CALLBACK (notify_mute_cb), playsink);
* mute with the volume otherwise. */ g_object_set (chain->volume, "mute", playsink->mute, NULL);
chain->mute = playsink->mute_changed = FALSE;
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;
}
g_object_set (chain->conv, "use-volume", FALSE, NULL); g_object_set (chain->conv, "use-volume", FALSE, NULL);
} else if (conv) { } else if (conv) {
@ -3021,18 +2994,17 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw)
if (conv->volume && (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME)) { if (conv->volume && (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME)) {
chain->volume = conv->volume; chain->volume = conv->volume;
chain->mute = chain->volume;
chain->notify_volume_id = chain->notify_volume_id =
g_signal_connect (chain->volume, "notify::volume", g_signal_connect (chain->volume, "notify::volume",
G_CALLBACK (notify_volume_cb), playsink); 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); G_CALLBACK (notify_mute_cb), playsink);
/* configure with the latest volume and mute */ /* configure with the latest volume and mute */
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); 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"); 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); activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
disconnect_audio_chain (playsink->audiochain, playsink); disconnect_audio_chain (playsink->audiochain, playsink);
playsink->audiochain->volume = NULL; playsink->audiochain->volume = NULL;
playsink->audiochain->mute = NULL;
if (playsink->audiochain->ts_offset) if (playsink->audiochain->ts_offset)
gst_object_unref (playsink->audiochain->ts_offset); gst_object_unref (playsink->audiochain->ts_offset);
playsink->audiochain->ts_offset = NULL; playsink->audiochain->ts_offset = NULL;
@ -3610,7 +3581,6 @@ gst_play_sink_do_reconfigure (GstPlaySink * playsink)
if (playsink->audiochain->sink_volume) { if (playsink->audiochain->sink_volume) {
disconnect_audio_chain (playsink->audiochain, playsink); disconnect_audio_chain (playsink->audiochain, playsink);
playsink->audiochain->volume = NULL; playsink->audiochain->volume = NULL;
playsink->audiochain->mute = NULL;
if (playsink->audiochain->ts_offset) if (playsink->audiochain->ts_offset)
gst_object_unref (playsink->audiochain->ts_offset); gst_object_unref (playsink->audiochain->ts_offset);
playsink->audiochain->ts_offset = NULL; playsink->audiochain->ts_offset = NULL;
@ -4813,11 +4783,10 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition)
/* fall through */ /* fall through */
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
if (playsink->audiochain && playsink->audiochain->sink_volume) { 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 */ * provided by a sink */
disconnect_audio_chain (playsink->audiochain, playsink); disconnect_audio_chain (playsink->audiochain, playsink);
playsink->audiochain->volume = NULL; playsink->audiochain->volume = NULL;
playsink->audiochain->mute = NULL;
} }
if (playsink->audiochain && playsink->audiochain->ts_offset) { if (playsink->audiochain && playsink->audiochain->ts_offset) {