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