1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gstreamer.ObjectGst;
26 
27 private import glib.ErrorG;
28 private import glib.ListG;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.ParamSpec;
32 private import gobject.Signals;
33 private import gobject.Value;
34 private import gstreamer.ControlBinding;
35 private import gstreamerc.gstreamer;
36 public  import gstreamerc.gstreamertypes;
37 public  import gtkc.gdktypes;
38 private import std.algorithm;
39 
40 
41 /**
42  * #GstObject provides a root for the object hierarchy tree filed in by the
43  * GStreamer library.  It is currently a thin wrapper on top of
44  * #GInitiallyUnowned. It is an abstract class that is not very usable on its own.
45  * 
46  * #GstObject gives us basic refcounting, parenting functionality and locking.
47  * Most of the functions are just extended for special GStreamer needs and can be
48  * found under the same name in the base class of #GstObject which is #GObject
49  * (e.g. g_object_ref() becomes gst_object_ref()).
50  * 
51  * Since #GstObject derives from #GInitiallyUnowned, it also inherits the
52  * floating reference. Be aware that functions such as gst_bin_add() and
53  * gst_element_add_pad() take ownership of the floating reference.
54  * 
55  * In contrast to #GObject instances, #GstObject adds a name property. The functions
56  * gst_object_set_name() and gst_object_get_name() are used to set/get the name
57  * of the object.
58  * 
59  * <refsect2>
60  * <title>controlled properties</title>
61  * <para>
62  * Controlled properties offers a lightweight way to adjust gobject properties
63  * over stream-time. It works by using time-stamped value pairs that are queued
64  * for element-properties. At run-time the elements continuously pull value
65  * changes for the current stream-time.
66  * 
67  * What needs to be changed in a #GstElement?
68  * Very little - it is just two steps to make a plugin controllable!
69  * <orderedlist>
70  * <listitem><para>
71  * mark gobject-properties paramspecs that make sense to be controlled,
72  * by GST_PARAM_CONTROLLABLE.
73  * </para></listitem>
74  * <listitem><para>
75  * when processing data (get, chain, loop function) at the beginning call
76  * gst_object_sync_values(element,timestamp).
77  * This will make the controller update all GObject properties that are
78  * under its control with the current values based on the timestamp.
79  * </para></listitem>
80  * </orderedlist>
81  * 
82  * What needs to be done in applications?
83  * Again it's not a lot to change.
84  * <orderedlist>
85  * <listitem><para>
86  * create a #GstControlSource.
87  * csource = gst_interpolation_control_source_new ();
88  * g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
89  * </para></listitem>
90  * <listitem><para>
91  * Attach the #GstControlSource on the controller to a property.
92  * gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource));
93  * </para></listitem>
94  * <listitem><para>
95  * Set the control values
96  * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1);
97  * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);
98  * </para></listitem>
99  * <listitem><para>
100  * start your pipeline
101  * </para></listitem>
102  * </orderedlist>
103  * </para>
104  * </refsect2>
105  */
106 public class ObjectGst : ObjectG
107 {
108 	/** the main Gtk struct */
109 	protected GstObject* gstObject;
110 
111 	/** Get the main Gtk struct */
112 	public GstObject* getObjectGstStruct()
113 	{
114 		return gstObject;
115 	}
116 
117 	/** the main Gtk struct as a void* */
118 	protected override void* getStruct()
119 	{
120 		return cast(void*)gstObject;
121 	}
122 
123 	protected override void setStruct(GObject* obj)
124 	{
125 		gstObject = cast(GstObject*)obj;
126 		super.setStruct(obj);
127 	}
128 
129 	/**
130 	 * Sets our main struct and passes it to the parent class.
131 	 */
132 	public this (GstObject* gstObject, bool ownedRef = false)
133 	{
134 		this.gstObject = gstObject;
135 		super(cast(GObject*)gstObject, ownedRef);
136 	}
137 
138 
139 	/** */
140 	public static GType getType()
141 	{
142 		return gst_object_get_type();
143 	}
144 
145 	/**
146 	 * Checks to see if there is any object named @name in @list. This function
147 	 * does not do any locking of any kind. You might want to protect the
148 	 * provided list with the lock of the owner of the list. This function
149 	 * will lock each #GstObject in the list to compare the name, so be
150 	 * careful when passing a list with a locked object.
151 	 *
152 	 * Params:
153 	 *     list = a list of #GstObject to
154 	 *         check through
155 	 *     name = the name to search for
156 	 *
157 	 * Return: %TRUE if a #GstObject named @name does not appear in @list,
158 	 *     %FALSE if it does.
159 	 *
160 	 *     MT safe. Grabs and releases the LOCK of each object in the list.
161 	 */
162 	public static bool checkUniqueness(ListG list, string name)
163 	{
164 		return gst_object_check_uniqueness((list is null) ? null : list.getListGStruct(), Str.toStringz(name)) != 0;
165 	}
166 
167 	/**
168 	 * A default deep_notify signal callback for an object. The user data
169 	 * should contain a pointer to an array of strings that should be excluded
170 	 * from the notify. The default handler will print the new value of the property
171 	 * using g_print.
172 	 *
173 	 * MT safe. This function grabs and releases @object's LOCK for getting its
174 	 * path string.
175 	 *
176 	 * Params:
177 	 *     object = the #GObject that signalled the notify.
178 	 *     orig = a #GstObject that initiated the notify.
179 	 *     pspec = a #GParamSpec of the property.
180 	 *     excludedProps = a set of user-specified properties to exclude or %NULL to show
181 	 *         all changes.
182 	 */
183 	public static void defaultDeepNotify(ObjectG object, ObjectGst orig, ParamSpec pspec, string[] excludedProps)
184 	{
185 		gst_object_default_deep_notify((object is null) ? null : object.getObjectGStruct(), (orig is null) ? null : orig.getObjectGstStruct(), (pspec is null) ? null : pspec.getParamSpecStruct(), Str.toStringzArray(excludedProps));
186 	}
187 
188 	/**
189 	 * Increase the reference count of @object, and possibly remove the floating
190 	 * reference, if @object has a floating reference.
191 	 *
192 	 * In other words, if the object is floating, then this call "assumes ownership"
193 	 * of the floating reference, converting it to a normal reference by clearing
194 	 * the floating flag while leaving the reference count unchanged. If the object
195 	 * is not floating, then this call adds a new normal reference increasing the
196 	 * reference count by one.
197 	 *
198 	 * Params:
199 	 *     object = a #GstObject to sink
200 	 */
201 	public static void* refSink(void* object)
202 	{
203 		return gst_object_ref_sink(object);
204 	}
205 
206 	/**
207 	 * Atomically modifies a pointer to point to a new object.
208 	 * The reference count of @oldobj is decreased and the reference count of
209 	 * @newobj is increased.
210 	 *
211 	 * Either @newobj and the value pointed to by @oldobj may be %NULL.
212 	 *
213 	 * Params:
214 	 *     oldobj = pointer to a place of
215 	 *         a #GstObject to replace
216 	 *     newobj = a new #GstObject
217 	 *
218 	 * Return: %TRUE if @newobj was different from @oldobj
219 	 */
220 	public static bool replace(ref ObjectGst oldobj, ObjectGst newobj)
221 	{
222 		GstObject* outoldobj = oldobj.getObjectGstStruct();
223 		
224 		auto p = gst_object_replace(&outoldobj, (newobj is null) ? null : newobj.getObjectGstStruct()) != 0;
225 		
226 		oldobj = ObjectG.getDObject!(ObjectGst)(outoldobj);
227 		
228 		return p;
229 	}
230 
231 	/**
232 	 * Attach the #GstControlBinding to the object. If there already was a
233 	 * #GstControlBinding for this property it will be replaced.
234 	 *
235 	 * The @object will take ownership of the @binding.
236 	 *
237 	 * Params:
238 	 *     binding = the #GstControlBinding that should be used
239 	 *
240 	 * Return: %FALSE if the given @binding has not been setup for this object or
241 	 *     has been setup for a non suitable property, %TRUE otherwise.
242 	 */
243 	public bool addControlBinding(ControlBinding binding)
244 	{
245 		return gst_object_add_control_binding(gstObject, (binding is null) ? null : binding.getControlBindingStruct()) != 0;
246 	}
247 
248 	/**
249 	 * A default error function that uses g_printerr() to display the error message
250 	 * and the optional debug sting..
251 	 *
252 	 * The default handler will simply print the error string using g_print.
253 	 *
254 	 * Params:
255 	 *     error = the GError.
256 	 *     dbg = an additional debug information string, or %NULL
257 	 */
258 	public void defaultError(ErrorG error, string dbg)
259 	{
260 		gst_object_default_error(gstObject, (error is null) ? null : error.getErrorGStruct(), Str.toStringz(dbg));
261 	}
262 
263 	/**
264 	 * Gets the corresponding #GstControlBinding for the property. This should be
265 	 * unreferenced again after use.
266 	 *
267 	 * Params:
268 	 *     propertyName = name of the property
269 	 *
270 	 * Return: the #GstControlBinding for
271 	 *     @property_name or %NULL if the property is not controlled.
272 	 */
273 	public ControlBinding getControlBinding(string propertyName)
274 	{
275 		auto p = gst_object_get_control_binding(gstObject, Str.toStringz(propertyName));
276 		
277 		if(p is null)
278 		{
279 			return null;
280 		}
281 		
282 		return ObjectG.getDObject!(ControlBinding)(cast(GstControlBinding*) p, true);
283 	}
284 
285 	/**
286 	 * Obtain the control-rate for this @object. Audio processing #GstElement
287 	 * objects will use this rate to sub-divide their processing loop and call
288 	 * gst_object_sync_values() inbetween. The length of the processing segment
289 	 * should be up to @control-rate nanoseconds.
290 	 *
291 	 * If the @object is not under property control, this will return
292 	 * %GST_CLOCK_TIME_NONE. This allows the element to avoid the sub-dividing.
293 	 *
294 	 * The control-rate is not expected to change if the element is in
295 	 * %GST_STATE_PAUSED or %GST_STATE_PLAYING.
296 	 *
297 	 * Return: the control rate in nanoseconds
298 	 */
299 	public GstClockTime getControlRate()
300 	{
301 		return gst_object_get_control_rate(gstObject);
302 	}
303 
304 	/**
305 	 * Gets a number of #GValues for the given controlled property starting at the
306 	 * requested time. The array @values need to hold enough space for @n_values of
307 	 * #GValue.
308 	 *
309 	 * This function is useful if one wants to e.g. draw a graph of the control
310 	 * curve or apply a control curve sample by sample.
311 	 *
312 	 * Params:
313 	 *     propertyName = the name of the property to get
314 	 *     timestamp = the time that should be processed
315 	 *     interval = the time spacing between subsequent values
316 	 *     nValues = the number of values
317 	 *     values = array to put control-values in
318 	 *
319 	 * Return: %TRUE if the given array could be filled, %FALSE otherwise
320 	 */
321 	public bool getGValueArray(string propertyName, GstClockTime timestamp, GstClockTime interval, uint nValues, Value values)
322 	{
323 		return gst_object_get_g_value_array(gstObject, Str.toStringz(propertyName), timestamp, interval, nValues, (values is null) ? null : values.getValueStruct()) != 0;
324 	}
325 
326 	/**
327 	 * Returns a copy of the name of @object.
328 	 * Caller should g_free() the return value after usage.
329 	 * For a nameless object, this returns %NULL, which you can safely g_free()
330 	 * as well.
331 	 *
332 	 * Free-function: g_free
333 	 *
334 	 * Return: the name of @object. g_free()
335 	 *     after usage.
336 	 *
337 	 *     MT safe. This function grabs and releases @object's LOCK.
338 	 */
339 	public string getName()
340 	{
341 		auto retStr = gst_object_get_name(gstObject);
342 		
343 		scope(exit) Str.freeString(retStr);
344 		return Str.toString(retStr);
345 	}
346 
347 	/**
348 	 * Returns the parent of @object. This function increases the refcount
349 	 * of the parent object so you should gst_object_unref() it after usage.
350 	 *
351 	 * Return: parent of @object, this can be
352 	 *     %NULL if @object has no parent. unref after usage.
353 	 *
354 	 *     MT safe. Grabs and releases @object's LOCK.
355 	 */
356 	public ObjectGst getParent()
357 	{
358 		auto p = gst_object_get_parent(gstObject);
359 		
360 		if(p is null)
361 		{
362 			return null;
363 		}
364 		
365 		return ObjectG.getDObject!(ObjectGst)(cast(GstObject*) p, true);
366 	}
367 
368 	/**
369 	 * Generates a string describing the path of @object in
370 	 * the object hierarchy. Only useful (or used) for debugging.
371 	 *
372 	 * Free-function: g_free
373 	 *
374 	 * Return: a string describing the path of @object. You must
375 	 *     g_free() the string after usage.
376 	 *
377 	 *     MT safe. Grabs and releases the #GstObject's LOCK for all objects
378 	 *     in the hierarchy.
379 	 */
380 	public string getPathString()
381 	{
382 		auto retStr = gst_object_get_path_string(gstObject);
383 		
384 		scope(exit) Str.freeString(retStr);
385 		return Str.toString(retStr);
386 	}
387 
388 	/**
389 	 * Gets the value for the given controlled property at the requested time.
390 	 *
391 	 * Params:
392 	 *     propertyName = the name of the property to get
393 	 *     timestamp = the time the control-change should be read from
394 	 *
395 	 * Return: the GValue of the property at the given time,
396 	 *     or %NULL if the property isn't controlled.
397 	 */
398 	public Value getValue(string propertyName, GstClockTime timestamp)
399 	{
400 		auto p = gst_object_get_value(gstObject, Str.toStringz(propertyName), timestamp);
401 		
402 		if(p is null)
403 		{
404 			return null;
405 		}
406 		
407 		return ObjectG.getDObject!(Value)(cast(GValue*) p, true);
408 	}
409 
410 	/**
411 	 * Gets a number of values for the given controlled property starting at the
412 	 * requested time. The array @values need to hold enough space for @n_values of
413 	 * the same type as the objects property's type.
414 	 *
415 	 * This function is useful if one wants to e.g. draw a graph of the control
416 	 * curve or apply a control curve sample by sample.
417 	 *
418 	 * The values are unboxed and ready to be used. The similar function
419 	 * gst_object_get_g_value_array() returns the array as #GValues and is
420 	 * better suites for bindings.
421 	 *
422 	 * Params:
423 	 *     propertyName = the name of the property to get
424 	 *     timestamp = the time that should be processed
425 	 *     interval = the time spacing between subsequent values
426 	 *     nValues = the number of values
427 	 *     values = array to put control-values in
428 	 *
429 	 * Return: %TRUE if the given array could be filled, %FALSE otherwise
430 	 */
431 	public bool getValueArray(string propertyName, GstClockTime timestamp, GstClockTime interval, uint nValues, void* values)
432 	{
433 		return gst_object_get_value_array(gstObject, Str.toStringz(propertyName), timestamp, interval, nValues, values) != 0;
434 	}
435 
436 	/**
437 	 * Check if the @object has active controlled properties.
438 	 *
439 	 * Return: %TRUE if the object has active controlled properties
440 	 */
441 	public bool hasActiveControlBindings()
442 	{
443 		return gst_object_has_active_control_bindings(gstObject) != 0;
444 	}
445 
446 	/**
447 	 * Check if @object has an ancestor @ancestor somewhere up in
448 	 * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline.
449 	 *
450 	 * Deprecated: Use gst_object_has_as_ancestor() instead.
451 	 *
452 	 * MT safe. Grabs and releases @object's locks.
453 	 *
454 	 * Params:
455 	 *     ancestor = a #GstObject to check as ancestor
456 	 *
457 	 * Return: %TRUE if @ancestor is an ancestor of @object.
458 	 */
459 	public bool hasAncestor(ObjectGst ancestor)
460 	{
461 		return gst_object_has_ancestor(gstObject, (ancestor is null) ? null : ancestor.getObjectGstStruct()) != 0;
462 	}
463 
464 	/**
465 	 * Check if @object has an ancestor @ancestor somewhere up in
466 	 * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline.
467 	 *
468 	 * Params:
469 	 *     ancestor = a #GstObject to check as ancestor
470 	 *
471 	 * Return: %TRUE if @ancestor is an ancestor of @object.
472 	 *
473 	 *     MT safe. Grabs and releases @object's locks.
474 	 */
475 	public bool hasAsAncestor(ObjectGst ancestor)
476 	{
477 		return gst_object_has_as_ancestor(gstObject, (ancestor is null) ? null : ancestor.getObjectGstStruct()) != 0;
478 	}
479 
480 	/**
481 	 * Check if @parent is the parent of @object.
482 	 * E.g. a #GstElement can check if it owns a given #GstPad.
483 	 *
484 	 * Params:
485 	 *     parent = a #GstObject to check as parent
486 	 *
487 	 * Return: %FALSE if either @object or @parent is %NULL. %TRUE if @parent is
488 	 *     the parent of @object. Otherwise %FALSE.
489 	 *
490 	 *     MT safe. Grabs and releases @object's locks.
491 	 *
492 	 * Since: 1.6
493 	 */
494 	public bool hasAsParent(ObjectGst parent)
495 	{
496 		return gst_object_has_as_parent(gstObject, (parent is null) ? null : parent.getObjectGstStruct()) != 0;
497 	}
498 
499 	/**
500 	 * Increments the reference count on @object. This function
501 	 * does not take the lock on @object because it relies on
502 	 * atomic refcounting.
503 	 *
504 	 * This object returns the input parameter to ease writing
505 	 * constructs like :
506 	 * result = gst_object_ref (object->parent);
507 	 *
508 	 * Return: A pointer to @object
509 	 */
510 	public override ObjectGst doref()
511 	{
512 		auto p = gst_object_ref(gstObject);
513 		
514 		if(p is null)
515 		{
516 			return null;
517 		}
518 		
519 		return ObjectG.getDObject!(ObjectGst)(cast(GstObject*) p, true);
520 	}
521 
522 	/**
523 	 * Removes the corresponding #GstControlBinding. If it was the
524 	 * last ref of the binding, it will be disposed.
525 	 *
526 	 * Params:
527 	 *     binding = the binding
528 	 *
529 	 * Return: %TRUE if the binding could be removed.
530 	 */
531 	public bool removeControlBinding(ControlBinding binding)
532 	{
533 		return gst_object_remove_control_binding(gstObject, (binding is null) ? null : binding.getControlBindingStruct()) != 0;
534 	}
535 
536 	/**
537 	 * This function is used to disable the control bindings on a property for
538 	 * some time, i.e. gst_object_sync_values() will do nothing for the
539 	 * property.
540 	 *
541 	 * Params:
542 	 *     propertyName = property to disable
543 	 *     disabled = boolean that specifies whether to disable the controller
544 	 *         or not.
545 	 */
546 	public void setControlBindingDisabled(string propertyName, bool disabled)
547 	{
548 		gst_object_set_control_binding_disabled(gstObject, Str.toStringz(propertyName), disabled);
549 	}
550 
551 	/**
552 	 * This function is used to disable all controlled properties of the @object for
553 	 * some time, i.e. gst_object_sync_values() will do nothing.
554 	 *
555 	 * Params:
556 	 *     disabled = boolean that specifies whether to disable the controller
557 	 *         or not.
558 	 */
559 	public void setControlBindingsDisabled(bool disabled)
560 	{
561 		gst_object_set_control_bindings_disabled(gstObject, disabled);
562 	}
563 
564 	/**
565 	 * Change the control-rate for this @object. Audio processing #GstElement
566 	 * objects will use this rate to sub-divide their processing loop and call
567 	 * gst_object_sync_values() inbetween. The length of the processing segment
568 	 * should be up to @control-rate nanoseconds.
569 	 *
570 	 * The control-rate should not change if the element is in %GST_STATE_PAUSED or
571 	 * %GST_STATE_PLAYING.
572 	 *
573 	 * Params:
574 	 *     controlRate = the new control-rate in nanoseconds.
575 	 */
576 	public void setControlRate(GstClockTime controlRate)
577 	{
578 		gst_object_set_control_rate(gstObject, controlRate);
579 	}
580 
581 	/**
582 	 * Sets the name of @object, or gives @object a guaranteed unique
583 	 * name (if @name is %NULL).
584 	 * This function makes a copy of the provided name, so the caller
585 	 * retains ownership of the name it sent.
586 	 *
587 	 * Params:
588 	 *     name = new name of object
589 	 *
590 	 * Return: %TRUE if the name could be set. Since Objects that have
591 	 *     a parent cannot be renamed, this function returns %FALSE in those
592 	 *     cases.
593 	 *
594 	 *     MT safe.  This function grabs and releases @object's LOCK.
595 	 */
596 	public bool setName(string name)
597 	{
598 		return gst_object_set_name(gstObject, Str.toStringz(name)) != 0;
599 	}
600 
601 	/**
602 	 * Sets the parent of @object to @parent. The object's reference count will
603 	 * be incremented, and any floating reference will be removed (see gst_object_ref_sink()).
604 	 *
605 	 * Params:
606 	 *     parent = new parent of object
607 	 *
608 	 * Return: %TRUE if @parent could be set or %FALSE when @object
609 	 *     already had a parent or @object and @parent are the same.
610 	 *
611 	 *     MT safe. Grabs and releases @object's LOCK.
612 	 */
613 	public bool setParent(ObjectGst parent)
614 	{
615 		return gst_object_set_parent(gstObject, (parent is null) ? null : parent.getObjectGstStruct()) != 0;
616 	}
617 
618 	/**
619 	 * Returns a suggestion for timestamps where buffers should be split
620 	 * to get best controller results.
621 	 *
622 	 * Return: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE
623 	 *     if no control-rate was set.
624 	 */
625 	public GstClockTime suggestNextSync()
626 	{
627 		return gst_object_suggest_next_sync(gstObject);
628 	}
629 
630 	/**
631 	 * Sets the properties of the object, according to the #GstControlSources that
632 	 * (maybe) handle them and for the given timestamp.
633 	 *
634 	 * If this function fails, it is most likely the application developers fault.
635 	 * Most probably the control sources are not setup correctly.
636 	 *
637 	 * Params:
638 	 *     timestamp = the time that should be processed
639 	 *
640 	 * Return: %TRUE if the controller values could be applied to the object
641 	 *     properties, %FALSE otherwise
642 	 */
643 	public bool syncValues(GstClockTime timestamp)
644 	{
645 		return gst_object_sync_values(gstObject, timestamp) != 0;
646 	}
647 
648 	/**
649 	 * Clear the parent of @object, removing the associated reference.
650 	 * This function decreases the refcount of @object.
651 	 *
652 	 * MT safe. Grabs and releases @object's lock.
653 	 */
654 	public void unparent()
655 	{
656 		gst_object_unparent(gstObject);
657 	}
658 
659 	/**
660 	 * Decrements the reference count on @object.  If reference count hits
661 	 * zero, destroy @object. This function does not take the lock
662 	 * on @object as it relies on atomic refcounting.
663 	 *
664 	 * The unref method should never be called with the LOCK held since
665 	 * this might deadlock the dispose function.
666 	 */
667 	public override void unref()
668 	{
669 		gst_object_unref(gstObject);
670 	}
671 
672 	protected class OnDeepNotifyDelegateWrapper
673 	{
674 		void delegate(ObjectGst, ParamSpec, ObjectGst) dlg;
675 		gulong handlerId;
676 		ConnectFlags flags;
677 		this(void delegate(ObjectGst, ParamSpec, ObjectGst) dlg, gulong handlerId, ConnectFlags flags)
678 		{
679 			this.dlg = dlg;
680 			this.handlerId = handlerId;
681 			this.flags = flags;
682 		}
683 	}
684 	protected OnDeepNotifyDelegateWrapper[] onDeepNotifyListeners;
685 
686 	/**
687 	 * The deep notify signal is used to be notified of property changes. It is
688 	 * typically attached to the toplevel bin to receive notifications from all
689 	 * the elements contained in that bin.
690 	 *
691 	 * Params:
692 	 *     propObject = the object that originated the signal
693 	 *     prop = the property that changed
694 	 */
695 	gulong addOnDeepNotify(void delegate(ObjectGst, ParamSpec, ObjectGst) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
696 	{
697 		onDeepNotifyListeners ~= new OnDeepNotifyDelegateWrapper(dlg, 0, connectFlags);
698 		onDeepNotifyListeners[onDeepNotifyListeners.length - 1].handlerId = Signals.connectData(
699 			this,
700 			"deep-notify",
701 			cast(GCallback)&callBackDeepNotify,
702 			cast(void*)onDeepNotifyListeners[onDeepNotifyListeners.length - 1],
703 			cast(GClosureNotify)&callBackDeepNotifyDestroy,
704 			connectFlags);
705 		return onDeepNotifyListeners[onDeepNotifyListeners.length - 1].handlerId;
706 	}
707 	
708 	extern(C) static void callBackDeepNotify(GstObject* objectgstStruct, GstObject* propObject, GParamSpec* prop,OnDeepNotifyDelegateWrapper wrapper)
709 	{
710 		wrapper.dlg(ObjectG.getDObject!(ObjectGst)(propObject), ObjectG.getDObject!(ParamSpec)(prop), wrapper.outer);
711 	}
712 	
713 	extern(C) static void callBackDeepNotifyDestroy(OnDeepNotifyDelegateWrapper wrapper, GClosure* closure)
714 	{
715 		wrapper.outer.internalRemoveOnDeepNotify(wrapper);
716 	}
717 
718 	protected void internalRemoveOnDeepNotify(OnDeepNotifyDelegateWrapper source)
719 	{
720 		foreach(index, wrapper; onDeepNotifyListeners)
721 		{
722 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
723 			{
724 				onDeepNotifyListeners[index] = null;
725 				onDeepNotifyListeners = std.algorithm.remove(onDeepNotifyListeners, index);
726 				break;
727 			}
728 		}
729 	}
730 	
731 }