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