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 protected override void setStruct(GObject* obj) 160 { 161 gstBin = cast(GstBin*)obj; 162 super.setStruct(obj); 163 } 164 165 /** 166 * Sets our main struct and passes it to the parent class. 167 */ 168 public this (GstBin* gstBin, bool ownedRef = false) 169 { 170 this.gstBin = gstBin; 171 super(cast(GstElement*)gstBin, ownedRef); 172 } 173 174 // add the ChildProxy capabilities 175 mixin ChildProxyT!(GstBin); 176 177 /** */ 178 public this(Element elem) 179 { 180 super( elem.getElementStruct(), true ); 181 this.gstBin = cast(GstBin*)elem.getElementStruct(); 182 } 183 184 /** 185 * Adds a list of elements to a bin. 186 * This function is equivalent to calling add() for each member of the list. 187 * The return value of each add() is ignored. 188 */ 189 public void addMany( Element[] elems... ) 190 { 191 foreach( e; elems ) add( e ); 192 } 193 194 /** 195 * Remove a list of elements from a bin. 196 * This function is equivalent to calling remove() with each member of the list. 197 */ 198 public void removeMany( Element[] elems... ) 199 { 200 foreach( e; elems ) remove( e ); 201 } 202 203 /** 204 */ 205 206 /** */ 207 public static GType getType() 208 { 209 return gst_bin_get_type(); 210 } 211 212 /** 213 * Creates a new bin with the given name. 214 * 215 * Params: 216 * name = the name of the new bin 217 * 218 * Returns: a new #GstBin 219 * 220 * Throws: ConstructionException GTK+ fails to create the object. 221 */ 222 public this(string name) 223 { 224 auto p = gst_bin_new(Str.toStringz(name)); 225 226 if(p is null) 227 { 228 throw new ConstructionException("null returned by new"); 229 } 230 231 this(cast(GstBin*) p); 232 } 233 234 /** 235 * Adds the given element to the bin. Sets the element's parent, and thus 236 * takes ownership of the element. An element can only be added to one bin. 237 * 238 * If the element's pads are linked to other pads, the pads will be unlinked 239 * before the element is added to the bin. 240 * 241 * > When you add an element to an already-running pipeline, you will have to 242 * > take care to set the state of the newly-added element to the desired 243 * > state (usually PLAYING or PAUSED, same you set the pipeline to originally) 244 * > with gst_element_set_state(), or use gst_element_sync_state_with_parent(). 245 * > The bin or pipeline will not take care of this for you. 246 * 247 * MT safe. 248 * 249 * Params: 250 * element = the #GstElement to add 251 * 252 * Returns: %TRUE if the element could be added, %FALSE if 253 * the bin does not want to accept the element. 254 */ 255 public bool add(Element element) 256 { 257 return gst_bin_add(gstBin, (element is null) ? null : element.getElementStruct()) != 0; 258 } 259 260 /** 261 * Recursively looks for elements with an unlinked pad of the given 262 * direction within the specified bin and returns an unlinked pad 263 * if one is found, or %NULL otherwise. If a pad is found, the caller 264 * owns a reference to it and should use gst_object_unref() on the 265 * pad when it is not needed any longer. 266 * 267 * Params: 268 * direction = whether to look for an unlinked source or sink pad 269 * 270 * Returns: unlinked pad of the given 271 * direction, %NULL. 272 */ 273 public Pad findUnlinkedPad(GstPadDirection direction) 274 { 275 auto p = gst_bin_find_unlinked_pad(gstBin, direction); 276 277 if(p is null) 278 { 279 return null; 280 } 281 282 return ObjectG.getDObject!(Pad)(cast(GstPad*) p, true); 283 } 284 285 /** 286 * Looks for an element inside the bin that implements the given 287 * interface. If such an element is found, it returns the element. 288 * You can cast this element to the given interface afterwards. If you want 289 * all elements that implement the interface, use 290 * gst_bin_iterate_all_by_interface(). This function recurses into child bins. 291 * 292 * MT safe. Caller owns returned reference. 293 * 294 * Params: 295 * iface = the #GType of an interface 296 * 297 * Returns: A #GstElement inside the bin implementing the interface 298 */ 299 public Element getByInterface(GType iface) 300 { 301 auto p = gst_bin_get_by_interface(gstBin, iface); 302 303 if(p is null) 304 { 305 return null; 306 } 307 308 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 309 } 310 311 /** 312 * Gets the element with the given name from a bin. This 313 * function recurses into child bins. 314 * 315 * Returns %NULL if no element with the given name is found in the bin. 316 * 317 * MT safe. Caller owns returned reference. 318 * 319 * Params: 320 * name = the element name to search for 321 * 322 * Returns: the #GstElement with the given 323 * name, or %NULL 324 */ 325 public Element getByName(string name) 326 { 327 auto p = gst_bin_get_by_name(gstBin, Str.toStringz(name)); 328 329 if(p is null) 330 { 331 return null; 332 } 333 334 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 335 } 336 337 /** 338 * Gets the element with the given name from this bin. If the 339 * element is not found, a recursion is performed on the parent bin. 340 * 341 * Returns %NULL if: 342 * - no element with the given name is found in the bin 343 * 344 * MT safe. Caller owns returned reference. 345 * 346 * Params: 347 * name = the element name to search for 348 * 349 * Returns: the #GstElement with the given 350 * name, or %NULL 351 */ 352 public Element getByNameRecurseUp(string name) 353 { 354 auto p = gst_bin_get_by_name_recurse_up(gstBin, Str.toStringz(name)); 355 356 if(p is null) 357 { 358 return null; 359 } 360 361 return ObjectG.getDObject!(Element)(cast(GstElement*) p, true); 362 } 363 364 /** 365 * Return the suppressed flags of the bin. 366 * 367 * MT safe. 368 * 369 * Returns: the bin's suppressed #GstElementFlags. 370 * 371 * Since: 1.10 372 */ 373 public GstElementFlags getSuppressedFlags() 374 { 375 return gst_bin_get_suppressed_flags(gstBin); 376 } 377 378 /** 379 * Looks for all elements inside the bin that implements the given 380 * interface. You can safely cast all returned elements to the given interface. 381 * The function recurses inside child bins. The iterator will yield a series 382 * of #GstElement that should be unreffed after use. 383 * 384 * MT safe. Caller owns returned value. 385 * 386 * Params: 387 * iface = the #GType of an interface 388 * 389 * Returns: a #GstIterator of #GstElement 390 * for all elements in the bin implementing the given interface, 391 * or %NULL 392 */ 393 public Iterator iterateAllByInterface(GType iface) 394 { 395 auto p = gst_bin_iterate_all_by_interface(gstBin, iface); 396 397 if(p is null) 398 { 399 return null; 400 } 401 402 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 403 } 404 405 /** 406 * Gets an iterator for the elements in this bin. 407 * 408 * MT safe. Caller owns returned value. 409 * 410 * Returns: a #GstIterator of #GstElement, 411 * or %NULL 412 */ 413 public Iterator iterateElements() 414 { 415 auto p = gst_bin_iterate_elements(gstBin); 416 417 if(p is null) 418 { 419 return null; 420 } 421 422 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 423 } 424 425 /** 426 * Gets an iterator for the elements in this bin. 427 * This iterator recurses into GstBin children. 428 * 429 * MT safe. Caller owns returned value. 430 * 431 * Returns: a #GstIterator of #GstElement, 432 * or %NULL 433 */ 434 public Iterator iterateRecurse() 435 { 436 auto p = gst_bin_iterate_recurse(gstBin); 437 438 if(p is null) 439 { 440 return null; 441 } 442 443 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 444 } 445 446 /** 447 * Gets an iterator for all elements in the bin that have the 448 * #GST_ELEMENT_FLAG_SINK flag set. 449 * 450 * MT safe. Caller owns returned value. 451 * 452 * Returns: a #GstIterator of #GstElement, 453 * or %NULL 454 */ 455 public Iterator iterateSinks() 456 { 457 auto p = gst_bin_iterate_sinks(gstBin); 458 459 if(p is null) 460 { 461 return null; 462 } 463 464 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 465 } 466 467 /** 468 * Gets an iterator for the elements in this bin in topologically 469 * sorted order. This means that the elements are returned from 470 * the most downstream elements (sinks) to the sources. 471 * 472 * This function is used internally to perform the state changes 473 * of the bin elements and for clock selection. 474 * 475 * MT safe. Caller owns returned value. 476 * 477 * Returns: a #GstIterator of #GstElement, 478 * or %NULL 479 */ 480 public Iterator iterateSorted() 481 { 482 auto p = gst_bin_iterate_sorted(gstBin); 483 484 if(p is null) 485 { 486 return null; 487 } 488 489 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 490 } 491 492 /** 493 * Gets an iterator for all elements in the bin that have the 494 * #GST_ELEMENT_FLAG_SOURCE flag set. 495 * 496 * MT safe. Caller owns returned value. 497 * 498 * Returns: a #GstIterator of #GstElement, 499 * or %NULL 500 */ 501 public Iterator iterateSources() 502 { 503 auto p = gst_bin_iterate_sources(gstBin); 504 505 if(p is null) 506 { 507 return null; 508 } 509 510 return ObjectG.getDObject!(Iterator)(cast(GstIterator*) p, true); 511 } 512 513 /** 514 * Query @bin for the current latency using and reconfigures this latency to all the 515 * elements with a LATENCY event. 516 * 517 * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY 518 * is posted on the bus. 519 * 520 * This function simply emits the 'do-latency' signal so any custom latency 521 * calculations will be performed. 522 * 523 * Returns: %TRUE if the latency could be queried and reconfigured. 524 */ 525 public bool recalculateLatency() 526 { 527 return gst_bin_recalculate_latency(gstBin) != 0; 528 } 529 530 /** 531 * Removes the element from the bin, unparenting it as well. 532 * Unparenting the element means that the element will be dereferenced, 533 * so if the bin holds the only reference to the element, the element 534 * will be freed in the process of removing it from the bin. If you 535 * want the element to still exist after removing, you need to call 536 * gst_object_ref() before removing it from the bin. 537 * 538 * If the element's pads are linked to other pads, the pads will be unlinked 539 * before the element is removed from the bin. 540 * 541 * MT safe. 542 * 543 * Params: 544 * element = the #GstElement to remove 545 * 546 * Returns: %TRUE if the element could be removed, %FALSE if 547 * the bin does not want to remove the element. 548 */ 549 public bool remove(Element element) 550 { 551 return gst_bin_remove(gstBin, (element is null) ? null : element.getElementStruct()) != 0; 552 } 553 554 /** 555 * Suppress the given flags on the bin. #GstElementFlags of a 556 * child element are propagated when it is added to the bin. 557 * When suppressed flags are set, those specified flags will 558 * not be propagated to the bin. 559 * 560 * MT safe. 561 * 562 * Params: 563 * flags = the #GstElementFlags to suppress 564 * 565 * Since: 1.10 566 */ 567 public void setSuppressedFlags(GstElementFlags flags) 568 { 569 gst_bin_set_suppressed_flags(gstBin, flags); 570 } 571 572 /** 573 * Synchronizes the state of every child of @bin with the state 574 * of @bin. See also gst_element_sync_state_with_parent(). 575 * 576 * Returns: %TRUE if syncing the state was successful for all children, 577 * otherwise %FALSE. 578 * 579 * Since: 1.6 580 */ 581 public bool syncChildrenStates() 582 { 583 return gst_bin_sync_children_states(gstBin) != 0; 584 } 585 586 protected class OnDeepElementAddedDelegateWrapper 587 { 588 void delegate(Bin, Element, Bin) dlg; 589 gulong handlerId; 590 591 this(void delegate(Bin, Element, Bin) dlg) 592 { 593 this.dlg = dlg; 594 onDeepElementAddedListeners ~= this; 595 } 596 597 void remove(OnDeepElementAddedDelegateWrapper source) 598 { 599 foreach(index, wrapper; onDeepElementAddedListeners) 600 { 601 if (wrapper.handlerId == source.handlerId) 602 { 603 onDeepElementAddedListeners[index] = null; 604 onDeepElementAddedListeners = std.algorithm.remove(onDeepElementAddedListeners, index); 605 break; 606 } 607 } 608 } 609 } 610 OnDeepElementAddedDelegateWrapper[] onDeepElementAddedListeners; 611 612 /** 613 * Will be emitted after the element was added to sub_bin. 614 * 615 * Params: 616 * subBin = the #GstBin the element was added to 617 * element = the #GstElement that was added to @sub_bin 618 * 619 * Since: 1.10 620 */ 621 gulong addOnDeepElementAdded(void delegate(Bin, Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 622 { 623 auto wrapper = new OnDeepElementAddedDelegateWrapper(dlg); 624 wrapper.handlerId = Signals.connectData( 625 this, 626 "deep-element-added", 627 cast(GCallback)&callBackDeepElementAdded, 628 cast(void*)wrapper, 629 cast(GClosureNotify)&callBackDeepElementAddedDestroy, 630 connectFlags); 631 return wrapper.handlerId; 632 } 633 634 extern(C) static void callBackDeepElementAdded(GstBin* binStruct, GstBin* subBin, GstElement* element, OnDeepElementAddedDelegateWrapper wrapper) 635 { 636 wrapper.dlg(ObjectG.getDObject!(Bin)(subBin), ObjectG.getDObject!(Element)(element), wrapper.outer); 637 } 638 639 extern(C) static void callBackDeepElementAddedDestroy(OnDeepElementAddedDelegateWrapper wrapper, GClosure* closure) 640 { 641 wrapper.remove(wrapper); 642 } 643 644 protected class OnDeepElementRemovedDelegateWrapper 645 { 646 void delegate(Bin, Element, Bin) dlg; 647 gulong handlerId; 648 649 this(void delegate(Bin, Element, Bin) dlg) 650 { 651 this.dlg = dlg; 652 onDeepElementRemovedListeners ~= this; 653 } 654 655 void remove(OnDeepElementRemovedDelegateWrapper source) 656 { 657 foreach(index, wrapper; onDeepElementRemovedListeners) 658 { 659 if (wrapper.handlerId == source.handlerId) 660 { 661 onDeepElementRemovedListeners[index] = null; 662 onDeepElementRemovedListeners = std.algorithm.remove(onDeepElementRemovedListeners, index); 663 break; 664 } 665 } 666 } 667 } 668 OnDeepElementRemovedDelegateWrapper[] onDeepElementRemovedListeners; 669 670 /** 671 * Will be emitted after the element was removed from sub_bin. 672 * 673 * Params: 674 * subBin = the #GstBin the element was removed from 675 * element = the #GstElement that was removed from @sub_bin 676 * 677 * Since: 1.10 678 */ 679 gulong addOnDeepElementRemoved(void delegate(Bin, Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 680 { 681 auto wrapper = new OnDeepElementRemovedDelegateWrapper(dlg); 682 wrapper.handlerId = Signals.connectData( 683 this, 684 "deep-element-removed", 685 cast(GCallback)&callBackDeepElementRemoved, 686 cast(void*)wrapper, 687 cast(GClosureNotify)&callBackDeepElementRemovedDestroy, 688 connectFlags); 689 return wrapper.handlerId; 690 } 691 692 extern(C) static void callBackDeepElementRemoved(GstBin* binStruct, GstBin* subBin, GstElement* element, OnDeepElementRemovedDelegateWrapper wrapper) 693 { 694 wrapper.dlg(ObjectG.getDObject!(Bin)(subBin), ObjectG.getDObject!(Element)(element), wrapper.outer); 695 } 696 697 extern(C) static void callBackDeepElementRemovedDestroy(OnDeepElementRemovedDelegateWrapper wrapper, GClosure* closure) 698 { 699 wrapper.remove(wrapper); 700 } 701 702 protected class OnDoLatencyDelegateWrapper 703 { 704 bool delegate(Bin) dlg; 705 gulong handlerId; 706 707 this(bool delegate(Bin) dlg) 708 { 709 this.dlg = dlg; 710 onDoLatencyListeners ~= this; 711 } 712 713 void remove(OnDoLatencyDelegateWrapper source) 714 { 715 foreach(index, wrapper; onDoLatencyListeners) 716 { 717 if (wrapper.handlerId == source.handlerId) 718 { 719 onDoLatencyListeners[index] = null; 720 onDoLatencyListeners = std.algorithm.remove(onDoLatencyListeners, index); 721 break; 722 } 723 } 724 } 725 } 726 OnDoLatencyDelegateWrapper[] onDoLatencyListeners; 727 728 /** 729 * Will be emitted when the bin needs to perform latency calculations. This 730 * signal is only emitted for toplevel bins or when async-handling is 731 * enabled. 732 * 733 * Only one signal handler is invoked. If no signals are connected, the 734 * default handler is invoked, which will query and distribute the lowest 735 * possible latency to all sinks. 736 * 737 * Connect to this signal if the default latency calculations are not 738 * sufficient, like when you need different latencies for different sinks in 739 * the same pipeline. 740 */ 741 gulong addOnDoLatency(bool delegate(Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 742 { 743 auto wrapper = new OnDoLatencyDelegateWrapper(dlg); 744 wrapper.handlerId = Signals.connectData( 745 this, 746 "do-latency", 747 cast(GCallback)&callBackDoLatency, 748 cast(void*)wrapper, 749 cast(GClosureNotify)&callBackDoLatencyDestroy, 750 connectFlags); 751 return wrapper.handlerId; 752 } 753 754 extern(C) static int callBackDoLatency(GstBin* binStruct, OnDoLatencyDelegateWrapper wrapper) 755 { 756 return wrapper.dlg(wrapper.outer); 757 } 758 759 extern(C) static void callBackDoLatencyDestroy(OnDoLatencyDelegateWrapper wrapper, GClosure* closure) 760 { 761 wrapper.remove(wrapper); 762 } 763 764 protected class OnElementAddedDelegateWrapper 765 { 766 void delegate(Element, Bin) dlg; 767 gulong handlerId; 768 769 this(void delegate(Element, Bin) dlg) 770 { 771 this.dlg = dlg; 772 onElementAddedListeners ~= this; 773 } 774 775 void remove(OnElementAddedDelegateWrapper source) 776 { 777 foreach(index, wrapper; onElementAddedListeners) 778 { 779 if (wrapper.handlerId == source.handlerId) 780 { 781 onElementAddedListeners[index] = null; 782 onElementAddedListeners = std.algorithm.remove(onElementAddedListeners, index); 783 break; 784 } 785 } 786 } 787 } 788 OnElementAddedDelegateWrapper[] onElementAddedListeners; 789 790 /** 791 * Will be emitted after the element was added to the bin. 792 * 793 * Params: 794 * element = the #GstElement that was added to the bin 795 */ 796 gulong addOnElementAdded(void delegate(Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 797 { 798 auto wrapper = new OnElementAddedDelegateWrapper(dlg); 799 wrapper.handlerId = Signals.connectData( 800 this, 801 "element-added", 802 cast(GCallback)&callBackElementAdded, 803 cast(void*)wrapper, 804 cast(GClosureNotify)&callBackElementAddedDestroy, 805 connectFlags); 806 return wrapper.handlerId; 807 } 808 809 extern(C) static void callBackElementAdded(GstBin* binStruct, GstElement* element, OnElementAddedDelegateWrapper wrapper) 810 { 811 wrapper.dlg(ObjectG.getDObject!(Element)(element), wrapper.outer); 812 } 813 814 extern(C) static void callBackElementAddedDestroy(OnElementAddedDelegateWrapper wrapper, GClosure* closure) 815 { 816 wrapper.remove(wrapper); 817 } 818 819 protected class OnElementRemovedDelegateWrapper 820 { 821 void delegate(Element, Bin) dlg; 822 gulong handlerId; 823 824 this(void delegate(Element, Bin) dlg) 825 { 826 this.dlg = dlg; 827 onElementRemovedListeners ~= this; 828 } 829 830 void remove(OnElementRemovedDelegateWrapper source) 831 { 832 foreach(index, wrapper; onElementRemovedListeners) 833 { 834 if (wrapper.handlerId == source.handlerId) 835 { 836 onElementRemovedListeners[index] = null; 837 onElementRemovedListeners = std.algorithm.remove(onElementRemovedListeners, index); 838 break; 839 } 840 } 841 } 842 } 843 OnElementRemovedDelegateWrapper[] onElementRemovedListeners; 844 845 /** 846 * Will be emitted after the element was removed from the bin. 847 * 848 * Params: 849 * element = the #GstElement that was removed from the bin 850 */ 851 gulong addOnElementRemoved(void delegate(Element, Bin) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 852 { 853 auto wrapper = new OnElementRemovedDelegateWrapper(dlg); 854 wrapper.handlerId = Signals.connectData( 855 this, 856 "element-removed", 857 cast(GCallback)&callBackElementRemoved, 858 cast(void*)wrapper, 859 cast(GClosureNotify)&callBackElementRemovedDestroy, 860 connectFlags); 861 return wrapper.handlerId; 862 } 863 864 extern(C) static void callBackElementRemoved(GstBin* binStruct, GstElement* element, OnElementRemovedDelegateWrapper wrapper) 865 { 866 wrapper.dlg(ObjectG.getDObject!(Element)(element), wrapper.outer); 867 } 868 869 extern(C) static void callBackElementRemovedDestroy(OnElementRemovedDelegateWrapper wrapper, GClosure* closure) 870 { 871 wrapper.remove(wrapper); 872 } 873 }