gst/gstbus.*: Added async-message and sync-message signals to the bus.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 28 Sep 2005 16:43:20 +0000 (16:43 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 28 Sep 2005 16:43:20 +0000 (16:43 +0000)
Original commit message from CVS:
* gst/gstbus.c: (marshal_VOID__MINIOBJECT), (gst_bus_class_init),
(gst_bus_post), (poll_func), (gst_bus_async_signal_func),
(gst_bus_sync_signal_handler):
* gst/gstbus.h:
Added async-message and sync-message signals to the bus.
Added helper BusFunc to emit signals for all posted messages.

* gst/gstmessage.c: (gst_message_type_get_name),
(gst_message_type_to_quark), (gst_message_get_type):
* gst/gstmessage.h:
Register quarks for message names.

ChangeLog
gst/gstbus.c
gst/gstbus.h
gst/gstmessage.c
gst/gstmessage.h

index 7fcb44775159df49ae11b515012bed0db308a8e6..9aee4ac9050dde46e74c8de62de630d30fd49b15 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2005-09-28  Wim Taymans  <wim@fluendo.com>
+
+       * gst/gstbus.c: (marshal_VOID__MINIOBJECT), (gst_bus_class_init),
+       (gst_bus_post), (poll_func), (gst_bus_async_signal_func),
+       (gst_bus_sync_signal_handler):
+       * gst/gstbus.h:
+       Added async-message and sync-message signals to the bus.
+       Added helper BusFunc to emit signals for all posted messages.
+
+       * gst/gstmessage.c: (gst_message_type_get_name),
+       (gst_message_type_to_quark), (gst_message_get_type):
+       * gst/gstmessage.h:
+       Register quarks for message names.
+
 2005-09-28  Stefan Kost  <ensonic@users.sf.net>
 
        * docs/libs/gstreamer-libs-sections.txt:
index 6be0db4b98b5401d4c9ba316549b3918fdb32df4..7745572b31eec690309577d9bba058e8cf18a2cb 100644 (file)
 
 #include "gstbus.h"
 
+/* bus signals */
+enum
+{
+  SYNC_MESSAGE,
+  ASYNC_MESSAGE,
+  /* add more above */
+  LAST_SIGNAL
+};
 
 static void gst_bus_class_init (GstBusClass * klass);
 static void gst_bus_init (GstBus * bus);
@@ -79,8 +87,7 @@ static void gst_bus_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static GstObjectClass *parent_class = NULL;
-
-/* static guint gst_bus_signals[LAST_SIGNAL] = { 0 }; */
+static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
 
 GType
 gst_bus_get_type (void)
@@ -106,6 +113,34 @@ gst_bus_get_type (void)
   return bus_type;
 }
 
+/* fixme: do something about this */
+static void
+marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
+    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
+    gpointer marshal_data)
+{
+  typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1,
+      gpointer data2);
+  register marshalfunc_VOID__MINIOBJECT callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback =
+      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->
+      callback);
+
+  callback (data1, gst_value_get_mini_object (param_values + 1), data2);
+}
+
 static void
 gst_bus_class_init (GstBusClass * klass)
 {
@@ -123,6 +158,34 @@ gst_bus_class_init (GstBusClass * klass)
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bus_dispose);
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bus_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bus_get_property);
+
+  /**
+   * GstBus::sync-message:
+   * @bus: the object which received the signal
+   * @message: the message that has been posted synchronously
+   *
+   * A message has been posted on the bus. This signal is emited from the
+   * thread that posted the message so one has to be carefull with locking.
+   */
+  gst_bus_signals[SYNC_MESSAGE] =
+      g_signal_new ("sync-message", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+      G_STRUCT_OFFSET (GstBusClass, sync_message), NULL, NULL,
+      marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
+
+  /**
+   * GstBus::async-message:
+   * @bus: the object which received the signal
+   * @message: the message that has been posted asynchronously
+   *
+   * A message has been posted on the bus. This signal is emited from a
+   * GSource added to the mainloop.
+   */
+  gst_bus_signals[ASYNC_MESSAGE] =
+      g_signal_new ("async-message", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+      G_STRUCT_OFFSET (GstBusClass, async_message), NULL, NULL,
+      marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 }
 
 static void
@@ -231,8 +294,8 @@ gst_bus_post (GstBus * bus, GstMessage * message)
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
   g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
 
-  GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus, type %d",
-      message, GST_MESSAGE_TYPE (message));
+  GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus, type %s",
+      message, gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
 
   GST_LOCK (bus);
   /* check if the bus is flushing */
@@ -382,6 +445,7 @@ gst_bus_set_flushing (GstBus * bus, gboolean flushing)
   GST_UNLOCK (bus);
 }
 
+
 /**
  * gst_bus_pop:
  * @bus: a #GstBus to pop
@@ -671,9 +735,8 @@ poll_func (GstBus * bus, GstMessage * message, GstBusPollData * poll_data)
     poll_data->message = gst_message_ref (message);
     GST_DEBUG ("mainloop %p quit", poll_data->loop);
     g_main_loop_quit (poll_data->loop);
-  } else {
-    /* don't remove the source. */
   }
+
   /* we always keep the source alive so that we don't accidentialy
    * free the poll_data */
   return TRUE;
@@ -721,6 +784,8 @@ poll_destroy_timeout (GstBusPollData * poll_data)
  * specify a maximum time to poll with the @timeout parameter. If @timeout is
  * negative, this function will block indefinitely.
  *
+ * All messages not in @events will be popped off the bus and will be ignored.
+ *
  * This function will enter the default mainloop while polling.
  *
  * Returns: The message that was received, or NULL if the poll timed out. 
@@ -765,3 +830,50 @@ gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTimeDiff timeout)
 
   return ret;
 }
+
+/**
+ * gst_bus_async_signal_func:
+ * @bus: a #GstBus
+ * @message: the message received
+ * @data: user data
+ *
+ * A helper GstBusFunc that can be used to convert all asynchronous messages 
+ * into signals.
+ *
+ * Returns: TRUE
+ */
+gboolean
+gst_bus_async_signal_func (GstBus * bus, GstMessage * message, gpointer data)
+{
+  GQuark detail = 0;
+
+  detail = gst_message_type_to_quark (GST_MESSAGE_TYPE (message));
+
+  g_signal_emit (bus, gst_bus_signals[ASYNC_MESSAGE], detail, message);
+
+  /* we never remove this source based on signal emission return values */
+  return TRUE;
+}
+
+/**
+ * gst_bus_sync_signal_handler:
+ * @bus: a #GstBus
+ * @message: the message received
+ * @data: user data
+ *
+ * A helper GstBusSyncHandler that can be used to convert all synchronous
+ * messages into signals.
+ *
+ * Returns: GST_BUS_PASS
+ */
+GstBusSyncReply
+gst_bus_sync_signal_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+  GQuark detail = 0;
+
+  detail = gst_message_type_to_quark (GST_MESSAGE_TYPE (message));
+
+  g_signal_emit (bus, gst_bus_signals[SYNC_MESSAGE], detail, message);
+
+  return GST_BUS_PASS;
+}
index ff7625e3ba9c67f4d94c7a2c01eb2ffd7ef65d4a..534cb60aa0bcfd9e05e2a08139b987276d52a427 100644 (file)
@@ -102,6 +102,10 @@ struct _GstBusClass
 {
   GstObjectClass parent_class;
 
+  /* signals */
+  void (*sync_message)   (GstBus *bus, GstMessage *message);
+  void (*async_message)  (GstBus *bus, GstMessage *message);
+
   /*< private > */
   gpointer _gst_reserved[GST_PADDING];
 };
@@ -117,9 +121,10 @@ GstMessage *               gst_bus_peek                    (GstBus * bus);
 GstMessage *           gst_bus_pop                     (GstBus * bus);
 void                   gst_bus_set_flushing            (GstBus * bus, gboolean flushing);
 
+/* synchronous dispatching */
 void                   gst_bus_set_sync_handler        (GstBus * bus, GstBusSyncHandler func,
                                                         gpointer data);
-
+/* GSource based dispatching */
 GSource *              gst_bus_create_watch            (GstBus * bus, GstMessageType events);
 guint                  gst_bus_add_watch_full          (GstBus * bus,
                                                         gint priority,
@@ -132,9 +137,16 @@ guint                      gst_bus_add_watch               (GstBus * bus,
                                                         GstBusFunc func, 
                                                         gpointer user_data);
 
+/* polling the bus */
 GstMessage*            gst_bus_poll                    (GstBus *bus, GstMessageType events,
                                                          GstClockTimeDiff timeout);
 
+/* signal based dispatching helper functions. */
+gboolean               gst_bus_async_signal_func       (GstBus *bus, GstMessage *message,
+                                                        gpointer data);
+GstBusSyncReply                gst_bus_sync_signal_handler     (GstBus *bus, GstMessage *message,
+                                                        gpointer data);
+
 G_END_DECLS
 
 #endif /* __GST_BUS_H__ */
index 4a94e77b98af71cafdaae8debf9cb4d88e9961c6..d39b07cc7ecc87b98c3e4402d48142c063a512df 100644 (file)
@@ -47,7 +47,6 @@ static void gst_message_class_init (gpointer g_class, gpointer class_data);
 static void gst_message_finalize (GstMessage * message);
 static GstMessage *_gst_message_copy (GstMessage * message);
 
-
 void
 _gst_message_initialize (void)
 {
@@ -64,12 +63,63 @@ _gst_message_initialize (void)
   g_type_class_unref (ptr);
 }
 
+typedef struct
+{
+  gint type;
+  gchar *name;
+  GQuark quark;
+} GstMessageQuarks;
+
+static GstMessageQuarks message_quarks[] = {
+  {GST_MESSAGE_UNKNOWN, "unknown", 0},
+  {GST_MESSAGE_EOS, "eos", 0},
+  {GST_MESSAGE_ERROR, "error", 0},
+  {GST_MESSAGE_WARNING, "warning", 0},
+  {GST_MESSAGE_INFO, "info", 0},
+  {GST_MESSAGE_TAG, "tag", 0},
+  {GST_MESSAGE_BUFFERING, "buffering", 0},
+  {GST_MESSAGE_STATE_CHANGED, "state-changed", 0},
+  {GST_MESSAGE_STEP_DONE, "step-done", 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_SEGMENT_START, "segment-start", 0},
+  {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0},
+  {0, NULL, 0}
+};
+
+const gchar *
+gst_message_type_get_name (GstMessageType type)
+{
+  gint i;
+
+  for (i = 0; message_quarks[i].name; i++) {
+    if (type == message_quarks[i].type)
+      return message_quarks[i].name;
+  }
+  return "unknown";
+}
+
+GQuark
+gst_message_type_to_quark (GstMessageType type)
+{
+  gint i;
+
+  for (i = 0; message_quarks[i].name; i++) {
+    if (type == message_quarks[i].type)
+      return message_quarks[i].quark;
+  }
+  return 0;
+}
+
 GType
 gst_message_get_type (void)
 {
   static GType _gst_message_type;
 
   if (G_UNLIKELY (_gst_message_type == 0)) {
+    gint i;
     static const GTypeInfo message_info = {
       sizeof (GstMessageClass),
       NULL,
@@ -85,6 +135,11 @@ gst_message_get_type (void)
 
     _gst_message_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
         "GstMessage", &message_info, 0);
+
+    for (i = 0; message_quarks[i].name; i++) {
+      message_quarks[i].quark =
+          g_quark_from_static_string (message_quarks[i].name);
+    }
   }
   return _gst_message_type;
 }
index 8a6abb498180119d4dd645f21cd52ac91e254ec9..0eef07951b496083353e4b9acbf010efa69e58c1 100644 (file)
@@ -127,6 +127,9 @@ void                _gst_message_initialize         (void);
 
 GType          gst_message_get_type            (void);
 
+const gchar*   gst_message_type_get_name       (GstMessageType type);
+GQuark         gst_message_type_to_quark       (GstMessageType type);
+
 /* refcounting */
 #define         gst_message_ref(msg)           GST_MESSAGE (gst_mini_object_ref (GST_MINI_OBJECT (msg)))
 #define         gst_message_unref(msg)         gst_mini_object_unref (GST_MINI_OBJECT (msg))