mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-21 13:36:39 +00:00
playbin2: Look for volume/mute properties recursively in audio element.
Rather than only checking for volume property on the audio sink directly, recursively look for it on sinks within it (if it's a bin). Allows use of sink-as-volume-control where the application has supplied an audio-sink bin that includes a real audio sink internally.
This commit is contained in:
parent
67948a4027
commit
a264efc627
1 changed files with 57 additions and 6 deletions
|
@ -640,6 +640,50 @@ gst_play_sink_find_property (GstPlaySink * playsink, GstElement * obj,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
find_property_sink (GstElement * element, const gchar * name)
|
||||||
|
{
|
||||||
|
gint res;
|
||||||
|
gboolean is_sink;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (element);
|
||||||
|
is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
|
||||||
|
GST_OBJECT_UNLOCK (element);
|
||||||
|
|
||||||
|
if (is_sink &&
|
||||||
|
g_object_class_find_property (G_OBJECT_GET_CLASS (element), name)) {
|
||||||
|
res = 0;
|
||||||
|
GST_DEBUG_OBJECT (element, "found %s property on sink", name);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (element, "did not find %s property", name);
|
||||||
|
res = 1;
|
||||||
|
gst_object_unref (element);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find a sink in the hierarchy with a property named @name */
|
||||||
|
static GstElement *
|
||||||
|
gst_play_sink_find_property_sinks (GstPlaySink * playsink, GstElement * obj,
|
||||||
|
const gchar * name)
|
||||||
|
{
|
||||||
|
GstElement *result = NULL;
|
||||||
|
GstIterator *it;
|
||||||
|
|
||||||
|
if (GST_IS_BIN (obj)) {
|
||||||
|
it = gst_bin_iterate_recurse (GST_BIN_CAST (obj));
|
||||||
|
result = gst_iterator_find_custom (it,
|
||||||
|
(GCompareFunc) find_property_sink, (gpointer) name);
|
||||||
|
gst_iterator_free (it);
|
||||||
|
} else {
|
||||||
|
if (g_object_class_find_property (G_OBJECT_GET_CLASS (obj), name)) {
|
||||||
|
result = obj;
|
||||||
|
gst_object_ref (obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* try to change the state of an element. This function returns the element when
|
/* try to change the state of an element. This function returns the element when
|
||||||
* the state change could be performed. When this function returns NULL an error
|
* the state change could be performed. When this function returns NULL an error
|
||||||
* occured and the element is unreffed. */
|
* occured and the element is unreffed. */
|
||||||
|
@ -956,21 +1000,28 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue)
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the sink has the volume property, if it does we don't need to
|
/* check if the sink, or something within the sink, has the volume property.
|
||||||
* add a volume element. */
|
* If it does we don't need to add a volume element. */
|
||||||
|
elem = NULL;
|
||||||
if (g_object_class_find_property (G_OBJECT_GET_CLASS (chain->sink), "volume")) {
|
if (g_object_class_find_property (G_OBJECT_GET_CLASS (chain->sink), "volume")) {
|
||||||
|
elem = gst_object_ref (chain->sink);
|
||||||
|
} else if (GST_IS_BIN (chain->sink)) {
|
||||||
|
elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "volume");
|
||||||
|
}
|
||||||
|
if (elem) {
|
||||||
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;
|
||||||
/* use the sink to control the volume */
|
/* use the sink to control the volume */
|
||||||
chain->volume = chain->sink;
|
chain->volume = elem;
|
||||||
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
|
g_object_set (G_OBJECT (elem), "volume", playsink->volume, NULL);
|
||||||
/* if the sink also has a mute property we can use this as well. We'll only
|
/* 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
|
* use the mute property if there is a volume property. We can simulate the
|
||||||
* mute with the volume otherwise. */
|
* mute with the volume otherwise. */
|
||||||
if (g_object_class_find_property (G_OBJECT_GET_CLASS (chain->sink), "mute")) {
|
if (g_object_class_find_property (G_OBJECT_GET_CLASS (elem), "mute")) {
|
||||||
GST_DEBUG_OBJECT (playsink, "the sink has a mute property");
|
GST_DEBUG_OBJECT (playsink, "the sink has a mute property");
|
||||||
chain->mute = chain->sink;
|
chain->mute = elem;
|
||||||
}
|
}
|
||||||
|
gst_object_unref (elem);
|
||||||
} else {
|
} else {
|
||||||
/* no volume, we need to add a volume element when we can */
|
/* no volume, we need to add a volume element when we can */
|
||||||
GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
|
GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
|
||||||
|
|
Loading…
Reference in a new issue