| <chapter id="chapter-bus"> |
| <title>Bus</title> |
| <para> |
| A bus is a simple system that takes care of forwarding messages from |
| the pipeline threads to an application in its own thread context. The |
| advantage of a bus is that an application does not need to be |
| thread-aware in order to use &GStreamer;, even though &GStreamer; |
| itself is heavily threaded. |
| </para> |
| <para> |
| Every pipeline contains a bus by default, so applications do not need |
| to create a bus or anything. The only thing applications should do is |
| set a message handler on a bus, which is similar to a signal handler |
| to an object. When the mainloop is running, the bus will periodically |
| be checked for new messages, and the callback will be called when any |
| message is available. |
| </para> |
| |
| <sect1 id="section-bus-howto"> |
| <title>How to use a bus</title> |
| <para> |
| There are two different ways to use a bus: |
| <itemizedlist> |
| <listitem> |
| <para> |
| Run a GLib/Gtk+ main loop (or iterate the defauly GLib main |
| context yourself regularly) and attach some kind of watch to the |
| bus. This way the GLib main loop will check the bus for new |
| messages and notify you whenever there are messages. |
| </para> |
| <para> |
| Typically you would use <function>gst_bus_add_watch ()</function> |
| or <function>gst_bus_add_signal_watch ()</function> in this case. |
| </para> |
| <para> |
| To use a bus, attach a message handler to the bus of a pipeline |
| using <function>gst_bus_add_watch ()</function>. This handler will |
| be called whenever the pipeline emits a message to the bus. In this |
| handler, check the signal type (see next section) and do something |
| accordingly. The return value of the handler should be TRUE to |
| remove the message from the bus. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Check for messages on the bus yourself. This can be done using |
| <function>gst_bus_peek ()</function> and/or |
| <function>gst_bus_poll ()</function>. |
| </para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| <programlisting><!-- example-begin bus.c a --> |
| #include <gst/gst.h> |
| |
| static GMainLoop *loop; |
| |
| static gboolean |
| my_bus_callback (GstBus *bus, |
| GstMessage *message, |
| gpointer data) |
| { |
| g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); |
| |
| switch (GST_MESSAGE_TYPE (message)) { |
| case GST_MESSAGE_ERROR: { |
| GError *err; |
| gchar *debug; |
| |
| gst_message_parse_error (message, &err, &debug); |
| g_print ("Error: %s\n", err->message); |
| g_error_free (err); |
| g_free (debug); |
| |
| g_main_loop_quit (loop); |
| break; |
| } |
| case GST_MESSAGE_EOS: |
| /* end-of-stream */ |
| g_main_loop_quit (loop); |
| break; |
| default: |
| /* unhandled message */ |
| break; |
| } |
| |
| /* we want to be notified again the next time there is a message |
| * on the bus, so returning TRUE (FALSE means we want to stop watching |
| * for messages on the bus and our callback should not be called again) |
| */ |
| return TRUE; |
| } |
| |
| gint |
| main (gint argc, |
| gchar *argv[]) |
| { |
| GstElement *pipeline; |
| GstBus *bus; |
| |
| /* init */ |
| gst_init (&argc, &argv); |
| |
| /* create pipeline, add handler */ |
| pipeline = gst_pipeline_new ("my_pipeline"); |
| |
| /* adds a watch for new message on our pipeline's message bus to |
| * the default GLib main context, which is the main context that our |
| * GLib main loop is attached to below |
| */ |
| bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); |
| gst_bus_add_watch (bus, my_bus_callback, NULL); |
| gst_object_unref (bus); |
| <!-- example-end bus.c a --> |
| [..]<!-- example-begin bus.c b --> |
| <!-- example-begin bus.c c --> |
| /* create a mainloop that runs/iterates the default GLib main context |
| * (context NULL), in other words: makes the context check if anything |
| * it watches for has happened. When a message has been posted on the |
| * bus, the default main context will automatically call our |
| * my_bus_callback() function to notify us of that message. |
| * The main loop will be run until someone calls g_main_loop_quit() |
| */ |
| loop = g_main_loop_new (NULL, FALSE); |
| g_main_loop_run (loop); |
| |
| /* clean up */ |
| gst_element_set_state (pipeline, GST_STATE_NULL); |
| gst_object_unref (pipeline); |
| g_main_loop_unref (loop) |
| |
| return 0; |
| } |
| <!-- example-end bus.c c --> |
| </programlisting> |
| <para> |
| It is important to know that the handler will be called in the thread |
| context of the mainloop. This means that the interaction between the |
| pipeline and application over the bus is |
| <emphasis>asynchronous</emphasis>, and thus not suited for some |
| real-time purposes, such as cross-fading between audio tracks, doing |
| (theoretically) gapless playback or video effects. All such things |
| should be done in the pipeline context, which is easiest by writing |
| a &GStreamer; plug-in. It is very useful for its primary purpose, |
| though: passing messages from pipeline to application. |
| The advantage of this approach is that all the threading that |
| &GStreamer; does internally is hidden from the application and the |
| application developer does not have to worry about thread issues at |
| all. |
| </para> |
| <para> |
| Note that if you're using the default GLib mainloop integration, you |
| can, instead of attaching a watch, connect to the <quote>message</quote> |
| signal on the bus. This way you don't have to |
| <function>switch()</function> |
| on all possible message types; just connect to the interesting signals |
| in form of <quote>message::<type></quote>, where <type> |
| is a specific message type (see the next section for an explanation of |
| message types). |
| </para> |
| <para> |
| The above snippet could then also be written as: |
| </para> |
| <programlisting> |
| GstBus *bus; |
| |
| [..] |
| |
| bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline); |
| gst_bus_add_signal_watch (bus); |
| g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL); |
| g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL); |
| |
| [..] |
| </programlisting> |
| <para> |
| If you aren't using GLib mainloop, the message signals won't be available |
| by default. You can however use a small helper exported by to provide |
| integration with the mainloop you're using, and enable generation of bus |
| signals (see <ulink type="http" |
| url="&URLAPI;GstBus.html">documentation</ulink> for details) |
| </para> |
| </sect1> |
| |
| <sect1 id="section-bus-message-types"> |
| <title>Message types</title> |
| <para> |
| &GStreamer; has a few pre-defined message types that can be passed |
| over the bus. The messages are extensible, however. Plug-ins can |
| define additional messages, and applications can decide to either |
| have specific code for those or ignore them. All applications are |
| strongly recommended to at least handle error messages by providing |
| visual feedback to the user. |
| </para> |
| <para> |
| All messages have a message source, type and timestamp. The message |
| source can be used to see which element emitted the message. For some |
| messages, for example, only the ones emitted by the top-level pipeline |
| will be interesting to most applications (e.g. for state-change |
| notifications). Below is a list of all messages and a short explanation |
| of what they do and how to parse message-specific content. |
| </para> |
| <itemizedlist> |
| <listitem> |
| <para> |
| Error, warning and information notifications: those are used |
| by elements if a message should be shown to the user about the |
| state of the pipeline. Error messages are fatal and terminate |
| the data-passing. The error should be repaired to resume pipeline |
| activity. Warnings are not fatal, but imply a problem nevertheless. |
| Information messages are for non-problem notifications. All those |
| messages contain a <classname>GError</classname> with the main |
| error type and message, and optionally a debug string. Both |
| can be extracted using <function>gst_message_parse_error |
| ()</function>, <function>_parse_warning ()</function> and |
| <function>_parse_info ()</function>. Both error and debug string |
| should be free'ed after use. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| End-of-stream notification: this is emitted when the stream has |
| ended. The state of the pipeline will not change, but further |
| media handling will stall. Applications can use this to skip to |
| the next song in their playlist. After end-of-stream, it is also |
| possible to seek back in the stream. Playback will then continue |
| automatically. This message has no specific arguments. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Tags: emitted when metadata was found in the stream. This can be |
| emitted multiple times for a pipeline (e.g. once for descriptive |
| metadata such as artist name or song title, and another one for |
| stream-information, such as samplerate and bitrate). Applications |
| should cache metadata internally. <function>gst_message_parse_tag |
| ()</function> should be used to parse the taglist, which should |
| be <function>gst_tag_list_free ()</function>'ed when no longer |
| needed. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| State-changes: emitted after a successful state change. |
| <function>gst_message_parse_state_changed ()</function> can be |
| used to parse the old and new state of this transition. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Buffering: emitted during caching of network-streams. One can |
| manually extract the progress (in percent) from the message by |
| extracting the <quote>buffer-percent</quote> property from the |
| structure returned by <function>gst_message_get_structure |
| ()</function>. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Element messages: these are special messages that are unique to |
| certain elements and usually represent additional features. The |
| element's documentation should mention in detail which |
| element messages a particular element may send. As an example, |
| the 'qtdemux' QuickTime demuxer element may send a 'redirect' |
| element message on certain occasions if the stream contains a |
| redirect instruction. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Application-specific messages: any information on those can |
| be extracted by getting the message structure (see above) and |
| reading its fields. Usually these messages can safely be ignored. |
| </para> |
| <para> |
| Application messages are primarily meant for internal |
| use in applications in case the application needs to marshal |
| information from some thread into the main thread. This is |
| particularly useful when the application is making use of element |
| signals (as those signals will be emitted in the context of the |
| streaming thread). |
| </para> |
| </listitem> |
| </itemizedlist> |
| </sect1> |
| </chapter> |