mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
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:
parent
8be88f0364
commit
f99a24f8b3
1 changed files with 43 additions and 74 deletions
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue