First THREADED backport attempt, focusing on adding locks and making sure the API...
[platform/upstream/gstreamer.git] / gst / gstprobe.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *
5  * gstprobe.h: Header for GstProbe object
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "gst_private.h"
24 #include "gstprobe.h"
25
26 static GstProbe *
27 _gst_probe_copy (const GstProbe * src)
28 {
29   return gst_probe_new (src->single_shot, src->callback, src->user_data);
30 }
31
32 GType
33 gst_probe_get_type (void)
34 {
35   static GType gst_probe_type = 0;
36
37   if (!gst_probe_type) {
38     gst_probe_type = g_boxed_type_register_static ("GstProbe",
39         (GBoxedCopyFunc) _gst_probe_copy, (GBoxedFreeFunc) gst_probe_destroy);
40   }
41
42   return gst_probe_type;
43
44 }
45
46 /**
47  * gst_probe_new:
48  * @single_shot: TRUE if a single shot probe is required
49  * @callback: the function to call when the probe is triggered
50  * @user_data: data passed to the callback function
51  *
52  * Create a new probe with the specified parameters. The single shot
53  * probe will be fired only once. It is the responsability of the
54  * application to free the single probe after it has been fired.
55  *
56  * Returns: a new #GstProbe.
57  */
58 GstProbe *
59 gst_probe_new (gboolean single_shot,
60     GstProbeCallback callback, gpointer user_data)
61 {
62   GstProbe *probe;
63
64   g_return_val_if_fail (callback, NULL);
65
66   probe = g_new0 (GstProbe, 1);
67
68   probe->single_shot = single_shot;
69   probe->callback = callback;
70   probe->user_data = user_data;
71
72   GST_CAT_DEBUG (GST_CAT_PROBE, "created probe %p", probe);
73
74   return probe;
75 }
76
77 /**
78  * gst_probe_destroy:
79  * @probe: The probe to destroy
80  *
81  * Free the memory associated with the probe.
82  */
83 void
84 gst_probe_destroy (GstProbe * probe)
85 {
86   g_return_if_fail (probe);
87
88 #ifdef USE_POISONING
89   memset (probe, 0xff, sizeof (*probe));
90 #endif
91
92   g_free (probe);
93 }
94
95 /**
96  * gst_probe_perform:
97  * @probe: The probe to trigger
98  * @data: the GstData that triggered the probe.
99  *
100  * Perform the callback associated with the given probe.
101  *
102  * Returns: the result of the probe callback function.
103  */
104 gboolean
105 gst_probe_perform (GstProbe * probe, GstData ** data)
106 {
107   gboolean res = TRUE;
108
109   g_return_val_if_fail (probe, res);
110
111   GST_CAT_DEBUG (GST_CAT_PROBE, "performing probe %p", probe);
112
113   if (probe->callback)
114     res = probe->callback (probe, data, probe->user_data);
115
116   return res;
117 }
118
119 /**
120  * gst_probe_dispatcher_new:
121  *
122  * Create a new probe dispatcher
123  *
124  * Returns: a new probe dispatcher.
125  */
126 GstProbeDispatcher *
127 gst_probe_dispatcher_new (void)
128 {
129   GstProbeDispatcher *disp;
130
131   disp = g_new0 (GstProbeDispatcher, 1);
132
133   gst_probe_dispatcher_init (disp);
134
135   return disp;
136 }
137
138 /**
139  * gst_probe_dispatcher_destroy:
140  * @disp: the dispatcher to destroy
141  *
142  * Free the memory allocated by the probe dispatcher. All pending
143  * probes are removed first.
144  */
145 void
146 gst_probe_dispatcher_destroy (GstProbeDispatcher * disp)
147 {
148   g_return_if_fail (disp);
149
150 #ifdef USE_POISONING
151   memset (disp, 0xff, sizeof (*disp));
152 #endif
153
154   /* FIXME, free pending probes */
155   g_free (disp);
156 }
157
158 /**
159  * gst_probe_dispatcher_init:
160  * @disp: the dispatcher to initialize
161  *
162  * Initialize the dispatcher. Useful for statically allocated probe
163  * dispatchers.
164  */
165 void
166 gst_probe_dispatcher_init (GstProbeDispatcher * disp)
167 {
168   g_return_if_fail (disp);
169
170   disp->active = TRUE;
171   disp->probes = NULL;
172 }
173
174 /**
175  * gst_probe_dispatcher_set_active:
176  * @disp: the dispatcher to activate
177  * @active: boolean to indicate activation or deactivation
178  *
179  * Activate or deactivate the given dispatcher
180  * dispatchers.
181  */
182 void
183 gst_probe_dispatcher_set_active (GstProbeDispatcher * disp, gboolean active)
184 {
185   g_return_if_fail (disp);
186
187   disp->active = active;
188 }
189
190 /**
191  * gst_probe_dispatcher_add_probe:
192  * @disp: the dispatcher to add the probe to
193  * @probe: the probe to add to the dispatcher
194  *
195  * Adds the given probe to the dispatcher.
196  */
197 void
198 gst_probe_dispatcher_add_probe (GstProbeDispatcher * disp, GstProbe * probe)
199 {
200   g_return_if_fail (disp);
201   g_return_if_fail (probe);
202
203   GST_CAT_DEBUG (GST_CAT_PROBE, "adding probe %p to dispatcher %p", probe,
204       disp);
205
206   disp->probes = g_slist_prepend (disp->probes, probe);
207 }
208
209 /**
210  * gst_probe_dispatcher_remove_probe:
211  * @disp: the dispatcher to remove the probe from
212  * @probe: the probe to remove from the dispatcher
213  *
214  * Removes the given probe from the dispatcher.
215  */
216 void
217 gst_probe_dispatcher_remove_probe (GstProbeDispatcher * disp, GstProbe * probe)
218 {
219   g_return_if_fail (disp);
220   g_return_if_fail (probe);
221
222   GST_CAT_DEBUG (GST_CAT_PROBE, "removing probe %p from dispatcher %p",
223       probe, disp);
224
225   disp->probes = g_slist_remove (disp->probes, probe);
226 }
227
228 /**
229  * gst_probe_dispatcher_dispatch:
230  * @disp: the dispatcher to dispatch
231  * @data: the data that triggered the dispatch
232  *
233  * Trigger all registered probes on the given dispatcher.
234  *
235  * Returns: TRUE if all callbacks returned TRUE.
236  */
237 gboolean
238 gst_probe_dispatcher_dispatch (GstProbeDispatcher * disp, GstData ** data)
239 {
240   GSList *walk;
241   gboolean res = TRUE;
242
243   g_return_val_if_fail (disp, res);
244
245   GST_CAT_DEBUG (GST_CAT_PROBE, "dispatching data %p on dispatcher %p",
246       *data, disp);
247
248   walk = disp->probes;
249   while (walk) {
250     GstProbe *probe = (GstProbe *) walk->data;
251
252     walk = g_slist_next (walk);
253
254     res &= gst_probe_perform (probe, data);
255     /* it might have disappeared in the callback */
256     if (disp->active &&
257         g_slist_find (disp->probes, probe) && probe->single_shot) {
258       disp->probes = g_slist_remove (disp->probes, probe);
259
260       /* do not free the probe here as it cannot be made threadsafe */
261       //gst_probe_destroy (probe);
262     }
263   }
264
265   return res;
266 }