miniobjects: pass copy, dispose and free function to gst_mini_object_init()
[platform/upstream/gstreamer.git] / gst / gstmessage.c
index 91881bb..8bdef12 100644 (file)
@@ -32,7 +32,7 @@
  *
  * Messages are posted by objects in the pipeline and are passed to the
  * application using the #GstBus.
-
+ *
  * The basic use pattern of posting a message on a #GstBus is as follows:
  *
  * <example>
@@ -67,7 +67,7 @@ typedef struct
   GstStructure *structure;
 } GstMessageImpl;
 
-#define GST_MESSAGE_STRUCTURE(m) (((GstMessageImpl *)(m))->structure)
+#define GST_MESSAGE_STRUCTURE(m)  (((GstMessageImpl *)(m))->structure)
 
 typedef struct
 {
@@ -104,6 +104,7 @@ static GstMessageQuarks message_quarks[] = {
   {GST_MESSAGE_STEP_START, "step-start", 0},
   {GST_MESSAGE_QOS, "qos", 0},
   {GST_MESSAGE_PROGRESS, "progress", 0},
+  {GST_MESSAGE_TOC, "toc", 0},
   {0, NULL, 0}
 };
 
@@ -185,7 +186,7 @@ _gst_message_free (GstMessage * message)
     GST_MESSAGE_SRC (message) = NULL;
   }
 
-  if (message->lock) {
+  if (message->lock.p) {
     GST_MESSAGE_LOCK (message);
     GST_MESSAGE_SIGNAL (message);
     GST_MESSAGE_UNLOCK (message);
@@ -197,9 +198,13 @@ _gst_message_free (GstMessage * message)
     gst_structure_free (structure);
   }
 
-  g_slice_free1 (GST_MINI_OBJECT_SIZE (message), message);
+  g_slice_free1 (sizeof (GstMessageImpl), message);
 }
 
+static void
+gst_message_init (GstMessageImpl * message, GstMessageType type,
+    GstObject * src);
+
 static GstMessage *
 _gst_message_copy (GstMessage * message)
 {
@@ -212,34 +217,41 @@ _gst_message_copy (GstMessage * message)
 
   copy = g_slice_new0 (GstMessageImpl);
 
-  gst_mini_object_init (GST_MINI_OBJECT_CAST (copy),
-      _gst_message_type, sizeof (GstMessageImpl));
-
-  copy->message.mini_object.copy =
-      (GstMiniObjectCopyFunction) _gst_message_copy;
-  copy->message.mini_object.free =
-      (GstMiniObjectFreeFunction) _gst_message_free;
+  gst_message_init (copy, GST_MESSAGE_TYPE (message),
+      GST_MESSAGE_SRC (message));
 
-  GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
   GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
   GST_MESSAGE_SEQNUM (copy) = GST_MESSAGE_SEQNUM (message);
-  if (GST_MESSAGE_SRC (message)) {
-    GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
-  }
-
-  GST_MESSAGE_GET_LOCK (copy) = GST_MESSAGE_GET_LOCK (message);
-  GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
 
   structure = GST_MESSAGE_STRUCTURE (message);
   if (structure) {
-    copy->structure = gst_structure_copy (structure);
-    gst_structure_set_parent_refcount (copy->structure,
+    GST_MESSAGE_STRUCTURE (copy) = gst_structure_copy (structure);
+    gst_structure_set_parent_refcount (GST_MESSAGE_STRUCTURE (copy),
         &copy->message.mini_object.refcount);
+  } else {
+    GST_MESSAGE_STRUCTURE (copy) = NULL;
   }
 
   return GST_MESSAGE_CAST (copy);
 }
 
+static void
+gst_message_init (GstMessageImpl * message, GstMessageType type,
+    GstObject * src)
+{
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (message), _gst_message_type,
+      (GstMiniObjectCopyFunction) _gst_message_copy, NULL,
+      (GstMiniObjectFreeFunction) _gst_message_free);
+
+  GST_MESSAGE_TYPE (message) = type;
+  if (src)
+    gst_object_ref (src);
+  GST_MESSAGE_SRC (message) = src;
+  GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
+  GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
+}
+
+
 /**
  * gst_message_new_custom:
  * @type: The #GstMessageType to distinguish messages
@@ -263,32 +275,29 @@ gst_message_new_custom (GstMessageType type, GstObject * src,
 
   message = g_slice_new0 (GstMessageImpl);
 
-  gst_mini_object_init (GST_MINI_OBJECT_CAST (message),
-      _gst_message_type, sizeof (GstMessageImpl));
-
-  message->message.mini_object.copy =
-      (GstMiniObjectCopyFunction) _gst_message_copy;
-  message->message.mini_object.free =
-      (GstMiniObjectFreeFunction) _gst_message_free;
-
   GST_CAT_LOG (GST_CAT_MESSAGE, "source %s: creating new message %p %s",
       (src ? GST_OBJECT_NAME (src) : "NULL"), message,
       gst_message_type_get_name (type));
 
-  GST_MESSAGE_TYPE (message) = type;
-  if (src)
-    gst_object_ref (src);
-  GST_MESSAGE_SRC (message) = src;
-  GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
-  GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
-
   if (structure) {
-    gst_structure_set_parent_refcount (structure,
-        &message->message.mini_object.refcount);
+    /* structure must not have a parent */
+    if (!gst_structure_set_parent_refcount (structure,
+            &message->message.mini_object.refcount))
+      goto had_parent;
   }
-  message->structure = structure;
+  gst_message_init (message, type, src);
+
+  GST_MESSAGE_STRUCTURE (message) = structure;
 
   return GST_MESSAGE_CAST (message);
+
+  /* ERRORS */
+had_parent:
+  {
+    g_slice_free1 (sizeof (GstMessageImpl), message);
+    g_warning ("structure is already owned by another object");
+    return NULL;
+  }
 }
 
 /**
@@ -389,7 +398,7 @@ gst_message_new_error (GstObject * src, GError * error, const gchar * debug)
   GstStructure *structure;
 
   structure = gst_structure_new_id (GST_QUARK (MESSAGE_ERROR),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure);
 
@@ -416,7 +425,7 @@ gst_message_new_warning (GstObject * src, GError * error, const gchar * debug)
   GstStructure *structure;
 
   structure = gst_structure_new_id (GST_QUARK (MESSAGE_WARNING),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure);
 
@@ -445,7 +454,7 @@ gst_message_new_info (GstObject * src, GError * error, const gchar * debug)
   GstStructure *structure;
 
   structure = gst_structure_new_id (GST_QUARK (MESSAGE_INFO),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure);
 
@@ -467,13 +476,17 @@ gst_message_new_info (GstObject * src, GError * error, const gchar * debug)
 GstMessage *
 gst_message_new_tag (GstObject * src, GstTagList * tag_list)
 {
+  GstStructure *s;
   GstMessage *message;
+  GValue val = G_VALUE_INIT;
 
-  g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);
-
-  message =
-      gst_message_new_custom (GST_MESSAGE_TAG, src, (GstStructure *) tag_list);
+  g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), NULL);
 
+  s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_TAG));
+  g_value_init (&val, GST_TYPE_TAG_LIST);
+  g_value_take_boxed (&val, tag_list);
+  gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val);
+  message = gst_message_new_custom (GST_MESSAGE_TAG, src, s);
   return message;
 }
 
@@ -540,7 +553,7 @@ gst_message_new_state_changed (GstObject * src,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE_CHANGED),
       GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate,
       GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate,
       GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL);
@@ -853,24 +866,26 @@ gst_message_new_async_start (GstObject * src)
 /**
  * gst_message_new_async_done:
  * @src: (transfer none): The object originating the message.
- * @reset_time: if the running_time should be reset
+ * @running_time: the desired running_time
  *
  * The message is posted when elements completed an ASYNC state change.
- * @reset_time is set to TRUE when the element requests a new running_time
- * before going to PLAYING.
+ * @running_time contains the time of the desired running_time when this
+ * elements goes to PLAYING. A value of #GST_CLOCK_TIME_NONE for @running_time
+ * means that the element has no clock interaction and thus doesn't care about
+ * the running_time of the pipeline.
  *
  * Returns: (transfer full): The new async_done message.
  *
  * MT safe.
  */
 GstMessage *
-gst_message_new_async_done (GstObject * src, gboolean reset_time)
+gst_message_new_async_done (GstObject * src, GstClockTime running_time)
 {
   GstMessage *message;
   GstStructure *structure;
 
   structure = gst_structure_new_id (GST_QUARK (MESSAGE_ASYNC_DONE),
-      GST_QUARK (RESET_TIME), G_TYPE_BOOLEAN, reset_time, NULL);
+      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
   message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure);
 
   return message;
@@ -991,7 +1006,7 @@ gst_message_has_name (GstMessage * message, const gchar * name)
  *       gst_message_parse_tag (msg, &amp;tags);
  *       g_print ("Got tags from element %s\n", GST_OBJECT_NAME (msg->src));
  *       handle_tags (tags);
- *       gst_tag_list_free (tags);
+ *       gst_tag_list_unref (tags);
  *       break;
  *     }
  *     ...
@@ -1004,16 +1019,12 @@ gst_message_has_name (GstMessage * message, const gchar * name)
 void
 gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
 {
-  GstStructure *ret;
-
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
   g_return_if_fail (tag_list != NULL);
 
-  ret = gst_structure_copy (GST_MESSAGE_STRUCTURE (message));
-  gst_structure_remove_field (ret, "source-pad");
-
-  *tag_list = (GstTagList *) ret;
+  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
+      GST_QUARK (TAGLIST), GST_TYPE_TAG_LIST, tag_list, NULL);
 }
 
 /**
@@ -1338,7 +1349,7 @@ gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
   structure = GST_MESSAGE_STRUCTURE (message);
   error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1378,7 +1389,7 @@ gst_message_parse_warning (GstMessage * message, GError ** gerror,
   structure = GST_MESSAGE_STRUCTURE (message);
   error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1419,7 +1430,7 @@ gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug)
   structure = GST_MESSAGE_STRUCTURE (message);
   error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1529,14 +1540,14 @@ gst_message_parse_duration (GstMessage * message, GstFormat * format,
 /**
  * gst_message_parse_async_done:
  * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE.
- * @reset_time: (out): Result location for the reset_time or NULL
+ * @running_time: (out): Result location for the running_time or NULL
  *
- * Extract the reset_time from the async_done message.
+ * Extract the running_time from the async_done message.
  *
  * MT safe.
  */
 void
-gst_message_parse_async_done (GstMessage * message, gboolean * reset_time)
+gst_message_parse_async_done (GstMessage * message, GstClockTime * running_time)
 {
   GstStructure *structure;
 
@@ -1544,10 +1555,10 @@ gst_message_parse_async_done (GstMessage * message, gboolean * reset_time)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_DONE);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  if (reset_time)
-    *reset_time =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (RESET_TIME)));
+  if (running_time)
+    *running_time =
+        g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (RUNNING_TIME)));
 }
 
 /**
@@ -2159,3 +2170,111 @@ gst_message_parse_progress (GstMessage * message, GstProgressType * type,
       GST_QUARK (CODE), G_TYPE_STRING, code,
       GST_QUARK (TEXT), G_TYPE_STRING, text, NULL);
 }
+
+/**
+ * gst_message_new_toc:
+ * @src: the object originating the message.
+ * @toc: #GstToc structure for the message.
+ * @updated: whether TOC was updated or not.
+ *
+ * Create a new TOC message. The message is posted by elements
+ * that discovered or updated a TOC.
+ *
+ * Returns: a new TOC message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.37
+ */
+GstMessage *
+gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated)
+{
+  GstStructure *toc_struct;
+
+  g_return_val_if_fail (toc != NULL, NULL);
+
+  toc_struct = __gst_toc_to_structure (toc);
+
+  if (G_LIKELY (toc_struct != NULL)) {
+    __gst_toc_structure_set_updated (toc_struct, updated);
+    return gst_message_new_custom (GST_MESSAGE_TOC, src, toc_struct);
+  } else
+    return NULL;
+}
+
+/**
+ * gst_message_parse_toc:
+ * @message: a valid #GstMessage of type GST_MESSAGE_TOC.
+ * @toc: (out): return location for the TOC.
+ * @updated: (out): return location for the updated flag.
+ *
+ * Extract thef TOC from the #GstMessage. The TOC returned in the
+ * output argument is a copy; the caller must free it with
+ * gst_toc_free() when done.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.37
+ */
+void
+gst_message_parse_toc (GstMessage * message, GstToc ** toc, gboolean * updated)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TOC);
+  g_return_if_fail (toc != NULL);
+
+  *toc = __gst_toc_from_structure (GST_MESSAGE_STRUCTURE (message));
+
+  if (updated != NULL)
+    *updated =
+        __gst_toc_structure_get_updated (GST_MESSAGE_STRUCTURE (message));
+}
+
+/**
+ * gst_message_new_reset_time:
+ * @src: (transfer none): The object originating the message.
+ * @running_time: the requested running-time
+ *
+ * This message is posted when the pipeline running-time should be reset to
+ * @running_time, like after a flushing seek.
+ *
+ * Returns: (transfer full): The new reset_time message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_reset_time (GstObject * src, GstClockTime running_time)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_RESET_TIME),
+      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_RESET_TIME, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_reset_time:
+ * @message: A valid #GstMessage of type GST_MESSAGE_RESET_TIME.
+ * @running_time: (out): Result location for the running_time or NULL
+ *
+ * Extract the running-time from the RESET_TIME message.
+ *
+ * MT safe.
+ */
+void
+gst_message_parse_reset_time (GstMessage * message, GstClockTime * running_time)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_RESET_TIME);
+
+  structure = GST_MESSAGE_STRUCTURE (message);
+  if (running_time)
+    *running_time =
+        g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (RUNNING_TIME)));
+}