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.Bus; 26 27 private import glib.ConstructionException; 28 private import glib.Source; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gstreamer.Message; 32 private import gstreamer.ObjectGst; 33 private import gstreamerc.gstreamer; 34 public import gstreamerc.gstreamertypes; 35 private import std.algorithm; 36 37 38 /** 39 * The #GstBus is an object responsible for delivering #GstMessage packets in 40 * a first-in first-out way from the streaming threads (see #GstTask) to the 41 * application. 42 * 43 * Since the application typically only wants to deal with delivery of these 44 * messages from one thread, the GstBus will marshall the messages between 45 * different threads. This is important since the actual streaming of media 46 * is done in another thread than the application. 47 * 48 * The GstBus provides support for #GSource based notifications. This makes it 49 * possible to handle the delivery in the glib mainloop. 50 * 51 * The #GSource callback function gst_bus_async_signal_func() can be used to 52 * convert all bus messages into signal emissions. 53 * 54 * A message is posted on the bus with the gst_bus_post() method. With the 55 * gst_bus_peek() and gst_bus_pop() methods one can look at or retrieve a 56 * previously posted message. 57 * 58 * The bus can be polled with the gst_bus_poll() method. This methods blocks 59 * up to the specified timeout value until one of the specified messages types 60 * is posted on the bus. The application can then gst_bus_pop() the messages 61 * from the bus to handle them. 62 * Alternatively the application can register an asynchronous bus function 63 * using gst_bus_add_watch_full() or gst_bus_add_watch(). This function will 64 * install a #GSource in the default glib main loop and will deliver messages 65 * a short while after they have been posted. Note that the main loop should 66 * be running for the asynchronous callbacks. 67 * 68 * It is also possible to get messages from the bus without any thread 69 * marshalling with the gst_bus_set_sync_handler() method. This makes it 70 * possible to react to a message in the same thread that posted the 71 * message on the bus. This should only be used if the application is able 72 * to deal with messages from different threads. 73 * 74 * Every #GstPipeline has one bus. 75 * 76 * Note that a #GstPipeline will set its bus into flushing state when changing 77 * from READY to NULL state. 78 */ 79 public class Bus : ObjectGst 80 { 81 /** the main Gtk struct */ 82 protected GstBus* gstBus; 83 84 /** Get the main Gtk struct */ 85 public GstBus* getBusStruct(bool transferOwnership = false) 86 { 87 if (transferOwnership) 88 ownedRef = false; 89 return gstBus; 90 } 91 92 /** the main Gtk struct as a void* */ 93 protected override void* getStruct() 94 { 95 return cast(void*)gstBus; 96 } 97 98 protected override void setStruct(GObject* obj) 99 { 100 gstBus = cast(GstBus*)obj; 101 super.setStruct(obj); 102 } 103 104 /** 105 * Sets our main struct and passes it to the parent class. 106 */ 107 public this (GstBus* gstBus, bool ownedRef = false) 108 { 109 this.gstBus = gstBus; 110 super(cast(GstObject*)gstBus, ownedRef); 111 } 112 113 /** 114 * Adds a bus watch to the default main context with the default priority. 115 * This function is used to receive asynchronous messages in the main loop. 116 * The watch can be removed using g_source_remove() or by returning FALSE 117 * from func. 118 * MT safe. 119 * Params: 120 * dlg = A function to call when a message is received. 121 * Returns: 122 * The event source id. 123 */ 124 public uint addWatch( bool delegate(Message) dlg ) 125 { 126 onWatchListener = dlg; 127 return gst_bus_add_watch(gstBus, cast(GstBusFunc)&watchCallBack, cast(void*)this); 128 } 129 130 bool delegate(Message) onWatchListener; 131 132 extern(C) static int watchCallBack(GstBus* bus, GstMessage* msg, Bus bus_d )//gpointer data) 133 { 134 Message msg_d = new Message( msg ); 135 136 return bus_d.onWatchListener( msg_d ); 137 } 138 139 /** 140 * Use this for making an XOverlay. 141 * Sets the synchronous handler on the bus. The function will be called 142 * every time a new message is posted on the bus. Note that the function 143 * will be called in the same thread context as the posting object. This 144 * function is usually only called by the creator of the bus. Applications 145 * should handle messages asynchronously using the gst_bus watch and poll 146 * functions. 147 * You cannot replace an existing sync_handler. You can pass NULL to this 148 * function, which will clear the existing handler. 149 * Params: 150 * dlg = The handler function to install 151 */ 152 public void setSyncHandler( GstBusSyncReply delegate(Message) dlg ) 153 { 154 onSyncHandlerListener = dlg; 155 gst_bus_set_sync_handler(gstBus, cast(GstBusSyncHandler)&syncHandlerCallBack, cast(void*)this, null); 156 } 157 158 GstBusSyncReply delegate(Message) onSyncHandlerListener; 159 160 extern(C) static GstBusSyncReply syncHandlerCallBack(GstBus* bus, GstMessage* msg, Bus bus_d) 161 { 162 Message msg_d = new Message( msg ); 163 164 return bus_d.onSyncHandlerListener( msg_d ); 165 } 166 167 /** 168 */ 169 170 /** */ 171 public static GType getType() 172 { 173 return gst_bus_get_type(); 174 } 175 176 /** 177 * Creates a new #GstBus instance. 178 * 179 * Returns: a new #GstBus instance 180 * 181 * Throws: ConstructionException GTK+ fails to create the object. 182 */ 183 public this() 184 { 185 auto p = gst_bus_new(); 186 187 if(p is null) 188 { 189 throw new ConstructionException("null returned by new"); 190 } 191 192 this(cast(GstBus*) p, true); 193 } 194 195 /** 196 * Adds a bus signal watch to the default main context with the default priority 197 * (%G_PRIORITY_DEFAULT). It is also possible to use a non-default 198 * main context set up using g_main_context_push_thread_default() (before 199 * one had to create a bus watch source and attach it to the desired main 200 * context 'manually'). 201 * 202 * After calling this statement, the bus will emit the "message" signal for each 203 * message posted on the bus. 204 * 205 * This function may be called multiple times. To clean up, the caller is 206 * responsible for calling gst_bus_remove_signal_watch() as many times as this 207 * function is called. 208 * 209 * MT safe. 210 */ 211 public void addSignalWatch() 212 { 213 gst_bus_add_signal_watch(gstBus); 214 } 215 216 /** 217 * Adds a bus signal watch to the default main context with the given @priority 218 * (e.g. %G_PRIORITY_DEFAULT). It is also possible to use a non-default main 219 * context set up using g_main_context_push_thread_default() 220 * (before one had to create a bus watch source and attach it to the desired 221 * main context 'manually'). 222 * 223 * After calling this statement, the bus will emit the "message" signal for each 224 * message posted on the bus when the main loop is running. 225 * 226 * This function may be called multiple times. To clean up, the caller is 227 * responsible for calling gst_bus_remove_signal_watch() as many times as this 228 * function is called. 229 * 230 * There can only be a single bus watch per bus, you must remove any signal 231 * watch before you can set another type of watch. 232 * 233 * MT safe. 234 * 235 * Params: 236 * priority = The priority of the watch. 237 */ 238 public void addSignalWatchFull(int priority) 239 { 240 gst_bus_add_signal_watch_full(gstBus, priority); 241 } 242 243 /** 244 * Adds a bus watch to the default main context with the given @priority (e.g. 245 * %G_PRIORITY_DEFAULT). It is also possible to use a non-default main 246 * context set up using g_main_context_push_thread_default() (before 247 * one had to create a bus watch source and attach it to the desired main 248 * context 'manually'). 249 * 250 * This function is used to receive asynchronous messages in the main loop. 251 * There can only be a single bus watch per bus, you must remove it before you 252 * can set a new one. 253 * 254 * The bus watch will only work if a GLib main loop is being run. 255 * 256 * When @func is called, the message belongs to the caller; if you want to 257 * keep a copy of it, call gst_message_ref() before leaving @func. 258 * 259 * The watch can be removed using gst_bus_remove_watch() or by returning %FALSE 260 * from @func. If the watch was added to the default main context it is also 261 * possible to remove the watch using g_source_remove(). 262 * 263 * MT safe. 264 * 265 * Params: 266 * priority = The priority of the watch. 267 * func = A function to call when a message is received. 268 * userData = user data passed to @func. 269 * notify = the function to call when the source is removed. 270 * 271 * Returns: The event source id or 0 if @bus already got an event source. 272 */ 273 public uint addWatchFull(int priority, GstBusFunc func, void* userData, GDestroyNotify notify) 274 { 275 return gst_bus_add_watch_full(gstBus, priority, func, userData, notify); 276 } 277 278 /** 279 * A helper #GstBusFunc that can be used to convert all asynchronous messages 280 * into signals. 281 * 282 * Params: 283 * message = the #GstMessage received 284 * data = user data 285 * 286 * Returns: %TRUE 287 */ 288 public bool asyncSignalFunc(Message message, void* data) 289 { 290 return gst_bus_async_signal_func(gstBus, (message is null) ? null : message.getMessageStruct(), data) != 0; 291 } 292 293 /** 294 * Create watch for this bus. The GSource will be dispatched whenever 295 * a message is on the bus. After the GSource is dispatched, the 296 * message is popped off the bus and unreffed. 297 * 298 * Returns: a #GSource that can be added to a mainloop. 299 */ 300 public Source createWatch() 301 { 302 auto p = gst_bus_create_watch(gstBus); 303 304 if(p is null) 305 { 306 return null; 307 } 308 309 return new Source(cast(GSource*) p, true); 310 } 311 312 /** 313 * Instructs GStreamer to stop emitting the "sync-message" signal for this bus. 314 * See gst_bus_enable_sync_message_emission() for more information. 315 * 316 * In the event that multiple pieces of code have called 317 * gst_bus_enable_sync_message_emission(), the sync-message emissions will only 318 * be stopped after all calls to gst_bus_enable_sync_message_emission() were 319 * "cancelled" by calling this function. In this way the semantics are exactly 320 * the same as gst_object_ref() that which calls enable should also call 321 * disable. 322 * 323 * MT safe. 324 */ 325 public void disableSyncMessageEmission() 326 { 327 gst_bus_disable_sync_message_emission(gstBus); 328 } 329 330 /** 331 * Instructs GStreamer to emit the "sync-message" signal after running the bus's 332 * sync handler. This function is here so that code can ensure that they can 333 * synchronously receive messages without having to affect what the bin's sync 334 * handler is. 335 * 336 * This function may be called multiple times. To clean up, the caller is 337 * responsible for calling gst_bus_disable_sync_message_emission() as many times 338 * as this function is called. 339 * 340 * While this function looks similar to gst_bus_add_signal_watch(), it is not 341 * exactly the same -- this function enables <emphasis>synchronous</emphasis> emission of 342 * signals when messages arrive; gst_bus_add_signal_watch() adds an idle callback 343 * to pop messages off the bus <emphasis>asynchronously</emphasis>. The sync-message signal 344 * comes from the thread of whatever object posted the message; the "message" 345 * signal is marshalled to the main thread via the main loop. 346 * 347 * MT safe. 348 */ 349 public void enableSyncMessageEmission() 350 { 351 gst_bus_enable_sync_message_emission(gstBus); 352 } 353 354 /** 355 * Check if there are pending messages on the bus that 356 * should be handled. 357 * 358 * Returns: %TRUE if there are messages on the bus to be handled, %FALSE 359 * otherwise. 360 * 361 * MT safe. 362 */ 363 public bool havePending() 364 { 365 return gst_bus_have_pending(gstBus) != 0; 366 } 367 368 /** 369 * Peek the message on the top of the bus' queue. The message will remain 370 * on the bus' message queue. A reference is returned, and needs to be unreffed 371 * by the caller. 372 * 373 * Returns: the #GstMessage that is on the 374 * bus, or %NULL if the bus is empty. 375 * 376 * MT safe. 377 */ 378 public Message peek() 379 { 380 auto p = gst_bus_peek(gstBus); 381 382 if(p is null) 383 { 384 return null; 385 } 386 387 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 388 } 389 390 /** 391 * Poll the bus for messages. Will block while waiting for messages to come. 392 * You can specify a maximum time to poll with the @timeout parameter. If 393 * @timeout is negative, this function will block indefinitely. 394 * 395 * All messages not in @events will be popped off the bus and will be ignored. 396 * It is not possible to use message enums beyond #GST_MESSAGE_EXTENDED in the 397 * @events mask 398 * 399 * Because poll is implemented using the "message" signal enabled by 400 * gst_bus_add_signal_watch(), calling gst_bus_poll() will cause the "message" 401 * signal to be emitted for every message that poll sees. Thus a "message" 402 * signal handler will see the same messages that this function sees -- neither 403 * will steal messages from the other. 404 * 405 * This function will run a main loop from the default main context when 406 * polling. 407 * 408 * You should never use this function, since it is pure evil. This is 409 * especially true for GUI applications based on Gtk+ or Qt, but also for any 410 * other non-trivial application that uses the GLib main loop. As this function 411 * runs a GLib main loop, any callback attached to the default GLib main 412 * context may be invoked. This could be timeouts, GUI events, I/O events etc.; 413 * even if gst_bus_poll() is called with a 0 timeout. Any of these callbacks 414 * may do things you do not expect, e.g. destroy the main application window or 415 * some other resource; change other application state; display a dialog and 416 * run another main loop until the user clicks it away. In short, using this 417 * function may add a lot of complexity to your code through unexpected 418 * re-entrancy and unexpected changes to your application's state. 419 * 420 * For 0 timeouts use gst_bus_pop_filtered() instead of this function; for 421 * other short timeouts use gst_bus_timed_pop_filtered(); everything else is 422 * better handled by setting up an asynchronous bus watch and doing things 423 * from there. 424 * 425 * Params: 426 * events = a mask of #GstMessageType, representing the set of message types to 427 * poll for (note special handling of extended message types below) 428 * timeout = the poll timeout, as a #GstClockTime, or #GST_CLOCK_TIME_NONE to poll 429 * indefinitely. 430 * 431 * Returns: the message that was received, 432 * or %NULL if the poll timed out. The message is taken from the 433 * bus and needs to be unreffed with gst_message_unref() after 434 * usage. 435 */ 436 public Message poll(GstMessageType events, GstClockTime timeout) 437 { 438 auto p = gst_bus_poll(gstBus, events, timeout); 439 440 if(p is null) 441 { 442 return null; 443 } 444 445 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 446 } 447 448 /** 449 * Get a message from the bus. 450 * 451 * Returns: the #GstMessage that is on the 452 * bus, or %NULL if the bus is empty. The message is taken from 453 * the bus and needs to be unreffed with gst_message_unref() after 454 * usage. 455 * 456 * MT safe. 457 */ 458 public Message pop() 459 { 460 auto p = gst_bus_pop(gstBus); 461 462 if(p is null) 463 { 464 return null; 465 } 466 467 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 468 } 469 470 /** 471 * Get a message matching @type from the bus. Will discard all messages on 472 * the bus that do not match @type and that have been posted before the first 473 * message that does match @type. If there is no message matching @type on 474 * the bus, all messages will be discarded. It is not possible to use message 475 * enums beyond #GST_MESSAGE_EXTENDED in the @events mask. 476 * 477 * Params: 478 * types = message types to take into account 479 * 480 * Returns: the next #GstMessage matching 481 * @type that is on the bus, or %NULL if the bus is empty or there 482 * is no message matching @type. The message is taken from the bus 483 * and needs to be unreffed with gst_message_unref() after usage. 484 * 485 * MT safe. 486 */ 487 public Message popFiltered(GstMessageType types) 488 { 489 auto p = gst_bus_pop_filtered(gstBus, types); 490 491 if(p is null) 492 { 493 return null; 494 } 495 496 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 497 } 498 499 /** 500 * Post a message on the given bus. Ownership of the message 501 * is taken by the bus. 502 * 503 * Params: 504 * message = the #GstMessage to post 505 * 506 * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing. 507 * 508 * MT safe. 509 */ 510 public bool post(Message message) 511 { 512 return gst_bus_post(gstBus, (message is null) ? null : message.getMessageStruct()) != 0; 513 } 514 515 /** 516 * Removes a signal watch previously added with gst_bus_add_signal_watch(). 517 * 518 * MT safe. 519 */ 520 public void removeSignalWatch() 521 { 522 gst_bus_remove_signal_watch(gstBus); 523 } 524 525 /** 526 * Removes an installed bus watch from @bus. 527 * 528 * Returns: %TRUE on success or %FALSE if @bus has no event source. 529 * 530 * Since: 1.6 531 */ 532 public bool removeWatch() 533 { 534 return gst_bus_remove_watch(gstBus) != 0; 535 } 536 537 /** 538 * If @flushing, flush out and unref any messages queued in the bus. Releases 539 * references to the message origin objects. Will flush future messages until 540 * gst_bus_set_flushing() sets @flushing to %FALSE. 541 * 542 * MT safe. 543 * 544 * Params: 545 * flushing = whether or not to flush the bus 546 */ 547 public void setFlushing(bool flushing) 548 { 549 gst_bus_set_flushing(gstBus, flushing); 550 } 551 552 /** 553 * A helper GstBusSyncHandler that can be used to convert all synchronous 554 * messages into signals. 555 * 556 * Params: 557 * message = the #GstMessage received 558 * data = user data 559 * 560 * Returns: GST_BUS_PASS 561 */ 562 public GstBusSyncReply syncSignalHandler(Message message, void* data) 563 { 564 return gst_bus_sync_signal_handler(gstBus, (message is null) ? null : message.getMessageStruct(), data); 565 } 566 567 /** 568 * Get a message from the bus, waiting up to the specified timeout. 569 * 570 * If @timeout is 0, this function behaves like gst_bus_pop(). If @timeout is 571 * #GST_CLOCK_TIME_NONE, this function will block forever until a message was 572 * posted on the bus. 573 * 574 * Params: 575 * timeout = a timeout 576 * 577 * Returns: the #GstMessage that is on the 578 * bus after the specified timeout or %NULL if the bus is empty 579 * after the timeout expired. The message is taken from the bus 580 * and needs to be unreffed with gst_message_unref() after usage. 581 * 582 * MT safe. 583 */ 584 public Message timedPop(GstClockTime timeout) 585 { 586 auto p = gst_bus_timed_pop(gstBus, timeout); 587 588 if(p is null) 589 { 590 return null; 591 } 592 593 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 594 } 595 596 /** 597 * Get a message from the bus whose type matches the message type mask @types, 598 * waiting up to the specified timeout (and discarding any messages that do not 599 * match the mask provided). 600 * 601 * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If 602 * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a 603 * matching message was posted on the bus. 604 * 605 * Params: 606 * timeout = a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever 607 * types = message types to take into account, GST_MESSAGE_ANY for any type 608 * 609 * Returns: a #GstMessage matching the 610 * filter in @types, or %NULL if no matching message was found on 611 * the bus until the timeout expired. The message is taken from 612 * the bus and needs to be unreffed with gst_message_unref() after 613 * usage. 614 * 615 * MT safe. 616 */ 617 public Message timedPopFiltered(GstClockTime timeout, GstMessageType types) 618 { 619 auto p = gst_bus_timed_pop_filtered(gstBus, timeout, types); 620 621 if(p is null) 622 { 623 return null; 624 } 625 626 return ObjectG.getDObject!(Message)(cast(GstMessage*) p, true); 627 } 628 629 protected class OnMessageDelegateWrapper 630 { 631 static OnMessageDelegateWrapper[] listeners; 632 void delegate(Message, Bus) dlg; 633 gulong handlerId; 634 635 this(void delegate(Message, Bus) dlg) 636 { 637 this.dlg = dlg; 638 this.listeners ~= this; 639 } 640 641 void remove(OnMessageDelegateWrapper source) 642 { 643 foreach(index, wrapper; listeners) 644 { 645 if (wrapper.handlerId == source.handlerId) 646 { 647 listeners[index] = null; 648 listeners = std.algorithm.remove(listeners, index); 649 break; 650 } 651 } 652 } 653 } 654 655 /** 656 * A message has been posted on the bus. This signal is emitted from a 657 * GSource added to the mainloop. this signal will only be emitted when 658 * there is a mainloop running. 659 * 660 * Params: 661 * message = the message that has been posted asynchronously 662 */ 663 gulong addOnMessage(void delegate(Message, Bus) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 664 { 665 auto wrapper = new OnMessageDelegateWrapper(dlg); 666 wrapper.handlerId = Signals.connectData( 667 this, 668 "message", 669 cast(GCallback)&callBackMessage, 670 cast(void*)wrapper, 671 cast(GClosureNotify)&callBackMessageDestroy, 672 connectFlags); 673 return wrapper.handlerId; 674 } 675 676 extern(C) static void callBackMessage(GstBus* busStruct, GstMessage* message, OnMessageDelegateWrapper wrapper) 677 { 678 wrapper.dlg(ObjectG.getDObject!(Message)(message), wrapper.outer); 679 } 680 681 extern(C) static void callBackMessageDestroy(OnMessageDelegateWrapper wrapper, GClosure* closure) 682 { 683 wrapper.remove(wrapper); 684 } 685 686 protected class OnSyncMessageDelegateWrapper 687 { 688 static OnSyncMessageDelegateWrapper[] listeners; 689 void delegate(Message, Bus) dlg; 690 gulong handlerId; 691 692 this(void delegate(Message, Bus) dlg) 693 { 694 this.dlg = dlg; 695 this.listeners ~= this; 696 } 697 698 void remove(OnSyncMessageDelegateWrapper source) 699 { 700 foreach(index, wrapper; listeners) 701 { 702 if (wrapper.handlerId == source.handlerId) 703 { 704 listeners[index] = null; 705 listeners = std.algorithm.remove(listeners, index); 706 break; 707 } 708 } 709 } 710 } 711 712 /** 713 * A message has been posted on the bus. This signal is emitted from the 714 * thread that posted the message so one has to be careful with locking. 715 * 716 * This signal will not be emitted by default, you have to call 717 * gst_bus_enable_sync_message_emission() before. 718 * 719 * Params: 720 * message = the message that has been posted synchronously 721 */ 722 gulong addOnSyncMessage(void delegate(Message, Bus) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 723 { 724 auto wrapper = new OnSyncMessageDelegateWrapper(dlg); 725 wrapper.handlerId = Signals.connectData( 726 this, 727 "sync-message", 728 cast(GCallback)&callBackSyncMessage, 729 cast(void*)wrapper, 730 cast(GClosureNotify)&callBackSyncMessageDestroy, 731 connectFlags); 732 return wrapper.handlerId; 733 } 734 735 extern(C) static void callBackSyncMessage(GstBus* busStruct, GstMessage* message, OnSyncMessageDelegateWrapper wrapper) 736 { 737 wrapper.dlg(ObjectG.getDObject!(Message)(message), wrapper.outer); 738 } 739 740 extern(C) static void callBackSyncMessageDestroy(OnSyncMessageDelegateWrapper wrapper, GClosure* closure) 741 { 742 wrapper.remove(wrapper); 743 } 744 }