gst/gstmessage.*: Clean up.
authorWim Taymans <wim.taymans@gmail.com>
Sat, 8 Oct 2005 12:36:36 +0000 (12:36 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sat, 8 Oct 2005 12:36:36 +0000 (12:36 +0000)
Original commit message from CVS:
* gst/gstmessage.c: (gst_message_new_custom),
(gst_message_new_eos), (gst_message_new_error),
(gst_message_new_warning), (gst_message_new_tag),
(gst_message_new_state_changed), (gst_message_new_clock_provide),
(gst_message_new_new_clock), (gst_message_new_segment_start),
(gst_message_new_segment_done), (gst_message_parse_state_changed),
(gst_message_parse_clock_provide), (gst_message_parse_new_clock):
* gst/gstmessage.h:
Clean up.
Added clock related messages.

* gst/gstpipeline.c: (gst_pipeline_change_state):
Post message when the clock changed.

* tools/gst-launch.c: (event_loop):
Print new clock.

ChangeLog
gst/gstmessage.c
gst/gstmessage.h
gst/gstpipeline.c
tools/gst-launch.c

index 706ff46..d0e88fe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2005-10-08  Wim Taymans  <wim@fluendo.com>
+
+       * gst/gstmessage.c: (gst_message_new_custom),
+       (gst_message_new_eos), (gst_message_new_error),
+       (gst_message_new_warning), (gst_message_new_tag),
+       (gst_message_new_state_changed), (gst_message_new_clock_provide),
+       (gst_message_new_new_clock), (gst_message_new_segment_start),
+       (gst_message_new_segment_done), (gst_message_parse_state_changed),
+       (gst_message_parse_clock_provide), (gst_message_parse_new_clock):
+       * gst/gstmessage.h:
+       Clean up.
+       Added clock related messages.
+
+       * gst/gstpipeline.c: (gst_pipeline_change_state):
+       Post message when the clock changed.
+
+       * tools/gst-launch.c: (event_loop):
+       Print new clock.
+
 2005-10-08  Tim-Philipp Müller  <tim at centricular dot net>
 
        * tools/gst-inspect.c: (print_element_properties_info):
index 41d1b7c..80e25cc 100644 (file)
@@ -81,10 +81,13 @@ static GstMessageQuarks message_quarks[] = {
   {GST_MESSAGE_BUFFERING, "buffering", 0},
   {GST_MESSAGE_STATE_CHANGED, "state-changed", 0},
   {GST_MESSAGE_STEP_DONE, "step-done", 0},
+  {GST_MESSAGE_CLOCK_PROVIDE, "clock-provide", 0},
+  {GST_MESSAGE_CLOCK_LOST, "clock-lost", 0},
   {GST_MESSAGE_NEW_CLOCK, "new-clock", 0},
   {GST_MESSAGE_STRUCTURE_CHANGE, "structure-change", 0},
   {GST_MESSAGE_STREAM_STATUS, "stream-status", 0},
   {GST_MESSAGE_APPLICATION, "application", 0},
+  {GST_MESSAGE_ELEMENT, "element", 0},
   {GST_MESSAGE_SEGMENT_START, "segment-start", 0},
   {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0},
   {0, NULL, 0}
@@ -219,8 +222,24 @@ _gst_message_copy (GstMessage * message)
   return copy;
 }
 
-static GstMessage *
-gst_message_new (GstMessageType type, GstObject * src)
+/**
+ * gst_message_new_custom:
+ * @type: The #GstMessageType to distinguish messages
+ * @src: The object originating the message.
+ * @structure: The structure for the message. The message will take ownership of
+ * the structure.
+ *
+ * Create a new custom-typed message. This can be used for anything not
+ * handled by other message-specific functions to pass a message to the
+ * app. The structure field can be NULL.
+ *
+ * Returns: The new message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_custom (GstMessageType type, GstObject * src,
+    GstStructure * structure)
 {
   GstMessage *message;
 
@@ -237,7 +256,11 @@ gst_message_new (GstMessageType type, GstObject * src)
     message->src = NULL;
     GST_CAT_DEBUG (GST_CAT_MESSAGE, "NULL message source");
   }
-  message->structure = NULL;
+  if (structure) {
+    gst_structure_set_parent_refcount (structure,
+        &message->mini_object.refcount);
+  }
+  message->structure = structure;
 
   return message;
 }
@@ -259,7 +282,7 @@ gst_message_new_eos (GstObject * src)
 {
   GstMessage *message;
 
-  message = gst_message_new (GST_MESSAGE_EOS, src);
+  message = gst_message_new_custom (GST_MESSAGE_EOS, src, NULL);
 
   return message;
 }
@@ -282,14 +305,10 @@ GstMessage *
 gst_message_new_error (GstObject * src, GError * error, gchar * debug)
 {
   GstMessage *message;
-  GstStructure *s;
 
-  message = gst_message_new (GST_MESSAGE_ERROR, src);
-  /* gst_structure_new takes copies of the types passed in */
-  s = gst_structure_new ("GstMessageError", "gerror", GST_TYPE_G_ERROR, error,
-      "debug", G_TYPE_STRING, debug, NULL);
-  gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
-  message->structure = s;
+  message = gst_message_new_custom (GST_MESSAGE_ERROR, src,
+      gst_structure_new ("GstMessageError", "gerror", GST_TYPE_G_ERROR, error,
+          "debug", G_TYPE_STRING, debug, NULL));
 
   return message;
 }
@@ -311,14 +330,10 @@ GstMessage *
 gst_message_new_warning (GstObject * src, GError * error, gchar * debug)
 {
   GstMessage *message;
-  GstStructure *s;
 
-  message = gst_message_new (GST_MESSAGE_WARNING, src);
-  /* gst_structure_new takes copies of the types passed in */
-  s = gst_structure_new ("GstMessageWarning", "gerror", GST_TYPE_G_ERROR, error,
-      "debug", G_TYPE_STRING, debug, NULL);
-  gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
-  message->structure = s;
+  message = gst_message_new_custom (GST_MESSAGE_WARNING, src,
+      gst_structure_new ("GstMessageWarning", "gerror", GST_TYPE_G_ERROR, error,
+          "debug", G_TYPE_STRING, debug, NULL));
 
   return message;
 }
@@ -342,9 +357,8 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list)
 
   g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);
 
-  message = gst_message_new (GST_MESSAGE_TAG, src);
-  gst_structure_set_parent_refcount (tag_list, &message->mini_object.refcount);
-  message->structure = tag_list;
+  message =
+      gst_message_new_custom (GST_MESSAGE_TAG, src, (GstStructure *) tag_list);
 
   return message;
 }
@@ -368,16 +382,64 @@ gst_message_new_state_changed (GstObject * src,
     GstState old, GstState new, GstState pending)
 {
   GstMessage *message;
-  GstStructure *s;
 
-  message = gst_message_new (GST_MESSAGE_STATE_CHANGED, src);
+  message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src,
+      gst_structure_new ("GstMessageState",
+          "old-state", GST_TYPE_STATE, (gint) old,
+          "new-state", GST_TYPE_STATE, (gint) new,
+          "pending-state", GST_TYPE_STATE, (gint) pending, NULL));
+
+  return message;
+}
+
+/**
+ * gst_message_new_clock_provide:
+ * @src: The object originating the message.
+ * @ready: TRUE if the sender can provide a clock
+ *
+ * Create a clock provide message. This message is posted whenever an 
+ * element is ready to provide a clock or lost its ability to provide
+ * a clock (maybe because it paused or became EOS).
+ *
+ * This message is mainly used internally to manage the clock 
+ * selection.
+ *
+ * Returns: The new provide clock message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_clock_provide (GstObject * src, gboolean ready)
+{
+  GstMessage *message;
+
+  message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src,
+      gst_structure_new ("GstMessageClockProvide",
+          "ready", G_TYPE_BOOLEAN, ready, NULL));
 
-  s = gst_structure_new ("GstMessageState",
-      "old-state", GST_TYPE_STATE, (gint) old,
-      "new-state", GST_TYPE_STATE, (gint) new,
-      "pending-state", GST_TYPE_STATE, (gint) pending, NULL);
-  gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
-  message->structure = s;
+  return message;
+}
+
+/**
+ * gst_message_new_new_clock:
+ * @src: The object originating the message.
+ * @clock: the new selected clock
+ *
+ * Create a new clock message. This message is posted whenever the
+ * pipeline selectes a new clock for the pipeline.
+ *
+ * Returns: The new new clock message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_new_clock (GstObject * src, GstClock * clock)
+{
+  GstMessage *message;
+
+  message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src,
+      gst_structure_new ("GstMessageNewClock",
+          "clock", GST_TYPE_CLOCK, clock, NULL));
 
   return message;
 }
@@ -400,14 +462,10 @@ GstMessage *
 gst_message_new_segment_start (GstObject * src, GstClockTime timestamp)
 {
   GstMessage *message;
-  GstStructure *s;
-
-  message = gst_message_new (GST_MESSAGE_SEGMENT_START, src);
 
-  s = gst_structure_new ("GstMessageSegmentStart", "timestamp", G_TYPE_INT64,
-      (gint64) timestamp, NULL);
-  gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
-  message->structure = s;
+  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src,
+      gst_structure_new ("GstMessageSegmentStart", "timestamp", G_TYPE_INT64,
+          (gint64) timestamp, NULL));
 
   return message;
 }
@@ -430,14 +488,10 @@ GstMessage *
 gst_message_new_segment_done (GstObject * src, GstClockTime timestamp)
 {
   GstMessage *message;
-  GstStructure *s;
 
-  message = gst_message_new (GST_MESSAGE_SEGMENT_DONE, src);
-
-  s = gst_structure_new ("GstMessageSegmentDone", "timestamp", G_TYPE_INT64,
-      (gint64) timestamp, NULL);
-  gst_structure_set_parent_refcount (s, &message->mini_object.refcount);
-  message->structure = s;
+  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src,
+      gst_structure_new ("GstMessageSegmentDone", "timestamp", G_TYPE_INT64,
+          (gint64) timestamp, NULL));
 
   return message;
 }
@@ -479,36 +533,6 @@ gst_message_new_element (GstObject * src, GstStructure * structure)
 }
 
 /**
- * gst_message_new_custom:
- * @type: The #GstMessageType to distinguish messages
- * @src: The object originating the message.
- * @structure: The structure for the message. The message will take ownership of
- * the structure.
- *
- * Create a new custom-typed message. This can be used for anything not
- * handled by other message-specific functions to pass a message to the
- * app. The structure field can be NULL.
- *
- * Returns: The new message.
- *
- * MT safe.
- */
-GstMessage *
-gst_message_new_custom (GstMessageType type, GstObject * src,
-    GstStructure * structure)
-{
-  GstMessage *message;
-
-  message = gst_message_new (type, src);
-  if (structure) {
-    gst_structure_set_parent_refcount (structure,
-        &message->mini_object.refcount);
-    message->structure = structure;
-  }
-  return message;
-}
-
-/**
  * gst_message_get_structure:
  * @message: The #GstMessage.
  *
@@ -576,6 +600,51 @@ gst_message_parse_state_changed (GstMessage * message, GstState * old,
 }
 
 /**
+ * gst_message_parse_clock_provide:
+ * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_PROVIDE.
+ * @ready: If the src can provide a clock or not.
+ *
+ * Extracts the ready flag from the GstMessage.
+ *
+ * MT safe.
+ */
+void
+gst_message_parse_clock_provide (GstMessage * message, gboolean * ready)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);
+
+  if (ready)
+    gst_structure_get_boolean (message->structure, "ready", ready);
+}
+
+/**
+ * gst_message_parse_new_clock:
+ * @message: A valid #GstMessage of type GST_MESSAGE_NEW_CLOCK.
+ * @clock: A pointer to hold the selected new clock
+ *
+ * Extracts the new clock from the GstMessage.
+ * The clock object returned remains valid until the message is freed.
+ *
+ * MT safe.
+ */
+void
+gst_message_parse_new_clock (GstMessage * message, GstClock ** clock)
+{
+  const GValue *clock_gvalue;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);
+
+  clock_gvalue = gst_structure_get_value (message->structure, "clock");
+  g_return_if_fail (clock_gvalue != NULL);
+  g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
+
+  if (clock)
+    *clock = (GstClock *) g_value_get_object (clock_gvalue);
+}
+
+/**
  * gst_message_parse_error:
  * @message: A valid #GstMessage of type GST_MESSAGE_ERROR.
  *
index 3138638..e86d92b 100644 (file)
@@ -38,6 +38,11 @@ typedef struct _GstMessageClass GstMessageClass;
  * @GST_MESSAGE_BUFFERING: the pipeline is buffering
  * @GST_MESSAGE_STATE_CHANGED: a state change happened
  * @GST_MESSAGE_STEP_DONE: a framestep finished.
+ * @GST_MESSAGE_CLOCK_PROVIDE: an element notifies it capability of providing
+ *                             a clock.
+ * @GST_MESSAGE_CLOCK_LOST: The current clock as selected by the pipeline became
+ *                          unusable. The pipeline will select a new clock on the
+ *                          next PLAYING state change.
  * @GST_MESSAGE_NEW_CLOCK: a new clock was selected in the pipeline
  * @GST_MESSAGE_STRUCTURE_CHANGE: the structure of the pipeline changed.
  * @GST_MESSAGE_STREAM_STATUS: status about a stream, emitted when it starts,
@@ -50,6 +55,7 @@ typedef struct _GstMessageClass GstMessageClass;
  * @GST_MESSAGE_SEGMENT_DONE: pipeline completed playback of a segment.
  * @GST_MESSAGE_ANY: mask for all of the above messages.
  */
+/* NOTE: keep in sync with quark registration in gstmessage.c */
 typedef enum
 {
   GST_MESSAGE_UNKNOWN           = 0,
@@ -61,13 +67,15 @@ typedef enum
   GST_MESSAGE_BUFFERING         = (1 << 5),
   GST_MESSAGE_STATE_CHANGED     = (1 << 6),
   GST_MESSAGE_STEP_DONE         = (1 << 7),
-  GST_MESSAGE_NEW_CLOCK         = (1 << 8),
-  GST_MESSAGE_STRUCTURE_CHANGE  = (1 << 9),
-  GST_MESSAGE_STREAM_STATUS     = (1 << 10),
-  GST_MESSAGE_APPLICATION       = (1 << 11),
-  GST_MESSAGE_ELEMENT           = (1 << 12),
-  GST_MESSAGE_SEGMENT_START     = (1 << 13),
-  GST_MESSAGE_SEGMENT_DONE      = (1 << 14),
+  GST_MESSAGE_CLOCK_PROVIDE     = (1 << 8),
+  GST_MESSAGE_CLOCK_LOST        = (1 << 9),
+  GST_MESSAGE_NEW_CLOCK         = (1 << 10),
+  GST_MESSAGE_STRUCTURE_CHANGE  = (1 << 11),
+  GST_MESSAGE_STREAM_STATUS     = (1 << 12),
+  GST_MESSAGE_APPLICATION       = (1 << 13),
+  GST_MESSAGE_ELEMENT           = (1 << 14),
+  GST_MESSAGE_SEGMENT_START     = (1 << 15),
+  GST_MESSAGE_SEGMENT_DONE      = (1 << 16),
   GST_MESSAGE_ANY               = 0xffffffff
 } GstMessageType;
 
@@ -146,6 +154,9 @@ GstMessage *        gst_message_new_warning         (GstObject * src, GError * error, gchar *
 GstMessage *   gst_message_new_tag             (GstObject * src, GstTagList * tag_list);
 GstMessage *   gst_message_new_state_changed   (GstObject * src, GstState old_state,
                                                  GstState new_state, GstState pending);
+GstMessage *   gst_message_new_clock_provide   (GstObject * src, gboolean ready);
+GstMessage *   gst_message_new_clock_lost      (GstObject * src);
+GstMessage *   gst_message_new_new_clock       (GstObject * src, GstClock *clock);
 GstMessage *   gst_message_new_segment_start   (GstObject * src, GstClockTime timestamp);
 GstMessage *   gst_message_new_segment_done    (GstObject * src, GstClockTime timestamp);
 GstMessage *   gst_message_new_application     (GstObject * src, GstStructure * structure);
@@ -159,6 +170,8 @@ void                gst_message_parse_warning       (GstMessage *message, GError **gerror, gchar **d
 void           gst_message_parse_tag           (GstMessage *message, GstTagList **tag_list);
 void           gst_message_parse_state_changed (GstMessage *message, GstState *old_state,
                                                  GstState *new_state, GstState *pending);
+void           gst_message_parse_clock_provide (GstMessage *message, gboolean *ready);
+void           gst_message_parse_new_clock     (GstMessage *message, GstClock **clock);
 void           gst_message_parse_segment_start (GstMessage *message, GstClockTime *timestamp);
 void           gst_message_parse_segment_done  (GstMessage *message, GstClockTime *timestamp);
 
index c18aa96..db7683a 100644 (file)
@@ -316,15 +316,13 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
       /* when going to playing, select a clock */
       if ((clock = gst_element_provide_clock (element))) {
         GstClockTime start_time;
-
-        /* distribute the clock */
-        gst_element_set_clock (element, clock);
+        gboolean new_clock;
 
         /* get start time */
         start_time = gst_clock_get_time (clock);
-        gst_object_unref (clock);
 
         GST_LOCK (element);
+        new_clock = element->clock != clock;
         element->base_time = start_time -
             pipeline->stream_time + pipeline->delay;
         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
@@ -332,6 +330,17 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
             GST_TIME_ARGS (pipeline->stream_time),
             GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
         GST_UNLOCK (element);
+
+        /* now distribute the clock */
+        gst_element_set_clock (element, clock);
+
+        if (new_clock) {
+          /* if we selected a new clock, let the app know about it */
+          gst_element_post_message (element,
+              gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
+        }
+
+        gst_object_unref (clock);
       } else {
         GST_DEBUG ("no clock, using base time of 0");
         gst_element_set_base_time (element, 0);
index 6f2d42d..5bb82be 100644 (file)
@@ -393,6 +393,15 @@ event_loop (GstElement * pipeline, gboolean blocking)
     }
 
     switch (GST_MESSAGE_TYPE (message)) {
+      case GST_MESSAGE_NEW_CLOCK:
+      {
+        GstClock *clock;
+
+        gst_message_parse_new_clock (message, &clock);
+
+        g_print ("new clock: %p\n", clock);
+        break;
+      }
       case GST_MESSAGE_EOS:
         g_print (_
             ("Got EOS from element \"%s\".\n"),