LCOV - code coverage report
Current view: top level - libs/gst/controller - gstcontroller.c (source / functions) Hit Total Coverage
Test: GStreamer 0.10.32.1 Lines: 201 364 55.2 %
Date: 2011-03-25 Functions: 19 34 55.9 %
Branches: 120 418 28.7 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  *
       3                 :            :  * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
       4                 :            :  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
       5                 :            :  *
       6                 :            :  * gstcontroller.c: dynamic parameter control subsystem
       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., 59 Temple Place - Suite 330,
      21                 :            :  * Boston, MA 02111-1307, USA.
      22                 :            :  */
      23                 :            : 
      24                 :            : /**
      25                 :            :  * SECTION:gstcontroller
      26                 :            :  * @short_description: dynamic parameter control subsystem
      27                 :            :  *
      28                 :            :  * The controller subsystem offers a lightweight way to adjust gobject
      29                 :            :  * properties over stream-time. It works by using time-stamped value pairs that
      30                 :            :  * are queued for element-properties. At run-time the elements continously pull
      31                 :            :  * values changes for the current stream-time.
      32                 :            :  *
      33                 :            :  * What needs to be changed in a #GstElement?
      34                 :            :  * Very little - it is just two steps to make a plugin controllable!
      35                 :            :  * <orderedlist>
      36                 :            :  *   <listitem><para>
      37                 :            :  *     mark gobject-properties paramspecs that make sense to be controlled,
      38                 :            :  *     by GST_PARAM_CONTROLLABLE.
      39                 :            :  *   </para></listitem>
      40                 :            :  *   <listitem><para>
      41                 :            :  *     when processing data (get, chain, loop function) at the beginning call
      42                 :            :  *     gst_object_sync_values(element,timestamp).
      43                 :            :  *     This will made the controller to update all gobject properties that are under
      44                 :            :  *     control with the current values based on timestamp.
      45                 :            :  *   </para></listitem>
      46                 :            :  * </orderedlist>
      47                 :            :  *
      48                 :            :  * What needs to be done in applications?
      49                 :            :  * Again its not a lot to change.
      50                 :            :  * <orderedlist>
      51                 :            :  *   <listitem><para>
      52                 :            :  *     first put some properties under control, by calling
      53                 :            :  *     controller = gst_object_control_properties (object, "prop1", "prop2",...);
      54                 :            :  *   </para></listitem>
      55                 :            :  *   <listitem><para>
      56                 :            :  *     Get a #GstControlSource for the property and set it up.
      57                 :            :  *     csource = gst_interpolation_control_source_new ();
      58                 :            :  *     gst_interpolation_control_source_set_interpolation_mode(csource, mode);
      59                 :            :  *     gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
      60                 :            :  *     gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
      61                 :            :  *   </para></listitem>
      62                 :            :  *   <listitem><para>
      63                 :            :  *     Set the #GstControlSource in the controller.
      64                 :            :  *     gst_controller_set_control_source (controller, "prop1", csource);
      65                 :            :  *   </para></listitem>
      66                 :            :  *   <listitem><para>
      67                 :            :  *     start your pipeline
      68                 :            :  *   </para></listitem>
      69                 :            :  * </orderedlist>
      70                 :            :  */
      71                 :            : 
      72                 :            : #ifdef HAVE_CONFIG_H
      73                 :            : #  include "config.h"
      74                 :            : #endif
      75                 :            : 
      76                 :            : #include "gstcontroller.h"
      77                 :            : #include "gstcontrollerprivate.h"
      78                 :            : #include "gstcontrolsource.h"
      79                 :            : #include "gstinterpolationcontrolsource.h"
      80                 :            : 
      81                 :            : #define GST_CAT_DEFAULT controller_debug
      82                 :            : GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
      83                 :            : 
      84                 :            : static GObjectClass *parent_class = NULL;
      85                 :            : GQuark priv_gst_controller_key;
      86                 :            : 
      87                 :            : /* property ids */
      88                 :            : enum
      89                 :            : {
      90                 :            :   PROP_CONTROL_RATE = 1
      91                 :            : };
      92                 :            : 
      93                 :            : struct _GstControllerPrivate
      94                 :            : {
      95                 :            :   GstClockTime control_rate;
      96                 :            :   GstClockTime last_sync;
      97                 :            : };
      98                 :            : 
      99                 :            : /* helper */
     100                 :            : #ifndef GST_REMOVE_DEPRECATED
     101                 :            : static void
     102                 :          0 : gst_controlled_property_add_interpolation_control_source (GstControlledProperty
     103                 :            :     * self)
     104                 :            : {
     105                 :          0 :   GstControlSource *csource =
     106                 :          0 :       GST_CONTROL_SOURCE (gst_interpolation_control_source_new ());
     107                 :            : 
     108         [ #  # ]:          0 :   GST_INFO
     109                 :            :       ("Adding a GstInterpolationControlSource because of backward compatibility");
     110         [ #  # ]:          0 :   g_return_if_fail (!self->csource);
     111                 :          0 :   gst_control_source_bind (GST_CONTROL_SOURCE (csource), self->pspec);
     112                 :          0 :   self->csource = csource;
     113                 :            : }
     114                 :            : #endif
     115                 :            : 
     116                 :            : /*
     117                 :            :  * gst_controlled_property_new:
     118                 :            :  * @object: for which object the controlled property should be set up
     119                 :            :  * @name: the name of the property to be controlled
     120                 :            :  *
     121                 :            :  * Private method which initializes the fields of a new controlled property
     122                 :            :  * structure.
     123                 :            :  *
     124                 :            :  * Returns: a freshly allocated structure or %NULL
     125                 :            :  */
     126                 :            : static GstControlledProperty *
     127                 :         46 : gst_controlled_property_new (GObject * object, const gchar * name)
     128                 :            : {
     129                 :         46 :   GstControlledProperty *prop = NULL;
     130                 :            :   GParamSpec *pspec;
     131                 :            : 
     132         [ -  + ]:         46 :   GST_INFO ("trying to put property '%s' under control", name);
     133                 :            : 
     134                 :            :   /* check if the object has a property of that name */
     135         [ +  + ]:         46 :   if ((pspec =
     136                 :         46 :           g_object_class_find_property (G_OBJECT_GET_CLASS (object), name))) {
     137         [ -  + ]:         45 :     GST_DEBUG ("  psec->flags : 0x%08x", pspec->flags);
     138                 :            : 
     139                 :            :     /* check if this param is witable && controlable && !construct-only */
     140         [ +  + ]:         45 :     g_return_val_if_fail ((pspec->flags & (G_PARAM_WRITABLE |
     141                 :            :                 GST_PARAM_CONTROLLABLE | G_PARAM_CONSTRUCT_ONLY)) ==
     142                 :            :         (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE), NULL);
     143                 :            : 
     144         [ +  - ]:         42 :     if ((prop = g_slice_new (GstControlledProperty))) {
     145                 :         42 :       prop->pspec = pspec;
     146                 :         42 :       prop->name = pspec->name;
     147                 :         42 :       prop->csource = NULL;
     148                 :         42 :       prop->disabled = FALSE;
     149                 :         42 :       memset (&prop->last_value, 0, sizeof (GValue));
     150                 :         42 :       g_value_init (&prop->last_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
     151                 :            :     }
     152                 :            :   } else {
     153         [ -  + ]:          1 :     GST_WARNING ("class '%s' has no property '%s'", G_OBJECT_TYPE_NAME (object),
     154                 :            :         name);
     155                 :            :   }
     156                 :         46 :   return prop;
     157                 :            : }
     158                 :            : 
     159                 :            : /*
     160                 :            :  * gst_controlled_property_free:
     161                 :            :  * @prop: the object to free
     162                 :            :  *
     163                 :            :  * Private method which frees all data allocated by a #GstControlledProperty
     164                 :            :  * instance.
     165                 :            :  */
     166                 :            : static void
     167                 :         42 : gst_controlled_property_free (GstControlledProperty * prop)
     168                 :            : {
     169         [ +  + ]:         42 :   if (prop->csource)
     170                 :         26 :     g_object_unref (prop->csource);
     171                 :         42 :   g_value_unset (&prop->last_value);
     172                 :         42 :   g_slice_free (GstControlledProperty, prop);
     173                 :         42 : }
     174                 :            : 
     175                 :            : /*
     176                 :            :  * gst_controller_find_controlled_property:
     177                 :            :  * @self: the controller object to search for a property in
     178                 :            :  * @name: the gobject property name to look for
     179                 :            :  *
     180                 :            :  * Searches the list of properties under control.
     181                 :            :  *
     182                 :            :  * Returns: a #GstControlledProperty object of %NULL if the property is not
     183                 :            :  * being controlled.
     184                 :            :  */
     185                 :            : static GstControlledProperty *
     186                 :         46 : gst_controller_find_controlled_property (GstController * self,
     187                 :            :     const gchar * name)
     188                 :            : {
     189                 :            :   GstControlledProperty *prop;
     190                 :            :   GList *node;
     191                 :            : 
     192 [ +  - ][ +  + ]:         64 :   for (node = self->properties; node; node = g_list_next (node)) {
     193                 :         56 :     prop = node->data;
     194                 :            :     /* FIXME: eventually use GQuark to speed it up */
     195         [ +  + ]:         56 :     if (!strcmp (prop->name, name)) {
     196                 :         38 :       return prop;
     197                 :            :     }
     198                 :            :   }
     199         [ -  + ]:          8 :   GST_DEBUG ("controller does not (yet) manage property '%s'", name);
     200                 :            : 
     201                 :         46 :   return NULL;
     202                 :            : }
     203                 :            : 
     204                 :            : /*
     205                 :            :  * gst_controller_add_property:
     206                 :            :  * @self: the controller object or %NULL if none yet exists
     207                 :            :  * @object: object to bind the property
     208                 :            :  * @name: name of projecty in @object
     209                 :            :  * @ref_existing: pointer to flag that tracks if we need to ref an existng
     210                 :            :  *   controller still
     211                 :            :  *
     212                 :            :  * Creates a new #GstControlledProperty if there is none for property @name yet.
     213                 :            :  * In case this is the first controlled propery, it creates the controller as
     214                 :            :  * well.
     215                 :            :  *
     216                 :            :  * Returns: a newly created controller object or reffed existing one with the
     217                 :            :  * given property bound.
     218                 :            :  */
     219                 :            : static GstController *
     220                 :         53 : gst_controller_add_property (GstController * self, GObject * object,
     221                 :            :     const gchar * name, gboolean * ref_existing)
     222                 :            : {
     223                 :            :   /* test if this property isn't yet controlled */
     224 [ +  + ][ +  + ]:         99 :   if (!self || !gst_controller_find_controlled_property (self, name)) {
     225                 :            :     GstControlledProperty *prop;
     226                 :            : 
     227                 :            :     /* create GstControlledProperty and add to self->propeties List */
     228         [ +  + ]:         46 :     if ((prop = gst_controlled_property_new (object, name))) {
     229                 :            :       /* if we don't have a controller object yet, now is the time to create one */
     230         [ +  + ]:         42 :       if (!self) {
     231                 :         35 :         self = g_object_newv (GST_TYPE_CONTROLLER, 0, NULL);
     232                 :         35 :         self->object = g_object_ref (object);
     233                 :            :         /* store the controller */
     234                 :         35 :         g_object_set_qdata (object, priv_gst_controller_key, self);
     235                 :         35 :         *ref_existing = FALSE;
     236                 :            :       } else {
     237                 :            :         /* only want one single _ref(), even for multiple properties */
     238         [ +  + ]:          7 :         if (*ref_existing) {
     239                 :          3 :           g_object_ref (self);
     240                 :          3 :           *ref_existing = FALSE;
     241         [ -  + ]:          3 :           GST_INFO ("returning existing controller");
     242                 :            :         }
     243                 :            :       }
     244                 :         42 :       self->properties = g_list_prepend (self->properties, prop);
     245                 :            :     }
     246                 :            :   } else {
     247         [ -  + ]:          7 :     GST_WARNING ("trying to control property %s again", name);
     248         [ +  + ]:          7 :     if (*ref_existing) {
     249                 :          3 :       g_object_ref (self);
     250                 :          3 :       *ref_existing = FALSE;
     251                 :            :     }
     252                 :            :   }
     253                 :         53 :   return self;
     254                 :            : }
     255                 :            : 
     256                 :            : /* methods */
     257                 :            : 
     258                 :            : /**
     259                 :            :  * gst_controller_new_valist:
     260                 :            :  * @object: the object of which some properties should be controlled
     261                 :            :  * @var_args: %NULL terminated list of property names that should be controlled
     262                 :            :  *
     263                 :            :  * Creates a new GstController for the given object's properties
     264                 :            :  *
     265                 :            :  * Returns: the new controller.
     266                 :            :  */
     267                 :            : GstController *
     268                 :         41 : gst_controller_new_valist (GObject * object, va_list var_args)
     269                 :            : {
     270                 :            :   GstController *self;
     271                 :         41 :   gboolean ref_existing = TRUE;
     272                 :            :   gchar *name;
     273                 :            : 
     274 [ -  + ][ +  - ]:         41 :   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
         [ -  + ][ -  + ]
     275                 :            : 
     276         [ -  + ]:         41 :   GST_INFO ("setting up a new controller");
     277                 :            : 
     278                 :         41 :   self = g_object_get_qdata (object, priv_gst_controller_key);
     279                 :            :   /* create GstControlledProperty for each property */
     280 [ +  - ][ +  + ]:         87 :   while ((name = va_arg (var_args, gchar *))) {
     281                 :         46 :     self = gst_controller_add_property (self, object, name, &ref_existing);
     282                 :            :   }
     283                 :         41 :   va_end (var_args);
     284                 :            : 
     285         [ +  + ]:         41 :   if (self)
     286         [ -  + ]:         36 :     GST_INFO ("controller->ref_count=%d", G_OBJECT (self)->ref_count);
     287                 :         41 :   return self;
     288                 :            : }
     289                 :            : 
     290                 :            : /**
     291                 :            :  * gst_controller_new_list:
     292                 :            :  * @object: the object of which some properties should be controlled
     293                 :            :  * @list: list of property names that should be controlled
     294                 :            :  *
     295                 :            :  * Creates a new GstController for the given object's properties
     296                 :            :  *
     297                 :            :  * Returns: the new controller.
     298                 :            :  */
     299                 :            : GstController *
     300                 :          5 : gst_controller_new_list (GObject * object, GList * list)
     301                 :            : {
     302                 :            :   GstController *self;
     303                 :          5 :   gboolean ref_existing = TRUE;
     304                 :            :   gchar *name;
     305                 :            :   GList *node;
     306                 :            : 
     307 [ -  + ][ +  - ]:          5 :   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
         [ -  + ][ -  + ]
     308                 :            : 
     309         [ -  + ]:          5 :   GST_INFO ("setting up a new controller");
     310                 :            : 
     311                 :          5 :   self = g_object_get_qdata (object, priv_gst_controller_key);
     312                 :            :   /* create GstControlledProperty for each property */
     313 [ +  - ][ +  + ]:         12 :   for (node = list; node; node = g_list_next (node)) {
     314                 :          7 :     name = (gchar *) node->data;
     315                 :          7 :     self = gst_controller_add_property (self, object, name, &ref_existing);
     316                 :            :   }
     317                 :            : 
     318         [ +  - ]:          5 :   if (self)
     319         [ -  + ]:          5 :     GST_INFO ("controller->ref_count=%d", G_OBJECT (self)->ref_count);
     320                 :          5 :   return self;
     321                 :            : }
     322                 :            : 
     323                 :            : /**
     324                 :            :  * gst_controller_new:
     325                 :            :  * @object: the object of which some properties should be controlled
     326                 :            :  * @...: %NULL terminated list of property names that should be controlled
     327                 :            :  *
     328                 :            :  * Creates a new GstController for the given object's properties
     329                 :            :  *
     330                 :            :  * Returns: the new controller.
     331                 :            :  */
     332                 :            : GstController *
     333                 :         41 : gst_controller_new (GObject * object, ...)
     334                 :            : {
     335                 :            :   GstController *self;
     336                 :            :   va_list var_args;
     337                 :            : 
     338 [ -  + ][ +  - ]:         41 :   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
         [ -  + ][ -  + ]
     339                 :            : 
     340                 :         41 :   va_start (var_args, object);
     341                 :         41 :   self = gst_controller_new_valist (object, var_args);
     342                 :         41 :   va_end (var_args);
     343                 :            : 
     344                 :         41 :   return self;
     345                 :            : }
     346                 :            : 
     347                 :            : /**
     348                 :            :  * gst_controller_remove_properties_valist:
     349                 :            :  * @self: the controller object from which some properties should be removed
     350                 :            :  * @var_args: %NULL terminated list of property names that should be removed
     351                 :            :  *
     352                 :            :  * Removes the given object properties from the controller
     353                 :            :  *
     354                 :            :  * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
     355                 :            :  */
     356                 :            : gboolean
     357                 :          2 : gst_controller_remove_properties_valist (GstController * self, va_list var_args)
     358                 :            : {
     359                 :          2 :   gboolean res = TRUE;
     360                 :            :   GstControlledProperty *prop;
     361                 :            :   gchar *name;
     362                 :            : 
     363 [ -  + ][ +  - ]:          2 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ +  - ][ -  + ]
     364                 :            : 
     365 [ +  - ][ +  + ]:          4 :   while ((name = va_arg (var_args, gchar *))) {
     366                 :            :     /* find the property in the properties list of the controller, remove and free it */
     367                 :          2 :     g_mutex_lock (self->lock);
     368         [ +  + ]:          2 :     if ((prop = gst_controller_find_controlled_property (self, name))) {
     369                 :          1 :       self->properties = g_list_remove (self->properties, prop);
     370                 :            :       //g_signal_handler_disconnect (self->object, prop->notify_handler_id);
     371                 :          1 :       gst_controlled_property_free (prop);
     372                 :            :     } else {
     373                 :          1 :       res = FALSE;
     374                 :            :     }
     375                 :          2 :     g_mutex_unlock (self->lock);
     376                 :            :   }
     377                 :            : 
     378                 :          2 :   return res;
     379                 :            : }
     380                 :            : 
     381                 :            : /**
     382                 :            :  * gst_controller_remove_properties_list:
     383                 :            :  * @self: the controller object from which some properties should be removed
     384                 :            :  * @list: #GList of property names that should be removed
     385                 :            :  *
     386                 :            :  * Removes the given object properties from the controller
     387                 :            :  *
     388                 :            :  * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
     389                 :            :  */
     390                 :            : gboolean
     391                 :          0 : gst_controller_remove_properties_list (GstController * self, GList * list)
     392                 :            : {
     393                 :          0 :   gboolean res = TRUE;
     394                 :            :   GstControlledProperty *prop;
     395                 :            :   gchar *name;
     396                 :            :   GList *tmp;
     397                 :            : 
     398 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
     399                 :            : 
     400 [ #  # ][ #  # ]:          0 :   for (tmp = list; tmp; tmp = g_list_next (tmp)) {
     401                 :          0 :     name = (gchar *) tmp->data;
     402                 :            : 
     403                 :            :     /* find the property in the properties list of the controller, remove and free it */
     404                 :          0 :     g_mutex_lock (self->lock);
     405         [ #  # ]:          0 :     if ((prop = gst_controller_find_controlled_property (self, name))) {
     406                 :          0 :       self->properties = g_list_remove (self->properties, prop);
     407                 :            :       //g_signal_handler_disconnect (self->object, prop->notify_handler_id);
     408                 :          0 :       gst_controlled_property_free (prop);
     409                 :            :     } else {
     410                 :          0 :       res = FALSE;
     411                 :            :     }
     412                 :          0 :     g_mutex_unlock (self->lock);
     413                 :            :   }
     414                 :            : 
     415                 :          0 :   return res;
     416                 :            : }
     417                 :            : 
     418                 :            : /**
     419                 :            :  * gst_controller_remove_properties:
     420                 :            :  * @self: the controller object from which some properties should be removed
     421                 :            :  * @...: %NULL terminated list of property names that should be removed
     422                 :            :  *
     423                 :            :  * Removes the given object properties from the controller
     424                 :            :  *
     425                 :            :  * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
     426                 :            :  */
     427                 :            : gboolean
     428                 :          2 : gst_controller_remove_properties (GstController * self, ...)
     429                 :            : {
     430                 :            :   gboolean res;
     431                 :            :   va_list var_args;
     432                 :            : 
     433 [ -  + ][ +  - ]:          2 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ +  - ][ -  + ]
     434                 :            : 
     435                 :          2 :   va_start (var_args, self);
     436                 :          2 :   res = gst_controller_remove_properties_valist (self, var_args);
     437                 :          2 :   va_end (var_args);
     438                 :            : 
     439                 :          2 :   return res;
     440                 :            : }
     441                 :            : 
     442                 :            : /**
     443                 :            :  * gst_controller_set_property_disabled:
     444                 :            :  * @self: the #GstController which should be disabled
     445                 :            :  * @property_name: property to disable
     446                 :            :  * @disabled: boolean that specifies whether to disable the controller
     447                 :            :  * or not.
     448                 :            :  *
     449                 :            :  * This function is used to disable the #GstController on a property for
     450                 :            :  * some time, i.e. gst_controller_sync_values() will do nothing for the
     451                 :            :  * property.
     452                 :            :  *
     453                 :            :  * Since: 0.10.14
     454                 :            :  */
     455                 :            : 
     456                 :            : void
     457                 :          3 : gst_controller_set_property_disabled (GstController * self,
     458                 :            :     const gchar * property_name, gboolean disabled)
     459                 :            : {
     460                 :            :   GstControlledProperty *prop;
     461                 :            : 
     462 [ -  + ][ +  - ]:          3 :   g_return_if_fail (GST_IS_CONTROLLER (self));
         [ +  - ][ -  + ]
     463         [ -  + ]:          3 :   g_return_if_fail (property_name);
     464                 :            : 
     465                 :          3 :   g_mutex_lock (self->lock);
     466         [ +  - ]:          3 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
     467                 :          3 :     prop->disabled = disabled;
     468                 :            :   }
     469                 :          3 :   g_mutex_unlock (self->lock);
     470                 :            : }
     471                 :            : 
     472                 :            : 
     473                 :            : /**
     474                 :            :  * gst_controller_set_disabled:
     475                 :            :  * @self: the #GstController which should be disabled
     476                 :            :  * @disabled: boolean that specifies whether to disable the controller
     477                 :            :  * or not.
     478                 :            :  *
     479                 :            :  * This function is used to disable all properties of the #GstController
     480                 :            :  * for some time, i.e. gst_controller_sync_values() will do nothing.
     481                 :            :  *
     482                 :            :  * Since: 0.10.14
     483                 :            :  */
     484                 :            : 
     485                 :            : void
     486                 :          2 : gst_controller_set_disabled (GstController * self, gboolean disabled)
     487                 :            : {
     488                 :            :   GList *node;
     489                 :            :   GstControlledProperty *prop;
     490                 :            : 
     491 [ -  + ][ +  - ]:          4 :   g_return_if_fail (GST_IS_CONTROLLER (self));
         [ +  - ][ -  + ]
     492                 :            : 
     493                 :          2 :   g_mutex_lock (self->lock);
     494         [ +  + ]:          6 :   for (node = self->properties; node; node = node->next) {
     495                 :          4 :     prop = node->data;
     496                 :          4 :     prop->disabled = disabled;
     497                 :            :   }
     498                 :          2 :   g_mutex_unlock (self->lock);
     499                 :            : }
     500                 :            : 
     501                 :            : /**
     502                 :            :  * gst_controller_set_control_source:
     503                 :            :  * @self: the controller object
     504                 :            :  * @property_name: name of the property for which the #GstControlSource should be set
     505                 :            :  * @csource: the #GstControlSource that should be used for the property
     506                 :            :  *
     507                 :            :  * Sets the #GstControlSource for @property_name. If there already was a #GstControlSource
     508                 :            :  * for this property it will be unreferenced.
     509                 :            :  *
     510                 :            :  * Returns: %FALSE if the given property isn't handled by the controller or the new #GstControlSource
     511                 :            :  * couldn't be bound to the property, %TRUE if everything worked as expected.
     512                 :            :  *
     513                 :            :  * Since: 0.10.14
     514                 :            :  */
     515                 :            : gboolean
     516                 :         26 : gst_controller_set_control_source (GstController * self,
     517                 :            :     const gchar * property_name, GstControlSource * csource)
     518                 :            : {
     519                 :            :   GstControlledProperty *prop;
     520                 :         26 :   gboolean ret = FALSE;
     521                 :            : 
     522                 :         26 :   g_mutex_lock (self->lock);
     523         [ +  - ]:         26 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
     524                 :         26 :     GstControlSource *old = prop->csource;
     525                 :            : 
     526 [ +  - ][ +  - ]:         26 :     if (csource && (ret = gst_control_source_bind (csource, prop->pspec))) {
     527                 :         26 :       g_object_ref (csource);
     528                 :         26 :       prop->csource = csource;
     529         [ #  # ]:          0 :     } else if (!csource) {
     530                 :          0 :       ret = TRUE;
     531                 :          0 :       prop->csource = NULL;
     532                 :            :     }
     533                 :            : 
     534 [ +  - ][ -  + ]:         26 :     if (ret && old)
     535                 :          0 :       g_object_unref (old);
     536                 :            :   }
     537                 :         26 :   g_mutex_unlock (self->lock);
     538                 :            : 
     539                 :         26 :   return ret;
     540                 :            : }
     541                 :            : 
     542                 :            : /**
     543                 :            :  * gst_controller_get_control_source:
     544                 :            :  * @self: the controller object
     545                 :            :  * @property_name: name of the property for which the #GstControlSource should be get
     546                 :            :  *
     547                 :            :  * Gets the corresponding #GstControlSource for the property. This should be unreferenced
     548                 :            :  * again after use.
     549                 :            :  *
     550                 :            :  * Returns: the #GstControlSource for @property_name or NULL if the property is not
     551                 :            :  * controlled by this controller or no #GstControlSource was assigned yet.
     552                 :            :  *
     553                 :            :  * Since: 0.10.14
     554                 :            :  */
     555                 :            : GstControlSource *
     556                 :          1 : gst_controller_get_control_source (GstController * self,
     557                 :            :     const gchar * property_name)
     558                 :            : {
     559                 :            :   GstControlledProperty *prop;
     560                 :          1 :   GstControlSource *ret = NULL;
     561                 :            : 
     562 [ -  + ][ +  - ]:          1 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
         [ +  - ][ -  + ]
     563         [ -  + ]:          1 :   g_return_val_if_fail (property_name, NULL);
     564                 :            : 
     565                 :          1 :   g_mutex_lock (self->lock);
     566         [ +  - ]:          1 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
     567                 :          1 :     ret = prop->csource;
     568                 :            :   }
     569                 :          1 :   g_mutex_unlock (self->lock);
     570                 :            : 
     571         [ +  - ]:          1 :   if (ret)
     572                 :          1 :     g_object_ref (ret);
     573                 :            : 
     574                 :          1 :   return ret;
     575                 :            : }
     576                 :            : 
     577                 :            : /**
     578                 :            :  * gst_controller_get:
     579                 :            :  * @self: the controller object which handles the properties
     580                 :            :  * @property_name: the name of the property to get
     581                 :            :  * @timestamp: the time the control-change should be read from
     582                 :            :  *
     583                 :            :  * Gets the value for the given controller-handled property at the requested
     584                 :            :  * time.
     585                 :            :  *
     586                 :            :  * Returns: the GValue of the property at the given time, or %NULL if the
     587                 :            :  * property isn't handled by the controller
     588                 :            :  */
     589                 :            : GValue *
     590                 :          0 : gst_controller_get (GstController * self, const gchar * property_name,
     591                 :            :     GstClockTime timestamp)
     592                 :            : {
     593                 :            :   GstControlledProperty *prop;
     594                 :          0 :   GValue *val = NULL;
     595                 :            : 
     596 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
         [ #  # ][ #  # ]
     597         [ #  # ]:          0 :   g_return_val_if_fail (property_name, NULL);
     598         [ #  # ]:          0 :   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
     599                 :            : 
     600                 :          0 :   g_mutex_lock (self->lock);
     601         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
     602                 :          0 :     val = g_new0 (GValue, 1);
     603                 :          0 :     g_value_init (val, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
     604         [ #  # ]:          0 :     if (prop->csource) {
     605                 :            :       gboolean res;
     606                 :            : 
     607                 :            :       /* get current value via control source */
     608                 :          0 :       res = gst_control_source_get_value (prop->csource, timestamp, val);
     609         [ #  # ]:          0 :       if (!res) {
     610                 :          0 :         g_free (val);
     611                 :          0 :         val = NULL;
     612                 :            :       }
     613                 :            :     } else {
     614                 :          0 :       g_object_get_property (self->object, prop->name, val);
     615                 :            :     }
     616                 :            :   }
     617                 :          0 :   g_mutex_unlock (self->lock);
     618                 :            : 
     619                 :          0 :   return val;
     620                 :            : }
     621                 :            : 
     622                 :            : /**
     623                 :            :  * gst_controller_suggest_next_sync:
     624                 :            :  * @self: the controller that handles the values
     625                 :            :  *
     626                 :            :  * Returns a suggestion for timestamps where buffers should be split
     627                 :            :  * to get best controller results.
     628                 :            :  *
     629                 :            :  * Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE
     630                 :            :  * if no control-rate was set.
     631                 :            :  *
     632                 :            :  * Since: 0.10.13
     633                 :            :  */
     634                 :            : GstClockTime
     635                 :          0 : gst_controller_suggest_next_sync (GstController * self)
     636                 :            : {
     637                 :            :   GstClockTime ret;
     638                 :            : 
     639 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), GST_CLOCK_TIME_NONE);
         [ #  # ][ #  # ]
     640         [ #  # ]:          0 :   g_return_val_if_fail (self->priv->control_rate != GST_CLOCK_TIME_NONE,
     641                 :            :       GST_CLOCK_TIME_NONE);
     642                 :            : 
     643                 :          0 :   g_mutex_lock (self->lock);
     644                 :            : 
     645                 :            :   /* TODO: Implement more logic, depending on interpolation mode
     646                 :            :    * and control points
     647                 :            :    * FIXME: we need playback direction
     648                 :            :    */
     649                 :          0 :   ret = self->priv->last_sync + self->priv->control_rate;
     650                 :            : 
     651                 :          0 :   g_mutex_unlock (self->lock);
     652                 :            : 
     653                 :          0 :   return ret;
     654                 :            : }
     655                 :            : 
     656                 :            : /**
     657                 :            :  * gst_controller_sync_values:
     658                 :            :  * @self: the controller that handles the values
     659                 :            :  * @timestamp: the time that should be processed
     660                 :            :  *
     661                 :            :  * Sets the properties of the element, according to the controller that (maybe)
     662                 :            :  * handles them and for the given timestamp.
     663                 :            :  *
     664                 :            :  * If this function fails, it is most likely the application developers fault.
     665                 :            :  * Most probably the control sources are not setup correctly.
     666                 :            :  *
     667                 :            :  * Returns: %TRUE if the controller values could be applied to the object
     668                 :            :  * properties, %FALSE otherwise
     669                 :            :  */
     670                 :            : gboolean
     671                 :        148 : gst_controller_sync_values (GstController * self, GstClockTime timestamp)
     672                 :            : {
     673                 :            :   GstControlledProperty *prop;
     674                 :            :   GList *node;
     675                 :        148 :   gboolean ret = TRUE, val_ret;
     676                 :        148 :   GValue value = { 0, };
     677                 :            : 
     678 [ -  + ][ +  - ]:        148 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ +  - ][ -  + ]
     679         [ -  + ]:        148 :   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
     680                 :            : 
     681         [ -  + ]:        148 :   GST_LOG ("sync_values");
     682                 :            : 
     683                 :        148 :   g_mutex_lock (self->lock);
     684                 :        148 :   g_object_freeze_notify (self->object);
     685                 :            :   /* go over the controlled properties of the controller */
     686 [ +  - ][ +  + ]:        314 :   for (node = self->properties; node; node = g_list_next (node)) {
     687                 :        166 :     prop = node->data;
     688                 :            : 
     689 [ +  - ][ +  + ]:        166 :     if (!prop->csource || prop->disabled)
     690                 :         12 :       continue;
     691                 :            : 
     692         [ -  + ]:        154 :     GST_LOG ("property '%s' at ts=%" G_GUINT64_FORMAT, prop->name, timestamp);
     693                 :            : 
     694                 :            :     /* we can make this faster
     695                 :            :      * http://bugzilla.gnome.org/show_bug.cgi?id=536939
     696                 :            :      */
     697                 :        154 :     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
     698                 :        154 :     val_ret = gst_control_source_get_value (prop->csource, timestamp, &value);
     699         [ +  - ]:        154 :     if (G_LIKELY (val_ret)) {
     700                 :            :       /* always set the value for first time, but then only if it changed
     701                 :            :        * this should limit g_object_notify invocations.
     702                 :            :        * FIXME: can we detect negative playback rates?
     703                 :            :        */
     704   [ +  +  +  + ]:        270 :       if ((timestamp < self->priv->last_sync) ||
     705                 :        116 :           gst_value_compare (&value, &prop->last_value) != GST_VALUE_EQUAL) {
     706                 :        133 :         g_object_set_property (self->object, prop->name, &value);
     707                 :        133 :         g_value_copy (&value, &prop->last_value);
     708                 :            :       }
     709                 :            :     } else {
     710         [ #  # ]:          0 :       GST_DEBUG ("no control value for param %s", prop->name);
     711                 :            :     }
     712                 :        154 :     g_value_unset (&value);
     713                 :        154 :     ret &= val_ret;
     714                 :            :   }
     715                 :        148 :   self->priv->last_sync = timestamp;
     716                 :        148 :   g_object_thaw_notify (self->object);
     717                 :            : 
     718                 :        148 :   g_mutex_unlock (self->lock);
     719                 :            : 
     720                 :        148 :   return ret;
     721                 :            : }
     722                 :            : 
     723                 :            : /**
     724                 :            :  * gst_controller_get_value_arrays:
     725                 :            :  * @self: the controller that handles the values
     726                 :            :  * @timestamp: the time that should be processed
     727                 :            :  * @value_arrays: list to return the control-values in
     728                 :            :  *
     729                 :            :  * Function to be able to get an array of values for one or more given element
     730                 :            :  * properties.
     731                 :            :  *
     732                 :            :  * All fields of the %GstValueArray in the list must be filled correctly.
     733                 :            :  * Especially the GstValueArray->values arrays must be big enough to keep
     734                 :            :  * the requested amount of values.
     735                 :            :  *
     736                 :            :  * The types of the values in the array are the same as the property's type.
     737                 :            :  *
     738                 :            :  * <note><para>This doesn't modify the controlled GObject properties!</para></note>
     739                 :            :  *
     740                 :            :  * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
     741                 :            :  */
     742                 :            : gboolean
     743                 :          0 : gst_controller_get_value_arrays (GstController * self,
     744                 :            :     GstClockTime timestamp, GSList * value_arrays)
     745                 :            : {
     746                 :          0 :   gboolean res = TRUE;
     747                 :            :   GSList *node;
     748                 :            : 
     749 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
     750         [ #  # ]:          0 :   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
     751         [ #  # ]:          0 :   g_return_val_if_fail (value_arrays, FALSE);
     752                 :            : 
     753 [ #  # ][ #  # ]:          0 :   for (node = value_arrays; (res && node); node = g_slist_next (node)) {
                 [ #  # ]
     754                 :          0 :     res = gst_controller_get_value_array (self, timestamp, node->data);
     755                 :            :   }
     756                 :            : 
     757                 :          0 :   return (res);
     758                 :            : }
     759                 :            : 
     760                 :            : /**
     761                 :            :  * gst_controller_get_value_array:
     762                 :            :  * @self: the controller that handles the values
     763                 :            :  * @timestamp: the time that should be processed
     764                 :            :  * @value_array: array to put control-values in
     765                 :            :  *
     766                 :            :  * Function to be able to get an array of values for one element property.
     767                 :            :  *
     768                 :            :  * All fields of @value_array must be filled correctly. Especially the
     769                 :            :  * @value_array->values array must be big enough to keep the requested amount
     770                 :            :  * of values (as indicated by the nbsamples field).
     771                 :            :  *
     772                 :            :  * The type of the values in the array is the same as the property's type.
     773                 :            :  *
     774                 :            :  * <note><para>This doesn't modify the controlled GObject property!</para></note>
     775                 :            :  *
     776                 :            :  * Returns: %TRUE if the given array could be filled, %FALSE otherwise
     777                 :            :  */
     778                 :            : gboolean
     779                 :          0 : gst_controller_get_value_array (GstController * self, GstClockTime timestamp,
     780                 :            :     GstValueArray * value_array)
     781                 :            : {
     782                 :          0 :   gboolean res = FALSE;
     783                 :            :   GstControlledProperty *prop;
     784                 :            : 
     785 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
     786         [ #  # ]:          0 :   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
     787         [ #  # ]:          0 :   g_return_val_if_fail (value_array, FALSE);
     788         [ #  # ]:          0 :   g_return_val_if_fail (value_array->property_name, FALSE);
     789         [ #  # ]:          0 :   g_return_val_if_fail (value_array->values, FALSE);
     790                 :            : 
     791                 :          0 :   g_mutex_lock (self->lock);
     792                 :            : 
     793         [ #  # ]:          0 :   if ((prop =
     794                 :          0 :           gst_controller_find_controlled_property (self,
     795                 :            :               value_array->property_name))) {
     796                 :            :     /* get current value_array via control source */
     797                 :            : 
     798         [ #  # ]:          0 :     if (!prop->csource)
     799                 :          0 :       goto out;
     800                 :            : 
     801                 :          0 :     res =
     802                 :          0 :         gst_control_source_get_value_array (prop->csource, timestamp,
     803                 :            :         value_array);
     804                 :            :   }
     805                 :            : 
     806                 :            : out:
     807                 :          0 :   g_mutex_unlock (self->lock);
     808                 :          0 :   return res;
     809                 :            : }
     810                 :            : 
     811                 :            : /* gobject handling */
     812                 :            : 
     813                 :            : static void
     814                 :          0 : _gst_controller_get_property (GObject * object, guint property_id,
     815                 :            :     GValue * value, GParamSpec * pspec)
     816                 :            : {
     817                 :          0 :   GstController *self = GST_CONTROLLER (object);
     818                 :            : 
     819         [ #  # ]:          0 :   switch (property_id) {
     820                 :            :     case PROP_CONTROL_RATE:{
     821                 :            :       /* FIXME: don't change if element is playing, controller works for GObject
     822                 :            :          so this wont work
     823                 :            : 
     824                 :            :          GstState c_state, p_state;
     825                 :            :          GstStateChangeReturn ret;
     826                 :            : 
     827                 :            :          ret = gst_element_get_state (self->object, &c_state, &p_state, 0);
     828                 :            :          if ((ret == GST_STATE_CHANGE_SUCCESS &&
     829                 :            :          (c_state == GST_STATE_NULL || c_state == GST_STATE_READY)) ||
     830                 :            :          (ret == GST_STATE_CHANGE_ASYNC &&
     831                 :            :          (p_state == GST_STATE_NULL || p_state == GST_STATE_READY))) {
     832                 :            :        */
     833                 :          0 :       g_value_set_uint64 (value, self->priv->control_rate);
     834                 :            :       /*
     835                 :            :          }
     836                 :            :          else {
     837                 :            :          GST_WARNING ("Changing the control rate is only allowed if the elemnt"
     838                 :            :          " is in NULL or READY");
     839                 :            :          }
     840                 :            :        */
     841                 :            :     }
     842                 :          0 :       break;
     843                 :            :     default:{
     844                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     845                 :            :     }
     846                 :          0 :       break;
     847                 :            :   }
     848                 :          0 : }
     849                 :            : 
     850                 :            : /* sets the given properties for this object */
     851                 :            : static void
     852                 :          0 : _gst_controller_set_property (GObject * object, guint property_id,
     853                 :            :     const GValue * value, GParamSpec * pspec)
     854                 :            : {
     855                 :          0 :   GstController *self = GST_CONTROLLER (object);
     856                 :            : 
     857         [ #  # ]:          0 :   switch (property_id) {
     858                 :            :     case PROP_CONTROL_RATE:{
     859                 :          0 :       self->priv->control_rate = g_value_get_uint64 (value);
     860                 :            :     }
     861                 :          0 :       break;
     862                 :            :     default:{
     863                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     864                 :            :     }
     865                 :          0 :       break;
     866                 :            :   }
     867                 :          0 : }
     868                 :            : 
     869                 :            : static void
     870                 :         35 : _gst_controller_dispose (GObject * object)
     871                 :            : {
     872                 :         35 :   GstController *self = GST_CONTROLLER (object);
     873                 :            : 
     874         [ +  - ]:         35 :   if (self->object != NULL) {
     875                 :         35 :     g_mutex_lock (self->lock);
     876                 :            :     /* free list of properties */
     877         [ +  + ]:         35 :     if (self->properties) {
     878                 :            :       GList *node;
     879                 :            : 
     880 [ +  - ][ +  + ]:         75 :       for (node = self->properties; node; node = g_list_next (node)) {
     881                 :         41 :         GstControlledProperty *prop = node->data;
     882                 :            : 
     883                 :         41 :         gst_controlled_property_free (prop);
     884                 :            :       }
     885                 :         34 :       g_list_free (self->properties);
     886                 :         34 :       self->properties = NULL;
     887                 :            :     }
     888                 :            : 
     889                 :            :     /* remove controller from object's qdata list */
     890                 :         35 :     g_object_set_qdata (self->object, priv_gst_controller_key, NULL);
     891                 :         35 :     g_object_unref (self->object);
     892                 :         35 :     self->object = NULL;
     893                 :         35 :     g_mutex_unlock (self->lock);
     894                 :            :   }
     895                 :            : 
     896         [ +  - ]:         35 :   if (G_OBJECT_CLASS (parent_class)->dispose)
     897                 :         35 :     (G_OBJECT_CLASS (parent_class)->dispose) (object);
     898                 :         35 : }
     899                 :            : 
     900                 :            : static void
     901                 :         35 : _gst_controller_finalize (GObject * object)
     902                 :            : {
     903                 :         35 :   GstController *self = GST_CONTROLLER (object);
     904                 :            : 
     905                 :         35 :   g_mutex_free (self->lock);
     906                 :            : 
     907         [ +  - ]:         35 :   if (G_OBJECT_CLASS (parent_class)->finalize)
     908                 :         35 :     (G_OBJECT_CLASS (parent_class)->finalize) (object);
     909                 :         35 : }
     910                 :            : 
     911                 :            : static void
     912                 :         35 : _gst_controller_init (GTypeInstance * instance, gpointer g_class)
     913                 :            : {
     914                 :         35 :   GstController *self = GST_CONTROLLER (instance);
     915                 :            : 
     916                 :         35 :   self->lock = g_mutex_new ();
     917                 :         35 :   self->priv =
     918                 :         35 :       G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_CONTROLLER,
     919                 :            :       GstControllerPrivate);
     920                 :         35 :   self->priv->last_sync = GST_CLOCK_TIME_NONE;
     921                 :         35 :   self->priv->control_rate = 100 * GST_MSECOND;
     922                 :         35 : }
     923                 :            : 
     924                 :            : static void
     925                 :         31 : _gst_controller_class_init (GstControllerClass * klass)
     926                 :            : {
     927                 :         31 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     928                 :            : 
     929                 :         31 :   parent_class = g_type_class_peek_parent (klass);
     930                 :         31 :   g_type_class_add_private (klass, sizeof (GstControllerPrivate));
     931                 :            : 
     932                 :         31 :   gobject_class->set_property = _gst_controller_set_property;
     933                 :         31 :   gobject_class->get_property = _gst_controller_get_property;
     934                 :         31 :   gobject_class->dispose = _gst_controller_dispose;
     935                 :         31 :   gobject_class->finalize = _gst_controller_finalize;
     936                 :            : 
     937                 :         31 :   priv_gst_controller_key = g_quark_from_static_string ("gst::controller");
     938                 :            : 
     939                 :            :   /* register properties */
     940                 :         31 :   g_object_class_install_property (gobject_class, PROP_CONTROL_RATE,
     941                 :            :       g_param_spec_uint64 ("control-rate",
     942                 :            :           "control rate",
     943                 :            :           "Controlled properties will be updated at least every control-rate nanoseconds",
     944                 :            :           1, G_MAXUINT, 100 * GST_MSECOND,
     945                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     946                 :            : 
     947                 :            :   /* register signals */
     948                 :            :   /* set defaults for overridable methods */
     949                 :         31 : }
     950                 :            : 
     951                 :            : GType
     952                 :        333 : gst_controller_get_type (void)
     953                 :            : {
     954                 :            :   static volatile gsize type = 0;
     955                 :            : 
     956         [ +  + ]:        333 :   if (g_once_init_enter (&type)) {
     957                 :            :     GType _type;
     958                 :            :     static const GTypeInfo info = {
     959                 :            :       sizeof (GstControllerClass),
     960                 :            :       NULL,                     /* base_init */
     961                 :            :       NULL,                     /* base_finalize */
     962                 :            :       (GClassInitFunc) _gst_controller_class_init,      /* class_init */
     963                 :            :       NULL,                     /* class_finalize */
     964                 :            :       NULL,                     /* class_data */
     965                 :            :       sizeof (GstController),
     966                 :            :       0,                        /* n_preallocs */
     967                 :            :       (GInstanceInitFunc) _gst_controller_init, /* instance_init */
     968                 :            :       NULL                      /* value_table */
     969                 :            :     };
     970                 :         31 :     _type = g_type_register_static (G_TYPE_OBJECT, "GstController", &info, 0);
     971                 :         31 :     g_once_init_leave (&type, _type);
     972                 :            :   }
     973                 :        333 :   return type;
     974                 :            : }
     975                 :            : 
     976                 :            : /* FIXME: backward compatibility functions */
     977                 :            : 
     978                 :            : /*
     979                 :            :  * gst_controlled_property_set_interpolation_mode:
     980                 :            :  * @self: the controlled property object to change
     981                 :            :  * @mode: the new interpolation mode
     982                 :            :  *
     983                 :            :  * Sets the given Interpolation mode for the controlled property and activates
     984                 :            :  * the respective interpolation hooks.
     985                 :            :  *
     986                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
     987                 :            :  * directly.
     988                 :            :  *
     989                 :            :  * Returns: %TRUE for success
     990                 :            :  */
     991                 :            : #ifndef GST_REMOVE_DEPRECATED
     992                 :            : static gboolean
     993                 :          0 : gst_controlled_property_set_interpolation_mode (GstControlledProperty * self,
     994                 :            :     GstInterpolateMode mode)
     995                 :            : {
     996                 :            :   GstInterpolationControlSource *icsource;
     997                 :            : 
     998                 :            :   /* FIXME: backward compat, add GstInterpolationControlSource */
     999         [ #  # ]:          0 :   if (!self->csource)
    1000                 :          0 :     gst_controlled_property_add_interpolation_control_source (self);
    1001                 :            : 
    1002 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self->csource),
         [ #  # ][ #  # ]
    1003                 :            :       FALSE);
    1004                 :            : 
    1005                 :          0 :   icsource = GST_INTERPOLATION_CONTROL_SOURCE (self->csource);
    1006                 :            : 
    1007                 :          0 :   return gst_interpolation_control_source_set_interpolation_mode (icsource,
    1008                 :            :       mode);
    1009                 :            : }
    1010                 :            : #endif
    1011                 :            : 
    1012                 :            : /**
    1013                 :            :  * gst_controller_set:
    1014                 :            :  * @self: the controller object which handles the properties
    1015                 :            :  * @property_name: the name of the property to set
    1016                 :            :  * @timestamp: the time the control-change is schedules for
    1017                 :            :  * @value: the control-value
    1018                 :            :  *
    1019                 :            :  * Set the value of given controller-handled property at a certain time.
    1020                 :            :  *
    1021                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1022                 :            :  * directly.
    1023                 :            :  *
    1024                 :            :  * Returns: FALSE if the values couldn't be set (ex : properties not handled by controller), TRUE otherwise
    1025                 :            :  */
    1026                 :            : #ifndef GST_REMOVE_DEPRECATED
    1027                 :            : #ifdef GST_DISABLE_DEPRECATED
    1028                 :            : gboolean
    1029                 :            : gst_controller_set (GstController * self, const gchar * property_name,
    1030                 :            :     GstClockTime timestamp, GValue * value);
    1031                 :            : #endif
    1032                 :            : gboolean
    1033                 :          0 : gst_controller_set (GstController * self, const gchar * property_name,
    1034                 :            :     GstClockTime timestamp, GValue * value)
    1035                 :            : {
    1036                 :          0 :   gboolean res = FALSE;
    1037                 :            :   GstControlledProperty *prop;
    1038                 :            : 
    1039 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
    1040         [ #  # ]:          0 :   g_return_val_if_fail (property_name, FALSE);
    1041                 :            : 
    1042                 :          0 :   g_mutex_lock (self->lock);
    1043         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1044                 :            :     /* FIXME: backward compat, add GstInterpolationControlSource */
    1045         [ #  # ]:          0 :     if (!prop->csource)
    1046                 :          0 :       gst_controlled_property_add_interpolation_control_source (prop);
    1047                 :            : 
    1048 [ #  # ][ #  # ]:          0 :     if (!GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
         [ #  # ][ #  # ]
    1049                 :          0 :       goto out;
    1050                 :          0 :     res =
    1051                 :          0 :         gst_interpolation_control_source_set (GST_INTERPOLATION_CONTROL_SOURCE
    1052                 :            :         (prop->csource), timestamp, value);
    1053                 :            :   }
    1054                 :            : 
    1055                 :            : out:
    1056                 :          0 :   g_mutex_unlock (self->lock);
    1057                 :            : 
    1058                 :          0 :   return res;
    1059                 :            : }
    1060                 :            : #endif
    1061                 :            : 
    1062                 :            : /**
    1063                 :            :  * gst_controller_set_from_list:
    1064                 :            :  * @self: the controller object which handles the properties
    1065                 :            :  * @property_name: the name of the property to set
    1066                 :            :  * @timedvalues: a list with #GstTimedValue items
    1067                 :            :  *
    1068                 :            :  * Sets multiple timed values at once.
    1069                 :            :  *
    1070                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1071                 :            :  * directly.
    1072                 :            :  *
    1073                 :            :  * Returns: %FALSE if the values couldn't be set (ex : properties not handled by controller), %TRUE otherwise
    1074                 :            :  */
    1075                 :            : #ifndef GST_REMOVE_DEPRECATED
    1076                 :            : #ifdef GST_DISABLE_DEPRECATED
    1077                 :            : gboolean
    1078                 :            : gst_controller_set_from_list (GstController * self, const gchar * property_name,
    1079                 :            :     GSList * timedvalues);
    1080                 :            : #endif
    1081                 :            : gboolean
    1082                 :          0 : gst_controller_set_from_list (GstController * self, const gchar * property_name,
    1083                 :            :     GSList * timedvalues)
    1084                 :            : {
    1085                 :          0 :   gboolean res = FALSE;
    1086                 :            :   GstControlledProperty *prop;
    1087                 :            : 
    1088 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
    1089         [ #  # ]:          0 :   g_return_val_if_fail (property_name, FALSE);
    1090                 :            : 
    1091                 :          0 :   g_mutex_lock (self->lock);
    1092         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1093                 :            :     /* FIXME: backward compat, add GstInterpolationControlSource */
    1094         [ #  # ]:          0 :     if (!prop->csource)
    1095                 :          0 :       gst_controlled_property_add_interpolation_control_source (prop);
    1096                 :            : 
    1097 [ #  # ][ #  # ]:          0 :     if (!GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
         [ #  # ][ #  # ]
    1098                 :          0 :       goto out;
    1099                 :            : 
    1100                 :          0 :     res =
    1101                 :            :         gst_interpolation_control_source_set_from_list
    1102                 :          0 :         (GST_INTERPOLATION_CONTROL_SOURCE (prop->csource), timedvalues);
    1103                 :            :   }
    1104                 :            : 
    1105                 :            : out:
    1106                 :          0 :   g_mutex_unlock (self->lock);
    1107                 :            : 
    1108                 :          0 :   return res;
    1109                 :            : }
    1110                 :            : #endif
    1111                 :            : 
    1112                 :            : /**
    1113                 :            :  * gst_controller_unset:
    1114                 :            :  * @self: the controller object which handles the properties
    1115                 :            :  * @property_name: the name of the property to unset
    1116                 :            :  * @timestamp: the time the control-change should be removed from
    1117                 :            :  *
    1118                 :            :  * Used to remove the value of given controller-handled property at a certain
    1119                 :            :  * time.
    1120                 :            :  *
    1121                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1122                 :            :  * directly.
    1123                 :            :  *
    1124                 :            :  * Returns: %FALSE if the values couldn't be unset (ex : properties not handled by controller), %TRUE otherwise
    1125                 :            :  */
    1126                 :            : #ifndef GST_REMOVE_DEPRECATED
    1127                 :            : #ifdef GST_DISABLE_DEPRECATED
    1128                 :            : gboolean
    1129                 :            : gst_controller_unset (GstController * self, const gchar * property_name,
    1130                 :            :     GstClockTime timestamp);
    1131                 :            : #endif
    1132                 :            : gboolean
    1133                 :          0 : gst_controller_unset (GstController * self, const gchar * property_name,
    1134                 :            :     GstClockTime timestamp)
    1135                 :            : {
    1136                 :          0 :   gboolean res = FALSE;
    1137                 :            :   GstControlledProperty *prop;
    1138                 :            : 
    1139 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
    1140         [ #  # ]:          0 :   g_return_val_if_fail (property_name, FALSE);
    1141         [ #  # ]:          0 :   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
    1142                 :            : 
    1143                 :          0 :   g_mutex_lock (self->lock);
    1144         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1145 [ #  # ][ #  # ]:          0 :     if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
         [ #  # ][ #  # ]
                 [ #  # ]
    1146                 :            :       goto out;
    1147                 :            : 
    1148                 :          0 :     res =
    1149                 :          0 :         gst_interpolation_control_source_unset (GST_INTERPOLATION_CONTROL_SOURCE
    1150                 :            :         (prop->csource), timestamp);
    1151                 :            :   }
    1152                 :            : 
    1153                 :            : out:
    1154                 :          0 :   g_mutex_unlock (self->lock);
    1155                 :            : 
    1156                 :          0 :   return res;
    1157                 :            : }
    1158                 :            : #endif
    1159                 :            : 
    1160                 :            : /**
    1161                 :            :  * gst_controller_unset_all:
    1162                 :            :  * @self: the controller object which handles the properties
    1163                 :            :  * @property_name: the name of the property to unset
    1164                 :            :  *
    1165                 :            :  * Used to remove all time-stamped values of given controller-handled property
    1166                 :            :  *
    1167                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1168                 :            :  * directly.
    1169                 :            :  *
    1170                 :            :  * Returns: %FALSE if the values couldn't be unset (ex : properties not handled
    1171                 :            :  * by controller), %TRUE otherwise
    1172                 :            :  * Since: 0.10.5
    1173                 :            :  */
    1174                 :            : #ifndef GST_REMOVE_DEPRECATED
    1175                 :            : #ifdef GST_DISABLE_DEPRECATED
    1176                 :            : gboolean gst_controller_unset_all (GstController * self,
    1177                 :            :     const gchar * property_name);
    1178                 :            : #endif
    1179                 :            : gboolean
    1180                 :          0 : gst_controller_unset_all (GstController * self, const gchar * property_name)
    1181                 :            : {
    1182                 :            :   GstControlledProperty *prop;
    1183                 :            : 
    1184 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
    1185         [ #  # ]:          0 :   g_return_val_if_fail (property_name, FALSE);
    1186                 :            : 
    1187                 :          0 :   g_mutex_lock (self->lock);
    1188         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1189 [ #  # ][ #  # ]:          0 :     if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
         [ #  # ][ #  # ]
                 [ #  # ]
    1190                 :            :       goto out;
    1191                 :            : 
    1192                 :          0 :     gst_interpolation_control_source_unset_all (GST_INTERPOLATION_CONTROL_SOURCE
    1193                 :            :         (prop->csource));
    1194                 :            :   }
    1195                 :            : 
    1196                 :            : out:
    1197                 :          0 :   g_mutex_unlock (self->lock);
    1198                 :            : 
    1199                 :          0 :   return TRUE;
    1200                 :            : }
    1201                 :            : #endif
    1202                 :            : 
    1203                 :            : /**
    1204                 :            :  * gst_controller_get_all:
    1205                 :            :  * @self: the controller to get the list from
    1206                 :            :  * @property_name: the name of the property to get the list for
    1207                 :            :  *
    1208                 :            :  * Returns a read-only copy of the list of #GstTimedValue for the given property.
    1209                 :            :  * Free the list after done with it.
    1210                 :            :  *
    1211                 :            :  * <note><para>This doesn't modify the controlled GObject property!</para></note>
    1212                 :            :  *
    1213                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1214                 :            :  * directly.
    1215                 :            :  *
    1216                 :            :  * Returns: a copy of the list, or %NULL if the property isn't handled by the controller
    1217                 :            :  */
    1218                 :            : #ifndef GST_REMOVE_DEPRECATED
    1219                 :            : #ifdef GST_DISABLE_DEPRECATED
    1220                 :            : const GList *gst_controller_get_all (GstController * self,
    1221                 :            :     const gchar * property_name);
    1222                 :            : #endif
    1223                 :            : const GList *
    1224                 :          0 : gst_controller_get_all (GstController * self, const gchar * property_name)
    1225                 :            : {
    1226                 :          0 :   const GList *res = NULL;
    1227                 :            :   GstControlledProperty *prop;
    1228                 :            : 
    1229 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
         [ #  # ][ #  # ]
    1230         [ #  # ]:          0 :   g_return_val_if_fail (property_name, NULL);
    1231                 :            : 
    1232                 :          0 :   g_mutex_lock (self->lock);
    1233         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1234 [ #  # ][ #  # ]:          0 :     if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
         [ #  # ][ #  # ]
                 [ #  # ]
    1235                 :            :       goto out;
    1236                 :            : 
    1237                 :          0 :     res =
    1238                 :            :         gst_interpolation_control_source_get_all
    1239                 :          0 :         (GST_INTERPOLATION_CONTROL_SOURCE (prop->csource));
    1240                 :            :   }
    1241                 :            : 
    1242                 :            : out:
    1243                 :          0 :   g_mutex_unlock (self->lock);
    1244                 :            : 
    1245                 :          0 :   return res;
    1246                 :            : }
    1247                 :            : #endif
    1248                 :            : 
    1249                 :            : /**
    1250                 :            :  * gst_controller_set_interpolation_mode:
    1251                 :            :  * @self: the controller object
    1252                 :            :  * @property_name: the name of the property for which to change the interpolation
    1253                 :            :  * @mode: interpolation mode
    1254                 :            :  *
    1255                 :            :  * Sets the given interpolation mode on the given property.
    1256                 :            :  *
    1257                 :            :  * <note><para>User interpolation is not yet available and quadratic interpolation
    1258                 :            :  * is deprecated and maps to cubic interpolation.</para></note>
    1259                 :            :  *
    1260                 :            :  * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
    1261                 :            :  * directly.
    1262                 :            :  *
    1263                 :            :  * Returns: %TRUE if the property is handled by the controller, %FALSE otherwise
    1264                 :            :  */
    1265                 :            : #ifndef GST_REMOVE_DEPRECATED
    1266                 :            : #ifdef GST_DISABLE_DEPRECATED
    1267                 :            : gboolean
    1268                 :            : gst_controller_set_interpolation_mode (GstController * self,
    1269                 :            :     const gchar * property_name, GstInterpolateMode mode);
    1270                 :            : #endif
    1271                 :            : gboolean
    1272                 :          0 : gst_controller_set_interpolation_mode (GstController * self,
    1273                 :            :     const gchar * property_name, GstInterpolateMode mode)
    1274                 :            : {
    1275                 :          0 :   gboolean res = FALSE;
    1276                 :            :   GstControlledProperty *prop;
    1277                 :            : 
    1278 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
         [ #  # ][ #  # ]
    1279         [ #  # ]:          0 :   g_return_val_if_fail (property_name, FALSE);
    1280                 :            : 
    1281                 :          0 :   g_mutex_lock (self->lock);
    1282         [ #  # ]:          0 :   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
    1283                 :          0 :     res = gst_controlled_property_set_interpolation_mode (prop, mode);
    1284                 :            :   }
    1285                 :          0 :   g_mutex_unlock (self->lock);
    1286                 :            : 
    1287                 :          0 :   return res;
    1288                 :            : }
    1289                 :            : #endif

Generated by: LCOV version 1.9