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) |
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 |
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; |