1 /* GStreamer
2 * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
3 *
4 * gstdparam.c: Dynamic Parameter
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 */
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <math.h>
27 #include <string.h>
28 #include <gst/gstinfo.h>
30 #include "dparam.h"
31 #include "dparammanager.h"
32 #include <gst/gstmarshal.h>
34 GST_DEBUG_CATEGORY_EXTERN (_gst_control_debug);
35 #define GST_CAT_DEFAULT _gst_control_debug
37 static void gst_dparam_class_init (GstDParamClass * klass);
38 static void gst_dparam_init (GstDParam * dparam);
39 static void gst_dparam_dispose (GObject * object);
40 static void gst_dparam_get_property (GObject * object, guint prop_id,
41 GValue * value, GParamSpec * pspec);
42 static void gst_dparam_set_property (GObject * object, guint prop_id,
43 const GValue * value, GParamSpec * pspec);
45 enum
46 {
47 ARG_0,
48 ARG_VALUE_FLOAT,
49 ARG_VALUE_DOUBLE,
50 ARG_VALUE_INT,
51 ARG_VALUE_INT64,
52 };
54 enum
55 {
56 VALUE_CHANGED,
57 LAST_SIGNAL
58 };
60 static guint gst_dparam_signals[LAST_SIGNAL] = { 0 };
62 GType
63 gst_dparam_get_type (void)
64 {
65 static GType dparam_type = 0;
67 if (!dparam_type) {
68 static const GTypeInfo dparam_info = {
69 sizeof (GstDParamClass),
70 NULL,
71 NULL,
72 (GClassInitFunc) gst_dparam_class_init,
73 NULL,
74 NULL,
75 sizeof (GstDParam),
76 0,
77 (GInstanceInitFunc) gst_dparam_init,
78 };
80 dparam_type =
81 g_type_register_static (GST_TYPE_OBJECT, "GstDParam", &dparam_info, 0);
82 }
83 return dparam_type;
84 }
86 static void
87 gst_dparam_class_init (GstDParamClass * klass)
88 {
89 GObjectClass *gobject_class;
90 GstDParamClass *dparam_class;
91 GstObjectClass *gstobject_class;
93 gobject_class = (GObjectClass *) klass;
94 dparam_class = (GstDParamClass *) klass;
95 gstobject_class = (GstObjectClass *) klass;
97 gobject_class->get_property = gst_dparam_get_property;
98 gobject_class->set_property = gst_dparam_set_property;
100 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VALUE_FLOAT,
101 g_param_spec_float ("value_float", "Float Value",
102 "The value that should be changed if gfloat is the type",
103 -G_MAXFLOAT, G_MAXFLOAT, 0.0F, G_PARAM_READWRITE));
104 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VALUE_DOUBLE,
105 g_param_spec_double ("value_double", "Double Value",
106 "The value that should be changed if gdouble is the type",
107 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
108 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VALUE_INT,
109 g_param_spec_int ("value_int", "Integer Value",
110 "The value that should be changed if gint is the type",
111 G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
112 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VALUE_INT64,
113 g_param_spec_int64 ("value_int64", "64 bit Integer Value",
114 "The value that should be changed if gint64 is the type",
115 G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
117 gobject_class->dispose = gst_dparam_dispose;
119 gst_dparam_signals[VALUE_CHANGED] =
120 g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass),
121 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDParamClass, value_changed), NULL,
122 NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
123 /*gstobject_class->save_thyself = gst_dparam_save_thyself; */
125 }
127 static void
128 gst_dparam_init (GstDParam * dparam)
129 {
130 g_return_if_fail (dparam != NULL);
131 GST_DPARAM_TYPE (dparam) = 0;
132 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = 0LL;
133 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = 0LL;
134 GST_DPARAM_READY_FOR_UPDATE (dparam) = FALSE;
135 dparam->lock = g_mutex_new ();
136 }
138 /**
139 * gst_dparam_new:
140 * @type: the type that this dparam will store
141 *
142 * Create a new dynamic parameter controller.
143 *
144 * Returns: a new instance of GstDParam
145 */
146 GstDParam *
147 gst_dparam_new (GType type)
148 {
149 GstDParam *dparam;
151 dparam = g_object_new (gst_dparam_get_type (), NULL);
152 dparam->do_update_func = gst_dparam_do_update_default;
154 GST_DPARAM_TYPE (dparam) = type;
156 return dparam;
157 }
160 static void
161 gst_dparam_get_property (GObject * object, guint prop_id, GValue * value,
162 GParamSpec * pspec)
163 {
164 GstDParam *dparam;
166 g_return_if_fail (GST_IS_DPARAM (object));
167 dparam = GST_DPARAM (object);
169 switch (prop_id) {
170 case ARG_VALUE_FLOAT:
171 g_value_set_float (value, dparam->value_float);
172 break;
174 case ARG_VALUE_DOUBLE:
175 g_value_set_double (value, dparam->value_double);
176 break;
178 case ARG_VALUE_INT:
179 g_value_set_int (value, dparam->value_int);
180 break;
182 case ARG_VALUE_INT64:
183 g_value_set_int64 (value, dparam->value_int64);
184 break;
185 default:
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187 break;
188 }
189 }
191 static void
192 gst_dparam_set_property (GObject * object, guint prop_id, const GValue * value,
193 GParamSpec * pspec)
194 {
195 GstDParam *dparam;
197 g_return_if_fail (GST_IS_DPARAM (object));
198 dparam = GST_DPARAM (object);
199 GST_DPARAM_LOCK (dparam);
201 switch (prop_id) {
202 case ARG_VALUE_FLOAT:
203 GST_DEBUG ("setting value from %g to %g", dparam->value_float,
204 g_value_get_float (value));
205 dparam->value_float = g_value_get_float (value);
206 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
207 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam);
208 GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
209 break;
211 case ARG_VALUE_DOUBLE:
212 GST_DEBUG ("setting value from %g to %g",
213 dparam->value_double, g_value_get_double (value));
214 dparam->value_double = g_value_get_double (value);
215 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
216 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam);
217 GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
218 break;
220 case ARG_VALUE_INT:
221 GST_DEBUG ("setting value from %d to %d", dparam->value_int,
222 g_value_get_int (value));
223 dparam->value_int = g_value_get_int (value);
224 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
225 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam);
226 GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
227 break;
229 case ARG_VALUE_INT64:
230 GST_DEBUG ("setting value from %"
231 G_GINT64_FORMAT " to %"
232 G_GINT64_FORMAT, dparam->value_int64, g_value_get_int64 (value));
233 dparam->value_int64 = g_value_get_int64 (value);
234 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
235 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam);
236 GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
237 break;
239 default:
240 break;
241 }
243 /* note that this signal is sent while we still have the lock. */
244 g_signal_emit (G_OBJECT (dparam), gst_dparam_signals[VALUE_CHANGED], 0);
245 GST_DPARAM_UNLOCK (dparam);
246 }
248 /**
249 * gst_dparam_do_update_default:
250 * @dparam: the parameter to update
251 * @timestamp: when should the update take place
252 * @value: the new value
253 * @update_info: unused here
254 *
255 * Default implementation for changing a dynamic parameter.
256 * Subclasses might overwrite the behaviour of this.
257 *
258 */
259 void
260 gst_dparam_do_update_default (GstDParam * dparam, gint64 timestamp,
261 GValue * value, GstDParamUpdateInfo update_info)
262 {
263 GST_DPARAM_LOCK (dparam);
265 g_return_if_fail (G_VALUE_TYPE (value) == GST_DPARAM_TYPE (dparam));
266 GST_DEBUG ("updating value for %s(%p)", GST_DPARAM_NAME (dparam), dparam);
268 switch (G_VALUE_TYPE (value)) {
269 case G_TYPE_FLOAT:
270 g_value_set_float (value, dparam->value_float);
271 break;
273 case G_TYPE_DOUBLE:
274 g_value_set_double (value, dparam->value_double);
275 break;
277 case G_TYPE_INT:
278 g_value_set_int (value, dparam->value_int);
279 break;
281 case G_TYPE_INT64:
282 g_value_set_int64 (value, dparam->value_int64);
283 break;
285 default:
286 break;
287 }
289 GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
290 GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = timestamp;
291 GST_DPARAM_READY_FOR_UPDATE (dparam) = FALSE;
293 GST_DPARAM_UNLOCK (dparam);
294 }
296 static void
297 gst_dparam_dispose (GObject * object)
298 {
299 GstDParam *dparam = GST_DPARAM (object);
300 gchar *dparam_name = g_strdup (GST_DPARAM_NAME (dparam));
302 GST_DEBUG ("disposing of %s", dparam_name);
303 if (GST_DPARAM_MANAGER (dparam)) {
304 gst_dpman_detach_dparam (GST_DPARAM_MANAGER (dparam), dparam_name);
305 }
306 g_free (dparam_name);
307 }
309 /**
310 * gst_dparam_attach
311 * @dparam: GstDParam instance
312 * @manager: the GstDParamManager that this dparam belongs to
313 * @param_spec: the specification for the parameter
314 * @unit_name: the name of the unit
315 *
316 * Adding the parameter controller to the manager using the
317 * supplied specs and unit.
318 * See also gst_dpman_attach_dparam().
319 */
320 void
321 gst_dparam_attach (GstDParam * dparam, GstDParamManager * manager,
322 GParamSpec * param_spec, gchar * unit_name)
323 {
324 GValue value = { 0, };
326 g_return_if_fail (dparam != NULL);
327 g_return_if_fail (GST_IS_DPARAM (dparam));
328 g_return_if_fail (manager != NULL);
329 g_return_if_fail (GST_IS_DPMAN (manager));
330 g_return_if_fail (param_spec != NULL);
331 g_return_if_fail (unit_name != NULL);
332 g_return_if_fail (G_IS_PARAM_SPEC (param_spec));
333 g_return_if_fail (G_PARAM_SPEC_VALUE_TYPE (param_spec) ==
334 GST_DPARAM_TYPE (dparam));
336 gst_object_set_name (GST_OBJECT (dparam), g_param_spec_get_name (param_spec));
337 GST_DPARAM_PARAM_SPEC (dparam) = param_spec;
338 GST_DPARAM_MANAGER (dparam) = manager;
339 GST_DPARAM_UNIT_NAME (dparam) = unit_name;
340 GST_DPARAM_IS_LOG (dparam) = gst_unitconv_unit_is_logarithmic (unit_name);
341 GST_DEBUG ("attaching %s to dparam %p", GST_DPARAM_NAME (dparam), dparam);
343 // get default value from param-spec and set in dparam
344 g_value_init (&value, param_spec->value_type);
345 g_param_value_set_default (param_spec, &value);
346 switch (G_PARAM_SPEC_VALUE_TYPE (param_spec)) {
347 case G_TYPE_FLOAT:
348 dparam->value_float = g_value_get_float (&value);
349 break;
351 case G_TYPE_DOUBLE:
352 dparam->value_double = g_value_get_double (&value);
353 break;
355 case G_TYPE_INT:
356 dparam->value_int = g_value_get_int (&value);
357 break;
359 case G_TYPE_INT64:
360 dparam->value_int64 = g_value_get_int64 (&value);
361 break;
363 default:
364 break;
365 }
366 }
368 /**
369 * gst_dparam_detach
370 * @dparam: GstDParam instance
371 *
372 * Removes a previousely added parameter controller.
373 */
374 void
375 gst_dparam_detach (GstDParam * dparam)
376 {
378 g_return_if_fail (dparam != NULL);
379 g_return_if_fail (GST_IS_DPARAM (dparam));
381 GST_DEBUG ("detaching %s from dparam %p", GST_DPARAM_NAME (dparam), dparam);
383 gst_object_set_name (GST_OBJECT (dparam), NULL);
384 GST_DPARAM_PARAM_SPEC (dparam) = NULL;
385 GST_DPARAM_MANAGER (dparam) = NULL;
386 }