Make sure the hashtable is initialized when the object is used.
[platform/upstream/gstreamer.git] / libs / control / gstdparammanager.c
1 /* GStreamer
2  * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
3  *
4  * gstdparammanager.c: Dynamic Parameter group functionality
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "gstdparammanager.h"
23 #include <gst/gstelement.h>
24 #include <gst/gstinfo.h>
25
26 static GHashTable *_element_registry;
27
28 static void gst_dpman_class_init (GstDParamManagerClass *klass);
29 static void gst_dpman_init (GstDParamManager *dpman);
30 static void gst_dpman_dispose (GObject *object);
31 static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method);
32 static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name);
33 static void gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman);
34 static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman);
35 static guint gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp);
36 static guint gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp);
37 static guint gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count);
38
39 void 
40 _gst_dpman_initialize()
41 {
42 }
43
44 GType
45 gst_dpman_get_type (void)
46 {
47         static GType dpman_type = 0;
48
49         if (!dpman_type) {
50                 static const GTypeInfo dpman_info = {
51                         sizeof(GstDParamManagerClass),
52                         NULL,
53                         NULL,
54                         (GClassInitFunc)gst_dpman_class_init,
55                         NULL,
56                         NULL,
57                         sizeof(GstDParamManager),
58                         0,
59                         (GInstanceInitFunc)gst_dpman_init,
60                 };
61                 dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParamManager", &dpman_info, 0);
62         }
63         return dpman_type;
64 }
65
66 static void
67 gst_dpman_class_init (GstDParamManagerClass *klass)
68 {
69         GstObjectClass *gstobject_class;
70         GObjectClass *gobject_class;
71
72         gstobject_class = (GstObjectClass*) klass;
73         gobject_class = (GObjectClass*) klass;
74         gobject_class->dispose = gst_dpman_dispose;
75
76         klass->modes = g_hash_table_new(g_str_hash,g_str_equal);
77
78         gst_dpman_register_mode (klass, "synchronous", 
79                                gst_dpman_preprocess_synchronous, gst_dpman_process_noop, NULL, NULL);
80         gst_dpman_register_mode (klass, "asynchronous", 
81                                gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL);
82         gst_dpman_register_mode (klass, "disabled", 
83                                gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL);
84
85         _element_registry = g_hash_table_new(NULL,NULL);
86 }
87
88 static void
89 gst_dpman_init (GstDParamManager *dpman)
90 {
91         GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal);
92         GST_DPMAN_DPARAMS_LIST(dpman) = NULL;
93         GST_DPMAN_NAME(dpman) = NULL;
94         GST_DPMAN_PARENT(dpman) = NULL;
95         GST_DPMAN_MODE_NAME(dpman) = NULL;
96         GST_DPMAN_MODE(dpman) = NULL;
97         GST_DPMAN_MODE_DATA(dpman) = NULL;
98         GST_DPMAN_RATE(dpman) = 0;
99 }
100
101 /**
102  * gst_dpman_new:
103  * @name: name of the GstDParamManager instance
104  * @parent: element which created this instance
105  *
106  * Returns: a new instance of GstDParamManager
107  */
108 GstDParamManager* 
109 gst_dpman_new (gchar *name, GstElement *parent)
110 {
111         GstDParamManager *dpman;
112         
113         g_return_val_if_fail (name != NULL, NULL);
114
115         dpman = g_object_new (gst_dpman_get_type (), NULL);
116         gst_object_set_name (GST_OBJECT (dpman), name);
117         gst_dpman_set_parent(dpman, parent);
118
119         gst_dpman_set_mode(dpman, "disabled");
120
121         return dpman;
122 }
123
124
125 static void
126 gst_dpman_dispose (GObject *object)
127 {
128         GstDParamManager *dpman = GST_DPMAN(object);
129         
130
131 }
132
133 /**
134  * gst_dpman_add_required_dparam_callback:
135  * @dpman: GstDParamManager instance
136  * @dparam_name: a parameter name unique to this GstDParamManager
137  * @type: the GValue type that this parameter will store
138  * @update_func: callback to update the element with the new value
139  * @update_data: will be included in the call to update_func
140  *
141  * Returns: true if it was successfully added
142  */
143 gboolean 
144 gst_dpman_add_required_dparam_callback (GstDParamManager *dpman, 
145                                         gchar *dparam_name, 
146                                         GType type, 
147                                         GstDPMUpdateFunction update_func, 
148                                         gpointer update_data)
149 {
150         GstDParamWrapper* dpwrap;
151
152         g_return_val_if_fail (dpman != NULL, FALSE);
153         g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
154         g_return_val_if_fail (update_func != NULL, FALSE);
155
156         dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_CALLBACK);
157
158         g_return_val_if_fail (dpwrap != NULL, FALSE);
159
160         GST_DEBUG(GST_CAT_PARAMS,"adding required callback dparam '%s' of type %s\n", dparam_name, g_type_name(type));
161
162         dpwrap->update_func = update_func;
163         dpwrap->update_data = update_data;
164
165         return TRUE;    
166 }
167
168 /**
169  * gst_dpman_add_required_dparam_direct:
170  * @dpman: GstDParamManager instance
171  * @dparam_name: a parameter name unique to this GstDParamManager
172  * @type: the GValue type that this parameter will store
173  * @update_data: pointer to the member to be updated
174  *
175  * Returns: true if it was successfully added
176  */
177 gboolean 
178 gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, 
179                                         gchar *dparam_name, 
180                                         GType type, 
181                                         gpointer update_data)
182 {
183         GstDParamWrapper* dpwrap;
184
185         g_return_val_if_fail (dpman != NULL, FALSE);
186         g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
187         g_return_val_if_fail (update_data != NULL, FALSE);
188
189         dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_DIRECT);
190
191         g_return_val_if_fail (dpwrap != NULL, FALSE);
192
193         GST_DEBUG(GST_CAT_PARAMS,"adding required direct dparam '%s' of type %s\n", dparam_name, g_type_name(type));
194
195         dpwrap->update_data = update_data;
196
197         return TRUE;    
198 }
199
200 /**
201  * gst_dpman_add_required_dparam_array:
202  * @dpman: GstDParamManager instance
203  * @dparam_name: a parameter name unique to this GstDParamManager
204  * @type: the GValue type that this parameter will store
205  * @update_data: pointer to where the array will be stored
206  *
207  * Returns: true if it was successfully added
208  */
209 gboolean 
210 gst_dpman_add_required_dparam_array (GstDParamManager *dpman, 
211                                         gchar *dparam_name, 
212                                         GType type, 
213                                         gpointer update_data)
214 {
215         GstDParamWrapper* dpwrap;
216
217         g_return_val_if_fail (dpman != NULL, FALSE);
218         g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
219         g_return_val_if_fail (update_data != NULL, FALSE);
220
221         dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_ARRAY);
222
223         g_return_val_if_fail (dpwrap != NULL, FALSE);
224
225         GST_DEBUG(GST_CAT_PARAMS,"adding required array dparam '%s' of type %s\n", dparam_name, g_type_name(type));
226
227         dpwrap->update_data = update_data;
228
229         return TRUE;    
230 }
231
232 /**
233  * gst_dpman_remove_required_dparam:
234  * @dpman: GstDParamManager instance
235  * @dparam_name: the name of an existing parameter
236  *
237  */
238 void 
239 gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name)
240 {
241         GstDParamWrapper* dpwrap;
242
243         g_return_if_fail (dpman != NULL);
244         g_return_if_fail (GST_IS_DPMAN (dpman));
245         g_return_if_fail (dparam_name != NULL);
246
247         dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
248         
249         g_return_if_fail(dpwrap != NULL);
250         g_return_if_fail(dpwrap->dparam == NULL);
251
252         GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s\n", dparam_name);
253         
254         g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name);
255         GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
256
257         g_free(dpwrap->value);
258         g_free(dpwrap);
259 }
260
261 /**
262  * gst_dpman_attach_dparam:
263  * @dpman: GstDParamManager instance
264  * @dparam_name: a name previously added with gst_dpman_add_required_dparam
265  * @dparam: GstDParam instance to attach
266  *
267  * Returns: true if it was successfully attached
268  */
269 gboolean 
270 gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam)
271 {
272         GstDParamWrapper* dpwrap;
273
274         g_return_val_if_fail (dpman != NULL, FALSE);
275         g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
276         g_return_val_if_fail (dparam_name != NULL, FALSE);
277         g_return_val_if_fail (dparam != NULL, FALSE);
278         g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE);
279         g_return_val_if_fail (dparam != NULL, FALSE);
280
281         dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
282
283         g_return_val_if_fail(dpwrap != NULL, FALSE);
284         g_return_val_if_fail(dpwrap->value != NULL, FALSE);
285
286         dpwrap->dparam = dparam;
287         gst_dparam_attach(dparam, dpman, dpwrap->value, dpwrap->spec);
288
289         return TRUE;
290 }
291
292 /**
293  * gst_dpman_detach_dparam:
294  * @dpman: GstDParamManager instance
295  * @dparam_name: the name of a parameter with a previously attached GstDParam
296  *
297  */
298 void 
299 gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name)
300 {
301         GstDParamWrapper* dpwrap;
302
303         g_return_if_fail (dpman != NULL);
304         g_return_if_fail (GST_IS_DPMAN (dpman));
305         g_return_if_fail (dparam_name != NULL);
306         
307         dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
308
309         g_return_if_fail(dpwrap);
310         
311         gst_dparam_detach(dpwrap->dparam);
312         dpwrap->dparam = NULL;
313         
314 }
315
316 /**
317  * gst_dpman_get_dparam:
318  * @dpman: GstDParamManager instance
319  * @name: the name of an existing dparam instance
320  *
321  * Returns: the dparam with the given name - or NULL otherwise
322  */
323 GstDParam *
324 gst_dpman_get_dparam (GstDParamManager *dpman, gchar *name)
325 {
326         GstDParamWrapper* dpwrap;
327
328         g_return_val_if_fail (dpman != NULL, NULL);
329         g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
330         g_return_val_if_fail (name != NULL, NULL);
331         
332         dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
333         g_return_val_if_fail (dpwrap != NULL, NULL);
334         
335         return dpwrap->dparam;
336 }
337
338 /**
339  * gst_dpman_get_dparam_type:
340  * @dpman: GstDParamManager instance
341  * @name: the name of dparam
342  *
343  * Returns: the type that this dparam requires/uses
344  */
345 GType
346 gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name)
347 {
348         GstDParamWrapper* dpwrap;
349
350         g_return_val_if_fail (dpman != NULL, 0);
351         g_return_val_if_fail (GST_IS_DPMAN (dpman), 0);
352         g_return_val_if_fail (name != NULL, 0);
353         
354         dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
355         g_return_val_if_fail (dpwrap != NULL, 0);
356         
357         return G_VALUE_TYPE(dpwrap->value);
358 }
359
360 GstDParamSpec**
361 gst_dpman_list_dparam_specs(GstDParamManager *dpman)
362 {
363         GstDParamWrapper* dpwrap;
364         GSList *dpwraps;
365         GstDParamSpec** dparam_specs;
366         guint x = 0;
367
368         g_return_val_if_fail (dpman != NULL, NULL);
369         g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
370         
371         dpwraps = GST_DPMAN_DPARAMS_LIST(dpman);
372
373         dparam_specs = g_new0(GstDParamSpec*, g_slist_length(dpwraps) + 1);
374         
375         while (dpwraps){
376                 dpwrap = (GstDParamWrapper*)dpwraps->data;
377                 dparam_specs[x++] = dpwrap->spec;
378                 dpwraps = g_slist_next(dpwraps);
379         }
380         return dparam_specs;
381 }
382
383 GstDParamSpec*
384 gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name)
385 {
386         GstDParamWrapper* dpwrap;
387
388         g_return_val_if_fail (dpman != NULL, NULL);
389         g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
390         g_return_val_if_fail (dparam_name != NULL, NULL);
391
392         dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
393         return dpwrap->spec;
394 }
395
396 void
397 gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name)
398 {
399         
400 }
401
402 /**
403  * gst_dpman_register_mode
404  * @klass: GstDParamManagerClass class instance
405  * @modename: the unique name of the new mode
406  * @preprocessfunc: the function which will be called before each buffer is processed
407  * @processfunc: the function which may be called throughout the processing of a buffer
408  * @setupfunc: the function which initialises the mode when activated
409  * @teardownfunc: the function which frees any resources the mode uses
410  *
411  */
412 void
413 gst_dpman_register_mode (GstDParamManagerClass *klass,
414                          gchar *modename, 
415                          GstDPMModePreProcessFunction preprocessfunc,
416                          GstDPMModeProcessFunction processfunc,
417                          GstDPMModeSetupFunction setupfunc,
418                          GstDPMModeTeardownFunction teardownfunc)
419 {
420         GstDPMMode *mode;
421
422         g_return_if_fail (klass != NULL);
423         g_return_if_fail (modename != NULL);
424         g_return_if_fail (GST_IS_DPMAN_CLASS (klass));
425         
426         mode = g_new0(GstDPMMode,1);
427
428         mode->preprocessfunc = preprocessfunc;
429         mode->processfunc = processfunc;
430         mode->setupfunc = setupfunc;
431         mode->teardownfunc = teardownfunc;
432         
433         g_hash_table_insert(klass->modes, modename, mode);
434         GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered\n", modename);
435 }
436
437 /**
438  * gst_dpman_set_mode
439  * @dpman: GstDParamManager instance
440  * @modename: the name of the mode to use
441  *
442  * Returns: TRUE if the mode was set, FALSE otherwise
443  */
444 gboolean
445 gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename)
446 {
447         GstDPMMode *mode=NULL;
448         GstDParamManagerClass *oclass;
449         
450         g_return_val_if_fail (dpman != NULL, FALSE);
451         g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
452         g_return_val_if_fail (modename != NULL, FALSE);
453
454         oclass = (GstDParamManagerClass*)(G_OBJECT_GET_CLASS(dpman));
455         
456         mode = g_hash_table_lookup(oclass->modes, modename);
457         g_return_val_if_fail (mode != NULL, FALSE);
458         
459         if (GST_DPMAN_MODE(dpman) == mode) {
460                 GST_DEBUG(GST_CAT_PARAMS, "mode %s already set\n", modename);
461                 return TRUE;
462         }
463         
464         GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename);
465         if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){
466                 GST_DPMAN_TEARDOWNFUNC(dpman)(dpman);
467         }
468         
469         GST_DPMAN_MODE(dpman) = mode;
470
471         if (GST_DPMAN_SETUPFUNC(dpman)){
472                 GST_DPMAN_SETUPFUNC(dpman)(dpman);
473         }
474         
475         return TRUE;
476 }
477
478 /**
479  * gst_dpman_set_parent
480  * @dpman: GstDParamManager instance
481  * @parent: the element that this GstDParamManager belongs to
482  *
483  */
484 void
485 gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent)
486 {
487         g_return_if_fail (dpman != NULL);
488         g_return_if_fail (GST_IS_DPMAN (dpman));
489         g_return_if_fail (parent != NULL);
490         g_return_if_fail (GST_IS_ELEMENT (parent));
491
492         g_hash_table_insert(_element_registry, parent, dpman);
493         gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent));
494         g_signal_connect(G_OBJECT(parent), "state_change", 
495                          G_CALLBACK (gst_dpman_state_change), dpman);
496 }
497
498 /**
499  * gst_dpman_get_manager
500  * @parent: the element that the desired GstDParamManager belongs to
501  *
502  * Returns: the GstDParamManager which belongs to this element or NULL
503  * if it doesn't exist
504  */
505 GstDParamManager *
506 gst_dpman_get_manager (GstElement *parent)
507 {
508         GstDParamManager *dpman;
509         g_return_val_if_fail (parent != NULL, NULL);
510         g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
511         
512         dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent);
513         return dpman;
514 }
515
516 /**
517  * gst_dpman_set_rate_change_pad
518  * @dpman: GstDParamManager instance
519  * @pad: the pad which may have a "rate" caps property
520  *
521  */
522 void
523 gst_dpman_set_rate_change_pad(GstDParamManager *dpman, GstPad *pad)
524 {
525         g_return_if_fail (dpman != NULL);
526         g_return_if_fail (GST_IS_DPMAN (dpman));
527         g_return_if_fail (pad != NULL);
528         g_return_if_fail (GST_IS_PAD (pad));
529
530         g_signal_connect(G_OBJECT(pad), "caps_changed", 
531                          G_CALLBACK (gst_dpman_caps_changed), dpman);
532 }
533
534 static GstDParamWrapper* 
535 gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name)
536 {
537         g_return_val_if_fail (dpman != NULL, NULL);
538         g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
539         g_return_val_if_fail (dparam_name != NULL, NULL);
540         
541         return g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
542 }
543
544 static GstDParamWrapper* 
545 gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method)
546 {
547         GstDParamWrapper* dpwrap;
548
549         g_return_val_if_fail (dpman != NULL, NULL);
550         g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
551         g_return_val_if_fail (dparam_name != NULL, NULL);
552
553         g_return_val_if_fail(gst_dpman_get_wrapper(dpman, dparam_name) == NULL, NULL);
554
555         dpwrap = g_new0(GstDParamWrapper,1);
556         dpwrap->update_method = update_method;
557         dpwrap->value = g_new0(GValue,1);
558         g_value_init(dpwrap->value, type);
559         
560         dpwrap->spec = g_new0(GstDParamSpec,1);
561         dpwrap->spec->dparam_name = dparam_name;
562         dpwrap->spec->min_val = g_new0(GValue,1);
563         dpwrap->spec->max_val = g_new0(GValue,1);
564         dpwrap->spec->default_val = g_new0(GValue,1);
565         g_value_init(dpwrap->spec->min_val, type);
566         g_value_init(dpwrap->spec->max_val, type);
567         g_value_init(dpwrap->spec->default_val, type);
568
569         g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap);
570         GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
571         
572         return dpwrap;  
573 }
574
575
576 static void 
577 gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman)
578 {
579         GSList *dwraps;
580         GstDParam *dparam;
581         GstDParamWrapper *dpwrap;
582
583         g_return_if_fail (dpman != NULL);
584         g_return_if_fail (GST_IS_DPMAN (dpman));
585         
586         if (state == GST_STATE_PLAYING){
587                 GST_DEBUG(GST_CAT_PARAMS, "initialising params\n");
588                         
589                 // force all params to be updated
590                 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
591                 while (dwraps){
592                         dpwrap = (GstDParamWrapper*)dwraps->data;
593                         dparam = dpwrap->dparam;
594                         
595                         if (dparam){
596                                 GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
597                                 if (dparam->spec){
598                                         g_value_copy(dparam->spec->default_val, GST_DPARAM_VALUE(dparam));
599                                 }
600                         }
601                         dwraps = g_slist_next(dwraps);
602                 }
603         }
604 }
605
606 static void
607 gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman)
608 {
609         g_return_if_fail (caps != NULL);
610         g_return_if_fail (dpman != NULL);
611         g_return_if_fail (GST_IS_DPMAN (dpman));
612         
613         GST_DPMAN_RATE(dpman) = gst_caps_get_int (caps, "rate");
614         
615         GST_DEBUG(GST_CAT_PARAMS, "got caps change %d\n", GST_DPMAN_RATE(dpman));
616 }
617
618 static guint 
619 gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp)
620 {
621         GSList *dwraps;
622         GstDParam *dparam;
623         GstDParamWrapper *dpwrap;
624         guint x;
625
626         g_return_val_if_fail (dpman != NULL, frames);
627         g_return_val_if_fail (GST_IS_DPMAN (dpman), frames);
628
629         // now check whether any passive dparams are ready for an update
630         dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
631         while (dwraps){
632                 dpwrap = (GstDParamWrapper*)dwraps->data;
633                 dparam = dpwrap->dparam;
634
635                 if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) && 
636                               (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp))){
637                                 
638                     // this will make dpwrap->value contain the latest value.
639                     // now we just need to get it to the element
640                         GST_DPARAM_DO_UPDATE(dparam, timestamp);
641                         
642                         switch (dpwrap->update_method) {
643                                 
644                                 // direct method - set the value directly in the struct of the element
645                                 case GST_DPMAN_DIRECT:
646                                         GST_DEBUG(GST_CAT_PARAMS, "doing direct update\n");
647                                         switch (G_VALUE_TYPE(dpwrap->value)){
648                                                 case G_TYPE_CHAR:
649                                                         *(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
650                                                         break;
651                                                 case G_TYPE_UCHAR:
652                                                         *(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
653                                                         break;
654                                                 case G_TYPE_BOOLEAN:
655                                                         *(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
656                                                         break;
657                                                 case G_TYPE_INT:
658                                                         *(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
659                                                         break;
660                                                 case G_TYPE_UINT:
661                                                         *(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
662                                                         break;
663                                                 case G_TYPE_LONG:
664                                                         *(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
665                                                         break;
666                                                 case G_TYPE_ULONG:
667                                                         *(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
668                                                         break;
669                                                 case G_TYPE_FLOAT:
670                                                         *(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
671                                                         break;
672                                                 case G_TYPE_DOUBLE:
673                                                         *(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
674                                                         break;
675                                                 case G_TYPE_POINTER:
676                                                         *(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
677                                                         break;
678                                                 default:
679                                                         break;
680                                         }
681                                         break;
682
683                                 // callback method - call the element's callback so it can do what it likes
684                                 case GST_DPMAN_CALLBACK:
685                                         GST_DEBUG(GST_CAT_PARAMS, "doing callback update\n");
686                                         GST_DPMAN_DO_UPDATE(dpwrap);
687                                         break;
688                                         
689                                 // array method - generate an array of the right size 
690                                 // with each value being the same (in synchronous update mode)
691                                 case GST_DPMAN_ARRAY:
692                                         GST_DEBUG(GST_CAT_PARAMS, "doing array update\n");
693                                         switch (G_VALUE_TYPE(dpwrap->value)){
694                                                 case G_TYPE_CHAR:
695                                                         (gchar*)dpwrap->update_data = g_new(gchar, frames);
696                                                         *(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
697                                                         for (x = 1 ; x < frames ; x++)
698                                                                 ((gchar*)dpwrap->update_data)[x] = *(gchar*)dpwrap->update_data;
699                                                         break;
700                                                 case G_TYPE_UCHAR:
701                                                         (guchar*)dpwrap->update_data = g_new(guchar, frames);
702                                                         *(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
703                                                         for (x = 1 ; x < frames ; x++)
704                                                                 ((guchar*)dpwrap->update_data)[x] = *(guchar*)dpwrap->update_data;
705                                                         break;
706                                                 case G_TYPE_BOOLEAN:
707                                                         (gboolean*)dpwrap->update_data = g_new(gboolean, frames);
708                                                         *(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
709                                                         for (x = 1 ; x < frames ; x++)
710                                                                 ((gboolean*)dpwrap->update_data)[x] = *(gboolean*)dpwrap->update_data;
711                                                         break;
712                                                 case G_TYPE_INT:
713                                                         (gint*)dpwrap->update_data = g_new(gint, frames);
714                                                         *(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
715                                                         for (x = 1 ; x < frames ; x++)
716                                                                 ((gint*)dpwrap->update_data)[x] = *(gint*)dpwrap->update_data;
717                                                         break;
718                                                 case G_TYPE_UINT:
719                                                         (guint*)dpwrap->update_data = g_new(guint, frames);
720                                                         *(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
721                                                         for (x = 1 ; x < frames ; x++)
722                                                                 ((guint*)dpwrap->update_data)[x] = *(guint*)dpwrap->update_data;
723                                                         break;
724                                                 case G_TYPE_LONG:
725                                                         (glong*)dpwrap->update_data = g_new(glong, frames);
726                                                         *(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
727                                                         for (x = 1 ; x < frames ; x++)
728                                                                 ((glong*)dpwrap->update_data)[x] = *(glong*)dpwrap->update_data;
729                                                         break;
730                                                 case G_TYPE_ULONG:
731                                                         (gulong*)dpwrap->update_data = g_new(gulong, frames);
732                                                         *(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
733                                                         for (x = 1 ; x < frames ; x++)
734                                                                 ((gulong*)dpwrap->update_data)[x] = *(gulong*)dpwrap->update_data;
735                                                         break;
736                                                 case G_TYPE_FLOAT:
737                                                         (gfloat*)dpwrap->update_data = g_new(gfloat, frames);
738                                                         *(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
739                                                         for (x = 1 ; x < frames ; x++)
740                                                                 ((gfloat*)dpwrap->update_data)[x] = *(gfloat*)dpwrap->update_data;
741                                                         break;
742                                                 case G_TYPE_DOUBLE:
743                                                         (gdouble*)dpwrap->update_data = g_new(gdouble, frames);
744                                                         *(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
745                                                         for (x = 1 ; x < frames ; x++)
746                                                                 ((gdouble*)dpwrap->update_data)[x] = *(gdouble*)dpwrap->update_data;
747                                                         break;
748                                                 case G_TYPE_POINTER:
749                                                         (gpointer*)dpwrap->update_data = g_new(gpointer, frames);
750                                                         *(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
751                                                         for (x = 1 ; x < frames ; x++)
752                                                                 ((gpointer*)dpwrap->update_data)[x] = *(gpointer*)dpwrap->update_data;
753                                                         break;
754                                                 default:
755                                                         break;
756                                         }
757                                         break;
758                                 default:
759                                         break;
760                         }
761                 }
762                 dwraps = g_slist_next(dwraps);
763         }
764         return frames;
765 }
766
767 static guint 
768 gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp)
769 {
770         return frames;
771 }
772
773 static guint 
774 gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count)
775 {
776         return 0;
777 }
778