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:
Michael Smith 2009-02-10 17:10:33 -08:00
parent 67948a4027
commit a264efc627

View file

@ -640,6 +640,50 @@ gst_play_sink_find_property (GstPlaySink * playsink, GstElement * obj,
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
* the state change could be performed. When this function returns NULL an error
* occured and the element is unreffed. */
@ -956,21 +1000,28 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue)
prev = NULL;
}
/* check if the sink has the volume property, if it does we don't need to
* add a volume element. */
/* 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 = NULL;
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");
have_volume = TRUE;
/* use the sink to control the volume */
chain->volume = chain->sink;
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
chain->volume = elem;
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
* use the mute property if there is a volume property. We can simulate the
* 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");
chain->mute = chain->sink;
chain->mute = elem;
}
gst_object_unref (elem);
} else {
/* no volume, we need to add a volume element when we can */
GST_DEBUG_OBJECT (playsink, "the sink has no volume property");