diff --git a/ChangeLog b/ChangeLog index 3c4936f9e3..416553610a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2006-02-10 Andy Wingo + + * gst/gstbus.c (gst_bus_class_init): Declare our private data + structure. + (gst_bus_init): Cache the location of the private data in the + instance structure. + (gst_bus_enable_sync_message_emission) + (gst_bus_disable_sync_message_emission): Implement new public + functions. + (gst_bus_post): Emit the sync-message signal if the user asked for + it. Fixes #330684. + + * gst/gstbus.h (GstBus): Use a padding pointer to cache the + location of the bus-private structuure. + (gst_bus_enable_sync_message_emission) + (gst_bus_disable_sync_message_emission): New public functions. + 2006-02-10 Jan Schmidt * docs/pwg/building-boiler.xml: diff --git a/gst/gstbus.c b/gst/gstbus.c index 73d65b94e0..20ce504885 100644 --- a/gst/gstbus.c +++ b/gst/gstbus.c @@ -100,6 +100,11 @@ static guint gst_bus_signals[LAST_SIGNAL] = { 0 }; /* the context we wakeup when we posted a message on the bus */ static GMainContext *main_context; +struct _GstBusPrivate +{ + guint num_sync_message_emitters; +}; + GType gst_bus_get_type (void) { @@ -199,6 +204,8 @@ gst_bus_class_init (GstBusClass * klass) marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE); main_context = g_main_context_default (); + + g_type_class_add_private (klass, sizeof (GstBusPrivate)); } static void @@ -207,6 +214,8 @@ gst_bus_init (GstBus * bus) bus->queue = g_queue_new (); bus->queue_lock = g_mutex_new (); + bus->priv = G_TYPE_INSTANCE_GET_PRIVATE (bus, GST_TYPE_BUS, GstBusPrivate); + GST_DEBUG_OBJECT (bus, "created"); } @@ -301,6 +310,7 @@ gst_bus_post (GstBus * bus, GstMessage * message) { GstBusSyncReply reply = GST_BUS_PASS; GstBusSyncHandler handler; + gboolean emit_sync_message; gpointer handler_data; g_return_val_if_fail (GST_IS_BUS (bus), FALSE); @@ -316,12 +326,19 @@ gst_bus_post (GstBus * bus, GstMessage * message) handler = bus->sync_handler; handler_data = bus->sync_handler_data; + emit_sync_message = bus->priv->num_sync_message_emitters > 0; GST_OBJECT_UNLOCK (bus); /* first call the sync handler if it is installed */ if (handler) reply = handler (bus, message, handler_data); + /* emit sync-message if requested to do so via + gst_bus_enable_sync_message_emission. terrible but effective */ + if (emit_sync_message && reply != GST_BUS_DROP + && handler != gst_bus_sync_signal_handler) + gst_bus_sync_signal_handler (bus, message, NULL); + /* now see what we should do with the message */ switch (reply) { case GST_BUS_DROP: @@ -904,6 +921,71 @@ gst_bus_sync_signal_handler (GstBus * bus, GstMessage * message, gpointer data) return GST_BUS_PASS; } +/** + * gst_bus_enable_sync_message_emission: + * @bus: a #GstBus on which you want to receive the "sync-message" signal + * + * Instructs GStreamer to emit the sync-message signal after running the bus's + * sync handler. This function is here so that code can ensure that they can + * synchronously receive messages without having to affect what the bin's sync + * handler is. + * + * This function may be called multiple times. To clean up, the caller is + * responsible for calling gst_bus_disable_sync_message_emission() as many times + * as this function is called. + * + * While this function looks similar to gst_bus_add_signal_watch(), it is not + * exactly the same -- this function enables synchronous emission of + * signals when messages arrive; gst_bus_add_signal_watch adds an idle callback + * to pop messages off the bus asynchronously. The sync-message signal + * comes from the thread of whatever object posted the message; the message + * signal is marshalled to the main thread via the main loop. + * + * MT safe. + */ +void +gst_bus_enable_sync_message_emission (GstBus * bus) +{ + g_return_if_fail (GST_IS_BUS (bus)); + + GST_OBJECT_LOCK (bus); + + bus->priv->num_sync_message_emitters++; + + GST_OBJECT_UNLOCK (bus); +} + +/** + * gst_bus_disable_sync_message_emission: + * @bus: a #GstBus on which you previously called + * gst_bus_enable_sync_message_emission() + * + * Instructs GStreamer to stop emitting the sync-message signal for this bus. + * See gst_bus_enable_sync_message_emission() for more information. + * + * In the event that multiple pieces of code have called + * gst_bus_enable_sync_message_emission(), the sync-message emissions will only + * be stopped after all calls to gst_bus_enable_sync_message_emission() were + * "cancelled" by calling this function. In this way the semantics are exactly + * the same as gst_object_ref(); that which calls enable should also call + * disable. + * + * MT safe. + */ +void +gst_bus_disable_sync_message_emission (GstBus * bus) +{ + g_return_if_fail (GST_IS_BUS (bus)); + + g_return_if_fail (bus->num_signal_watchers == 0); + + GST_OBJECT_LOCK (bus); + + bus->priv->num_sync_message_emitters--; + + GST_OBJECT_UNLOCK (bus); +} + /** * gst_bus_add_signal_watch_full: * @bus: a #GstBus on which you want to receive the "message" signal diff --git a/gst/gstbus.h b/gst/gstbus.h index 8cfff77ce9..d8e336964d 100644 --- a/gst/gstbus.h +++ b/gst/gstbus.h @@ -23,6 +23,7 @@ #define __GST_BUS_H__ typedef struct _GstBus GstBus; +typedef struct _GstBusPrivate GstBusPrivate; typedef struct _GstBusClass GstBusClass; #include @@ -121,7 +122,8 @@ struct _GstBus guint num_signal_watchers; /*< private > */ - gpointer _gst_reserved[GST_PADDING]; + GstBusPrivate *priv; + gpointer _gst_reserved[GST_PADDING - 1]; }; struct _GstBusClass @@ -176,6 +178,9 @@ void gst_bus_add_signal_watch (GstBus * bus); void gst_bus_add_signal_watch_full (GstBus * bus, gint priority); void gst_bus_remove_signal_watch (GstBus * bus); +void gst_bus_enable_sync_message_emission (GstBus * bus); +void gst_bus_disable_sync_message_emission (GstBus * bus); + G_END_DECLS #endif /* __GST_BUS_H__ */ diff --git a/win32/common/config.h b/win32/common/config.h index 1c0f838e89..34cd8a7edf 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -21,7 +21,7 @@ #undef GST_GCOV_ENABLED /* Default errorlevel to use */ -#define GST_LEVEL_DEFAULT GST_LEVEL_NONE +#define GST_LEVEL_DEFAULT GST_LEVEL_ERROR /* GStreamer license */ #define GST_LICENSE "LGPL" @@ -30,16 +30,16 @@ #define GST_PACKAGE_ORIGIN "Unknown package origin" /* package name in plugins */ -#define GST_PACKAGE_NAME "GStreamer source release" +#define GST_PACKAGE_NAME "GStreamer CVS/prerelease" /* Define the version */ -#define GST_VERSION "0.10.3" +#define GST_VERSION "0.10.3.1" /* Define the MAJOR.MINOR version */ #define GST_MAJORMINOR "0.10" /* Define host CPU */ -#define HOST_CPU "i686" +#define HOST_CPU "powerpc" /* Define if the host CPU is an Alpha */ #undef HAVE_CPU_ALPHA @@ -216,7 +216,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.3" +#define VERSION "0.10.3.1" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */