gstreamer_core/gst/gstbus.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    93 
    93 
    94 static void gst_bus_class_init (GstBusClass * klass);
    94 static void gst_bus_class_init (GstBusClass * klass);
    95 static void gst_bus_init (GstBus * bus);
    95 static void gst_bus_init (GstBus * bus);
    96 static void gst_bus_dispose (GObject * object);
    96 static void gst_bus_dispose (GObject * object);
    97 
    97 
    98 static void gst_bus_set_property (GObject * object, guint prop_id,
    98 static void gst_bus_set_main_context (GstBus * bus, GMainContext * ctx);
    99     const GValue * value, GParamSpec * pspec);
       
   100 static void gst_bus_get_property (GObject * object, guint prop_id,
       
   101     GValue * value, GParamSpec * pspec);
       
   102 
    99 
   103 static GstObjectClass *parent_class = NULL;
   100 static GstObjectClass *parent_class = NULL;
   104 static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
   101 static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
   105 
   102 
   106 /* the context we wakeup when we posted a message on the bus */
       
   107 static GMainContext *main_context;
       
   108 
       
   109 struct _GstBusPrivate
   103 struct _GstBusPrivate
   110 {
   104 {
   111   guint num_sync_message_emitters;
   105   guint num_sync_message_emitters;
   112 
       
   113   GCond *queue_cond;
   106   GCond *queue_cond;
       
   107   GSource *watch_id;
       
   108   GMainContext *main_context;
   114 };
   109 };
   115 #ifdef __SYMBIAN32__
   110 
   116 EXPORT_C
   111 G_DEFINE_TYPE (GstBus, gst_bus, GST_TYPE_OBJECT);
   117 #endif
       
   118 
       
   119 
       
   120 GType
       
   121 gst_bus_get_type (void)
       
   122 {
       
   123   static GType bus_type = 0;
       
   124 
       
   125   if (G_UNLIKELY (bus_type == 0)) {
       
   126     static const GTypeInfo bus_info = {
       
   127       sizeof (GstBusClass),
       
   128       NULL,
       
   129       NULL,
       
   130       (GClassInitFunc) gst_bus_class_init,
       
   131       NULL,
       
   132       NULL,
       
   133       sizeof (GstBus),
       
   134       0,
       
   135       (GInstanceInitFunc) gst_bus_init,
       
   136       NULL
       
   137     };
       
   138 
       
   139     bus_type = g_type_register_static (GST_TYPE_OBJECT, "GstBus", &bus_info, 0);
       
   140   }
       
   141   return bus_type;
       
   142 }
       
   143 
   112 
   144 /* fixme: do something about this */
   113 /* fixme: do something about this */
   145 static void
   114 static void
   146 marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
   115 marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
   147     guint n_param_values, const GValue * param_values, gpointer invocation_hint,
   116     guint n_param_values, const GValue * param_values, gpointer invocation_hint,
   161   } else {
   130   } else {
   162     data1 = g_value_peek_pointer (param_values + 0);
   131     data1 = g_value_peek_pointer (param_values + 0);
   163     data2 = closure->data;
   132     data2 = closure->data;
   164   }
   133   }
   165   callback =
   134   callback =
   166       (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->
   135       (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
   167       callback);
   136       cc->callback);
   168 
   137 
   169   callback (data1, gst_value_get_mini_object (param_values + 1), data2);
   138   callback (data1, gst_value_get_mini_object (param_values + 1), data2);
   170 }
   139 }
   171 
   140 
   172 static void
   141 static void
   173 gst_bus_class_init (GstBusClass * klass)
   142 gst_bus_class_init (GstBusClass * klass)
   174 {
   143 {
   175   GObjectClass *gobject_class;
   144   GObjectClass *gobject_class = (GObjectClass *) klass;
   176   GstObjectClass *gstobject_class;
       
   177 
       
   178   gobject_class = (GObjectClass *) klass;
       
   179   gstobject_class = (GstObjectClass *) klass;
       
   180 
   145 
   181   parent_class = g_type_class_peek_parent (klass);
   146   parent_class = g_type_class_peek_parent (klass);
   182 
   147 
   183   if (!g_thread_supported ())
       
   184     g_thread_init (NULL);
       
   185 
       
   186   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bus_dispose);
   148   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bus_dispose);
   187   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bus_set_property);
       
   188   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bus_get_property);
       
   189 
   149 
   190   /**
   150   /**
   191    * GstBus::sync-message:
   151    * GstBus::sync-message:
   192    * @bus: the object which received the signal
   152    * @bus: the object which received the signal
   193    * @message: the message that has been posted synchronously
   153    * @message: the message that has been posted synchronously
   221       g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
   181       g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
   222       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
   182       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
   223       G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
   183       G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
   224       marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
   184       marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
   225 
   185 
   226   main_context = g_main_context_default ();
       
   227 
       
   228   g_type_class_add_private (klass, sizeof (GstBusPrivate));
   186   g_type_class_add_private (klass, sizeof (GstBusPrivate));
   229 }
   187 }
   230 
   188 
   231 static void
   189 static void
   232 gst_bus_init (GstBus * bus)
   190 gst_bus_init (GstBus * bus)
   241 }
   199 }
   242 
   200 
   243 static void
   201 static void
   244 gst_bus_dispose (GObject * object)
   202 gst_bus_dispose (GObject * object)
   245 {
   203 {
   246   GstBus *bus;
   204   GstBus *bus = GST_BUS (object);
   247 
       
   248   bus = GST_BUS (object);
       
   249 
   205 
   250   if (bus->queue) {
   206   if (bus->queue) {
   251     GstMessage *message;
   207     GstMessage *message;
   252 
   208 
   253     g_mutex_lock (bus->queue_lock);
   209     g_mutex_lock (bus->queue_lock);
   263     bus->queue_lock = NULL;
   219     bus->queue_lock = NULL;
   264     g_cond_free (bus->priv->queue_cond);
   220     g_cond_free (bus->priv->queue_cond);
   265     bus->priv->queue_cond = NULL;
   221     bus->priv->queue_cond = NULL;
   266   }
   222   }
   267 
   223 
       
   224   if (bus->priv->main_context) {
       
   225     g_main_context_unref (bus->priv->main_context);
       
   226     bus->priv->main_context = NULL;
       
   227   }
       
   228 
   268   G_OBJECT_CLASS (parent_class)->dispose (object);
   229   G_OBJECT_CLASS (parent_class)->dispose (object);
   269 }
   230 }
   270 
   231 
   271 static void
   232 static void
   272 gst_bus_set_property (GObject * object, guint prop_id,
   233 gst_bus_wakeup_main_context (GstBus * bus)
   273     const GValue * value, GParamSpec * pspec)
   234 {
   274 {
   235   GMainContext *ctx;
   275   GstBus *bus;
   236 
   276 
   237   GST_OBJECT_LOCK (bus);
   277   bus = GST_BUS (object);
   238   if ((ctx = bus->priv->main_context))
   278 
   239     g_main_context_ref (ctx);
   279   switch (prop_id) {
   240   GST_OBJECT_UNLOCK (bus);
   280     default:
   241 
   281       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   242   g_main_context_wakeup (ctx);
   282       break;
   243 
   283   }
   244   if (ctx)
       
   245     g_main_context_unref (ctx);
   284 }
   246 }
   285 
   247 
   286 static void
   248 static void
   287 gst_bus_get_property (GObject * object, guint prop_id,
   249 gst_bus_set_main_context (GstBus * bus, GMainContext * ctx)
   288     GValue * value, GParamSpec * pspec)
   250 {
   289 {
   251   GST_OBJECT_LOCK (bus);
   290   GstBus *bus;
   252 
   291 
   253   if (bus->priv->main_context != NULL) {
   292   bus = GST_BUS (object);
   254     g_main_context_unref (bus->priv->main_context);
   293 
   255     bus->priv->main_context = NULL;
   294   switch (prop_id) {
   256   }
   295     default:
   257 
   296       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   258   if (ctx != NULL) {
   297       break;
   259     bus->priv->main_context = g_main_context_ref (ctx);
   298   }
   260   }
       
   261 
       
   262   GST_DEBUG_OBJECT (bus, "setting main context to %p, GLib default context: %p",
       
   263       ctx, g_main_context_default ());
       
   264 
       
   265   GST_OBJECT_UNLOCK (bus);
   299 }
   266 }
   300 
   267 
   301 /**
   268 /**
   302  * gst_bus_new:
   269  * gst_bus_new:
   303  *
   270  *
   385       g_queue_push_tail (bus->queue, message);
   352       g_queue_push_tail (bus->queue, message);
   386       g_cond_broadcast (bus->priv->queue_cond);
   353       g_cond_broadcast (bus->priv->queue_cond);
   387       g_mutex_unlock (bus->queue_lock);
   354       g_mutex_unlock (bus->queue_lock);
   388       GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);
   355       GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);
   389 
   356 
   390       /* FIXME cannot assume sources are only in the default context */
   357       gst_bus_wakeup_main_context (bus);
   391       g_main_context_wakeup (main_context);
       
   392 
   358 
   393       break;
   359       break;
   394     case GST_BUS_ASYNC:
   360     case GST_BUS_ASYNC:
   395     {
   361     {
   396       /* async delivery, we need a mutex and a cond to block
   362       /* async delivery, we need a mutex and a cond to block
   410       g_mutex_lock (bus->queue_lock);
   376       g_mutex_lock (bus->queue_lock);
   411       g_queue_push_tail (bus->queue, message);
   377       g_queue_push_tail (bus->queue, message);
   412       g_cond_broadcast (bus->priv->queue_cond);
   378       g_cond_broadcast (bus->priv->queue_cond);
   413       g_mutex_unlock (bus->queue_lock);
   379       g_mutex_unlock (bus->queue_lock);
   414 
   380 
   415       /* FIXME cannot assume sources are only in the default context */
   381       gst_bus_wakeup_main_context (bus);
   416       g_main_context_wakeup (main_context);
       
   417 
   382 
   418       /* now block till the message is freed */
   383       /* now block till the message is freed */
   419       g_cond_wait (cond, lock);
   384       g_cond_wait (cond, lock);
   420       g_mutex_unlock (lock);
   385       g_mutex_unlock (lock);
   421 
   386 
   779  */
   744  */
   780 typedef struct
   745 typedef struct
   781 {
   746 {
   782   GSource source;
   747   GSource source;
   783   GstBus *bus;
   748   GstBus *bus;
       
   749   gboolean inited;
   784 } GstBusSource;
   750 } GstBusSource;
   785 
   751 
   786 static gboolean
   752 static gboolean
   787 gst_bus_source_prepare (GSource * source, gint * timeout)
   753 gst_bus_source_prepare (GSource * source, gint * timeout)
   788 {
   754 {
   789   GstBusSource *bsrc = (GstBusSource *) source;
   755   GstBusSource *bsrc = (GstBusSource *) source;
       
   756 
       
   757   /* we do this here now that we know that we're attached to a main context
       
   758    * (we don't support detaching a source from a main context and then
       
   759    * re-attaching it to a different main context) */
       
   760   if (G_UNLIKELY (!bsrc->inited)) {
       
   761     gst_bus_set_main_context (bsrc->bus, g_source_get_context (source));
       
   762     bsrc->inited = TRUE;
       
   763   }
   790 
   764 
   791   *timeout = -1;
   765   *timeout = -1;
   792   return gst_bus_have_pending (bsrc->bus);
   766   return gst_bus_have_pending (bsrc->bus);
   793 }
   767 }
   794 
   768 
   815   bus = bsource->bus;
   789   bus = bsource->bus;
   816 
   790 
   817   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
   791   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
   818 
   792 
   819   message = gst_bus_pop (bus);
   793   message = gst_bus_pop (bus);
   820   g_return_val_if_fail (message != NULL, FALSE);
   794 
       
   795   /* The message queue might be empty if some other thread or callback set
       
   796    * the bus to flushing between check/prepare and dispatch */
       
   797   if (G_UNLIKELY (message == NULL))
       
   798     return TRUE;
   821 
   799 
   822   if (!handler)
   800   if (!handler)
   823     goto no_handler;
   801     goto no_handler;
   824 
   802 
   825   GST_DEBUG_OBJECT (bus, "source %p calling dispatch with %p", source, message);
   803   GST_DEBUG_OBJECT (bus, "source %p calling dispatch with %p", source, message);
   842 
   820 
   843 static void
   821 static void
   844 gst_bus_source_finalize (GSource * source)
   822 gst_bus_source_finalize (GSource * source)
   845 {
   823 {
   846   GstBusSource *bsource = (GstBusSource *) source;
   824   GstBusSource *bsource = (GstBusSource *) source;
   847 
   825   GstBus *bus;
       
   826 
       
   827   bus = bsource->bus;
       
   828 
       
   829   GST_DEBUG_OBJECT (bus, "finalize source %p", source);
       
   830 
       
   831   GST_OBJECT_LOCK (bus);
       
   832   if (bus->priv->watch_id == source)
       
   833     bus->priv->watch_id = NULL;
       
   834   GST_OBJECT_UNLOCK (bus);
       
   835 
       
   836   gst_bus_set_main_context (bsource->bus, NULL);
   848   gst_object_unref (bsource->bus);
   837   gst_object_unref (bsource->bus);
   849   bsource->bus = NULL;
   838   bsource->bus = NULL;
   850 }
   839 }
   851 
   840 
   852 static GSourceFuncs gst_bus_source_funcs = {
   841 static GSourceFuncs gst_bus_source_funcs = {
   877 
   866 
   878   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
   867   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
   879 
   868 
   880   source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
   869   source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
   881       sizeof (GstBusSource));
   870       sizeof (GstBusSource));
   882   gst_object_ref (bus);
   871   source->bus = gst_object_ref (bus);
   883   source->bus = bus;
   872   source->inited = FALSE;
   884 
   873 
   885   return (GSource *) source;
   874   return (GSource *) source;
       
   875 }
       
   876 
       
   877 /* must be called with the bus OBJECT LOCK */
       
   878 static guint
       
   879 gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
       
   880     GstBusFunc func, gpointer user_data, GDestroyNotify notify)
       
   881 {
       
   882   guint id;
       
   883   GSource *source;
       
   884 
       
   885   if (bus->priv->watch_id) {
       
   886     GST_ERROR_OBJECT (bus,
       
   887         "Tried to add new watch while one was already there");
       
   888     return 0;
       
   889   }
       
   890 
       
   891   source = gst_bus_create_watch (bus);
       
   892 
       
   893   if (priority != G_PRIORITY_DEFAULT)
       
   894     g_source_set_priority (source, priority);
       
   895 
       
   896   g_source_set_callback (source, (GSourceFunc) func, user_data, notify);
       
   897 
       
   898   id = g_source_attach (source, NULL);
       
   899   g_source_unref (source);
       
   900 
       
   901   if (id) {
       
   902     bus->priv->watch_id = source;
       
   903   }
       
   904 
       
   905   GST_DEBUG_OBJECT (bus, "New source %p with id %u", source, id);
       
   906   return id;
   886 }
   907 }
   887 
   908 
   888 /**
   909 /**
   889  * gst_bus_add_watch_full:
   910  * gst_bus_add_watch_full:
   890  * @bus: a #GstBus to create the watch for.
   911  * @bus: a #GstBus to create the watch for.
   893  * @user_data: user data passed to @func.
   914  * @user_data: user data passed to @func.
   894  * @notify: the function to call when the source is removed.
   915  * @notify: the function to call when the source is removed.
   895  *
   916  *
   896  * Adds a bus watch to the default main context with the given @priority.
   917  * Adds a bus watch to the default main context with the given @priority.
   897  * This function is used to receive asynchronous messages in the main loop.
   918  * This function is used to receive asynchronous messages in the main loop.
       
   919  * There can only be a single bus watch per bus, you must remove it before you
       
   920  * can set a new one.
   898  *
   921  *
   899  * When @func is called, the message belongs to the caller; if you want to
   922  * When @func is called, the message belongs to the caller; if you want to
   900  * keep a copy of it, call gst_message_ref() before leaving @func.
   923  * keep a copy of it, call gst_message_ref() before leaving @func.
   901  *
   924  *
   902  * The watch can be removed using g_source_remove() or by returning FALSE
   925  * The watch can be removed using g_source_remove() or by returning FALSE
   913 guint
   936 guint
   914 gst_bus_add_watch_full (GstBus * bus, gint priority,
   937 gst_bus_add_watch_full (GstBus * bus, gint priority,
   915     GstBusFunc func, gpointer user_data, GDestroyNotify notify)
   938     GstBusFunc func, gpointer user_data, GDestroyNotify notify)
   916 {
   939 {
   917   guint id;
   940   guint id;
   918   GSource *source;
       
   919 
   941 
   920   g_return_val_if_fail (GST_IS_BUS (bus), 0);
   942   g_return_val_if_fail (GST_IS_BUS (bus), 0);
   921 
   943 
   922   source = gst_bus_create_watch (bus);
   944   GST_OBJECT_LOCK (bus);
   923 
   945   id = gst_bus_add_watch_full_unlocked (bus, priority, func, user_data, notify);
   924   if (priority != G_PRIORITY_DEFAULT)
   946   GST_OBJECT_UNLOCK (bus);
   925     g_source_set_priority (source, priority);
   947 
   926 
       
   927   g_source_set_callback (source, (GSourceFunc) func, user_data, notify);
       
   928 
       
   929   id = g_source_attach (source, NULL);
       
   930   g_source_unref (source);
       
   931 
       
   932   GST_DEBUG_OBJECT (bus, "New source %p", source);
       
   933   return id;
   948   return id;
   934 }
   949 }
   935 
   950 
   936 /**
   951 /**
   937  * gst_bus_add_watch:
   952  * gst_bus_add_watch:
   939  * @func: A function to call when a message is received.
   954  * @func: A function to call when a message is received.
   940  * @user_data: user data passed to @func.
   955  * @user_data: user data passed to @func.
   941  *
   956  *
   942  * Adds a bus watch to the default main context with the default priority.
   957  * Adds a bus watch to the default main context with the default priority.
   943  * This function is used to receive asynchronous messages in the main loop.
   958  * This function is used to receive asynchronous messages in the main loop.
       
   959  * There can only be a single bus watch per bus, you must remove it before you
       
   960  * can set a new one.
   944  *
   961  *
   945  * The watch can be removed using g_source_remove() or by returning FALSE
   962  * The watch can be removed using g_source_remove() or by returning FALSE
   946  * from @func.
   963  * from @func.
   947  *
   964  *
   948  * Returns: The event source id.
   965  * Returns: The event source id.
  1026 /**
  1043 /**
  1027  * gst_bus_poll:
  1044  * gst_bus_poll:
  1028  * @bus: a #GstBus
  1045  * @bus: a #GstBus
  1029  * @events: a mask of #GstMessageType, representing the set of message types to
  1046  * @events: a mask of #GstMessageType, representing the set of message types to
  1030  * poll for.
  1047  * poll for.
  1031  * @timeout: the poll timeout, as a #GstClockTimeDiff, or -1 to poll indefinitely.
  1048  * @timeout: the poll timeout, as a #GstClockTimeDiff, or -1 to poll
       
  1049  * indefinitely.
  1032  *
  1050  *
  1033  * Poll the bus for messages. Will block while waiting for messages to come.
  1051  * Poll the bus for messages. Will block while waiting for messages to come.
  1034  * You can specify a maximum time to poll with the @timeout parameter. If
  1052  * You can specify a maximum time to poll with the @timeout parameter. If
  1035  * @timeout is negative, this function will block indefinitely.
  1053  * @timeout is negative, this function will block indefinitely.
  1036  *
  1054  *
  1042  * signal handler will see the same messages that this function sees -- neither
  1060  * signal handler will see the same messages that this function sees -- neither
  1043  * will steal messages from the other.
  1061  * will steal messages from the other.
  1044  *
  1062  *
  1045  * This function will run a main loop from the default main context when
  1063  * This function will run a main loop from the default main context when
  1046  * polling.
  1064  * polling.
       
  1065  *
       
  1066  * You should never use this function, since it is pure evil. This is
       
  1067  * especially true for GUI applications based on Gtk+ or Qt, but also for any
       
  1068  * other non-trivial application that uses the GLib main loop. As this function
       
  1069  * runs a GLib main loop, any callback attached to the default GLib main
       
  1070  * context may be invoked. This could be timeouts, GUI events, I/O events etc.;
       
  1071  * even if gst_bus_poll() is called with a 0 timeout. Any of these callbacks
       
  1072  * may do things you do not expect, e.g. destroy the main application window or
       
  1073  * some other resource; change other application state; display a dialog and
       
  1074  * run another main loop until the user clicks it away. In short, using this
       
  1075  * function may add a lot of complexity to your code through unexpected
       
  1076  * re-entrancy and unexpected changes to your application's state.
       
  1077  *
       
  1078  * For 0 timeouts use gst_bus_pop_filtered() instead of this function; for
       
  1079  * other short timeouts use gst_bus_timed_pop_filtered(); everything else is
       
  1080  * better handled by setting up an asynchronous bus watch and doing things
       
  1081  * from there.
  1047  *
  1082  *
  1048  * Returns: The message that was received, or NULL if the poll timed out.
  1083  * Returns: The message that was received, or NULL if the poll timed out.
  1049  * The message is taken from the bus and needs to be unreffed with
  1084  * The message is taken from the bus and needs to be unreffed with
  1050  * gst_message_unref() after usage.
  1085  * gst_message_unref() after usage.
  1051  */
  1086  */
  1190 gst_bus_enable_sync_message_emission (GstBus * bus)
  1225 gst_bus_enable_sync_message_emission (GstBus * bus)
  1191 {
  1226 {
  1192   g_return_if_fail (GST_IS_BUS (bus));
  1227   g_return_if_fail (GST_IS_BUS (bus));
  1193 
  1228 
  1194   GST_OBJECT_LOCK (bus);
  1229   GST_OBJECT_LOCK (bus);
  1195 
       
  1196   bus->priv->num_sync_message_emitters++;
  1230   bus->priv->num_sync_message_emitters++;
  1197 
       
  1198   GST_OBJECT_UNLOCK (bus);
  1231   GST_OBJECT_UNLOCK (bus);
  1199 }
  1232 }
  1200 
  1233 
  1201 /**
  1234 /**
  1202  * gst_bus_disable_sync_message_emission:
  1235  * gst_bus_disable_sync_message_emission:
  1221 
  1254 
  1222 void
  1255 void
  1223 gst_bus_disable_sync_message_emission (GstBus * bus)
  1256 gst_bus_disable_sync_message_emission (GstBus * bus)
  1224 {
  1257 {
  1225   g_return_if_fail (GST_IS_BUS (bus));
  1258   g_return_if_fail (GST_IS_BUS (bus));
  1226 
       
  1227   g_return_if_fail (bus->num_signal_watchers == 0);
  1259   g_return_if_fail (bus->num_signal_watchers == 0);
  1228 
  1260 
  1229   GST_OBJECT_LOCK (bus);
  1261   GST_OBJECT_LOCK (bus);
  1230 
       
  1231   bus->priv->num_sync_message_emitters--;
  1262   bus->priv->num_sync_message_emitters--;
  1232 
       
  1233   GST_OBJECT_UNLOCK (bus);
  1263   GST_OBJECT_UNLOCK (bus);
  1234 }
  1264 }
  1235 
  1265 
  1236 /**
  1266 /**
  1237  * gst_bus_add_signal_watch_full:
  1267  * gst_bus_add_signal_watch_full:
  1244  *
  1274  *
  1245  * This function may be called multiple times. To clean up, the caller is
  1275  * This function may be called multiple times. To clean up, the caller is
  1246  * responsible for calling gst_bus_remove_signal_watch() as many times as this
  1276  * responsible for calling gst_bus_remove_signal_watch() as many times as this
  1247  * function is called.
  1277  * function is called.
  1248  *
  1278  *
       
  1279  * There can only be a single bus watch per bus, you most remove all signal watch
       
  1280  * before you can set another type of watch.
       
  1281  *
  1249  * MT safe.
  1282  * MT safe.
  1250  */
  1283  */
  1251 #ifdef __SYMBIAN32__
  1284 #ifdef __SYMBIAN32__
  1252 EXPORT_C
  1285 EXPORT_C
  1253 #endif
  1286 #endif
  1261   GST_OBJECT_LOCK (bus);
  1294   GST_OBJECT_LOCK (bus);
  1262 
  1295 
  1263   if (bus->num_signal_watchers > 0)
  1296   if (bus->num_signal_watchers > 0)
  1264     goto done;
  1297     goto done;
  1265 
  1298 
       
  1299   /* this should not fail because the counter above takes care of it */
  1266   g_assert (bus->signal_watch_id == 0);
  1300   g_assert (bus->signal_watch_id == 0);
  1267 
  1301 
  1268   bus->signal_watch_id =
  1302   bus->signal_watch_id =
  1269       gst_bus_add_watch_full (bus, priority, gst_bus_async_signal_func, NULL,
  1303       gst_bus_add_watch_full_unlocked (bus, priority, gst_bus_async_signal_func,
  1270       NULL);
  1304       NULL, NULL);
       
  1305 
       
  1306   if (G_UNLIKELY (bus->signal_watch_id == 0))
       
  1307     goto add_failed;
  1271 
  1308 
  1272 done:
  1309 done:
  1273 
  1310 
  1274   bus->num_signal_watchers++;
  1311   bus->num_signal_watchers++;
  1275 
  1312 
  1276   GST_OBJECT_UNLOCK (bus);
  1313   GST_OBJECT_UNLOCK (bus);
       
  1314   return;
       
  1315 
       
  1316   /* ERRORS */
       
  1317 add_failed:
       
  1318   {
       
  1319     g_critical ("Could not add signal watch to bus %s", GST_OBJECT_NAME (bus));
       
  1320     GST_OBJECT_UNLOCK (bus);
       
  1321     return;
       
  1322   }
  1277 }
  1323 }
  1278 
  1324 
  1279 /**
  1325 /**
  1280  * gst_bus_add_signal_watch:
  1326  * gst_bus_add_signal_watch:
  1281  * @bus: a #GstBus on which you want to receive the "message" signal
  1327  * @bus: a #GstBus on which you want to receive the "message" signal
  1293  */
  1339  */
  1294 #ifdef __SYMBIAN32__
  1340 #ifdef __SYMBIAN32__
  1295 EXPORT_C
  1341 EXPORT_C
  1296 #endif
  1342 #endif
  1297 
  1343 
  1298  
       
  1299 void
  1344 void
  1300 gst_bus_add_signal_watch (GstBus * bus)
  1345 gst_bus_add_signal_watch (GstBus * bus)
  1301 {
  1346 {
  1302   gst_bus_add_signal_watch_full (bus, G_PRIORITY_DEFAULT);
  1347   gst_bus_add_signal_watch_full (bus, G_PRIORITY_DEFAULT);
  1303 }
  1348 }
  1315 #endif
  1360 #endif
  1316 
  1361 
  1317 void
  1362 void
  1318 gst_bus_remove_signal_watch (GstBus * bus)
  1363 gst_bus_remove_signal_watch (GstBus * bus)
  1319 {
  1364 {
       
  1365   guint id = 0;
       
  1366 
  1320   g_return_if_fail (GST_IS_BUS (bus));
  1367   g_return_if_fail (GST_IS_BUS (bus));
  1321 
  1368 
  1322   /* I know the callees don't take this lock, so go ahead and abuse it */
  1369   /* I know the callees don't take this lock, so go ahead and abuse it */
  1323   GST_OBJECT_LOCK (bus);
  1370   GST_OBJECT_LOCK (bus);
  1324 
  1371 
  1328   bus->num_signal_watchers--;
  1375   bus->num_signal_watchers--;
  1329 
  1376 
  1330   if (bus->num_signal_watchers > 0)
  1377   if (bus->num_signal_watchers > 0)
  1331     goto done;
  1378     goto done;
  1332 
  1379 
  1333   g_source_remove (bus->signal_watch_id);
  1380   id = bus->signal_watch_id;
  1334   bus->signal_watch_id = 0;
  1381   bus->signal_watch_id = 0;
       
  1382 
       
  1383   GST_DEBUG_OBJECT (bus, "removing signal watch %u", id);
  1335 
  1384 
  1336 done:
  1385 done:
  1337   GST_OBJECT_UNLOCK (bus);
  1386   GST_OBJECT_UNLOCK (bus);
       
  1387 
       
  1388   if (id)
       
  1389     g_source_remove (id);
       
  1390 
  1338   return;
  1391   return;
  1339 
  1392 
       
  1393   /* ERRORS */
  1340 error:
  1394 error:
  1341   {
  1395   {
  1342     g_critical ("Bus %s has no signal watches attached", GST_OBJECT_NAME (bus));
  1396     g_critical ("Bus %s has no signal watches attached", GST_OBJECT_NAME (bus));
  1343     GST_OBJECT_UNLOCK (bus);
  1397     GST_OBJECT_UNLOCK (bus);
  1344     return;
  1398     return;