summaryrefslogtreecommitdiff
path: root/docs/manual/basics-bus.xml
blob: 4fdb37bcdd6b3d93fdaad4b380916863a135c3c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<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 default 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 &lt;gst/gst.h&gt;

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, &amp;err, &amp;debug);
      g_print ("Error: %s\n", err-&gt;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 (&amp;argc, &amp;argv);

  /* create pipeline, add handler */
  pipeline = gst_pipeline_new ("my_pipeline");

  /* adds a watch for new message on our pipeline&apos;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::&lt;type&gt;</quote>, where &lt;type&gt; 
      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 asynchronous message signals won't
      be available by default. You can however install a custom sync handler
      that wakes up the custom mainloop and that uses
      <function>gst_bus_async_signal_func ()</function> to emit the signals.
      (see also <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>