more tests (and fixes) for the controller more docs for the controller integrated...
authorStefan Kost <ensonic@users.sourceforge.net>
Fri, 5 Aug 2005 10:02:44 +0000 (10:02 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Fri, 5 Aug 2005 10:02:44 +0000 (10:02 +0000)
Original commit message from CVS:
more tests (and fixes) for the controller
more docs for the controller
integrated companies docs for the adapter

75 files changed:
ChangeLog
check/gst-libs/controller.c
docs/gst/gstreamer-docs.sgml
docs/gst/gstreamer-sections.txt
docs/gst/gstreamer.types
docs/gst/tmpl/gst.sgml
docs/gst/tmpl/gstbasesink.sgml
docs/gst/tmpl/gstbasesrc.sgml
docs/gst/tmpl/gstbasetransform.sgml
docs/gst/tmpl/gstbin.sgml
docs/gst/tmpl/gstbuffer.sgml
docs/gst/tmpl/gstcaps.sgml
docs/gst/tmpl/gstclock.sgml
docs/gst/tmpl/gstcompat.sgml
docs/gst/tmpl/gstconfig.sgml
docs/gst/tmpl/gstelement.sgml
docs/gst/tmpl/gstelementdetails.sgml
docs/gst/tmpl/gstelementfactory.sgml
docs/gst/tmpl/gstenumtypes.sgml
docs/gst/tmpl/gsterror.sgml
docs/gst/tmpl/gstevent.sgml
docs/gst/tmpl/gstfakesink.sgml
docs/gst/tmpl/gstfakesrc.sgml
docs/gst/tmpl/gstfilesink.sgml
docs/gst/tmpl/gstfilesrc.sgml
docs/gst/tmpl/gstfilter.sgml
docs/gst/tmpl/gstformat.sgml
docs/gst/tmpl/gstghostpad.sgml
docs/gst/tmpl/gstimplementsinterface.sgml
docs/gst/tmpl/gstindex.sgml
docs/gst/tmpl/gstindexfactory.sgml
docs/gst/tmpl/gstinfo.sgml
docs/gst/tmpl/gstiterator.sgml
docs/gst/tmpl/gstmacros.sgml
docs/gst/tmpl/gstmemchunk.sgml
docs/gst/tmpl/gstminiobject.sgml
docs/gst/tmpl/gstobject.sgml
docs/gst/tmpl/gstpad.sgml
docs/gst/tmpl/gstpadtemplate.sgml
docs/gst/tmpl/gstparse.sgml
docs/gst/tmpl/gstpipeline.sgml
docs/gst/tmpl/gstplugin.sgml
docs/gst/tmpl/gstpluginfeature.sgml
docs/gst/tmpl/gstquery.sgml
docs/gst/tmpl/gstqueue.sgml
docs/gst/tmpl/gstregistry.sgml
docs/gst/tmpl/gstregistrypool.sgml
docs/gst/tmpl/gststructure.sgml
docs/gst/tmpl/gstsystemclock.sgml
docs/gst/tmpl/gsttaglist.sgml
docs/gst/tmpl/gsttagsetter.sgml
docs/gst/tmpl/gsttrace.sgml
docs/gst/tmpl/gsttrashstack.sgml
docs/gst/tmpl/gsttypefind.sgml
docs/gst/tmpl/gsttypefindfactory.sgml
docs/gst/tmpl/gsttypes.sgml
docs/gst/tmpl/gsturihandler.sgml
docs/gst/tmpl/gsturitype.sgml
docs/gst/tmpl/gstutils.sgml
docs/gst/tmpl/gstvalue.sgml
docs/gst/tmpl/gstversion.sgml
docs/gst/tmpl/gstxml.sgml
docs/libs/gstreamer-libs-docs.sgml
docs/libs/gstreamer-libs-sections.txt
docs/libs/tmpl/gstdataprotocol.sgml
docs/libs/tmpl/gstgetbits.sgml
gst/base/gstadapter.c
libs/gst/base/gstadapter.c
libs/gst/controller/gst-controller.c
libs/gst/controller/gst-controller.h
libs/gst/controller/gst-helper.c
libs/gst/controller/gstcontroller.c
libs/gst/controller/gstcontroller.h
libs/gst/controller/gsthelper.c
tests/check/libs/controller.c

index 0da40db..7607784 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2005-08-05  Stefan Kost  <ensonic@users.sf.net>
+
+       * check/gst-libs/controller.c: (gst_test_mono_source_get_property),
+       (gst_test_mono_source_set_property),
+       (gst_test_mono_source_class_init), (GST_START_TEST),
+       (gst_controller_suite):
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * docs/gst/gstreamer.types:
+       * docs/libs/gstreamer-libs-docs.sgml:
+       * docs/libs/gstreamer-libs-sections.txt:
+       * gst/base/gstadapter.c:
+       * libs/gst/controller/gst-controller.c:
+       (gst_controlled_property_new), (gst_controlled_property_free),
+       (gst_controller_new_valist),
+       (gst_controller_remove_properties_valist),
+       (gst_controller_sink_values), (_gst_controller_finalize):
+       * libs/gst/controller/gst-controller.h:
+       * libs/gst/controller/gst-helper.c:
+       (gst_object_control_properties), (gst_object_uncontrol_properties),
+       (gst_object_get_controller), (gst_object_set_controller),
+       (gst_object_sink_values), (gst_object_get_value_arrays),
+       (gst_object_get_value_array):
+          more tests (and fixes) for the controller
+          more docs for the controller
+          integrated companies docs for the adapter 
+
 2005-08-05  Thomas Vander Stichele  <thomas at apestaart dot org>
 
        * check/elements/gstfakesrc.c: (setup_fakesrc), (cleanup_fakesrc),
index 5fde800..dc1e100 100644 (file)
@@ -30,7 +30,7 @@ enum
 {
   ARG_ULONG = 1,
   ARG_DOUBLE,
-  ARG_SWITCH,
+  ARG_BOOLEAN,
   ARG_COUNT
 };
 
@@ -47,6 +47,9 @@ typedef struct _GstTestMonoSourceClass GstTestMonoSourceClass;
 struct _GstTestMonoSource
 {
   GstElement parent;
+  gulong val_ulong;
+  gdouble val_double;
+  gboolean val_bool;
 };
 struct _GstTestMonoSourceClass
 {
@@ -59,14 +62,17 @@ static void
 gst_test_mono_source_get_property (GObject * object,
     guint property_id, GValue * value, GParamSpec * pspec)
 {
-  //GstTestMonoSource *self = GST_TEST_MONO_SOURCE(object);
+  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
 
   switch (property_id) {
     case ARG_ULONG:
+      g_value_set_ulong (value, self->val_ulong);
       break;
-    default:{
+    case ARG_DOUBLE:
+      g_value_set_double (value, self->val_double);
+      break;
+    default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
       break;
   }
 }
@@ -75,14 +81,17 @@ static void
 gst_test_mono_source_set_property (GObject * object,
     guint property_id, const GValue * value, GParamSpec * pspec)
 {
-  //GstTestMonoSource *self = GST_TEST_MONO_SOURCE(object);
+  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
 
   switch (property_id) {
     case ARG_ULONG:
+      self->val_ulong = g_value_get_ulong (value);
+      break;
+    case ARG_DOUBLE:
+      self->val_double = g_value_get_double (value);
       break;
-    default:{
+    default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
       break;
   }
 }
@@ -100,6 +109,12 @@ gst_test_mono_source_class_init (GstTestMonoSourceClass * klass)
           "ulong prop",
           "ulong number parameter for the test_mono_source",
           0, G_MAXULONG, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, ARG_DOUBLE,
+      g_param_spec_double ("double",
+          "double prop",
+          "double number parameter for the test_mono_source",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 }
 
 static void
@@ -177,8 +192,97 @@ GST_START_TEST (controller_new_fail)
   ctrl = gst_controller_new (G_OBJECT (elem), "_schrompf_", NULL);
   fail_unless (ctrl == NULL, NULL);
 
-  /* that property exists, but is not controllable */
-  ASSERT_CRITICAL (ctrl = gst_controller_new (G_OBJECT (elem), "name", NULL));
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for an element with controlled params */
+GST_START_TEST (controller_new_okay1)
+{
+  GstController *ctrl;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  g_object_unref (ctrl);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* controlling several params should return the same controller */
+GST_START_TEST (controller_new_okay2)
+{
+  GstController *ctrl1, *ctrl2;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl1 = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl1 != NULL, NULL);
+
+  /* that property should exist and should be controllable */
+  ctrl2 = gst_controller_new (G_OBJECT (elem), "double", NULL);
+  fail_unless (ctrl2 != NULL, NULL);
+  fail_unless (ctrl1 == ctrl2, NULL);
+
+  g_object_unref (ctrl2);
+  g_object_unref (ctrl1);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* controlling a params twice should be handled */
+GST_START_TEST (controller_param_twice)
+{
+  GstController *ctrl;
+  GstElement *elem;
+  gboolean res;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  /* it should have been added at least once, let remove it */
+  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
+  fail_unless (res, NULL);
+
+  /* removing it agian should not work */
+  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
+  fail_unless (!res, NULL);
+
+  g_object_unref (ctrl);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests if we cleanup properly */
+GST_START_TEST (controller_finalize)
+{
+  GstController *ctrl;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  /* free the controller */
+  g_object_unref (ctrl);
+
+  /* object shouldn't have a controller anymore */
+  ctrl = gst_object_get_controller (G_OBJECT (elem));
   fail_unless (ctrl == NULL, NULL);
 
   g_object_unref (elem);
@@ -186,11 +290,13 @@ GST_START_TEST (controller_new_fail)
 
 GST_END_TEST;
 
-/* tests for an element with controlled params */
-GST_START_TEST (controller_new_okay)
+/* test timed value handling without interpolation */
+GST_START_TEST (controller_interpolate_none)
 {
   GstController *ctrl;
   GstElement *elem;
+  gboolean res;
+  GValue val_ulong = { 0, };
 
   elem = gst_element_factory_make ("testmonosource", "test_source");
 
@@ -198,6 +304,26 @@ GST_START_TEST (controller_new_okay)
   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
   fail_unless (ctrl != NULL, NULL);
 
+  /* set interpolation mode */
+  gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE);
+
+  /* set control values */
+  g_value_init (&val_ulong, G_TYPE_ULONG);
+  g_value_set_ulong (&val_ulong, 0);
+  res = gst_controller_set (ctrl, "ulong", 0 * GST_SECOND, &val_ulong);
+  fail_unless (res, NULL);
+  g_value_set_ulong (&val_ulong, 100);
+  res = gst_controller_set (ctrl, "ulong", 2 * GST_SECOND, &val_ulong);
+  fail_unless (res, NULL);
+
+  /* now pull in values for some timestamps */
+  gst_controller_sink_values (ctrl, 0 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
+  gst_controller_sink_values (ctrl, 1 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
+  gst_controller_sink_values (ctrl, 2 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 100, NULL);
+
   g_object_unref (ctrl);
   g_object_unref (elem);
 }
@@ -215,7 +341,11 @@ gst_controller_suite (void)
   suite_add_tcase (s, tc);
   tcase_add_test (tc, controller_init);
   tcase_add_test (tc, controller_new_fail);
-  tcase_add_test (tc, controller_new_okay);
+  tcase_add_test (tc, controller_new_okay1);
+  tcase_add_test (tc, controller_new_okay2);
+  tcase_add_test (tc, controller_param_twice);
+  tcase_add_test (tc, controller_finalize);
+  tcase_add_test (tc, controller_interpolate_none);
 
   return s;
 }
index cef54fd..686a062 100644 (file)
@@ -55,6 +55,7 @@
 <!ENTITY GstVersion SYSTEM "xml/gstversion.xml">
 <!ENTITY GstXML SYSTEM "xml/gstxml.xml">
 
+<!ENTITY GstAdapter SYSTEM "xml/gstadapter.xml">
 <!ENTITY GstBaseSrc SYSTEM "xml/gstbasesrc.xml">
 <!ENTITY GstBaseSink SYSTEM "xml/gstbasesink.xml">
 <!ENTITY GstBaseTransform SYSTEM "xml/gstbasetransform.xml">
       These base classes are provided to be extended by elements.
     </para>
 
+    &GstAdapter;
     &GstBaseSrc;
     &GstBaseSink;
     &GstBaseTransform;
-       &GstPushSrc;
+    &GstPushSrc;
 
   </chapter>
 
index a63e5b4..0dd957c 100644 (file)
@@ -1634,6 +1634,30 @@ gst_xml_get_type
 # base classes
 
 <SECTION>
+<FILE>gstadapter</FILE>
+<TITLE>GstAdapter</TITLE>
+GstAdapter
+GstAdapterClass
+gst_adapter_new
+gst_adapter_clear
+gst_adapter_push
+gst_adapter_peek
+gst_adapter_flush
+gst_adapter_available
+gst_adapter_available_fast
+<SUBSECTION Standard>
+GST_ADAPTER_SRC
+GST_IS_ADAPTER_SRC
+GST_TYPE_ADAPTER_SRC
+GST_ADAPTER_SRC_CLASS
+GST_IS_ADAPTER_SRC_CLASS
+GST_ADAPTER_SRC_GET_CLASS
+<SUBSECTION Private>
+gst_adapter_src_get_type
+</SECTION>
+
+
+<SECTION>
 <FILE>gstbasesrc</FILE>
 <TITLE>GstBaseSrc</TITLE>
 GstBaseSrc
index 9e15f08..f320e5c 100644 (file)
@@ -33,11 +33,13 @@ gst_xml_get_type
 
 % base classes
 
+#include <gst/base/gstadapter.h>
 #include <gst/base/gstbasesrc.h>
 #include <gst/base/gstbasesink.h>
 #include <gst/base/gstbasetransform.h>
 #include <gst/base/gstpushsrc.h>
 
+gst_adapter_get_type
 gst_base_src_get_type
 gst_base_sink_get_type
 gst_base_transform_get_type
index eb88667..fc6631a 100644 (file)
@@ -87,6 +87,9 @@ Check out both <ulink url="http://www.cse.ogi.edu/sysl/">OGI's
 pipeline</ulink> and Microsoft's DirectShow for some background.
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION gst_init ##### -->
 <para>
 
index 4ba69f2..429222d 100644 (file)
@@ -14,6 +14,9 @@ GstBaseSink
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstBaseSink ##### -->
 <para>
 
index 5b06188..ada1af9 100644 (file)
@@ -14,6 +14,9 @@ GstBaseSrc
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstBaseSrc ##### -->
 <para>
 
index d566f39..4ae5603 100644 (file)
@@ -14,6 +14,9 @@ GstBaseTransform
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstBaseTransform ##### -->
 <para>
 
index 2007814..18938a4 100644 (file)
@@ -55,6 +55,9 @@ clock providers in the bin.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstBin ##### -->
 <para>
 
index a8c176f..08d3c89 100644 (file)
@@ -85,6 +85,9 @@ Last reviewed on August 12th, 2004 (0.8.5)
 #GstPad, #GstMiniObject
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstBuffer ##### -->
 <para>
 The basic structure of a buffer.
index 25ad066..fdc72d3 100644 (file)
@@ -14,6 +14,9 @@ Structure describing sets of media formats
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstCaps ##### -->
 <para>
 
index 052fe05..231085a 100644 (file)
@@ -22,6 +22,9 @@ a good measure of the current playback time in the pipeline.
 #GstSystemClock
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstClock ##### -->
 <para>
 
index 16c29cd..402c11c 100644 (file)
@@ -16,3 +16,6 @@ This can be done in CFLAGS for compiling old code.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
index ed05367..6e71764 100644 (file)
@@ -37,6 +37,9 @@ If a subsystem is disabled in GStreamer, a value is defined in
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### MACRO GST_DISABLE_LOADSAVE_REGISTRY ##### -->
 <para>
 
index 4708c06..703e7dd 100644 (file)
@@ -65,6 +65,9 @@ and gst_element_set_clock().  You can wait for the clock to reach a given
 
 <!-- basic object functions -->
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstElement ##### -->
 <para>
 
index 8c57fce..757ebbc 100644 (file)
@@ -14,6 +14,9 @@ Defines public information about a #GstElement
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstElementDetails ##### -->
 <para>
 This struct is used to define public information about the element.  It
index 5e74564..c68b5b4 100644 (file)
@@ -54,6 +54,9 @@ so that the autopluggers can select a plugin more appropriatly
 #GstElement, #GstPlugin, #GstPluginFeature, #GstPadTemplate.
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstElementFactory ##### -->
 <para>
 
index e9361f1..52ba68c 100644 (file)
@@ -14,3 +14,6 @@ all gstreamer core related enumerations
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
index 11701fc..3b972c3 100644 (file)
@@ -14,6 +14,9 @@ Categorized error messages
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstCoreError ##### -->
 <para>
 
index 66277de..4872e40 100644 (file)
@@ -27,6 +27,9 @@ gst_event_new_flush() creates a new flush event.
 #GstPad, #GstElement
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstEvent ##### -->
 <para>
 
index 7755271..bbf1d94 100644 (file)
@@ -14,6 +14,9 @@ GstFakeSink
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstFakeSink ##### -->
 <para>
 
index ad63acc..28fcaf6 100644 (file)
@@ -14,6 +14,9 @@ GstFakeSrc
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstFakeSrc ##### -->
 <para>
 
@@ -39,6 +42,7 @@ GstFakeSrc
 @:
 @:
 @:
+@:
 @: 
 
 <!-- ##### ARG GstFakeSrc:data ##### -->
index e3bd8dd..9ec2717 100644 (file)
@@ -14,6 +14,9 @@ GstFileSink
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstFileSink ##### -->
 <para>
 
index e7d7274..806b545 100644 (file)
@@ -14,6 +14,9 @@ GstFileSrc
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstFileSrc ##### -->
 <para>
 
index 8f5a2fe..49932ee 100644 (file)
@@ -17,6 +17,9 @@ on its own.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### USER_FUNCTION GstFilterFunc ##### -->
 <para>
 
index 99d947e..ae7b43d 100644 (file)
@@ -15,6 +15,9 @@ formats can be used to perform seeking or conversions/query operations.
 #GstPad, #GstElement
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstFormat ##### -->
 <para>
 Standard predefined formats
index 520c300..b92fdbd 100644 (file)
@@ -14,6 +14,9 @@ Pseudo link pads
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstGhostPad ##### -->
 <para>
 
index 5683450..df7fb5f 100644 (file)
@@ -14,6 +14,9 @@ Core interface implemented by #GstElements that allows runtime querying of inter
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstImplementsInterface ##### -->
 <para>
 
index 74254d5..1eac0ee 100644 (file)
@@ -15,6 +15,9 @@ in a pipeline.
 #GstIndexFactory
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstIndex ##### -->
 <para>
 
index f458efd..7c86974 100644 (file)
@@ -14,6 +14,9 @@ GstIndexFactory is used to dynamically create GstIndex implementations.
 #GstIndex
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstIndexFactory ##### -->
 <para>
 The GstIndexFactory object
index be07e23..d2d2d58 100644 (file)
@@ -68,6 +68,9 @@ categories. These are explained at GST_DEBUG_CATEGORY_INIT().
 and environment variables that affect the debugging output.
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstDebugLevel ##### -->
 <para>
 The level defines the importance of a debugging message. The more important a 
index 307d499..9bc68df 100644 (file)
@@ -14,6 +14,9 @@ GstIterator
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstIterator ##### -->
 <para>
 
index 49b0cc6..8149bca 100644 (file)
@@ -14,3 +14,6 @@ various portabillity helper macros
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
index af74215..8ce3af2 100644 (file)
@@ -21,6 +21,9 @@ The GstMemChunk is used to allocate critical resources for #GstBuffer and
 #GstBuffer, #GstEvent, #GstData
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstMemChunk ##### -->
 <para>
 The memchunk structure
index 5481e39..ff0a8f1 100644 (file)
@@ -14,6 +14,9 @@ GstMiniObject
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstMiniObject ##### -->
 <para>
 
index ab9e443..583afec 100644 (file)
@@ -67,6 +67,9 @@ object.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstObject ##### -->
 <para>
 
index d215a3d..fa5a64d 100644 (file)
@@ -57,6 +57,9 @@ Last reviewed on December 13th, 2002 (0.5.0.1)
 #GstPadTemplate, #GstElement, #GstEvent
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstPad ##### -->
 <para>
 
index 1ff9a28..060a3d1 100644 (file)
@@ -73,6 +73,9 @@ The following example shows you how to add the padtemplate to an elementfactory:
 #GstPad, #GstElementFactory
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstPadTemplate ##### -->
 <para>
 The padtemplate object.
index 5b70820..e43a2da 100644 (file)
@@ -14,6 +14,9 @@ get a pipeline from a text pipeline description
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION gst_parse_error_quark ##### -->
 <para>
 
index bbd6ecd..74912fa 100644 (file)
@@ -21,6 +21,9 @@ the pipeline, use gst_object_unref() to free its resources.
 #GstBin
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstPipeline ##### -->
 <para>
 
index cd93138..17a0ae7 100644 (file)
@@ -35,6 +35,9 @@ to bring the plugin into memory.
 #GstPluginFeature, #GstType, #GstAutoplug, #GstElementFactory
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION gst_plugin_error_quark ##### -->
 <para>
 Get the error quark
index 6395293..96a2e5e 100644 (file)
@@ -14,6 +14,9 @@ This is a base class for anything that can be added to a #GstPlugin.
 #GstPlugin
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstPluginFeature ##### -->
 <para>
 
index ed0755b..3fcf8be 100644 (file)
@@ -15,6 +15,9 @@ Query types can be used to perform queries on pads and elements.
 #GstPad, #GstElement
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstQueryType ##### -->
 <para>
 Standard predefined Query types
index 71ce9c5..3d2a500 100644 (file)
@@ -25,6 +25,9 @@ The queue blocks by default.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstQueue ##### -->
 <para>
 
index a554aee..be6b381 100644 (file)
@@ -15,3 +15,6 @@ All registries build the #GstRegistryPool.
 #GstPlugin, #GstPluginFeature
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
index 82b21c6..99de4f9 100644 (file)
@@ -15,6 +15,9 @@ the system.
 GstRegistry
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION gst_registry_pool_list ##### -->
 <para>
 
index 7bbb0bf..14fd72e 100644 (file)
@@ -14,6 +14,9 @@ Generic structure containing fields of names and values
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstStructure ##### -->
 <para>
 
index 714c32c..71c56fd 100644 (file)
@@ -15,6 +15,9 @@ system time.
 #GstClock
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstSystemClock ##### -->
 <para>
 
index 6dc2830..b45b446 100644 (file)
@@ -14,6 +14,9 @@ List of tags and values used to describe media metadata
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF GstTagList ##### -->
 <para>
 
index 4c55270..d80b667 100644 (file)
@@ -14,6 +14,9 @@ Element interface that allows setting and retrieval of media metadata
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstTagSetter ##### -->
 <para>
 
index 6ccaa79..b08a807 100644 (file)
@@ -14,6 +14,9 @@ Tracing functionality
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstTrace ##### -->
 <para>
 
index 81bb80f..27eeeeb 100644 (file)
@@ -14,6 +14,9 @@ gsttrashstack
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstTrashStack ##### -->
 <para>
 
index d729fd0..eb4ab7e 100644 (file)
@@ -14,6 +14,9 @@ typefinding subsystem
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstTypeFind ##### -->
 <para>
 
index 9aea96a..0ec2797 100644 (file)
@@ -67,6 +67,9 @@ the given data. You can get quite a bit more complicated than that though.
 <link linkend="gstreamer-Writing-typefind-functions">Writing typefind functions</link>
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstTypeFindFactory ##### -->
 <para>
 Object that stores information about a typefind function
index c83b048..58aaf1f 100644 (file)
@@ -14,6 +14,9 @@ various global enums and constants
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstElementState ##### -->
 <para>
 These contants describe the state a #GstElement is in and transition scheduled for the #GstElement (the pending state).
index fb5512f..7a3b021 100644 (file)
@@ -15,6 +15,9 @@ and the element property that can handle a given URI.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstURIHandler ##### -->
 <para>
 
index 99e0afc..1c2391c 100644 (file)
@@ -14,6 +14,9 @@ describes URI types
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstURIType ##### -->
 <para>
 
index 44b2c6d..6d7d55a 100644 (file)
@@ -14,6 +14,9 @@ various utility functions
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION gst_util_set_value_from_string ##### -->
 <para>
 
index ae47d26..72251a3 100644 (file)
@@ -14,6 +14,9 @@ GValue implementations specific to GStreamer
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### MACRO GST_MAKE_FOURCC ##### -->
 <para>
 will transform four characters into a host-endiannness guint32 fourcc:
index d6bcdfc..4a17d3c 100644 (file)
@@ -15,6 +15,9 @@ The version macros get defined by including "gst/gst.h".
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### MACRO GST_VERSION_MAJOR ##### -->
 <para>
 The major version of GStreamer at compile time
index 056f62e..4ae6709 100644 (file)
@@ -14,6 +14,9 @@ XML save/restore operations of pipelines
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT GstXML ##### -->
 <para>
 
index c978128..53f5cd5 100644 (file)
@@ -5,6 +5,7 @@
 %version-entities;
 <!ENTITY GstBytestream SYSTEM "xml/gstbytestream.xml">
 <!ENTITY GstController SYSTEM "xml/gstcontroller.xml">
+<!ENTITY GstControllerGObject SYSTEM "xml/gstcontrollergobject.xml">
 <!ENTITY GstGetbits SYSTEM "xml/gstgetbits.xml">
 <!-- has not yet been written
 <!ENTITY GstPutbits SYSTEM "xml/gstputbits.xml">
@@ -40,7 +41,7 @@
     <chapter id="gstreamer-control">
       <title>gstcontrol</title>
       &GstController;
-      <!--&GstControllerGObject; -->
+      &GstControllerGObject;
     </chapter>
 
   </part>
index bb6ec06..4111007 100644 (file)
@@ -142,3 +142,18 @@ GST_TYPE_CONTROLLER
 <SUBSECTION Private>
 gst_controller_get_type
 </SECTION>
+
+<SECTION>
+<FILE>gstcontrollergobject</FILE>
+<TITLE>GstControllerGObject</TITLE>
+<INCLUDE>libs/controller/gstcontroller.h</INCLUDE>
+gst_object_control_properties
+gst_object_uncontrol_properties
+gst_object_get_controller
+gst_object_set_controller
+gst_object_sink_values
+gst_object_get_value_arrays
+gst_object_get_value_array
+<SUBSECTION Standard>
+<SUBSECTION Private>
+</SECTION>
index 0cd1515..1bb87c8 100644 (file)
@@ -27,6 +27,9 @@ network connections also need a protocol to do this.
 #GstBuffer, #GstCaps, #GstEvent
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM GstDPHeaderFlag ##### -->
 <para>
 
index 1d107d6..e3e087a 100644 (file)
@@ -14,6 +14,9 @@ accelerated routines for getting bits from a data stream.
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT gst_getbits_t ##### -->
 <para>
 
index 09239d0..7c2b3ad 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:gstadapter
+ * @short_description: object to splice and merge buffers to desired size
+ * @see_also: #GstBytestream, #GstFilePad
+ *
+ * This class is for elements that receive buffers in an undesired size. 
+ * While for example raw video contains one image per buffer, the same is not 
+ * true for a lot of other formats, especially those that come directly from 
+ * a file. So if you have undefined buffer sizes and require a specific size, 
+ * this object is for you.
+ *
+ * The theory of operation is like this: All buffers received are put
+ * into the adapter using gst_adapter_push() and the data is then read back 
+ * in chunks of the desired size using gst_adapter_peek(). After the data is
+ * processed, it is freed using gst_adapter_flush(). An example function that
+ * needs to process data in 10 byte chunks could look like this:
+ * <programlisting>
+ * void
+ * process_buffer (GstAdapter *adapter, GstBuffer *buffer)
+ * {
+ *   guint8 *data;
+ *   // put buffer into adapter
+ *   #gst_adapter_push (adapter, buffer);
+ *   // while we can read out 10 bytes, process them
+ *   while ((data = #gst_adapter_peek (adapter, 10))) {
+ *     // process the 10 bytes here
+ *     // after processing the data, flush it
+ *     #gst_adapter_flush (adapter, 10);
+ *   }
+ * }
+ * </programlisting>
+ * For another example, a simple element inside GStreamer that uses GstAdapter
+ * is the libvisual element.
+ *
+ * A last thing to note is that while GstAdapter is pretty optimized, 
+ * merging buffers still might be an operation that requires a memcpy() 
+ * operation, and this operation is not the fastest. Because of this, some 
+ * functions like gst_adapter_available_fast() are provided to help speed up 
+ * such cases should you want to.
+ */
+
 #include <string.h>
 
 #include "gstadapter.h"
index 09239d0..7c2b3ad 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:gstadapter
+ * @short_description: object to splice and merge buffers to desired size
+ * @see_also: #GstBytestream, #GstFilePad
+ *
+ * This class is for elements that receive buffers in an undesired size. 
+ * While for example raw video contains one image per buffer, the same is not 
+ * true for a lot of other formats, especially those that come directly from 
+ * a file. So if you have undefined buffer sizes and require a specific size, 
+ * this object is for you.
+ *
+ * The theory of operation is like this: All buffers received are put
+ * into the adapter using gst_adapter_push() and the data is then read back 
+ * in chunks of the desired size using gst_adapter_peek(). After the data is
+ * processed, it is freed using gst_adapter_flush(). An example function that
+ * needs to process data in 10 byte chunks could look like this:
+ * <programlisting>
+ * void
+ * process_buffer (GstAdapter *adapter, GstBuffer *buffer)
+ * {
+ *   guint8 *data;
+ *   // put buffer into adapter
+ *   #gst_adapter_push (adapter, buffer);
+ *   // while we can read out 10 bytes, process them
+ *   while ((data = #gst_adapter_peek (adapter, 10))) {
+ *     // process the 10 bytes here
+ *     // after processing the data, flush it
+ *     #gst_adapter_flush (adapter, 10);
+ *   }
+ * }
+ * </programlisting>
+ * For another example, a simple element inside GStreamer that uses GstAdapter
+ * is the libvisual element.
+ *
+ * A last thing to note is that while GstAdapter is pretty optimized, 
+ * merging buffers still might be an operation that requires a memcpy() 
+ * operation, and this operation is not the fastest. Because of this, some 
+ * functions like gst_adapter_available_fast() are provided to help speed up 
+ * such cases should you want to.
+ */
+
 #include <string.h>
 
 #include "gstadapter.h"
index e6f7609..27bee4f 100644 (file)
@@ -217,7 +217,6 @@ gst_controlled_property_new (GObject * object, const gchar * name)
       gchar *signal_name;
 
       prop->name = pspec->name; // so we don't use the same mem twice
-      prop->object = object;
       prop->type = G_PARAM_SPEC_VALUE_TYPE (pspec);
       gst_controlled_property_set_interpolation_mode (prop,
           GST_INTERPOLATE_NONE);
@@ -298,7 +297,6 @@ gst_controlled_property_free (GstControlledProperty * prop)
 {
   GList *node;
 
-  g_signal_handler_disconnect (prop->object, prop->notify_handler_id);
   for (node = prop->values; node; node = g_list_next (node)) {
     g_free (node->data);
   }
@@ -370,16 +368,25 @@ gst_controller_new_valist (GObject * object, va_list var_args)
   self = g_object_get_qdata (object, controller_key);
   // create GstControlledProperty for each property
   while ((name = va_arg (var_args, gchar *))) {
-    // create GstControlledProperty and add to self->propeties List
-    if ((prop = gst_controlled_property_new (object, name))) {
-      // if we don't have a controller object yet, now is the time to create one
-      if (!self) {
-        self = g_object_new (GST_TYPE_CONTROLLER, NULL);
-        self->lock = g_mutex_new ();
-        // store the controller
-        g_object_set_qdata (object, controller_key, self);
+    // test if this property isn't yet controlled
+    if (!self || !(prop = gst_controller_find_controlled_property (self, name))) {
+      // create GstControlledProperty and add to self->propeties List
+      if ((prop = gst_controlled_property_new (object, name))) {
+        // if we don't have a controller object yet, now is the time to create one
+        if (!self) {
+          self = g_object_new (GST_TYPE_CONTROLLER, NULL);
+          self->lock = g_mutex_new ();
+          self->object = object;
+          // store the controller
+          g_object_set_qdata (object, controller_key, self);
+        } else {
+          // increment ref-count
+          self = g_object_ref (self);
+        }
+        self->properties = g_list_prepend (self->properties, prop);
       }
-      self->properties = g_list_prepend (self->properties, prop);
+    } else {
+      GST_WARNING ("trying to control property again");
     }
   }
   va_end (var_args);
@@ -434,6 +441,7 @@ gst_controller_remove_properties_valist (GstController * self, va_list var_args)
     g_mutex_lock (self->lock);
     if ((prop = gst_controller_find_controlled_property (self, name))) {
       self->properties = g_list_remove (self->properties, prop);
+      g_signal_handler_disconnect (self->object, prop->notify_handler_id);
       gst_controlled_property_free (prop);
     } else {
       res = FALSE;
@@ -712,7 +720,7 @@ gst_controller_sink_values (GstController * self, GstClockTime timestamp)
       value = prop->get (prop, timestamp);
       prop->last_value.timestamp = timestamp;
       g_value_copy (value, &prop->last_value.value);
-      g_object_set_property (prop->object, prop->name, value);
+      g_object_set_property (self->object, prop->name, value);
     }
   }
   g_mutex_unlock (self->lock);
@@ -864,16 +872,21 @@ _gst_controller_finalize (GObject * object)
 {
   GstController *self = GST_CONTROLLER (object);
   GList *node;
+  GstControlledProperty *prop;
 
-  // free list of properties
+  /* free list of properties */
   if (self->properties) {
     for (node = self->properties; node; node = g_list_next (node)) {
-      gst_controlled_property_free (node->data);
+      prop = node->data;
+      g_signal_handler_disconnect (self->object, prop->notify_handler_id);
+      gst_controlled_property_free (prop);
     }
     g_list_free (self->properties);
     self->properties = NULL;
   }
   g_mutex_free (self->lock);
+  /* remove controller from objects qdata list */
+  g_object_set_qdata (self->object, controller_key, NULL);
 
   if (G_OBJECT_CLASS (parent_class)->finalize)
     (G_OBJECT_CLASS (parent_class)->finalize) (object);
index a9472c4..ff3e184 100644 (file)
@@ -110,7 +110,6 @@ typedef struct _GstInterpolateMethod
 typedef struct _GstControlledProperty
 {
   gchar *name;                  // name of the property
-  GObject *object;              // the object we control
   GType type;                   // type of the handled property
   GValue default_value;         // default value for the handled property
   GValue result_value;          // result value location for the interpolation method
@@ -160,6 +159,7 @@ struct _GstController
 
   GList *properties;  // List of GstControlledProperty
   GMutex *lock;       // Secure property access, elements will access from threads
+  GObject *object;    // the object we control
 };
 
 struct _GstControllerClass
@@ -207,17 +207,17 @@ gboolean gst_controller_set_interpolation_mode (GstController * self,
 
 /* GObject convenience functions */
 
-GstController *g_object_control_properties (GObject * object, ...);
-gboolean g_object_uncontrol_properties (GObject * object, ...);
+GstController *gst_object_control_properties (GObject * object, ...);
+gboolean gst_object_uncontrol_properties (GObject * object, ...);
 
-GstController *g_object_get_controller (GObject * object);
-gboolean g_object_set_controller (GObject * object, GstController * controller);
+GstController *gst_object_get_controller (GObject * object);
+gboolean gst_object_set_controller (GObject * object, GstController * controller);
 
-gboolean g_object_sink_values (GObject * object, GstClockTime timestamp);
+gboolean gst_object_sink_values (GObject * object, GstClockTime timestamp);
 
-gboolean g_object_get_value_arrays (GObject * object,
+gboolean gst_object_get_value_arrays (GObject * object,
     GstClockTime timestamp, GSList * value_arrays);
-gboolean g_object_get_value_array (GObject * object,
+gboolean gst_object_get_value_array (GObject * object,
     GstClockTime timestamp, GstValueArray * value_array);
 
 /* lib init/done */
index de221cb..d308fd4 100644 (file)
@@ -14,7 +14,7 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
 extern GQuark controller_key;
 
 /**
- * g_object_control_properties:
+ * gst_object_control_properties:
  * @object: the object of which some properties should be controlled
  * @var_args: %NULL terminated list of property names that should be controlled
  *
@@ -28,7 +28,7 @@ extern GQuark controller_key;
  * one or more of the given properties aren't available, or cannot be controlled, for the given element.
  */
 GstController *
-g_object_control_properties (GObject * object, ...)
+gst_object_control_properties (GObject * object, ...)
 {
   GstController *ctrl;
 
@@ -43,7 +43,7 @@ g_object_control_properties (GObject * object, ...)
 }
 
 /**
- * g_object_uncontrol_properties:
+ * gst_object_uncontrol_properties:
  * @object: the object of which some properties should not be controlled anymore
  * @var_args: %NULL terminated list of property names that should be controlled
  *
@@ -55,7 +55,7 @@ g_object_control_properties (GObject * object, ...)
  * controller, %TRUE otherwise
  */
 gboolean
-g_object_uncontrol_properties (GObject * object, ...)
+gst_object_uncontrol_properties (GObject * object, ...)
 {
   gboolean res = FALSE;
   GstController *ctrl;
@@ -73,14 +73,14 @@ g_object_uncontrol_properties (GObject * object, ...)
 }
 
 /**
- * g_object_get_controller:
+ * gst_object_get_controller:
  * @object: the object that has controlled properties
  *
  * Returns: the controller handling some of the given element's properties,
  * %NULL if no controller
  */
 GstController *
-g_object_get_controller (GObject * object)
+gst_object_get_controller (GObject * object)
 {
   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
 
@@ -88,7 +88,7 @@ g_object_get_controller (GObject * object)
 }
 
 /**
- * g_object_set_controller:
+ * gst_object_set_controller:
  * @object: the object that should get the controller
  * @controller: the controller object to plug in
  *
@@ -97,7 +97,7 @@ g_object_get_controller (GObject * object)
  * Returns: %FALSE if the GObject already has an controller, %TRUE otherwise
  */
 gboolean
-g_object_set_controller (GObject * object, GstController * controller)
+gst_object_set_controller (GObject * object, GstController * controller)
 {
   GstController *ctrl;
 
@@ -111,7 +111,7 @@ g_object_set_controller (GObject * object, GstController * controller)
 }
 
 /**
- * g_object_sink_values:
+ * gst_object_sink_values:
  * @object: the object that has controlled properties
  * @timestamp: the time that should be processed
  *
@@ -120,7 +120,7 @@ g_object_set_controller (GObject * object, GstController * controller)
  * Returns: same thing as gst_controller_sink_values()
  */
 gboolean
-g_object_sink_values (GObject * object, GstClockTime timestamp)
+gst_object_sink_values (GObject * object, GstClockTime timestamp)
 {
   GstController *ctrl = NULL;
 
@@ -133,7 +133,7 @@ g_object_sink_values (GObject * object, GstClockTime timestamp)
 }
 
 /**
- * g_object_get_value_arrays:
+ * gst_object_get_value_arrays:
  * @object: the object that has controlled properties
  * @timestamp: the time that should be processed
  * @value_arrays: list to return the control-values in
@@ -150,7 +150,7 @@ g_object_sink_values (GObject * object, GstClockTime timestamp)
  * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
  */
 gboolean
-g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
+gst_object_get_value_arrays (GObject * object, GstClockTime timestamp,
     GSList * value_arrays)
 {
   GstController *ctrl;
@@ -164,7 +164,7 @@ g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
 }
 
 /**
- * g_object_get_value_array:
+ * gst_object_get_value_array:
  * @self: the object that has controlled properties
  * @timestamp: the time that should be processed
  * @value_array: array to put control-values in
@@ -179,7 +179,7 @@ g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
  * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
  */
 gboolean
-g_object_get_value_array (GObject * object, GstClockTime timestamp,
+gst_object_get_value_array (GObject * object, GstClockTime timestamp,
     GstValueArray * value_array)
 {
   GstController *ctrl;
index e6f7609..27bee4f 100644 (file)
@@ -217,7 +217,6 @@ gst_controlled_property_new (GObject * object, const gchar * name)
       gchar *signal_name;
 
       prop->name = pspec->name; // so we don't use the same mem twice
-      prop->object = object;
       prop->type = G_PARAM_SPEC_VALUE_TYPE (pspec);
       gst_controlled_property_set_interpolation_mode (prop,
           GST_INTERPOLATE_NONE);
@@ -298,7 +297,6 @@ gst_controlled_property_free (GstControlledProperty * prop)
 {
   GList *node;
 
-  g_signal_handler_disconnect (prop->object, prop->notify_handler_id);
   for (node = prop->values; node; node = g_list_next (node)) {
     g_free (node->data);
   }
@@ -370,16 +368,25 @@ gst_controller_new_valist (GObject * object, va_list var_args)
   self = g_object_get_qdata (object, controller_key);
   // create GstControlledProperty for each property
   while ((name = va_arg (var_args, gchar *))) {
-    // create GstControlledProperty and add to self->propeties List
-    if ((prop = gst_controlled_property_new (object, name))) {
-      // if we don't have a controller object yet, now is the time to create one
-      if (!self) {
-        self = g_object_new (GST_TYPE_CONTROLLER, NULL);
-        self->lock = g_mutex_new ();
-        // store the controller
-        g_object_set_qdata (object, controller_key, self);
+    // test if this property isn't yet controlled
+    if (!self || !(prop = gst_controller_find_controlled_property (self, name))) {
+      // create GstControlledProperty and add to self->propeties List
+      if ((prop = gst_controlled_property_new (object, name))) {
+        // if we don't have a controller object yet, now is the time to create one
+        if (!self) {
+          self = g_object_new (GST_TYPE_CONTROLLER, NULL);
+          self->lock = g_mutex_new ();
+          self->object = object;
+          // store the controller
+          g_object_set_qdata (object, controller_key, self);
+        } else {
+          // increment ref-count
+          self = g_object_ref (self);
+        }
+        self->properties = g_list_prepend (self->properties, prop);
       }
-      self->properties = g_list_prepend (self->properties, prop);
+    } else {
+      GST_WARNING ("trying to control property again");
     }
   }
   va_end (var_args);
@@ -434,6 +441,7 @@ gst_controller_remove_properties_valist (GstController * self, va_list var_args)
     g_mutex_lock (self->lock);
     if ((prop = gst_controller_find_controlled_property (self, name))) {
       self->properties = g_list_remove (self->properties, prop);
+      g_signal_handler_disconnect (self->object, prop->notify_handler_id);
       gst_controlled_property_free (prop);
     } else {
       res = FALSE;
@@ -712,7 +720,7 @@ gst_controller_sink_values (GstController * self, GstClockTime timestamp)
       value = prop->get (prop, timestamp);
       prop->last_value.timestamp = timestamp;
       g_value_copy (value, &prop->last_value.value);
-      g_object_set_property (prop->object, prop->name, value);
+      g_object_set_property (self->object, prop->name, value);
     }
   }
   g_mutex_unlock (self->lock);
@@ -864,16 +872,21 @@ _gst_controller_finalize (GObject * object)
 {
   GstController *self = GST_CONTROLLER (object);
   GList *node;
+  GstControlledProperty *prop;
 
-  // free list of properties
+  /* free list of properties */
   if (self->properties) {
     for (node = self->properties; node; node = g_list_next (node)) {
-      gst_controlled_property_free (node->data);
+      prop = node->data;
+      g_signal_handler_disconnect (self->object, prop->notify_handler_id);
+      gst_controlled_property_free (prop);
     }
     g_list_free (self->properties);
     self->properties = NULL;
   }
   g_mutex_free (self->lock);
+  /* remove controller from objects qdata list */
+  g_object_set_qdata (self->object, controller_key, NULL);
 
   if (G_OBJECT_CLASS (parent_class)->finalize)
     (G_OBJECT_CLASS (parent_class)->finalize) (object);
index a9472c4..ff3e184 100644 (file)
@@ -110,7 +110,6 @@ typedef struct _GstInterpolateMethod
 typedef struct _GstControlledProperty
 {
   gchar *name;                  // name of the property
-  GObject *object;              // the object we control
   GType type;                   // type of the handled property
   GValue default_value;         // default value for the handled property
   GValue result_value;          // result value location for the interpolation method
@@ -160,6 +159,7 @@ struct _GstController
 
   GList *properties;  // List of GstControlledProperty
   GMutex *lock;       // Secure property access, elements will access from threads
+  GObject *object;    // the object we control
 };
 
 struct _GstControllerClass
@@ -207,17 +207,17 @@ gboolean gst_controller_set_interpolation_mode (GstController * self,
 
 /* GObject convenience functions */
 
-GstController *g_object_control_properties (GObject * object, ...);
-gboolean g_object_uncontrol_properties (GObject * object, ...);
+GstController *gst_object_control_properties (GObject * object, ...);
+gboolean gst_object_uncontrol_properties (GObject * object, ...);
 
-GstController *g_object_get_controller (GObject * object);
-gboolean g_object_set_controller (GObject * object, GstController * controller);
+GstController *gst_object_get_controller (GObject * object);
+gboolean gst_object_set_controller (GObject * object, GstController * controller);
 
-gboolean g_object_sink_values (GObject * object, GstClockTime timestamp);
+gboolean gst_object_sink_values (GObject * object, GstClockTime timestamp);
 
-gboolean g_object_get_value_arrays (GObject * object,
+gboolean gst_object_get_value_arrays (GObject * object,
     GstClockTime timestamp, GSList * value_arrays);
-gboolean g_object_get_value_array (GObject * object,
+gboolean gst_object_get_value_array (GObject * object,
     GstClockTime timestamp, GstValueArray * value_array);
 
 /* lib init/done */
index de221cb..d308fd4 100644 (file)
@@ -14,7 +14,7 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
 extern GQuark controller_key;
 
 /**
- * g_object_control_properties:
+ * gst_object_control_properties:
  * @object: the object of which some properties should be controlled
  * @var_args: %NULL terminated list of property names that should be controlled
  *
@@ -28,7 +28,7 @@ extern GQuark controller_key;
  * one or more of the given properties aren't available, or cannot be controlled, for the given element.
  */
 GstController *
-g_object_control_properties (GObject * object, ...)
+gst_object_control_properties (GObject * object, ...)
 {
   GstController *ctrl;
 
@@ -43,7 +43,7 @@ g_object_control_properties (GObject * object, ...)
 }
 
 /**
- * g_object_uncontrol_properties:
+ * gst_object_uncontrol_properties:
  * @object: the object of which some properties should not be controlled anymore
  * @var_args: %NULL terminated list of property names that should be controlled
  *
@@ -55,7 +55,7 @@ g_object_control_properties (GObject * object, ...)
  * controller, %TRUE otherwise
  */
 gboolean
-g_object_uncontrol_properties (GObject * object, ...)
+gst_object_uncontrol_properties (GObject * object, ...)
 {
   gboolean res = FALSE;
   GstController *ctrl;
@@ -73,14 +73,14 @@ g_object_uncontrol_properties (GObject * object, ...)
 }
 
 /**
- * g_object_get_controller:
+ * gst_object_get_controller:
  * @object: the object that has controlled properties
  *
  * Returns: the controller handling some of the given element's properties,
  * %NULL if no controller
  */
 GstController *
-g_object_get_controller (GObject * object)
+gst_object_get_controller (GObject * object)
 {
   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
 
@@ -88,7 +88,7 @@ g_object_get_controller (GObject * object)
 }
 
 /**
- * g_object_set_controller:
+ * gst_object_set_controller:
  * @object: the object that should get the controller
  * @controller: the controller object to plug in
  *
@@ -97,7 +97,7 @@ g_object_get_controller (GObject * object)
  * Returns: %FALSE if the GObject already has an controller, %TRUE otherwise
  */
 gboolean
-g_object_set_controller (GObject * object, GstController * controller)
+gst_object_set_controller (GObject * object, GstController * controller)
 {
   GstController *ctrl;
 
@@ -111,7 +111,7 @@ g_object_set_controller (GObject * object, GstController * controller)
 }
 
 /**
- * g_object_sink_values:
+ * gst_object_sink_values:
  * @object: the object that has controlled properties
  * @timestamp: the time that should be processed
  *
@@ -120,7 +120,7 @@ g_object_set_controller (GObject * object, GstController * controller)
  * Returns: same thing as gst_controller_sink_values()
  */
 gboolean
-g_object_sink_values (GObject * object, GstClockTime timestamp)
+gst_object_sink_values (GObject * object, GstClockTime timestamp)
 {
   GstController *ctrl = NULL;
 
@@ -133,7 +133,7 @@ g_object_sink_values (GObject * object, GstClockTime timestamp)
 }
 
 /**
- * g_object_get_value_arrays:
+ * gst_object_get_value_arrays:
  * @object: the object that has controlled properties
  * @timestamp: the time that should be processed
  * @value_arrays: list to return the control-values in
@@ -150,7 +150,7 @@ g_object_sink_values (GObject * object, GstClockTime timestamp)
  * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
  */
 gboolean
-g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
+gst_object_get_value_arrays (GObject * object, GstClockTime timestamp,
     GSList * value_arrays)
 {
   GstController *ctrl;
@@ -164,7 +164,7 @@ g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
 }
 
 /**
- * g_object_get_value_array:
+ * gst_object_get_value_array:
  * @self: the object that has controlled properties
  * @timestamp: the time that should be processed
  * @value_array: array to put control-values in
@@ -179,7 +179,7 @@ g_object_get_value_arrays (GObject * object, GstClockTime timestamp,
  * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
  */
 gboolean
-g_object_get_value_array (GObject * object, GstClockTime timestamp,
+gst_object_get_value_array (GObject * object, GstClockTime timestamp,
     GstValueArray * value_array)
 {
   GstController *ctrl;
index 5fde800..dc1e100 100644 (file)
@@ -30,7 +30,7 @@ enum
 {
   ARG_ULONG = 1,
   ARG_DOUBLE,
-  ARG_SWITCH,
+  ARG_BOOLEAN,
   ARG_COUNT
 };
 
@@ -47,6 +47,9 @@ typedef struct _GstTestMonoSourceClass GstTestMonoSourceClass;
 struct _GstTestMonoSource
 {
   GstElement parent;
+  gulong val_ulong;
+  gdouble val_double;
+  gboolean val_bool;
 };
 struct _GstTestMonoSourceClass
 {
@@ -59,14 +62,17 @@ static void
 gst_test_mono_source_get_property (GObject * object,
     guint property_id, GValue * value, GParamSpec * pspec)
 {
-  //GstTestMonoSource *self = GST_TEST_MONO_SOURCE(object);
+  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
 
   switch (property_id) {
     case ARG_ULONG:
+      g_value_set_ulong (value, self->val_ulong);
       break;
-    default:{
+    case ARG_DOUBLE:
+      g_value_set_double (value, self->val_double);
+      break;
+    default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
       break;
   }
 }
@@ -75,14 +81,17 @@ static void
 gst_test_mono_source_set_property (GObject * object,
     guint property_id, const GValue * value, GParamSpec * pspec)
 {
-  //GstTestMonoSource *self = GST_TEST_MONO_SOURCE(object);
+  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
 
   switch (property_id) {
     case ARG_ULONG:
+      self->val_ulong = g_value_get_ulong (value);
+      break;
+    case ARG_DOUBLE:
+      self->val_double = g_value_get_double (value);
       break;
-    default:{
+    default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
       break;
   }
 }
@@ -100,6 +109,12 @@ gst_test_mono_source_class_init (GstTestMonoSourceClass * klass)
           "ulong prop",
           "ulong number parameter for the test_mono_source",
           0, G_MAXULONG, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, ARG_DOUBLE,
+      g_param_spec_double ("double",
+          "double prop",
+          "double number parameter for the test_mono_source",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 }
 
 static void
@@ -177,8 +192,97 @@ GST_START_TEST (controller_new_fail)
   ctrl = gst_controller_new (G_OBJECT (elem), "_schrompf_", NULL);
   fail_unless (ctrl == NULL, NULL);
 
-  /* that property exists, but is not controllable */
-  ASSERT_CRITICAL (ctrl = gst_controller_new (G_OBJECT (elem), "name", NULL));
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for an element with controlled params */
+GST_START_TEST (controller_new_okay1)
+{
+  GstController *ctrl;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  g_object_unref (ctrl);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* controlling several params should return the same controller */
+GST_START_TEST (controller_new_okay2)
+{
+  GstController *ctrl1, *ctrl2;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl1 = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl1 != NULL, NULL);
+
+  /* that property should exist and should be controllable */
+  ctrl2 = gst_controller_new (G_OBJECT (elem), "double", NULL);
+  fail_unless (ctrl2 != NULL, NULL);
+  fail_unless (ctrl1 == ctrl2, NULL);
+
+  g_object_unref (ctrl2);
+  g_object_unref (ctrl1);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* controlling a params twice should be handled */
+GST_START_TEST (controller_param_twice)
+{
+  GstController *ctrl;
+  GstElement *elem;
+  gboolean res;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  /* it should have been added at least once, let remove it */
+  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
+  fail_unless (res, NULL);
+
+  /* removing it agian should not work */
+  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
+  fail_unless (!res, NULL);
+
+  g_object_unref (ctrl);
+  g_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests if we cleanup properly */
+GST_START_TEST (controller_finalize)
+{
+  GstController *ctrl;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testmonosource", "test_source");
+
+  /* that property should exist and should be controllable */
+  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
+  fail_unless (ctrl != NULL, NULL);
+
+  /* free the controller */
+  g_object_unref (ctrl);
+
+  /* object shouldn't have a controller anymore */
+  ctrl = gst_object_get_controller (G_OBJECT (elem));
   fail_unless (ctrl == NULL, NULL);
 
   g_object_unref (elem);
@@ -186,11 +290,13 @@ GST_START_TEST (controller_new_fail)
 
 GST_END_TEST;
 
-/* tests for an element with controlled params */
-GST_START_TEST (controller_new_okay)
+/* test timed value handling without interpolation */
+GST_START_TEST (controller_interpolate_none)
 {
   GstController *ctrl;
   GstElement *elem;
+  gboolean res;
+  GValue val_ulong = { 0, };
 
   elem = gst_element_factory_make ("testmonosource", "test_source");
 
@@ -198,6 +304,26 @@ GST_START_TEST (controller_new_okay)
   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
   fail_unless (ctrl != NULL, NULL);
 
+  /* set interpolation mode */
+  gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE);
+
+  /* set control values */
+  g_value_init (&val_ulong, G_TYPE_ULONG);
+  g_value_set_ulong (&val_ulong, 0);
+  res = gst_controller_set (ctrl, "ulong", 0 * GST_SECOND, &val_ulong);
+  fail_unless (res, NULL);
+  g_value_set_ulong (&val_ulong, 100);
+  res = gst_controller_set (ctrl, "ulong", 2 * GST_SECOND, &val_ulong);
+  fail_unless (res, NULL);
+
+  /* now pull in values for some timestamps */
+  gst_controller_sink_values (ctrl, 0 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
+  gst_controller_sink_values (ctrl, 1 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
+  gst_controller_sink_values (ctrl, 2 * GST_SECOND);
+  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 100, NULL);
+
   g_object_unref (ctrl);
   g_object_unref (elem);
 }
@@ -215,7 +341,11 @@ gst_controller_suite (void)
   suite_add_tcase (s, tc);
   tcase_add_test (tc, controller_init);
   tcase_add_test (tc, controller_new_fail);
-  tcase_add_test (tc, controller_new_okay);
+  tcase_add_test (tc, controller_new_okay1);
+  tcase_add_test (tc, controller_new_okay2);
+  tcase_add_test (tc, controller_param_twice);
+  tcase_add_test (tc, controller_finalize);
+  tcase_add_test (tc, controller_interpolate_none);
 
   return s;
 }