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