diff --git a/ChangeLog b/ChangeLog index 7fcb447751..9aee4ac905 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2005-09-28 Wim Taymans + + * 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 * docs/libs/gstreamer-libs-sections.txt: diff --git a/gst/gstbus.c b/gst/gstbus.c index 6be0db4b98..7745572b31 100644 --- a/gst/gstbus.c +++ b/gst/gstbus.c @@ -68,6 +68,14 @@ #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; +} diff --git a/gst/gstbus.h b/gst/gstbus.h index ff7625e3ba..534cb60aa0 100644 --- a/gst/gstbus.h +++ b/gst/gstbus.h @@ -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__ */ diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 4a94e77b98..d39b07cc7e 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -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; } diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 8a6abb4981..0eef07951b 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -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))