1 /* GStreamer
2  *
3  * unit test for the controller library
4  *
5  * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
6  * Copyright (C) <2006-2007> Sebastian Dröge <slomo@circular-chaos.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <gst/gst.h>
29 #include <gst/check/gstcheck.h>
30 
31 /* local test element */
32 
33 enum
34 {
35   PROP_INT = 1,
36   PROP_FLOAT,
37   PROP_DOUBLE,
38   PROP_BOOLEAN,
39   PROP_READONLY,
40   PROP_STATIC,
41   PROP_CONSTRUCTONLY,
42   PROP_COUNT
43 };
44 
45 #define GST_TYPE_TEST_OBJ            (gst_test_obj_get_type ())
46 #define GST_TEST_OBJ(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj))
47 #define GST_TEST_OBJ_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass))
48 #define GST_IS_TEST_OBJ(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ))
49 #define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ))
50 #define GST_TEST_OBJ_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass))
51 
52 typedef struct _GstTestObj GstTestObj;
53 typedef struct _GstTestObjClass GstTestObjClass;
54 
55 struct _GstTestObj
56 {
57   GstElement parent;
58   gint val_int;
59   gfloat val_float;
60   gdouble val_double;
61   gboolean val_boolean;
62 };
63 struct _GstTestObjClass
64 {
65   GstElementClass parent_class;
66 };
67 
68 static GType gst_test_obj_get_type (void);
69 
70 static void
gst_test_obj_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)71 gst_test_obj_get_property (GObject * object,
72     guint property_id, GValue * value, GParamSpec * pspec)
73 {
74   GstTestObj *self = GST_TEST_OBJ (object);
75 
76   switch (property_id) {
77     case PROP_INT:
78       g_value_set_int (value, self->val_int);
79       break;
80     case PROP_FLOAT:
81       g_value_set_float (value, self->val_float);
82       break;
83     case PROP_DOUBLE:
84       g_value_set_double (value, self->val_double);
85       break;
86     case PROP_BOOLEAN:
87       g_value_set_boolean (value, self->val_boolean);
88       break;
89     default:
90       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
91       break;
92   }
93 }
94 
95 static void
gst_test_obj_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)96 gst_test_obj_set_property (GObject * object,
97     guint property_id, const GValue * value, GParamSpec * pspec)
98 {
99   GstTestObj *self = GST_TEST_OBJ (object);
100 
101   switch (property_id) {
102     case PROP_INT:
103       self->val_int = g_value_get_int (value);
104       GST_DEBUG ("test value int=%d", self->val_int);
105       break;
106     case PROP_FLOAT:
107       self->val_float = g_value_get_float (value);
108       GST_DEBUG ("test value float=%f", self->val_float);
109       break;
110     case PROP_DOUBLE:
111       self->val_double = g_value_get_double (value);
112       GST_DEBUG ("test value double=%lf", self->val_double);
113       break;
114     case PROP_BOOLEAN:
115       self->val_boolean = g_value_get_boolean (value);
116       GST_DEBUG ("test value boolean=%d", self->val_boolean);
117       break;
118     case PROP_CONSTRUCTONLY:
119       break;
120     default:
121       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
122       break;
123   }
124 }
125 
126 static void
gst_test_obj_class_init(GstTestObjClass * klass)127 gst_test_obj_class_init (GstTestObjClass * klass)
128 {
129   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
130   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
131 
132   gobject_class->set_property = gst_test_obj_set_property;
133   gobject_class->get_property = gst_test_obj_get_property;
134 
135   g_object_class_install_property (gobject_class, PROP_INT,
136       g_param_spec_int ("int",
137           "int prop",
138           "int number parameter",
139           0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
140 
141   g_object_class_install_property (gobject_class, PROP_FLOAT,
142       g_param_spec_float ("float",
143           "float prop",
144           "float number parameter",
145           0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
146 
147   g_object_class_install_property (gobject_class, PROP_DOUBLE,
148       g_param_spec_double ("double",
149           "double prop",
150           "double number parameter",
151           0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
152 
153   g_object_class_install_property (gobject_class, PROP_BOOLEAN,
154       g_param_spec_boolean ("boolean",
155           "boolean prop",
156           "boolean parameter",
157           FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
158 
159   g_object_class_install_property (gobject_class, PROP_READONLY,
160       g_param_spec_int ("readonly",
161           "readonly prop",
162           "readonly parameter",
163           0, G_MAXINT, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE));
164 
165   g_object_class_install_property (gobject_class, PROP_STATIC,
166       g_param_spec_int ("static",
167           "static prop",
168           "static parameter", 0, G_MAXINT, 0, G_PARAM_READWRITE));
169 
170   g_object_class_install_property (gobject_class, PROP_CONSTRUCTONLY,
171       g_param_spec_int ("construct-only",
172           "construct-only prop",
173           "construct-only parameter",
174           0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
175 
176   gst_element_class_set_metadata (element_class,
177       "test object for unit tests",
178       "Test", "Use in unit tests", "Stefan Sauer <ensonic@users.sf.net>");
179 }
180 
181 static GType
gst_test_obj_get_type(void)182 gst_test_obj_get_type (void)
183 {
184   static volatile gsize test_obj_type = 0;
185 
186   if (g_once_init_enter (&test_obj_type)) {
187     GType type;
188     static const GTypeInfo info = {
189       (guint16) sizeof (GstTestObjClass),
190       NULL,                     // base_init
191       NULL,                     // base_finalize
192       (GClassInitFunc) gst_test_obj_class_init, // class_init
193       NULL,                     // class_finalize
194       NULL,                     // class_data
195       (guint16) sizeof (GstTestObj),
196       0,                        // n_preallocs
197       NULL,                     // instance_init
198       NULL                      // value_table
199     };
200     type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0);
201     g_once_init_leave (&test_obj_type, type);
202   }
203   return test_obj_type;
204 }
205 
206 /* test control source */
207 
208 #define GST_TYPE_TEST_CONTROL_SOURCE            (gst_test_control_source_get_type ())
209 #define GST_TEST_CONTROL_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSource))
210 #define GST_TEST_CONTROL_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass))
211 #define GST_IS_TEST_CONTROL_SOURCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_SOURCE))
212 #define GST_IS_TEST_CONTROL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_SOURCE))
213 #define GST_TEST_CONTROL_SOURCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass))
214 
215 typedef struct _GstTestControlSource GstTestControlSource;
216 typedef struct _GstTestControlSourceClass GstTestControlSourceClass;
217 
218 struct _GstTestControlSource
219 {
220   GstControlSource parent;
221 
222   gdouble value;
223 };
224 struct _GstTestControlSourceClass
225 {
226   GstControlSourceClass parent_class;
227 };
228 
229 static GType gst_test_control_source_get_type (void);
230 
231 static GstTestControlSource *
gst_test_control_source_new(void)232 gst_test_control_source_new (void)
233 {
234   GstTestControlSource *csource =
235       g_object_new (GST_TYPE_TEST_CONTROL_SOURCE, NULL);
236 
237   /* Clear floating flag */
238   gst_object_ref_sink (csource);
239 
240   return csource;
241 }
242 
243 static gboolean
gst_test_control_source_get(GstTestControlSource * self,GstClockTime timestamp,gdouble * value)244 gst_test_control_source_get (GstTestControlSource * self,
245     GstClockTime timestamp, gdouble * value)
246 {
247   *value = self->value;
248   return TRUE;
249 }
250 
251 static gboolean
gst_test_control_source_get_value_array(GstTestControlSource * self,GstClockTime timestamp,GstClockTime interval,guint n_values,gdouble * values)252 gst_test_control_source_get_value_array (GstTestControlSource * self,
253     GstClockTime timestamp, GstClockTime interval, guint n_values,
254     gdouble * values)
255 {
256   guint i;
257 
258   for (i = 0; i < n_values; i++) {
259     *values = self->value;
260     values++;
261   }
262   return TRUE;
263 }
264 
265 static void
gst_test_control_source_init(GstTestControlSource * self)266 gst_test_control_source_init (GstTestControlSource * self)
267 {
268   GstControlSource *cs = (GstControlSource *) self;
269 
270   cs->get_value = (GstControlSourceGetValue) gst_test_control_source_get;
271   cs->get_value_array = (GstControlSourceGetValueArray)
272       gst_test_control_source_get_value_array;
273   self->value = 0.0;
274 }
275 
276 static GType
gst_test_control_source_get_type(void)277 gst_test_control_source_get_type (void)
278 {
279   static volatile gsize test_countrol_source_type = 0;
280 
281   if (g_once_init_enter (&test_countrol_source_type)) {
282     GType type;
283     static const GTypeInfo info = {
284       (guint16) sizeof (GstTestControlSourceClass),
285       NULL,                     // base_init
286       NULL,                     // base_finalize
287       NULL,                     // class_init
288       NULL,                     // class_finalize
289       NULL,                     // class_data
290       (guint16) sizeof (GstTestControlSource),
291       0,                        // n_preallocs
292       (GInstanceInitFunc) gst_test_control_source_init, // instance_init
293       NULL                      // value_table
294     };
295     type =
296         g_type_register_static (GST_TYPE_CONTROL_SOURCE, "GstTestControlSource",
297         &info, 0);
298     g_once_init_leave (&test_countrol_source_type, type);
299   }
300   return test_countrol_source_type;
301 }
302 
303 /* test control binding */
304 
305 enum
306 {
307   PROP_CS = 1,
308 };
309 
310 #define GST_TYPE_TEST_CONTROL_BINDING            (gst_test_control_binding_get_type ())
311 #define GST_TEST_CONTROL_BINDING(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBinding))
312 #define GST_TEST_CONTROL_BINDING_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass))
313 #define GST_IS_TEST_CONTROL_BINDING(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_BINDING))
314 #define GST_IS_TEST_CONTROL_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_BINDING))
315 #define GST_TEST_CONTROL_BINDING_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass))
316 
317 typedef struct _GstTestControlBinding GstTestControlBinding;
318 typedef struct _GstTestControlBindingClass GstTestControlBindingClass;
319 
320 struct _GstTestControlBinding
321 {
322   GstControlBinding parent;
323 
324   GstControlSource *cs;
325 };
326 struct _GstTestControlBindingClass
327 {
328   GstControlBindingClass parent_class;
329 };
330 
331 static GType gst_test_control_binding_get_type (void);
332 static GstControlBindingClass *gst_test_control_binding_parent_class = NULL;
333 
334 static GstControlBinding *
gst_test_control_binding_new(GstObject * object,const gchar * property_name,GstControlSource * cs)335 gst_test_control_binding_new (GstObject * object, const gchar * property_name,
336     GstControlSource * cs)
337 {
338   GstTestControlBinding *self;
339   self = (GstTestControlBinding *) g_object_new (GST_TYPE_TEST_CONTROL_BINDING,
340       "object", object, "name", property_name, NULL);
341 
342   self->cs = gst_object_ref (cs);
343 
344   return (GstControlBinding *) self;
345 }
346 
347 static void
gst_test_control_binding_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)348 gst_test_control_binding_get_property (GObject * object,
349     guint property_id, GValue * value, GParamSpec * pspec)
350 {
351   GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (object);
352 
353   switch (property_id) {
354     case PROP_CS:
355       g_value_set_object (value, self->cs);
356       break;
357     default:
358       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
359       break;
360   }
361 }
362 
363 static void
gst_test_control_binding_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)364 gst_test_control_binding_set_property (GObject * object,
365     guint property_id, const GValue * value, GParamSpec * pspec)
366 {
367   GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (object);
368 
369   switch (property_id) {
370     case PROP_CS:
371       self->cs = g_value_dup_object (value);
372       break;
373     default:
374       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
375       break;
376   }
377 }
378 
379 static void
gst_test_control_binding_finalize(GObject * obj)380 gst_test_control_binding_finalize (GObject * obj)
381 {
382   GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (obj);
383 
384   gst_object_unref (self->cs);
385 
386   G_OBJECT_CLASS (gst_test_control_binding_parent_class)->finalize (obj);
387 }
388 
389 static void
gst_test_control_binding_class_init(gpointer klass,gpointer class_data)390 gst_test_control_binding_class_init (gpointer klass, gpointer class_data)
391 {
392   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
393 
394   gst_test_control_binding_parent_class = g_type_class_peek_parent (klass);
395 
396   gobject_class->set_property = gst_test_control_binding_set_property;
397   gobject_class->get_property = gst_test_control_binding_get_property;
398   gobject_class->finalize = gst_test_control_binding_finalize;
399 
400   g_object_class_install_property (gobject_class, PROP_CS,
401       g_param_spec_object ("control-source", "ControlSource",
402           "The control source",
403           GST_TYPE_CONTROL_SOURCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
404 }
405 
406 static GType
gst_test_control_binding_get_type(void)407 gst_test_control_binding_get_type (void)
408 {
409   static volatile gsize test_countrol_binding_type = 0;
410 
411   if (g_once_init_enter (&test_countrol_binding_type)) {
412     GType type;
413     static const GTypeInfo info = {
414       (guint16) sizeof (GstTestControlBindingClass),
415       NULL,                     // base_init
416       NULL,                     // base_finalize
417       gst_test_control_binding_class_init,      // class_init
418       NULL,                     // class_finalize
419       NULL,                     // class_data
420       (guint16) sizeof (GstTestControlBinding),
421       0,                        // n_preallocs
422       NULL,                     // instance_init
423       NULL                      // value_table
424     };
425     type =
426         g_type_register_static (GST_TYPE_CONTROL_BINDING,
427         "GstTestControlBinding", &info, 0);
428     g_once_init_leave (&test_countrol_binding_type, type);
429   }
430   return test_countrol_binding_type;
431 }
432 
433 
434 static void
setup(void)435 setup (void)
436 {
437   gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ);
438 }
439 
440 static void
teardown(void)441 teardown (void)
442 {
443 }
444 
445 
446 /* TESTS */
447 
448 /* tests for an element with no controlled params */
GST_START_TEST(controller_new_fail1)449 GST_START_TEST (controller_new_fail1)
450 {
451   GstElement *elem;
452   GstTestControlSource *cs;
453   GstControlBinding *cb;
454 
455   elem = gst_element_factory_make ("testobj", NULL);
456   cs = gst_test_control_source_new ();
457 
458   /* that property should not exist */
459   cb = gst_test_control_binding_new (GST_OBJECT (elem), "_schrompf_",
460       GST_CONTROL_SOURCE (cs));
461   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
462 
463   gst_object_unref (cb);
464   gst_object_unref (cs);
465   gst_object_unref (elem);
466 }
467 
468 GST_END_TEST;
469 
470 /* tests for readonly params */
GST_START_TEST(controller_new_fail2)471 GST_START_TEST (controller_new_fail2)
472 {
473   GstElement *elem;
474   GstTestControlSource *cs;
475   GstControlBinding *cb;
476 
477   elem = gst_element_factory_make ("testobj", NULL);
478   cs = gst_test_control_source_new ();
479 
480   /* that property should exist and but is readonly */
481   cb = gst_test_control_binding_new (GST_OBJECT (elem), "readonly",
482       GST_CONTROL_SOURCE (cs));
483   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
484 
485   gst_object_unref (cb);
486   gst_object_unref (cs);
487   gst_object_unref (elem);
488 }
489 
490 GST_END_TEST;
491 
492 /* tests for static params */
GST_START_TEST(controller_new_fail3)493 GST_START_TEST (controller_new_fail3)
494 {
495   GstElement *elem;
496   GstTestControlSource *cs;
497   GstControlBinding *cb;
498 
499   elem = gst_element_factory_make ("testobj", NULL);
500   cs = gst_test_control_source_new ();
501 
502   /* that property should exist and but is not controlable */
503   cb = gst_test_control_binding_new (GST_OBJECT (elem), "static",
504       GST_CONTROL_SOURCE (cs));
505   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
506 
507   gst_object_unref (cb);
508   gst_object_unref (cs);
509   gst_object_unref (elem);
510 }
511 
512 GST_END_TEST;
513 
514 /* tests for construct-only params */
GST_START_TEST(controller_new_fail4)515 GST_START_TEST (controller_new_fail4)
516 {
517   GstElement *elem;
518   GstTestControlSource *cs;
519   GstControlBinding *cb;
520 
521   elem = gst_element_factory_make ("testobj", NULL);
522   cs = gst_test_control_source_new ();
523 
524   /* that property should exist and but is construct-only */
525   cb = gst_test_control_binding_new (GST_OBJECT (elem), "construct-only",
526       GST_CONTROL_SOURCE (cs));
527   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
528 
529   gst_object_unref (cb);
530   gst_object_unref (cs);
531   gst_object_unref (elem);
532 }
533 
534 GST_END_TEST;
535 
536 
537 /* tests for an element with controlled params */
GST_START_TEST(controller_new_okay1)538 GST_START_TEST (controller_new_okay1)
539 {
540   GstElement *elem;
541   GstTestControlSource *cs;
542   GstControlBinding *cb;
543 
544   elem = gst_element_factory_make ("testobj", NULL);
545   cs = gst_test_control_source_new ();
546 
547   /* that property should exist and should be controllable */
548   cb = gst_test_control_binding_new (GST_OBJECT (elem), "int",
549       GST_CONTROL_SOURCE (cs));
550   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
551 
552   gst_object_unref (cb);
553   gst_object_unref (cs);
554   gst_object_unref (elem);
555 }
556 
557 GST_END_TEST;
558 
559 /* tests for an element with several controlled params */
GST_START_TEST(controller_new_okay2)560 GST_START_TEST (controller_new_okay2)
561 {
562   GstElement *elem;
563   GstTestControlSource *cs1, *cs2;
564   GstControlBinding *cb1, *cb2;
565 
566   elem = gst_element_factory_make ("testobj", NULL);
567   cs1 = gst_test_control_source_new ();
568   cs2 = gst_test_control_source_new ();
569 
570   /* these properties should exist and should be controllable */
571   cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int",
572       GST_CONTROL_SOURCE (cs1));
573   fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL);
574 
575   cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "boolean",
576       GST_CONTROL_SOURCE (cs2));
577   fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL);
578 
579   gst_object_unref (cb1);
580   gst_object_unref (cb2);
581   gst_object_unref (cs1);
582   gst_object_unref (cs2);
583   gst_object_unref (elem);
584 }
585 
586 GST_END_TEST;
587 
588 /* controlling a param twice should be handled */
GST_START_TEST(controller_param_twice)589 GST_START_TEST (controller_param_twice)
590 {
591   GstElement *elem;
592   GstTestControlSource *cs;
593   GstControlBinding *cb;
594   gboolean res;
595 
596   elem = gst_element_factory_make ("testobj", NULL);
597   cs = gst_test_control_source_new ();
598 
599   /* that property should exist and should be controllable */
600   cb = gst_test_control_binding_new (GST_OBJECT (elem), "int",
601       GST_CONTROL_SOURCE (cs));
602   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
603   cb = gst_object_ref (cb);
604 
605   res = gst_object_add_control_binding (GST_OBJECT (elem), cb);
606   fail_unless (res, NULL);
607 
608   /* setting it again will just unset the old and set it again
609    * this might cause some trouble with binding the control source again
610    */
611   res = gst_object_add_control_binding (GST_OBJECT (elem), cb);
612   fail_unless (res, NULL);
613 
614   /* it should have been added now, let remove it */
615   res = gst_object_remove_control_binding (GST_OBJECT (elem), cb);
616   fail_unless (res, NULL);
617 
618   /* removing it again should not work */
619   res = gst_object_remove_control_binding (GST_OBJECT (elem), cb);
620   fail_unless (!res, NULL);
621 
622   gst_object_unref (cb);
623   gst_object_unref (cs);
624   gst_object_unref (elem);
625 }
626 
627 GST_END_TEST;
628 
629 /* tests if we can run controller methods against any GObject */
GST_START_TEST(controller_any_gobject)630 GST_START_TEST (controller_any_gobject)
631 {
632   GstElement *elem;
633   gboolean res;
634 
635   elem = gst_element_factory_make ("bin", "test_elem");
636 
637   /* that element is not controllable */
638   res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
639   /* Syncing should still succeed as there's nothing to sync */
640   fail_unless (res == TRUE, NULL);
641 
642   gst_object_unref (elem);
643 }
644 
645 GST_END_TEST;
646 
647 /* tests if we cleanup properly */
GST_START_TEST(controller_controlsource_refcounts)648 GST_START_TEST (controller_controlsource_refcounts)
649 {
650   GstElement *elem;
651   GstControlBinding *cb, *test_cb;
652   GstControlSource *cs, *test_cs;
653 
654   elem = gst_element_factory_make ("testobj", NULL);
655 
656   cs = (GstControlSource *) gst_test_control_source_new ();
657   fail_unless (cs != NULL, NULL);
658 
659   fail_unless_equals_int (G_OBJECT (cs)->ref_count, 1);
660 
661   cb = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs);
662   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
663   fail_unless_equals_int (G_OBJECT (cs)->ref_count, 2);
664   fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), cb));
665 
666   test_cb = gst_object_get_control_binding (GST_OBJECT (elem), "int");
667   fail_unless (test_cb != NULL, NULL);
668 
669   g_object_get (test_cb, "control-source", &test_cs, NULL);
670   fail_unless (test_cs != NULL, NULL);
671   fail_unless (test_cs == cs);
672   fail_unless_equals_int (G_OBJECT (cs)->ref_count, 3);
673   gst_object_unref (test_cs);
674   gst_object_unref (test_cb);
675   gst_object_unref (cs);
676 
677   gst_object_unref (elem);
678 }
679 
680 GST_END_TEST;
681 
682 /* tests if we can bind a control source twice */
GST_START_TEST(controller_bind_twice)683 GST_START_TEST (controller_bind_twice)
684 {
685   GstElement *elem;
686   GstControlSource *cs;
687   GstControlBinding *cb1, *cb2;
688 
689   elem = gst_element_factory_make ("testobj", NULL);
690 
691   cs = (GstControlSource *) gst_test_control_source_new ();
692   fail_unless (cs != NULL, NULL);
693 
694   cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs);
695   fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL);
696   cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "double", cs);
697   fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL);
698 
699   gst_object_unref (cb1);
700   gst_object_unref (cb2);
701   gst_object_unref (cs);
702   gst_object_unref (elem);
703 }
704 
705 GST_END_TEST;
706 
707 
708 static Suite *
gst_controller_suite(void)709 gst_controller_suite (void)
710 {
711   Suite *s = suite_create ("Controller");
712   TCase *tc = tcase_create ("general");
713 
714   suite_add_tcase (s, tc);
715   tcase_add_checked_fixture (tc, setup, teardown);
716   tcase_add_test (tc, controller_new_fail1);
717   tcase_add_test (tc, controller_new_fail2);
718   tcase_add_test (tc, controller_new_fail3);
719   tcase_add_test (tc, controller_new_fail4);
720   tcase_add_test (tc, controller_new_okay1);
721   tcase_add_test (tc, controller_new_okay2);
722   tcase_add_test (tc, controller_param_twice);
723   tcase_add_test (tc, controller_any_gobject);
724   tcase_add_test (tc, controller_controlsource_refcounts);
725   tcase_add_test (tc, controller_bind_twice);
726 
727   return s;
728 }
729 
730 GST_CHECK_MAIN (gst_controller);
731