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