Bus
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.
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.
How to use a bus
To use a bus, attach a message handler to the default bus of a pipeline
using gst_bus_add_watch (). 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.
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
my_bus_callback (GstBus *bus,
GstMessage *message,
gpointer data)
{
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;
}
/* remove message from the queue */
return TRUE;
}
gint
main (gint argc,
gchar *argv[])
{
GMainLoop *loop;
GstElement *pipeline;
/* init */
gst_init (&argc, &argv);
/* create pipeline, add handler */
pipeline = gst_pipeline_new ("my_pipeline");
gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
my_bus_callback, NULL);
[..]
/* in the mainloop, all messages posted to the bus by the pipeline
* will automatically be sent to our callback. */
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
return 0;
}
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
asynchronous, 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.
Message types
&GStreamer; has a few pre-defined message types that can be passed
over the bus. The messages are extendible, 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.
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.
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
acvitity. Warnings are not fatal, but imply a problem nevertheless.
Information messages are for non-problem notifications. All those
messages contain a GError with the main
error type and message, and optionally a debug string. Both
can be extracted using gst_message_parse_error
(), _parse_warning () and
_parse_info (). Both error and debug string
should be free'ed after use.
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.
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. gst_message_parse_tag
() should be used to parse the taglist, which should
be dereferenced after use.
State-changes: emitted after a successful state change.
gst_message_parse_state_changed () can be
used to parse the old and new state of this transition.
Buffering: emitted during caching of network-streams. One can
manually extract the progress (in percent) from the message by
extracting the buffer-percent
property from the
structure returned by gst_message_parse_structure
().
Other application-specific messages: any information on those can
be extracted by getting a structure (see above) and reading
properties. In most cases, such messages can conveniently be
ignored.