Test that removing probes from within the probe functions works.
[platform/upstream/gstreamer.git] / gst / gstmessage.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  *
4  * gstmessage.c: GstMessage subsystem
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /**
22  * SECTION:gstmessage
23  * @short_description: Lightweight objects to signal the application of pipeline events
24  * @see_also: #GstBus,#GstMiniObject
25  *
26  * Messages are implemented as a subclass of #GstMiniObject with a generic 
27  * #GstStructure as the content. This allows for writing custom messages without
28  * requiring an API change while allowing a wide range of different types
29  * of messages.
30  *
31  * Messages are posted by objects in the pipeline and are passed to the 
32  * application using the #GstBus. 
33  */
34
35 #include <string.h>             /* memcpy */
36
37 #include "gst_private.h"
38 #include "gsterror.h"
39 #include "gstinfo.h"
40 #include "gstmessage.h"
41 #include "gsttaglist.h"
42 #include "gstutils.h"
43
44
45 static void gst_message_init (GTypeInstance * instance, gpointer g_class);
46 static void gst_message_class_init (gpointer g_class, gpointer class_data);
47 static void gst_message_finalize (GstMessage * message);
48 static GstMessage *_gst_message_copy (GstMessage * message);
49
50
51 void
52 _gst_message_initialize (void)
53 {
54   gpointer ptr;
55
56   GST_CAT_INFO (GST_CAT_GST_INIT, "init messages");
57
58   gst_message_get_type ();
59
60   /* the GstMiniObject types need to be class_ref'd once before it can be
61    * done from multiple threads;
62    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
63   ptr = g_type_class_ref (GST_TYPE_MESSAGE);
64   g_type_class_unref (ptr);
65 }
66
67 GType
68 gst_message_get_type (void)
69 {
70   static GType _gst_message_type;
71
72   if (G_UNLIKELY (_gst_message_type == 0)) {
73     static const GTypeInfo message_info = {
74       sizeof (GstMessageClass),
75       NULL,
76       NULL,
77       gst_message_class_init,
78       NULL,
79       NULL,
80       sizeof (GstMessage),
81       0,
82       gst_message_init,
83       NULL
84     };
85
86     _gst_message_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
87         "GstMessage", &message_info, 0);
88   }
89   return _gst_message_type;
90 }
91
92 static void
93 gst_message_class_init (gpointer g_class, gpointer class_data)
94 {
95   GstMessageClass *message_class = GST_MESSAGE_CLASS (g_class);
96
97   message_class->mini_object_class.copy =
98       (GstMiniObjectCopyFunction) _gst_message_copy;
99   message_class->mini_object_class.finalize =
100       (GstMiniObjectFinalizeFunction) gst_message_finalize;
101 }
102
103 static void
104 gst_message_init (GTypeInstance * instance, gpointer g_class)
105 {
106   GstMessage *message = GST_MESSAGE (instance);
107
108   GST_CAT_INFO (GST_CAT_MESSAGE, "new message %p", message);
109   GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
110 }
111
112 static void
113 gst_message_finalize (GstMessage * message)
114 {
115   g_return_if_fail (message != NULL);
116
117   GST_CAT_INFO (GST_CAT_MESSAGE, "finalize message %p", message);
118
119   if (GST_MESSAGE_SRC (message)) {
120     gst_object_unref (GST_MESSAGE_SRC (message));
121     GST_MESSAGE_SRC (message) = NULL;
122   }
123
124   if (message->lock) {
125     GST_MESSAGE_LOCK (message);
126     GST_MESSAGE_SIGNAL (message);
127     GST_MESSAGE_UNLOCK (message);
128   }
129
130   if (message->structure) {
131     gst_structure_set_parent_refcount (message->structure, NULL);
132     gst_structure_free (message->structure);
133   }
134 }
135
136 static GstMessage *
137 _gst_message_copy (GstMessage * message)
138 {
139   GstMessage *copy;
140
141   GST_CAT_INFO (GST_CAT_MESSAGE, "copy message %p", message);
142
143   copy = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);
144
145   /* FIXME, need to copy relevant data from the miniobject. */
146   //memcpy (copy, message, sizeof (GstMessage));
147
148   GST_MESSAGE_GET_LOCK (copy) = GST_MESSAGE_GET_LOCK (message);
149   GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
150   GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
151   GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
152
153   if (GST_MESSAGE_SRC (message)) {
154     GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
155   }
156
157   if (message->structure) {
158     copy->structure = gst_structure_copy (message->structure);
159     gst_structure_set_parent_refcount (copy->structure,
160         &message->mini_object.refcount);
161   }
162
163   return copy;
164 }
165
166 static GstMessage *
167 gst_message_new (GstMessageType type, GstObject * src)
168 {
169   GstMessage *message;
170
171   message = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);
172
173   GST_CAT_INFO (GST_CAT_MESSAGE, "creating new message %p %d", message, type);
174
175   message->type = type;
176   if (src) {
177     message->src = gst_object_ref (src);
178     GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, src, "message source");
179   } else {
180     message->src = NULL;
181     GST_CAT_DEBUG (GST_CAT_MESSAGE, "NULL message source");
182   }
183   message->structure = NULL;
184
185   return message;
186 }
187
188 /**
189  * gst_message_new_eos:
190  * @src: The object originating the message.
191  *
192  * Create a new eos message. This message is generated and posted in
193  * the sink elements of a GstBin. The bin will only forward the EOS
194  * message to the application if all sinks have posted an EOS message.
195  *
196  * Returns: The new eos message.
197  *
198  * MT safe.
199  */
200 GstMessage *
201 gst_message_new_eos (GstObject * src)
202 {
203   GstMessage *message;
204
205   message = gst_message_new (GST_MESSAGE_EOS, src);
206
207   return message;
208 }
209
210 /**
211  * gst_message_new_error:
212  * @src: The object originating the message.
213  * @error: The GError for this message.
214  * @debug: A debugging string for something or other.
215  *
216  * Create a new error message. The message will copy @error and
217  * @debug. This message is posted by element when a fatal event
218  * occured. The pipeline will probably (partially) stop. 
219  *
220  * Returns: The new error message.
221  *
222  * MT safe.
223  */
224 GstMessage *
225 gst_message_new_error (GstObject * src, GError * error, gchar * debug)
226 {
227   GstMessage *message;
228   GstStructure *s;
229
230   message = gst_message_new (GST_MESSAGE_ERROR, src);
231   /* gst_structure_new takes copies of the types passed in */
232   s = gst_structure_new ("GstMessageError", "gerror", GST_TYPE_G_ERROR, error,
233       "debug", G_TYPE_STRING, debug, NULL);
234   gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
235   message->structure = s;
236
237   return message;
238 }
239
240 /**
241  * gst_message_new_warning:
242  * @src: The object originating the message.
243  * @error: The GError for this message.
244  * @debug: A debugging string for something or other.
245  *
246  * Create a new warning message. The message will make copies of @error and
247  * @debug.
248  *
249  * Returns: The new warning message.
250  *
251  * MT safe.
252  */
253 GstMessage *
254 gst_message_new_warning (GstObject * src, GError * error, gchar * debug)
255 {
256   GstMessage *message;
257   GstStructure *s;
258
259   message = gst_message_new (GST_MESSAGE_WARNING, src);
260   /* gst_structure_new takes copies of the types passed in */
261   s = gst_structure_new ("GstMessageWarning", "gerror", GST_TYPE_G_ERROR, error,
262       "debug", G_TYPE_STRING, debug, NULL);
263   gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
264   message->structure = s;
265
266   return message;
267 }
268
269 /**
270  * gst_message_new_tag:
271  * @src: The object originating the message.
272  * @tag_list: The tag list for the message.
273  *
274  * Create a new tag message. The message will take ownership of the tag list.
275  * The message is posted by elements that discovered a new taglist.
276  *
277  * Returns: The new tag message.
278  *
279  * MT safe.
280  */
281 GstMessage *
282 gst_message_new_tag (GstObject * src, GstTagList * tag_list)
283 {
284   GstMessage *message;
285
286   g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);
287
288   message = gst_message_new (GST_MESSAGE_TAG, src);
289   gst_structure_set_parent_refcount (tag_list, &message->mini_object.refcount);
290   message->structure = tag_list;
291
292   return message;
293 }
294
295 /**
296  * gst_message_new_state_change:
297  * @src: The object originating the message.
298  * @old: The previous state.
299  * @new: The new (current) state.
300  *
301  * Create a state change message. This message is posted whenever an element changed
302  * its state.
303  *
304  * Returns: The new state change message.
305  *
306  * MT safe.
307  */
308 GstMessage *
309 gst_message_new_state_changed (GstObject * src, GstState old, GstState new)
310 {
311   GstMessage *message;
312   GstStructure *s;
313
314   message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src);
315
316   s = gst_structure_new ("GstMessageState", "old-state", G_TYPE_INT, (gint) old,
317       "new-state", G_TYPE_INT, (gint) new, NULL);
318   gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
319   message->structure = s;
320
321   return message;
322 }
323
324 /**
325  * gst_message_new_segment_start:
326  * @src: The object originating the message.
327  * @timestamp: The timestamp of the segment being played
328  *
329  * Create a new segment message. This message is posted by elements that
330  * start playback of a segment as a result of a segment seek. This message
331  * is not received by the application but is used for maintenance reasons in
332  * container elements.
333  *
334  * Returns: The new segment start message.
335  *
336  * MT safe.
337  */
338 GstMessage *
339 gst_message_new_segment_start (GstObject * src, GstClockTime timestamp)
340 {
341   GstMessage *message;
342   GstStructure *s;
343
344   message = gst_message_new (GST_MESSAGE_SEGMENT_START, src);
345
346   s = gst_structure_new ("GstMessageSegmentStart", "timestamp", G_TYPE_INT64,
347       (gint64) timestamp, NULL);
348   gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
349   message->structure = s;
350
351   return message;
352 }
353
354 /**
355  * gst_message_new_segment_done:
356  * @src: The object originating the message.
357  * @timestamp: The timestamp of the segment being played
358  *
359  * Create a new segment done message. This message is posted by elements that
360  * finish playback of a segment as a result of a segment seek. This message
361  * is received by the application after all elements that posted a segment_start
362  * have posted the segment_done.
363  *
364  * Returns: The new segment done message.
365  *
366  * MT safe.
367  */
368 GstMessage *
369 gst_message_new_segment_done (GstObject * src, GstClockTime timestamp)
370 {
371   GstMessage *message;
372   GstStructure *s;
373
374   message = gst_message_new (GST_MESSAGE_SEGMENT_DONE, src);
375
376   s = gst_structure_new ("GstMessageSegmentDone", "timestamp", G_TYPE_INT64,
377       (gint64) timestamp, NULL);
378   gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
379   message->structure = s;
380
381   return message;
382 }
383
384 /**
385  * gst_message_new_custom:
386  * @type: The #GstMessageType to distinguish messages
387  * @src: The object originating the message.
388  * @structure: The structure for the message. The message will take ownership of
389  * the structure.
390  *
391  * Create a new custom-typed message. This can be used for anything not
392  * handled by other message-specific functions to pass a message to the
393  * app. The structure field can be NULL.
394  *
395  * Returns: The new message.
396  *
397  * MT safe.
398  */
399 GstMessage *
400 gst_message_new_custom (GstMessageType type, GstObject * src,
401     GstStructure * structure)
402 {
403   GstMessage *message;
404
405   message = gst_message_new (type, src);
406   if (structure) {
407     gst_structure_set_parent_refcount (structure,
408         &message->mini_object.refcount);
409     message->structure = structure;
410   }
411   return message;
412 }
413
414 /**
415  * gst_message_get_structure:
416  * @message: The #GstMessage.
417  *
418  * Access the structure of the message.
419  *
420  * Returns: The structure of the message. The structure is still
421  * owned by the message, which means that you should not free it and 
422  * that the pointer becomes invalid when you free the message.
423  *
424  * MT safe.
425  */
426 const GstStructure *
427 gst_message_get_structure (GstMessage * message)
428 {
429   g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
430
431   return message->structure;
432 }
433
434 /**
435  * gst_message_parse_tag:
436  * @message: A valid #GstMessage of type GST_MESSAGE_TAG.
437  *
438  * Extracts the tag list from the GstMessage. The tag list returned in the
439  * output argument is a copy; the caller must free it when done.
440  *
441  * MT safe.
442  */
443 void
444 gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
445 {
446   g_return_if_fail (GST_IS_MESSAGE (message));
447   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
448
449   *tag_list = (GstTagList *) gst_structure_copy (message->structure);
450 }
451
452 /**
453  * gst_message_parse_state_changed:
454  * @message: A valid #GstMessage of type GST_MESSAGE_STATE_CHANGED.
455  *
456  * Extracts the old and new states from the GstMessage.
457  *
458  * MT safe.
459  */
460 void
461 gst_message_parse_state_changed (GstMessage * message, GstState * old,
462     GstState * new)
463 {
464   g_return_if_fail (GST_IS_MESSAGE (message));
465   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED);
466
467   if (!gst_structure_get_int (message->structure, "old-state", (gint *) old))
468     g_assert_not_reached ();
469   if (!gst_structure_get_int (message->structure, "new-state", (gint *) new))
470     g_assert_not_reached ();
471 }
472
473 /**
474  * gst_message_parse_error:
475  * @message: A valid #GstMessage of type GST_MESSAGE_ERROR.
476  *
477  * Extracts the GError and debug string from the GstMessage. The values returned
478  * in the output arguments are copies; the caller must free them when done.
479  *
480  * MT safe.
481  */
482 void
483 gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
484 {
485   const GValue *error_gvalue;
486   GError *error_val;
487
488   g_return_if_fail (GST_IS_MESSAGE (message));
489   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
490
491   error_gvalue = gst_structure_get_value (message->structure, "gerror");
492   g_return_if_fail (error_gvalue != NULL);
493   g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
494
495   error_val = (GError *) g_value_get_boxed (error_gvalue);
496   if (error_val)
497     *gerror = g_error_copy (error_val);
498   else
499     *gerror = NULL;
500   *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
501 }
502
503 /**
504  * gst_message_parse_warning:
505  * @message: A valid #GstMessage of type GST_MESSAGE_WARNING.
506  *
507  * Extracts the GError and debug string from the GstMessage. The values returned
508  * in the output arguments are copies; the caller must free them when done.
509  *
510  * MT safe.
511  */
512 void
513 gst_message_parse_warning (GstMessage * message, GError ** gerror,
514     gchar ** debug)
515 {
516   const GValue *error_gvalue;
517   GError *error_val;
518
519   g_return_if_fail (GST_IS_MESSAGE (message));
520   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
521
522   error_gvalue = gst_structure_get_value (message->structure, "gerror");
523   g_return_if_fail (error_gvalue != NULL);
524   g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
525
526   error_val = (GError *) g_value_get_boxed (error_gvalue);
527   if (error_val)
528     *gerror = g_error_copy (error_val);
529   else
530     *gerror = NULL;
531
532   *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
533 }
534
535 /**
536  * gst_message_parse_segment_start:
537  * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_START.
538  *
539  * Extracts the timestamp from the segment start message.
540  *
541  * MT safe.
542  */
543 void
544 gst_message_parse_segment_start (GstMessage * message, GstClockTime * timestamp)
545 {
546   const GValue *time_gvalue;
547
548   g_return_if_fail (GST_IS_MESSAGE (message));
549   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START);
550
551   time_gvalue = gst_structure_get_value (message->structure, "timstamp");
552   g_return_if_fail (time_gvalue != NULL);
553   g_return_if_fail (G_VALUE_TYPE (time_gvalue) == G_TYPE_INT64);
554
555   if (timestamp)
556     *timestamp = (GstClockTime) g_value_get_int64 (time_gvalue);
557 }
558
559 /**
560  * gst_message_parse_segment_done:
561  * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_DONE.
562  *
563  * Extracts the timestamp from the segment done message.
564  *
565  * MT safe.
566  */
567 void
568 gst_message_parse_segment_done (GstMessage * message, GstClockTime * timestamp)
569 {
570   const GValue *time_gvalue;
571
572   g_return_if_fail (GST_IS_MESSAGE (message));
573   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE);
574
575   time_gvalue = gst_structure_get_value (message->structure, "timstamp");
576   g_return_if_fail (time_gvalue != NULL);
577   g_return_if_fail (G_VALUE_TYPE (time_gvalue) == G_TYPE_INT64);
578
579   if (timestamp)
580     *timestamp = (GstClockTime) g_value_get_int64 (time_gvalue);
581 }