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. */
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");