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