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.Bin; 26 27 private import glib.ConstructionException; 28 private import glib.Str; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gstreamer.ChildProxyIF; 32 private import gstreamer.ChildProxyT; 33 private import gstreamer.Element; 34 private import gstreamer.Iterator; 35 private import gstreamer.Pad; 36 private import gstreamer.c.functions; 37 public import gstreamer.c.types; 38 public import gstreamerc.gstreamertypes; 39 private import std.algorithm; 40 41 42 /** 43 * #GstBin is an element that can contain other #GstElement, allowing them to be 44 * managed as a group. 45 * Pads from the child elements can be ghosted to the bin, see #GstGhostPad. 46 * This makes the bin look like any other elements and enables creation of 47 * higher-level abstraction elements. 48 * 49 * A new #GstBin is created with gst_bin_new(). Use a #GstPipeline instead if you 50 * want to create a toplevel bin because a normal bin doesn't have a bus or 51 * handle clock distribution of its own. 52 * 53 * After the bin has been created you will typically add elements to it with 54 * gst_bin_add(). You can remove elements with gst_bin_remove(). 55 * 56 * An element can be retrieved from a bin with gst_bin_get_by_name(), using the 57 * elements name. gst_bin_get_by_name_recurse_up() is mainly used for internal 58 * purposes and will query the parent bins when the element is not found in the 59 * current bin. 60 * 61 * An iterator of elements in a bin can be retrieved with 62 * gst_bin_iterate_elements(). Various other iterators exist to retrieve the 63 * elements in a bin. 64 * 65 * gst_object_unref() is used to drop your reference to the bin. 66 * 67 * The #GstBin::element-added signal is fired whenever a new element is added to 68 * the bin. Likewise the #GstBin::element-removed signal is fired whenever an 69 * element is removed from the bin. 70 * 71 * ## Notes 72 * 73 * A #GstBin internally intercepts every #GstMessage posted by its children and 74 * implements the following default behaviour for each of them: 75 * 76 * * GST_MESSAGE_EOS: This message is only posted by sinks in the PLAYING 77 * state. If all sinks posted the EOS message, this bin will post and EOS 78 * message upwards. 79 * 80 * * GST_MESSAGE_SEGMENT_START: Just collected and never forwarded upwards. 81 * The messages are used to decide when all elements have completed playback 82 * of their segment. 83 * 84 * * GST_MESSAGE_SEGMENT_DONE: Is posted by #GstBin when all elements that posted 85 * a SEGMENT_START have posted a SEGMENT_DONE. 86 * 87 * * GST_MESSAGE_DURATION_CHANGED: Is posted by an element that detected a change 88 * in the stream duration. The default bin behaviour is to clear any 89 * cached duration values so that the next duration query will perform 90 * a full duration recalculation. The duration change is posted to the 91 * application so that it can refetch the new duration with a duration 92 * query. Note that these messages can be posted before the bin is 93 * prerolled, in which case the duration query might fail. 94 * 95 * * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it 96 * can no longer provide a clock. The default bin behaviour is to 97 * check if the lost clock was the one provided by the bin. If so and 98 * the bin is currently in the PLAYING state, the message is forwarded to 99 * the bin parent. 100 * This message is also generated when a clock provider is removed from 101 * the bin. If this message is received by the application, it should 102 * PAUSE the pipeline and set it back to PLAYING to force a new clock 103 * distribution. 104 * 105 * * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element 106 * can provide a clock. This mostly happens when a new clock 107 * provider is added to the bin. The default behaviour of the bin is to 108 * mark the currently selected clock as dirty, which will perform a clock 109 * recalculation the next time the bin is asked to provide a clock. 110 * This message is never sent tot the application but is forwarded to 111 * the parent of the bin. 112 * 113 * * OTHERS: posted upwards. 114 * 115 * A #GstBin implements the following default behaviour for answering to a 116 * #GstQuery: 117 * 118 * * GST_QUERY_DURATION:If the query has been asked before with the same format 119 * and the bin is a toplevel bin (ie. has no parent), 120 * use the cached previous value. If no previous value was cached, the 121 * query is sent to all sink elements in the bin and the MAXIMUM of all 122 * values is returned. If the bin is a toplevel bin the value is cached. 123 * If no sinks are available in the bin, the query fails. 124 * 125 * * GST_QUERY_POSITION:The query is sent to all sink elements in the bin and the 126 * MAXIMUM of all values is returned. If no sinks are available in the bin, 127 * the query fails. 128 * 129 * * OTHERS:the query is forwarded to all sink elements, the result 130 * of the first sink that answers the query successfully is returned. If no 131 * sink is in the bin, the query fails. 132 * 133 * A #GstBin will by default forward any event sent to it to all sink 134 * (#GST_EVENT_TYPE_DOWNSTREAM) or source (#GST_EVENT_TYPE_UPSTREAM) elements 135 * depending on the event type. 136 * If all the elements return %TRUE, the bin will also return %TRUE, else %FALSE 137 * is returned. If no elements of the required type are in the bin, the event 138 * handler will return %TRUE. 139 */ 140 public class Bin : Element, ChildProxyIF 141 { 142 /** the main Gtk struct */ 143 protected GstBin* gstBin; 144 145 /** Get the main Gtk struct */ 146 public GstBin* getBinStruct(bool transferOwnership = false) 147 { 148 if (transferOwnership) 149 ownedRef = false; 150 return gstBin; 151 } 152 153 /** the main Gtk struct as a void* */ 154 protected override void* getStruct() 155 { 156 return cast(void*)gstBin; 157 } 158 159 /** 160 * Sets our main struct and passes it to the parent class. 161 */ 162 public this (GstBin* gstBin, bool ownedRef = false) 163 { 164 this.gstBin = gstBin; 165 super(cast(GstElement*)gstBin, ownedRef); 166 } 167 168 // add the ChildProxy capabilities 169 mixin ChildProxyT!(GstBin); 170 171 /** */ 172 public this(Element elem) 173 { 174 super( elem.getElementStruct(), true ); 175 this.gstBin = cast(GstBin*)elem.getElementStruct(); 176 } 177 178 /** 179 * Adds a list of elements to a bin. 180 * This function is equivalent to calling add() for each member of the list. 181 * The return value of each add() is ignored. 182 */ 183 public void addMany( Element[] elems... ) 184 { 185 foreach( e; elems ) add( e ); 186 } 187 188 /** 189 * Remove a list of elements from a bin. 190 * This function is equivalent to calling remove() with each member of the list. 191 */ 192 public void removeMany( Element[] elems... ) 193 { 194 foreach( e; elems ) remove( e ); 195 } 196 197 /** 198 */ 199 200 /** */ 201 public static GType getType() 202 { 203 return gst_bin_get_type(); 204 } 205 206 /** 207 * Creates a new bin with the given name. 208 * 209 * Params: 210 * name = the name of the new bin 211 * 212 * Returns: a new #GstBin 213 * 214 * Throws: ConstructionException GTK+ fails to create the object. 215 */ 216 public this(string name) 217 { 218 auto p = gst_bin_new(Str.toStringz(name)); 219 220 if(p is null) 221 { 222 throw new ConstructionException("null returned by new"); 223 } 224 225 this(cast(GstBin*) p); 226 } 227 228 /** 229 * Adds the given element to the bin. Sets the element's parent, and thus 230 * takes ownership of the element. An element can only be added to one bin. 231 * 232 * If the element's pads are linked to other pads, the pads will be unlinked 233 * before the element is added to the bin. 234 * 235 * > When you add an element to an already-running pipeline, you will have to 236 * > take care to set the state of the newly-added element to the desired 237 * > state (usually PLAYING or PAUSED, same you set the pipeline to originally) 238 * > with gst_element_set_state(), or use gst_element_sync_state_with_parent(). 239 * > The bin or pipeline will not take care of this for you. 240 * 241 * MT safe. 242 * 243 * Params: 244 * element = the #GstElement to add 245 * 246 * Returns: %TRUE if the element could be added, %FALSE if 247 * the bin does not want to accept the element. 248 */ 249 public bool add(Element element) 250 { 251 return gst_bin_add(gstBin, (element is null) ? null : element.getElementStruct()) != 0; 252 } 253 254 /** 255 * Recursively looks for elements with an unlinked pad of the given 256 * direction within the specified bin and returns an unlinked pad 257 * if one is found, or %NULL otherwise. If a pad is found, the caller 258 * owns a reference to it and should use gst_object_unref() on the 259 * pad when it is not needed any longer. 260 * 261 * Params: 262 * direction = whether to look for an unlinked source or sink pad 263 * 264 * Returns: unlinked pad of the given 265 * direction, %NULL. 266 */ 267 public Pad findUnlinkedPad(GstPadDirection direction) 268 { 269 auto p = gst_bin_find_unlinked_pad(gstBin, direction); 270 271 if(p is null) 272 { 273 return null; 274 } 275 276 return ObjectG.getDObject!(Pad)(cast(GstPad*) p, true); 277 } 278 279 /** 280 * Looks for an element inside the bin that implements the given 281 * interface. If such an element is found, it returns the element. 282 * You can cast this element to the given interface afterwards. If you want 283 * all elements that implement the interface, use 284 * gst_bin_iterate_all_by_interface(). This function recurses into child bins. 285 * 286 * MT safe. Caller owns returned reference. 287 * 288 * Params: 289 * iface = the #GType of an interface 290 * 291 * Returns: A #GstElement inside the bin implementing the interface 292 */ 293 public Element getByInterface(GType iface) 294 { 295 auto p = gst_bin_get_by_interface(gstBin, iface); 296 297 if(p is null) 298 { 299 return null; 300 } 301 302 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 303 } 304 305 /** 306 * Gets the element with the given name from a bin. This 307 * function recurses into child bins. 308 * 309 * Returns %NULL if no element with the given name is found in the bin. 310 * 311 * MT safe. Caller owns returned reference. 312 * 313 * Params: 314 * name = the element name to search for 315 * 316 * Returns: the #GstElement with the given 317 * name, or %NULL 318 */ 319 public Element getByName(string name) 320 { 321 auto p = gst_bin_get_by_name(gstBin, Str.toStringz(name)); 322 323 if(p is null) 324 { 325 return null; 326 } 327 328 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 329 } 330 331 /** 332 * Gets the element with the given name from this bin. If the 333 * element is not found, a recursion is performed on the parent bin. 334 * 335 * Returns %NULL if: 336 * - no element with the given name is found in the bin 337 * 338 * MT safe. Caller owns returned reference. 339 * 340 * Params: 341 * name = the element name to search for 342 * 343 * Returns: the #GstElement with the given 344 * name, or %NULL 345 */ 346 public Element getByNameRecurseUp(string name) 347 { 348 auto p = gst_bin_get_by_name_recurse_up(gstBin, Str.toStringz(name)); 349 350 if(p is null) 351 { 352 return null; 353 } 354 355 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 356 } 357 358 /** 359 * Return the suppressed flags of the bin. 360 * 361 * MT safe. 362 * 363 * Returns: the bin's suppressed #GstElementFlags. 364 * 365 * Since: 1.10 366 */ 367 public GstElementFlags getSuppressedFlags() 368 { 369 return gst_bin_get_suppressed_flags(gstBin); 370 } 371 372 /** 373 * Looks for all elements inside the bin that implements the given 374 * interface. You can safely cast all returned elements to the given interface. 375 * The function recurses inside child bins. The iterator will yield a series 376 * of #GstElement that should be unreffed after use. 377 * 378 * MT safe. Caller owns returned value. 379 * 380 * Params: 381 * iface = the #GType of an interface 382 * 383 * Returns: a #GstIterator of #GstElement 384 * for all elements in the bin implementing the given interface, 385 * or %NULL 386 */ 387 public Iterator iterateAllByInterface(GType iface) 388 { 389 auto p = gst_bin_iterate_all_by_interface(gstBin, iface); 390 391 if(p is null) 392 { 393 return null; 394 } 395 396 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 397 } 398 399 /** 400 * Gets an iterator for the elements in this bin. 401 * 402 * MT safe. Caller owns returned value. 403 * 404 * Returns: a #GstIterator of #GstElement, 405 * or %NULL 406 */ 407 public Iterator iterateElements() 408 { 409 auto p = gst_bin_iterate_elements(gstBin); 410 411 if(p is null) 412 { 413 return null; 414 } 415 416 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 417 } 418 419 /** 420 * Gets an iterator for the elements in this bin. 421 * This iterator recurses into GstBin children. 422 * 423 * MT safe. Caller owns returned value. 424 * 425 * Returns: a #GstIterator of #GstElement, 426 * or %NULL 427 */ 428 public Iterator iterateRecurse() 429 { 430 auto p = gst_bin_iterate_recurse(gstBin); 431 432 if(p is null) 433 { 434 return null; 435 } 436 437 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 438 } 439 440 /** 441 * Gets an iterator for all elements in the bin that have the 442 * #GST_ELEMENT_FLAG_SINK flag set. 443 * 444 * MT safe. Caller owns returned value. 445 * 446 * Returns: a #GstIterator of #GstElement, 447 * or %NULL 448 */ 449 public Iterator iterateSinks() 450 { 451 auto p = gst_bin_iterate_sinks(gstBin); 452 453 if(p is null) 454 { 455 return null; 456 } 457 458 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 459 } 460 461 /** 462 * Gets an iterator for the elements in this bin in topologically 463 * sorted order. This means that the elements are returned from 464 * the most downstream elements (sinks) to the sources. 465 * 466 * This function is used internally to perform the state changes 467 * of the bin elements and for clock selection. 468 * 469 * MT safe. Caller owns returned value. 470 * 471 * Returns: a #GstIterator of #GstElement, 472 * or %NULL 473 */ 474 public Iterator iterateSorted() 475 { 476 auto p = gst_bin_iterate_sorted(gstBin); 477 478 if(p is null) 479 { 480 return null; 481 } 482 483 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 484 } 485 486 /** 487 * Gets an iterator for all elements in the bin that have the 488 * #GST_ELEMENT_FLAG_SOURCE flag set. 489 * 490 * MT safe. Caller owns returned value. 491 * 492 * Returns: a #GstIterator of #GstElement, 493 * or %NULL 494 */ 495 public Iterator iterateSources() 496 { 497 auto p = gst_bin_iterate_sources(gstBin); 498 499 if(p is null) 500 { 501 return null; 502 } 503 504 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 505 } 506 507 /** 508 * Query @bin for the current latency using and reconfigures this latency to all the 509 * elements with a LATENCY event. 510 * 511 * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY 512 * is posted on the bus. 513 * 514 * This function simply emits the 'do-latency' signal so any custom latency 515 * calculations will be performed. 516 * 517 * Returns: %TRUE if the latency could be queried and reconfigured. 518 */ 519 public bool recalculateLatency() 520 { 521 return gst_bin_recalculate_latency(gstBin) != 0; 522 } 523 524 /** 525 * Removes the element from the bin, unparenting it as well. 526 * Unparenting the element means that the element will be dereferenced, 527 * so if the bin holds the only reference to the element, the element 528 * will be freed in the process of removing it from the bin. If you 529 * want the element to still exist after removing, you need to call 530 * gst_object_ref() before removing it from the bin. 531 * 532 * If the element's pads are linked to other pads, the pads will be unlinked 533 * before the element is removed from the bin. 534 * 535 * MT safe. 536 * 537 * Params: 538 * element = the #GstElement to remove 539 * 540 * Returns: %TRUE if the element could be removed, %FALSE if 541 * the bin does not want to remove the element. 542 */ 543 public bool remove(Element element) 544 { 545 return gst_bin_remove(gstBin, (element is null) ? null : element.getElementStruct()) != 0; 546 } 547 548 /** 549 * Suppress the given flags on the bin. #GstElementFlags of a 550 * child element are propagated when it is added to the bin. 551 * When suppressed flags are set, those specified flags will 552 * not be propagated to the bin. 553 * 554 * MT safe. 555 * 556 * Params: 557 * flags = the #GstElementFlags to suppress 558 * 559 * Since: 1.10 560 */ 561 public void setSuppressedFlags(GstElementFlags flags) 562 { 563 gst_bin_set_suppressed_flags(gstBin, flags); 564 } 565 566 /** 567 * Synchronizes the state of every child of @bin with the state 568 * of @bin. See also gst_element_sync_state_with_parent(). 569 * 570 * Returns: %TRUE if syncing the state was successful for all children, 571 * otherwise %FALSE. 572 * 573 * Since: 1.6 574 */ 575 public bool syncChildrenStates() 576 { 577 return gst_bin_sync_children_states(gstBin) != 0; 578 } 579 580 protected class OnDeepElementAddedDelegateWrapper 581 { 582 void delegate(Bin, Element, Bin) dlg; 583 gulong handlerId; 584 585 this(void delegate(Bin, Element, Bin) dlg) 586 { 587 this.dlg = dlg; 588 onDeepElementAddedListeners ~= this; 589 } 590 591 void remove(OnDeepElementAddedDelegateWrapper source) 592 { 593 foreach(index, wrapper; onDeepElementAddedListeners) 594 { 595 if (wrapper.handlerId == source.handlerId) 596 { 597 onDeepElementAddedListeners[index] = null; 598 onDeepElementAddedListeners = std.algorithm.remove(onDeepElementAddedListeners, index); 599 break; 600 } 601 } 602 } 603 } 604 OnDeepElementAddedDelegateWrapper[] onDeepElementAddedListeners; 605 606 /** 607 * Will be emitted after the element was added to sub_bin. 608 * 609 * Params: 610 * subBin = the #GstBin the element was added to 611 * element = the #GstElement that was added to @sub_bin 612 * 613 * Since: 1.10 614 */ 615 gulong addOnDeepElementAdded(void delegate(Bin, Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 616 { 617 auto wrapper = new OnDeepElementAddedDelegateWrapper(dlg); 618 wrapper.handlerId = Signals.connectData( 619 this, 620 "deep-element-added", 621 cast(GCallback)&callBackDeepElementAdded, 622 cast(void*)wrapper, 623 cast(GClosureNotify)&callBackDeepElementAddedDestroy, 624 connectFlags); 625 return wrapper.handlerId; 626 } 627 628 extern(C) static void callBackDeepElementAdded(GstBin* binStruct, GstBin* subBin, GstElement* element, OnDeepElementAddedDelegateWrapper wrapper) 629 { 630 wrapper.dlg(ObjectG.getDObject!(Bin)(subBin), ObjectG.getDObject!(Element)(element), wrapper.outer); 631 } 632 633 extern(C) static void callBackDeepElementAddedDestroy(OnDeepElementAddedDelegateWrapper wrapper, GClosure* closure) 634 { 635 wrapper.remove(wrapper); 636 } 637 638 protected class OnDeepElementRemovedDelegateWrapper 639 { 640 void delegate(Bin, Element, Bin) dlg; 641 gulong handlerId; 642 643 this(void delegate(Bin, Element, Bin) dlg) 644 { 645 this.dlg = dlg; 646 onDeepElementRemovedListeners ~= this; 647 } 648 649 void remove(OnDeepElementRemovedDelegateWrapper source) 650 { 651 foreach(index, wrapper; onDeepElementRemovedListeners) 652 { 653 if (wrapper.handlerId == source.handlerId) 654 { 655 onDeepElementRemovedListeners[index] = null; 656 onDeepElementRemovedListeners = std.algorithm.remove(onDeepElementRemovedListeners, index); 657 break; 658 } 659 } 660 } 661 } 662 OnDeepElementRemovedDelegateWrapper[] onDeepElementRemovedListeners; 663 664 /** 665 * Will be emitted after the element was removed from sub_bin. 666 * 667 * Params: 668 * subBin = the #GstBin the element was removed from 669 * element = the #GstElement that was removed from @sub_bin 670 * 671 * Since: 1.10 672 */ 673 gulong addOnDeepElementRemoved(void delegate(Bin, Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 674 { 675 auto wrapper = new OnDeepElementRemovedDelegateWrapper(dlg); 676 wrapper.handlerId = Signals.connectData( 677 this, 678 "deep-element-removed", 679 cast(GCallback)&callBackDeepElementRemoved, 680 cast(void*)wrapper, 681 cast(GClosureNotify)&callBackDeepElementRemovedDestroy, 682 connectFlags); 683 return wrapper.handlerId; 684 } 685 686 extern(C) static void callBackDeepElementRemoved(GstBin* binStruct, GstBin* subBin, GstElement* element, OnDeepElementRemovedDelegateWrapper wrapper) 687 { 688 wrapper.dlg(ObjectG.getDObject!(Bin)(subBin), ObjectG.getDObject!(Element)(element), wrapper.outer); 689 } 690 691 extern(C) static void callBackDeepElementRemovedDestroy(OnDeepElementRemovedDelegateWrapper wrapper, GClosure* closure) 692 { 693 wrapper.remove(wrapper); 694 } 695 696 protected class OnDoLatencyDelegateWrapper 697 { 698 bool delegate(Bin) dlg; 699 gulong handlerId; 700 701 this(bool delegate(Bin) dlg) 702 { 703 this.dlg = dlg; 704 onDoLatencyListeners ~= this; 705 } 706 707 void remove(OnDoLatencyDelegateWrapper source) 708 { 709 foreach(index, wrapper; onDoLatencyListeners) 710 { 711 if (wrapper.handlerId == source.handlerId) 712 { 713 onDoLatencyListeners[index] = null; 714 onDoLatencyListeners = std.algorithm.remove(onDoLatencyListeners, index); 715 break; 716 } 717 } 718 } 719 } 720 OnDoLatencyDelegateWrapper[] onDoLatencyListeners; 721 722 /** 723 * Will be emitted when the bin needs to perform latency calculations. This 724 * signal is only emitted for toplevel bins or when async-handling is 725 * enabled. 726 * 727 * Only one signal handler is invoked. If no signals are connected, the 728 * default handler is invoked, which will query and distribute the lowest 729 * possible latency to all sinks. 730 * 731 * Connect to this signal if the default latency calculations are not 732 * sufficient, like when you need different latencies for different sinks in 733 * the same pipeline. 734 */ 735 gulong addOnDoLatency(bool delegate(Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 736 { 737 auto wrapper = new OnDoLatencyDelegateWrapper(dlg); 738 wrapper.handlerId = Signals.connectData( 739 this, 740 "do-latency", 741 cast(GCallback)&callBackDoLatency, 742 cast(void*)wrapper, 743 cast(GClosureNotify)&callBackDoLatencyDestroy, 744 connectFlags); 745 return wrapper.handlerId; 746 } 747 748 extern(C) static int callBackDoLatency(GstBin* binStruct, OnDoLatencyDelegateWrapper wrapper) 749 { 750 return wrapper.dlg(wrapper.outer); 751 } 752 753 extern(C) static void callBackDoLatencyDestroy(OnDoLatencyDelegateWrapper wrapper, GClosure* closure) 754 { 755 wrapper.remove(wrapper); 756 } 757 758 protected class OnElementAddedDelegateWrapper 759 { 760 void delegate(Element, Bin) dlg; 761 gulong handlerId; 762 763 this(void delegate(Element, Bin) dlg) 764 { 765 this.dlg = dlg; 766 onElementAddedListeners ~= this; 767 } 768 769 void remove(OnElementAddedDelegateWrapper source) 770 { 771 foreach(index, wrapper; onElementAddedListeners) 772 { 773 if (wrapper.handlerId == source.handlerId) 774 { 775 onElementAddedListeners[index] = null; 776 onElementAddedListeners = std.algorithm.remove(onElementAddedListeners, index); 777 break; 778 } 779 } 780 } 781 } 782 OnElementAddedDelegateWrapper[] onElementAddedListeners; 783 784 /** 785 * Will be emitted after the element was added to the bin. 786 * 787 * Params: 788 * element = the #GstElement that was added to the bin 789 */ 790 gulong addOnElementAdded(void delegate(Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 791 { 792 auto wrapper = new OnElementAddedDelegateWrapper(dlg); 793 wrapper.handlerId = Signals.connectData( 794 this, 795 "element-added", 796 cast(GCallback)&callBackElementAdded, 797 cast(void*)wrapper, 798 cast(GClosureNotify)&callBackElementAddedDestroy, 799 connectFlags); 800 return wrapper.handlerId; 801 } 802 803 extern(C) static void callBackElementAdded(GstBin* binStruct, GstElement* element, OnElementAddedDelegateWrapper wrapper) 804 { 805 wrapper.dlg(ObjectG.getDObject!(Element)(element), wrapper.outer); 806 } 807 808 extern(C) static void callBackElementAddedDestroy(OnElementAddedDelegateWrapper wrapper, GClosure* closure) 809 { 810 wrapper.remove(wrapper); 811 } 812 813 protected class OnElementRemovedDelegateWrapper 814 { 815 void delegate(Element, Bin) dlg; 816 gulong handlerId; 817 818 this(void delegate(Element, Bin) dlg) 819 { 820 this.dlg = dlg; 821 onElementRemovedListeners ~= this; 822 } 823 824 void remove(OnElementRemovedDelegateWrapper source) 825 { 826 foreach(index, wrapper; onElementRemovedListeners) 827 { 828 if (wrapper.handlerId == source.handlerId) 829 { 830 onElementRemovedListeners[index] = null; 831 onElementRemovedListeners = std.algorithm.remove(onElementRemovedListeners, index); 832 break; 833 } 834 } 835 } 836 } 837 OnElementRemovedDelegateWrapper[] onElementRemovedListeners; 838 839 /** 840 * Will be emitted after the element was removed from the bin. 841 * 842 * Params: 843 * element = the #GstElement that was removed from the bin 844 */ 845 gulong addOnElementRemoved(void delegate(Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 846 { 847 auto wrapper = new OnElementRemovedDelegateWrapper(dlg); 848 wrapper.handlerId = Signals.connectData( 849 this, 850 "element-removed", 851 cast(GCallback)&callBackElementRemoved, 852 cast(void*)wrapper, 853 cast(GClosureNotify)&callBackElementRemovedDestroy, 854 connectFlags); 855 return wrapper.handlerId; 856 } 857 858 extern(C) static void callBackElementRemoved(GstBin* binStruct, GstElement* element, OnElementRemovedDelegateWrapper wrapper) 859 { 860 wrapper.dlg(ObjectG.getDObject!(Element)(element), wrapper.outer); 861 } 862 863 extern(C) static void callBackElementRemovedDestroy(OnElementRemovedDelegateWrapper wrapper, GClosure* closure) 864 { 865 wrapper.remove(wrapper); 866 } 867 }