mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
controller: merge controller into gstobject
This make the controller even more lightweight (no extra object, no extra lock, less indirections). For object that don't use the controller the only 'overhead' is a 3 unused fields in the gst_object structure.
This commit is contained in:
parent
08d9f54044
commit
a1599f5f7e
14 changed files with 762 additions and 1712 deletions
|
@ -67,7 +67,6 @@ Windows. It is released under the GNU Library General Public License
|
||||||
<xi:include href="xml/gstchildproxy.xml" />
|
<xi:include href="xml/gstchildproxy.xml" />
|
||||||
<xi:include href="xml/gstclock.xml" />
|
<xi:include href="xml/gstclock.xml" />
|
||||||
<xi:include href="xml/gstconfig.xml" />
|
<xi:include href="xml/gstconfig.xml" />
|
||||||
<xi:include href="xml/gstcontroller.xml" />
|
|
||||||
<xi:include href="xml/gstcontrolsource.xml" />
|
<xi:include href="xml/gstcontrolsource.xml" />
|
||||||
<xi:include href="xml/gstdatetime.xml" />
|
<xi:include href="xml/gstdatetime.xml" />
|
||||||
<xi:include href="xml/gstelement.xml" />
|
<xi:include href="xml/gstelement.xml" />
|
||||||
|
|
|
@ -556,41 +556,6 @@ GST_PADDING_INIT
|
||||||
GST_USING_PRINTF_EXTENSION
|
GST_USING_PRINTF_EXTENSION
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
|
||||||
<FILE>gstcontroller</FILE>
|
|
||||||
<TITLE>GstController</TITLE>
|
|
||||||
GstController
|
|
||||||
gst_controller_new
|
|
||||||
gst_controller_new_list
|
|
||||||
gst_controller_new_valist
|
|
||||||
gst_controller_add_properties
|
|
||||||
gst_controller_add_properties_list
|
|
||||||
gst_controller_add_properties_valist
|
|
||||||
gst_controller_remove_properties
|
|
||||||
gst_controller_remove_properties_list
|
|
||||||
gst_controller_remove_properties_valist
|
|
||||||
gst_controller_is_active
|
|
||||||
gst_controller_set_disabled
|
|
||||||
gst_controller_set_property_disabled
|
|
||||||
gst_controller_suggest_next_sync
|
|
||||||
gst_controller_sync_values
|
|
||||||
gst_controller_get_control_source
|
|
||||||
gst_controller_set_control_source
|
|
||||||
gst_controller_get
|
|
||||||
gst_controller_get_value_arrays
|
|
||||||
gst_controller_get_value_array
|
|
||||||
<SUBSECTION Standard>
|
|
||||||
GstControllerClass
|
|
||||||
GstControllerPrivate
|
|
||||||
GST_CONTROLLER
|
|
||||||
GST_IS_CONTROLLER
|
|
||||||
GST_CONTROLLER_CLASS
|
|
||||||
GST_IS_CONTROLLER_CLASS
|
|
||||||
GST_CONTROLLER_GET_CLASS
|
|
||||||
GST_TYPE_CONTROLLER
|
|
||||||
<SUBSECTION Private>
|
|
||||||
gst_controller_get_type
|
|
||||||
</SECTION>
|
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>gstcontrolsource</FILE>
|
<FILE>gstcontrolsource</FILE>
|
||||||
|
@ -1568,9 +1533,9 @@ gst_object_control_properties
|
||||||
gst_object_uncontrol_properties
|
gst_object_uncontrol_properties
|
||||||
gst_object_suggest_next_sync
|
gst_object_suggest_next_sync
|
||||||
gst_object_sync_values
|
gst_object_sync_values
|
||||||
gst_object_has_active_automation
|
gst_object_has_active_controlled_properties
|
||||||
gst_object_set_automation_disabled
|
gst_object_set_controlled_properties_disabled
|
||||||
gst_object_set_property_automation_disabled
|
gst_object_set_controlled_property_disabled
|
||||||
gst_object_get_control_source
|
gst_object_get_control_source
|
||||||
gst_object_set_control_source
|
gst_object_set_control_source
|
||||||
gst_object_get_value
|
gst_object_get_value
|
||||||
|
|
|
@ -12,7 +12,6 @@ gst_bin_get_type
|
||||||
gst_bus_get_type
|
gst_bus_get_type
|
||||||
gst_child_proxy_get_type
|
gst_child_proxy_get_type
|
||||||
gst_clock_get_type
|
gst_clock_get_type
|
||||||
gst_controller_get_type
|
|
||||||
gst_control_source_get_type
|
gst_control_source_get_type
|
||||||
gst_element_factory_get_type
|
gst_element_factory_get_type
|
||||||
gst_element_get_type
|
gst_element_get_type
|
||||||
|
|
|
@ -399,3 +399,18 @@ The 0.11 porting guide
|
||||||
gst_tag_list_new() has been renamed to gst_tag_list_new_empty().
|
gst_tag_list_new() has been renamed to gst_tag_list_new_empty().
|
||||||
gst_tag_list_new_full*() have been renamed to gst_tag_list_new*().
|
gst_tag_list_new_full*() have been renamed to gst_tag_list_new*().
|
||||||
|
|
||||||
|
* GstController:
|
||||||
|
has now been merged into GstObject. The control sources are in the
|
||||||
|
controller library still.
|
||||||
|
|
||||||
|
For plugins the effect is that gst_controller_init() is gone and
|
||||||
|
gst_object_sync_values() is taking a GstObject * instead of GObject *.
|
||||||
|
|
||||||
|
For applications the effect is larger. The whole gst_controller_* API is
|
||||||
|
gone and now available in simplified form under gst_object_*.
|
||||||
|
|
||||||
|
gst_controller_new* -> gst_object_control_properties
|
||||||
|
gst_controller_add_properties -> gst_object_control_properties
|
||||||
|
gst_controller_set_control_source -> gst_object_set_control_source
|
||||||
|
gst_controller_get_control_source -> gst_object_get_control_source
|
||||||
|
gst_controller_set_property_disabled -> gst_object_set_controlled_property_disabled
|
||||||
|
|
|
@ -56,7 +56,6 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
|
||||||
gstcaps.c \
|
gstcaps.c \
|
||||||
gstchildproxy.c \
|
gstchildproxy.c \
|
||||||
gstclock.c \
|
gstclock.c \
|
||||||
gstcontroller.c \
|
|
||||||
gstcontrolsource.c \
|
gstcontrolsource.c \
|
||||||
gstdatetime.c \
|
gstdatetime.c \
|
||||||
gstdebugutils.c \
|
gstdebugutils.c \
|
||||||
|
@ -150,7 +149,6 @@ gst_headers = \
|
||||||
gstchildproxy.h \
|
gstchildproxy.h \
|
||||||
gstclock.h \
|
gstclock.h \
|
||||||
gstcompat.h \
|
gstcompat.h \
|
||||||
gstcontroller.h \
|
|
||||||
gstcontrolsource.h \
|
gstcontrolsource.h \
|
||||||
gstdatetime.h \
|
gstdatetime.h \
|
||||||
gstdebugutils.h \
|
gstdebugutils.h \
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include <gst/gstcaps.h>
|
#include <gst/gstcaps.h>
|
||||||
#include <gst/gstchildproxy.h>
|
#include <gst/gstchildproxy.h>
|
||||||
#include <gst/gstclock.h>
|
#include <gst/gstclock.h>
|
||||||
#include <gst/gstcontroller.h>
|
|
||||||
#include <gst/gstcontrolsource.h>
|
#include <gst/gstcontrolsource.h>
|
||||||
#include <gst/gstdatetime.h>
|
#include <gst/gstdatetime.h>
|
||||||
#include <gst/gstdebugutils.h>
|
#include <gst/gstdebugutils.h>
|
||||||
|
|
1042
gst/gstcontroller.c
1042
gst/gstcontroller.c
File diff suppressed because it is too large
Load diff
|
@ -1,116 +0,0 @@
|
||||||
/* GStreamer
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 Stefan Kost <ensonic at users dot sf dot net>
|
|
||||||
* 2011 Stefan Sauer <ensonic at users dot sf dot net>
|
|
||||||
*
|
|
||||||
* gstcontroller.h: dynamic parameter control subsystem
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Library General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Library General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __GST_CONTROLLER_H__
|
|
||||||
#define __GST_CONTROLLER_H__
|
|
||||||
|
|
||||||
#include <gst/gstconfig.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <glib/gprintf.h>
|
|
||||||
|
|
||||||
#include <gst/gstobject.h>
|
|
||||||
#include <gst/gstcontrolsource.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/* type macros */
|
|
||||||
|
|
||||||
#define GST_TYPE_CONTROLLER (gst_controller_get_type ())
|
|
||||||
#define GST_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CONTROLLER, GstController))
|
|
||||||
#define GST_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CONTROLLER, GstControllerClass))
|
|
||||||
#define GST_IS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CONTROLLER))
|
|
||||||
#define GST_IS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CONTROLLERE))
|
|
||||||
#define GST_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTROLLER, GstControllerClass))
|
|
||||||
|
|
||||||
typedef struct _GstController GstController;
|
|
||||||
typedef struct _GstControllerClass GstControllerClass;
|
|
||||||
typedef struct _GstControllerPrivate GstControllerPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GstController:
|
|
||||||
*
|
|
||||||
* The instance structure of GstController
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct _GstController
|
|
||||||
{
|
|
||||||
GObject parent;
|
|
||||||
|
|
||||||
GList *properties; /* List of GstControlledProperty */
|
|
||||||
GMutex *lock; /* Secure property access, elements will access from threads */
|
|
||||||
GstObject *object; /* the object we control */
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
GstControllerPrivate *priv;
|
|
||||||
gpointer _gst_reserved[GST_PADDING - 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstControllerClass
|
|
||||||
{
|
|
||||||
GObjectClass parent_class;
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
|
||||||
};
|
|
||||||
|
|
||||||
GType gst_controller_get_type (void);
|
|
||||||
|
|
||||||
/* GstController functions */
|
|
||||||
|
|
||||||
GstController *gst_controller_new_valist (GstObject * object, va_list var_args);
|
|
||||||
GstController *gst_controller_new_list (GstObject * object, GList *list);
|
|
||||||
GstController *gst_controller_new (GstObject * object, ...) G_GNUC_NULL_TERMINATED;
|
|
||||||
|
|
||||||
gboolean gst_controller_add_properties_valist (GstController * self, va_list var_args);
|
|
||||||
gboolean gst_controller_add_properties_list (GstController * self, GList *list);
|
|
||||||
gboolean gst_controller_add_properties (GstController * self, ...) G_GNUC_NULL_TERMINATED;
|
|
||||||
|
|
||||||
gboolean gst_controller_remove_properties_valist (GstController * self, va_list var_args);
|
|
||||||
gboolean gst_controller_remove_properties_list (GstController * self, GList *list);
|
|
||||||
gboolean gst_controller_remove_properties (GstController * self, ...) G_GNUC_NULL_TERMINATED;
|
|
||||||
|
|
||||||
gboolean gst_controller_is_active (GstController * self);
|
|
||||||
void gst_controller_set_disabled (GstController *self, gboolean disabled);
|
|
||||||
void gst_controller_set_property_disabled (GstController *self, const gchar * property_name, gboolean disabled);
|
|
||||||
gboolean gst_controller_set_control_source (GstController *self, const gchar * property_name, GstControlSource *csource);
|
|
||||||
GstControlSource * gst_controller_get_control_source (GstController *self, const gchar * property_name);
|
|
||||||
|
|
||||||
GstClockTime gst_controller_suggest_next_sync (GstController *self);
|
|
||||||
gboolean gst_controller_sync_values (GstController * self,
|
|
||||||
GstClockTime timestamp);
|
|
||||||
|
|
||||||
GValue *gst_controller_get (GstController * self, const gchar * property_name,
|
|
||||||
GstClockTime timestamp);
|
|
||||||
gboolean gst_controller_get_value_arrays (GstController * self,
|
|
||||||
GstClockTime timestamp, GSList * value_arrays);
|
|
||||||
gboolean gst_controller_get_value_array (GstController * self,
|
|
||||||
GstClockTime timestamp, GstValueArray * value_array);
|
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __GST_CONTROLLER_H__ */
|
|
|
@ -48,8 +48,8 @@
|
||||||
|
|
||||||
#include "gstcontrolsource.h"
|
#include "gstcontrolsource.h"
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT controller_debug
|
#define GST_CAT_DEFAULT control_source_debug
|
||||||
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (GstControlSource, gst_control_source, G_TYPE_OBJECT);
|
G_DEFINE_ABSTRACT_TYPE (GstControlSource, gst_control_source, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ gst_control_source_class_init (GstControlSourceClass * klass)
|
||||||
|
|
||||||
/* Has to be implemented by children */
|
/* Has to be implemented by children */
|
||||||
klass->bind = NULL;
|
klass->bind = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolsource", 0,
|
||||||
|
"dynamic parameter control sources");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
532
gst/gstobject.c
532
gst/gstobject.c
|
@ -80,6 +80,56 @@
|
||||||
* gst_object_set_name() and gst_object_get_name() are used to set/get the name
|
* gst_object_set_name() and gst_object_get_name() are used to set/get the name
|
||||||
* of the object.
|
* of the object.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>controlled properties</title>
|
||||||
|
* Controlled properties offers a lightweight way to adjust gobject
|
||||||
|
* properties over stream-time. It works by using time-stamped value pairs that
|
||||||
|
* are queued for element-properties. At run-time the elements continously pull
|
||||||
|
* values changes for the current stream-time.
|
||||||
|
*
|
||||||
|
* What needs to be changed in a #GstElement?
|
||||||
|
* Very little - it is just two steps to make a plugin controllable!
|
||||||
|
* <orderedlist>
|
||||||
|
* <listitem><para>
|
||||||
|
* mark gobject-properties paramspecs that make sense to be controlled,
|
||||||
|
* by GST_PARAM_CONTROLLABLE.
|
||||||
|
* </para></listitem>
|
||||||
|
* <listitem><para>
|
||||||
|
* when processing data (get, chain, loop function) at the beginning call
|
||||||
|
* gst_object_sync_values(element,timestamp).
|
||||||
|
* This will made the controller to update all gobject properties that are under
|
||||||
|
* control with the current values based on timestamp.
|
||||||
|
* </para></listitem>
|
||||||
|
* </orderedlist>
|
||||||
|
*
|
||||||
|
* What needs to be done in applications?
|
||||||
|
* Again its not a lot to change.
|
||||||
|
* <orderedlist>
|
||||||
|
* <listitem><para>
|
||||||
|
* first put some properties under control, by calling
|
||||||
|
* gst_object_control_properties (object, "prop1", "prop2",...);
|
||||||
|
* </para></listitem>
|
||||||
|
* <listitem><para>
|
||||||
|
* create a #GstControlSource.
|
||||||
|
* csource = gst_interpolation_control_source_new ();
|
||||||
|
* gst_interpolation_control_source_set_interpolation_mode(csource, mode);
|
||||||
|
* </para></listitem>
|
||||||
|
* <listitem><para>
|
||||||
|
* Attach the #GstControlSource on the controller to a property.
|
||||||
|
* gst_object_set_control_source (object, "prop1", csource);
|
||||||
|
* </para></listitem>
|
||||||
|
* <listitem><para>
|
||||||
|
* Set the control values
|
||||||
|
* gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
|
||||||
|
* gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
|
||||||
|
* </para></listitem>
|
||||||
|
* <listitem><para>
|
||||||
|
* start your pipeline
|
||||||
|
* </para></listitem>
|
||||||
|
* </orderedlist>
|
||||||
|
* </refsect2>
|
||||||
|
*
|
||||||
* Last reviewed on 2005-11-09 (0.9.4)
|
* Last reviewed on 2005-11-09 (0.9.4)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -88,8 +138,10 @@
|
||||||
|
|
||||||
#include "gstobject.h"
|
#include "gstobject.h"
|
||||||
#include "gstmarshal.h"
|
#include "gstmarshal.h"
|
||||||
#include "gstcontroller.h"
|
#include "gstclock.h"
|
||||||
|
#include "gstcontrolsource.h"
|
||||||
#include "gstinfo.h"
|
#include "gstinfo.h"
|
||||||
|
#include "gstparamspecs.h"
|
||||||
#include "gstutils.h"
|
#include "gstutils.h"
|
||||||
|
|
||||||
#ifndef GST_DISABLE_TRACE
|
#ifndef GST_DISABLE_TRACE
|
||||||
|
@ -142,6 +194,21 @@ static guint gst_object_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static GParamSpec *properties[PROP_LAST];
|
static GParamSpec *properties[PROP_LAST];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GstControlledProperty:
|
||||||
|
*/
|
||||||
|
typedef struct _GstControlledProperty
|
||||||
|
{
|
||||||
|
GParamSpec *pspec; /* GParamSpec for this property */
|
||||||
|
const gchar *name; /* name of the property */
|
||||||
|
GstControlSource *csource; /* GstControlSource for this property */
|
||||||
|
gboolean disabled;
|
||||||
|
GValue last_value;
|
||||||
|
} GstControlledProperty;
|
||||||
|
|
||||||
|
static void gst_controlled_property_free (GstControlledProperty * prop);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_INITIALLY_UNOWNED);
|
G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_INITIALLY_UNOWNED);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -208,6 +275,9 @@ gst_object_init (GstObject * object)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
object->flags = 0;
|
object->flags = 0;
|
||||||
|
|
||||||
|
object->control_rate = 100 * GST_MSECOND;
|
||||||
|
object->last_sync = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,9 +424,14 @@ gst_object_dispose (GObject * object)
|
||||||
GST_OBJECT_PARENT (object) = NULL;
|
GST_OBJECT_PARENT (object) = NULL;
|
||||||
GST_OBJECT_UNLOCK (object);
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
if (self->ctrl) {
|
if (self->properties) {
|
||||||
g_object_unref (self->ctrl);
|
GList *node;
|
||||||
self->ctrl = NULL;
|
|
||||||
|
for (node = self->properties; node; node = g_list_next (node)) {
|
||||||
|
gst_controlled_property_free ((GstControlledProperty *) node->data);
|
||||||
|
}
|
||||||
|
g_list_free (self->properties);
|
||||||
|
self->properties = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
((GObjectClass *) gst_object_parent_class)->dispose (object);
|
((GObjectClass *) gst_object_parent_class)->dispose (object);
|
||||||
|
@ -958,6 +1033,151 @@ gst_object_get_path_string (GstObject * object)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* controller helper functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_controlled_property_new:
|
||||||
|
* @object: for which object the controlled property should be set up
|
||||||
|
* @name: the name of the property to be controlled
|
||||||
|
*
|
||||||
|
* Private method which initializes the fields of a new controlled property
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* Returns: a freshly allocated structure or %NULL
|
||||||
|
*/
|
||||||
|
static GstControlledProperty *
|
||||||
|
gst_controlled_property_new (GstObject * object, const gchar * name)
|
||||||
|
{
|
||||||
|
GstControlledProperty *prop = NULL;
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
GST_INFO ("trying to put property '%s' under control", name);
|
||||||
|
|
||||||
|
/* check if the object has a property of that name */
|
||||||
|
if ((pspec =
|
||||||
|
g_object_class_find_property (G_OBJECT_GET_CLASS (object), name))) {
|
||||||
|
GST_DEBUG (" psec->flags : 0x%08x", pspec->flags);
|
||||||
|
|
||||||
|
/* check if this param is witable && controlable && !construct-only */
|
||||||
|
g_return_val_if_fail ((pspec->flags & (G_PARAM_WRITABLE |
|
||||||
|
GST_PARAM_CONTROLLABLE | G_PARAM_CONSTRUCT_ONLY)) ==
|
||||||
|
(G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE), NULL);
|
||||||
|
|
||||||
|
if ((prop = g_slice_new (GstControlledProperty))) {
|
||||||
|
prop->pspec = pspec;
|
||||||
|
prop->name = pspec->name;
|
||||||
|
prop->csource = NULL;
|
||||||
|
prop->disabled = FALSE;
|
||||||
|
memset (&prop->last_value, 0, sizeof (GValue));
|
||||||
|
g_value_init (&prop->last_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("class '%s' has no property '%s'", G_OBJECT_TYPE_NAME (object),
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_controlled_property_free:
|
||||||
|
* @prop: the object to free
|
||||||
|
*
|
||||||
|
* Private method which frees all data allocated by a #GstControlledProperty
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_controlled_property_free (GstControlledProperty * prop)
|
||||||
|
{
|
||||||
|
if (prop->csource)
|
||||||
|
g_object_unref (prop->csource);
|
||||||
|
g_value_unset (&prop->last_value);
|
||||||
|
g_slice_free (GstControlledProperty, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_object_find_controlled_property:
|
||||||
|
* @self: the gobject to search for a property in
|
||||||
|
* @name: the gobject property name to look for
|
||||||
|
*
|
||||||
|
* Searches the list of properties under control.
|
||||||
|
*
|
||||||
|
* Returns: a #GstControlledProperty or %NULL if the property is not being
|
||||||
|
* controlled.
|
||||||
|
*/
|
||||||
|
static GstControlledProperty *
|
||||||
|
gst_object_find_controlled_property (GstObject * self, const gchar * name)
|
||||||
|
{
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
GList *node;
|
||||||
|
|
||||||
|
for (node = self->properties; node; node = g_list_next (node)) {
|
||||||
|
prop = node->data;
|
||||||
|
/* FIXME: eventually use GQuark to speed it up */
|
||||||
|
if (!strcmp (prop->name, name)) {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GST_DEBUG ("controller does not (yet) manage property '%s'", name);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_object_add_controlled_property:
|
||||||
|
* @self: the object
|
||||||
|
* @name: name of projecty in @object
|
||||||
|
*
|
||||||
|
* Creates a new #GstControlledProperty if there is none for property @name yet.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the property has been added to the controller
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
gst_object_add_controlled_property (GstObject * self, const gchar * name)
|
||||||
|
{
|
||||||
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
/* test if this property isn't yet controlled */
|
||||||
|
if (!gst_object_find_controlled_property (self, name)) {
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
|
/* create GstControlledProperty and add to self->properties list */
|
||||||
|
if ((prop = gst_controlled_property_new (self, name))) {
|
||||||
|
self->properties = g_list_prepend (self->properties, prop);
|
||||||
|
GST_DEBUG_OBJECT (self, "property %s added", name);
|
||||||
|
} else
|
||||||
|
res = FALSE;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (self, "trying to control property %s again", name);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_object_remove_controlled_property:
|
||||||
|
* @self: the object
|
||||||
|
* @name: name of projecty in @object
|
||||||
|
*
|
||||||
|
* Removes a #GstControlledProperty for property @name.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the property has been removed from the controller
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
gst_object_remove_controlled_property (GstObject * self, const gchar * name)
|
||||||
|
{
|
||||||
|
gboolean res = TRUE;
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
|
if ((prop = gst_object_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);
|
||||||
|
GST_DEBUG_OBJECT (self, "property %s removed", name);
|
||||||
|
} else {
|
||||||
|
res = FALSE;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* controller functions */
|
/* controller functions */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -975,24 +1195,18 @@ gst_object_get_path_string (GstObject * object)
|
||||||
gboolean
|
gboolean
|
||||||
gst_object_control_properties (GstObject * object, ...)
|
gst_object_control_properties (GstObject * object, ...)
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = TRUE;
|
||||||
va_list var_args;
|
va_list var_args;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
va_start (var_args, object);
|
va_start (var_args, object);
|
||||||
if (object->ctrl) {
|
GST_OBJECT_LOCK (object);
|
||||||
GstController *ctrl = gst_controller_new_valist (object, var_args);
|
while ((name = va_arg (var_args, gchar *))) {
|
||||||
|
res &= gst_object_add_controlled_property (object, name);
|
||||||
/* FIXME: see gst_controller_new_*() */
|
|
||||||
g_object_unref (object->ctrl);
|
|
||||||
object->ctrl = ctrl;
|
|
||||||
|
|
||||||
res = (object->ctrl != NULL);
|
|
||||||
} else {
|
|
||||||
res = gst_controller_add_properties_valist ((GstController *) object->ctrl,
|
|
||||||
var_args);
|
|
||||||
}
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
va_end (var_args);
|
va_end (var_args);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1010,17 +1224,19 @@ gst_object_control_properties (GstObject * object, ...)
|
||||||
gboolean
|
gboolean
|
||||||
gst_object_uncontrol_properties (GstObject * object, ...)
|
gst_object_uncontrol_properties (GstObject * object, ...)
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = TRUE;
|
||||||
|
va_list var_args;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
if (object->ctrl) {
|
va_start (var_args, object);
|
||||||
va_list var_args;
|
GST_OBJECT_LOCK (object);
|
||||||
|
while ((name = va_arg (var_args, gchar *))) {
|
||||||
va_start (var_args, object);
|
res &= gst_object_remove_controlled_property (object, name);
|
||||||
res = gst_controller_remove_properties_valist (
|
|
||||||
(GstController *) object->ctrl, var_args);
|
|
||||||
va_end (var_args);
|
|
||||||
}
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
va_end (var_args);
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,18 +1244,32 @@ gst_object_uncontrol_properties (GstObject * object, ...)
|
||||||
* gst_object_suggest_next_sync:
|
* gst_object_suggest_next_sync:
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
*
|
*
|
||||||
* Convenience function for GObject
|
* Returns a suggestion for timestamps where buffers should be split
|
||||||
|
* to get best controller results.
|
||||||
*
|
*
|
||||||
* Returns: same thing as gst_controller_suggest_next_sync()
|
* Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE
|
||||||
|
* if no control-rate was set.
|
||||||
*/
|
*/
|
||||||
GstClockTime
|
GstClockTime
|
||||||
gst_object_suggest_next_sync (GstObject * object)
|
gst_object_suggest_next_sync (GstObject * object)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), GST_CLOCK_TIME_NONE);
|
GstClockTime ret;
|
||||||
|
|
||||||
if (object->ctrl)
|
g_return_val_if_fail (GST_IS_OBJECT (object), GST_CLOCK_TIME_NONE);
|
||||||
return gst_controller_suggest_next_sync ((GstController *) object->ctrl);
|
g_return_val_if_fail (object->control_rate != GST_CLOCK_TIME_NONE,
|
||||||
return (GST_CLOCK_TIME_NONE);
|
GST_CLOCK_TIME_NONE);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (object);
|
||||||
|
|
||||||
|
/* TODO: Implement more logic, depending on interpolation mode and control
|
||||||
|
* points
|
||||||
|
* FIXME: we need playback direction
|
||||||
|
*/
|
||||||
|
ret = object->last_sync + object->control_rate;
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1047,64 +1277,122 @@ gst_object_suggest_next_sync (GstObject * object)
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
* @timestamp: the time that should be processed
|
* @timestamp: the time that should be processed
|
||||||
*
|
*
|
||||||
* Convenience function for GObject
|
* Sets the properties of the object, according to the #GstControlSources that
|
||||||
|
* (maybe) handle them and for the given timestamp.
|
||||||
*
|
*
|
||||||
* Returns: same thing as gst_controller_sync_values()
|
* If this function fails, it is most likely the application developers fault.
|
||||||
|
* Most probably the control sources are not setup correctly.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the controller values could be applied to the object
|
||||||
|
* properties, %FALSE otherwise
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_object_sync_values (GstObject * object, GstClockTime timestamp)
|
gst_object_sync_values (GstObject * object, GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
GstControlledProperty *prop;
|
||||||
|
GList *node;
|
||||||
|
gboolean ret = TRUE, val_ret;
|
||||||
|
GValue value = { 0, };
|
||||||
|
|
||||||
if (object->ctrl)
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
return gst_controller_sync_values ((GstController *) object->ctrl,
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
timestamp);
|
|
||||||
/* this is no failure, its called by elements regardless if there is a
|
GST_LOG ("sync_values");
|
||||||
* controller assigned or not */
|
|
||||||
return (TRUE);
|
/* FIXME: this deadlocks */
|
||||||
|
/* GST_OBJECT_LOCK (object); */
|
||||||
|
g_object_freeze_notify ((GObject *) object);
|
||||||
|
/* go over the controlled properties of the controller */
|
||||||
|
for (node = object->properties; node; node = g_list_next (node)) {
|
||||||
|
prop = node->data;
|
||||||
|
|
||||||
|
if (!prop->csource || prop->disabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GST_LOG ("property '%s' at ts=%" G_GUINT64_FORMAT, prop->name, timestamp);
|
||||||
|
|
||||||
|
/* we can make this faster
|
||||||
|
* http://bugzilla.gnome.org/show_bug.cgi?id=536939
|
||||||
|
*/
|
||||||
|
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
|
||||||
|
val_ret = gst_control_source_get_value (prop->csource, timestamp, &value);
|
||||||
|
if (G_LIKELY (val_ret)) {
|
||||||
|
/* always set the value for first time, but then only if it changed
|
||||||
|
* this should limit g_object_notify invocations.
|
||||||
|
* FIXME: can we detect negative playback rates?
|
||||||
|
*/
|
||||||
|
if ((timestamp < object->last_sync) ||
|
||||||
|
gst_value_compare (&value, &prop->last_value) != GST_VALUE_EQUAL) {
|
||||||
|
g_object_set_property ((GObject *) object, prop->name, &value);
|
||||||
|
g_value_copy (&value, &prop->last_value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG ("no control value for param %s", prop->name);
|
||||||
|
}
|
||||||
|
g_value_unset (&value);
|
||||||
|
ret &= val_ret;
|
||||||
|
}
|
||||||
|
object->last_sync = timestamp;
|
||||||
|
g_object_thaw_notify ((GObject *) object);
|
||||||
|
/* GST_OBJECT_UNLOCK (object); */
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_object_has_active_automation:
|
* gst_object_has_active_controlled_properties:
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
*
|
*
|
||||||
* Check if the object has an active controller. It has one if it has at least
|
* Check if the @object has an active controlled properties.
|
||||||
* one controlled property that is not disabled.
|
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the controller is active
|
* Returns: %TRUE if the object has active controlled properties
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_object_has_active_automation (GstObject * object)
|
gst_object_has_active_controlled_properties (GstObject * object)
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
GList *node;
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
res = gst_controller_is_active ((GstController *) object->ctrl);
|
for (node = object->properties; node; node = node->next) {
|
||||||
|
prop = node->data;
|
||||||
|
res |= !prop->disabled;
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_object_set_automation_disabled:
|
* gst_object_set_controlled_properties_disabled:
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
* @disabled: boolean that specifies whether to disable the controller
|
* @disabled: boolean that specifies whether to disable the controller
|
||||||
* or not.
|
* or not.
|
||||||
*
|
*
|
||||||
* This function is used to disable all properties of the #GstController
|
* This function is used to disable all controlled properties of the @object for
|
||||||
* for some time, i.e. gst_object_sync_values() will do nothing..
|
* some time, i.e. gst_object_sync_values() will do nothing..
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_object_set_automation_disabled (GstObject * object, gboolean disabled)
|
gst_object_set_controlled_properties_disabled (GstObject * object,
|
||||||
|
gboolean disabled)
|
||||||
{
|
{
|
||||||
|
GList *node;
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_OBJECT (object));
|
g_return_if_fail (GST_IS_OBJECT (object));
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
gst_controller_set_disabled (object->ctrl, disabled);
|
for (node = object->properties; node; node = node->next) {
|
||||||
|
prop = node->data;
|
||||||
|
prop->disabled = disabled;
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_object_set_property_automation_disabled:
|
* gst_object_set_controlled_property_disabled:
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
* @property_name: property to disable
|
* @property_name: property to disable
|
||||||
* @disabled: boolean that specifies whether to disable the controller
|
* @disabled: boolean that specifies whether to disable the controller
|
||||||
|
@ -1115,15 +1403,19 @@ gst_object_set_automation_disabled (GstObject * object, gboolean disabled)
|
||||||
* property.
|
* property.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_object_set_property_automation_disabled (GstObject * object,
|
gst_object_set_controlled_property_disabled (GstObject * object,
|
||||||
const gchar * property_name, gboolean disabled)
|
const gchar * property_name, gboolean disabled)
|
||||||
{
|
{
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_OBJECT (object));
|
g_return_if_fail (GST_IS_OBJECT (object));
|
||||||
g_return_if_fail (property_name);
|
g_return_if_fail (property_name);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
gst_controller_set_property_disabled ((GstController *) object->ctrl,
|
if ((prop = gst_object_find_controlled_property (object, property_name))) {
|
||||||
property_name, disabled);
|
prop->disabled = disabled;
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1142,14 +1434,30 @@ gboolean
|
||||||
gst_object_set_control_source (GstObject * object, const gchar * property_name,
|
gst_object_set_control_source (GstObject * object, const gchar * property_name,
|
||||||
GstControlSource * csource)
|
GstControlSource * csource)
|
||||||
{
|
{
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (property_name, FALSE);
|
g_return_val_if_fail (property_name, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_CONTROL_SOURCE (csource), FALSE);
|
g_return_val_if_fail ((!csource || GST_IS_CONTROL_SOURCE (csource)), FALSE);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
return gst_controller_set_control_source ((GstController *) object->ctrl,
|
if ((prop = gst_object_find_controlled_property (object, property_name))) {
|
||||||
property_name, csource);
|
GstControlSource *old = prop->csource;
|
||||||
return FALSE;
|
|
||||||
|
if (csource && (ret = gst_control_source_bind (csource, prop->pspec))) {
|
||||||
|
prop->csource = g_object_ref (csource);
|
||||||
|
} else if (!csource) {
|
||||||
|
ret = TRUE;
|
||||||
|
prop->csource = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret && old)
|
||||||
|
g_object_unref (old);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1167,26 +1475,64 @@ gst_object_set_control_source (GstObject * object, const gchar * property_name,
|
||||||
GstControlSource *
|
GstControlSource *
|
||||||
gst_object_get_control_source (GstObject * object, const gchar * property_name)
|
gst_object_get_control_source (GstObject * object, const gchar * property_name)
|
||||||
{
|
{
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
GstControlSource *ret = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
|
g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
|
||||||
g_return_val_if_fail (property_name, NULL);
|
g_return_val_if_fail (property_name, NULL);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
return gst_controller_get_control_source ((GstController *) object->ctrl,
|
if ((prop = gst_object_find_controlled_property (object, property_name))) {
|
||||||
property_name);
|
if ((ret = prop->csource))
|
||||||
return NULL;
|
g_object_ref (ret);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: docs
|
/**
|
||||||
|
* gst_object_get_value:
|
||||||
|
* @object: the object that has controlled properties
|
||||||
|
* @property_name: the name of the property to get
|
||||||
|
* @timestamp: the time the control-change should be read from
|
||||||
|
*
|
||||||
|
* Gets the value for the given controllered property at the requested time.
|
||||||
|
*
|
||||||
|
* Returns: the GValue of the property at the given time, or %NULL if the
|
||||||
|
* property isn't controlled.
|
||||||
|
*/
|
||||||
GValue *
|
GValue *
|
||||||
gst_object_get_value (GstObject * object, const gchar * property_name,
|
gst_object_get_value (GstObject * object, const gchar * property_name,
|
||||||
GstClockTime timestamp)
|
GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
GValue *val = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
|
g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
|
||||||
g_return_val_if_fail (property_name, NULL);
|
g_return_val_if_fail (property_name, NULL);
|
||||||
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
return gst_controller_get (object->ctrl, property_name, timestamp);
|
if ((prop = gst_object_find_controlled_property (object, property_name))) {
|
||||||
return NULL;
|
val = g_new0 (GValue, 1);
|
||||||
|
g_value_init (val, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
|
||||||
|
if (prop->csource) {
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
/* get current value via control source */
|
||||||
|
res = gst_control_source_get_value (prop->csource, timestamp, val);
|
||||||
|
if (!res) {
|
||||||
|
g_free (val);
|
||||||
|
val = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_object_get_property ((GObject *) object, prop->name, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1210,13 +1556,17 @@ gboolean
|
||||||
gst_object_get_value_arrays (GstObject * object, GstClockTime timestamp,
|
gst_object_get_value_arrays (GstObject * object, GstClockTime timestamp,
|
||||||
GSList * value_arrays)
|
GSList * value_arrays)
|
||||||
{
|
{
|
||||||
|
gboolean res = TRUE;
|
||||||
|
GSList *node;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
g_return_val_if_fail (value_arrays, FALSE);
|
||||||
|
|
||||||
if (object->ctrl)
|
for (node = value_arrays; (res && node); node = g_slist_next (node)) {
|
||||||
return gst_controller_get_value_arrays ((GstController *) object->ctrl,
|
res = gst_object_get_value_array (object, timestamp, node->data);
|
||||||
timestamp, value_arrays);
|
}
|
||||||
return (FALSE);
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1238,13 +1588,30 @@ gboolean
|
||||||
gst_object_get_value_array (GstObject * object, GstClockTime timestamp,
|
gst_object_get_value_array (GstObject * object, GstClockTime timestamp,
|
||||||
GstValueArray * value_array)
|
GstValueArray * value_array)
|
||||||
{
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
GstControlledProperty *prop;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
g_return_val_if_fail (value_array, FALSE);
|
||||||
|
g_return_val_if_fail (value_array->property_name, FALSE);
|
||||||
|
g_return_val_if_fail (value_array->values, FALSE);
|
||||||
|
|
||||||
if (object->ctrl)
|
GST_OBJECT_LOCK (object);
|
||||||
return gst_controller_get_value_array ((GstController *) object->ctrl,
|
|
||||||
timestamp, value_array);
|
if ((prop = gst_object_find_controlled_property (object,
|
||||||
return (FALSE);
|
value_array->property_name))) {
|
||||||
|
/* get current value_array via control source */
|
||||||
|
if (!prop->csource)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
res = gst_control_source_get_value_array (prop->csource, timestamp,
|
||||||
|
value_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1267,13 +1634,9 @@ gst_object_get_value_array (GstObject * object, GstClockTime timestamp,
|
||||||
GstClockTime
|
GstClockTime
|
||||||
gst_object_get_control_rate (GstObject * object)
|
gst_object_get_control_rate (GstObject * object)
|
||||||
{
|
{
|
||||||
GstClockTime control_rate = GST_CLOCK_TIME_NONE;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
if (object->ctrl)
|
return object->control_rate;
|
||||||
g_object_get (object->ctrl, "control-rate", &control_rate, NULL);
|
|
||||||
return (control_rate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1294,6 +1657,5 @@ gst_object_set_control_rate (GstObject * object, GstClockTime control_rate)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GST_IS_OBJECT (object));
|
g_return_if_fail (GST_IS_OBJECT (object));
|
||||||
|
|
||||||
if (object->ctrl)
|
object->control_rate = control_rate;
|
||||||
g_object_set (object->ctrl, "control-rate", control_rate, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,10 @@ struct _GstObject {
|
||||||
guint32 flags;
|
guint32 flags;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer ctrl; /* time controlled properties */
|
GList *properties; /* List of GstControlledProperty */
|
||||||
|
guint64 control_rate;
|
||||||
|
guint64 last_sync;
|
||||||
|
|
||||||
gpointer _gst_reserved;
|
gpointer _gst_reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,7 +232,6 @@ gchar * gst_object_get_path_string (GstObject *object);
|
||||||
gboolean gst_object_check_uniqueness (GList *list, const gchar *name);
|
gboolean gst_object_check_uniqueness (GList *list, const gchar *name);
|
||||||
|
|
||||||
/* controller functions */
|
/* controller functions */
|
||||||
#include <gst/gstclock.h>
|
|
||||||
#include <gst/gstcontrolsource.h>
|
#include <gst/gstcontrolsource.h>
|
||||||
|
|
||||||
gboolean gst_object_control_properties (GstObject * object, ...) G_GNUC_NULL_TERMINATED;
|
gboolean gst_object_control_properties (GstObject * object, ...) G_GNUC_NULL_TERMINATED;
|
||||||
|
@ -238,9 +240,9 @@ gboolean gst_object_uncontrol_properties (GstObject * object, ...) G_GNUC_NULL_T
|
||||||
GstClockTime gst_object_suggest_next_sync (GstObject * object);
|
GstClockTime gst_object_suggest_next_sync (GstObject * object);
|
||||||
gboolean gst_object_sync_values (GstObject * object, GstClockTime timestamp);
|
gboolean gst_object_sync_values (GstObject * object, GstClockTime timestamp);
|
||||||
|
|
||||||
gboolean gst_object_has_active_automation (GstObject *object);
|
gboolean gst_object_has_active_controlled_properties (GstObject *object);
|
||||||
void gst_object_set_automation_disabled (GstObject *object, gboolean disabled);
|
void gst_object_set_controlled_properties_disabled (GstObject *object, gboolean disabled);
|
||||||
void gst_object_set_property_automation_disabled (GstObject *object, const gchar * property_name, gboolean disabled);
|
void gst_object_set_controlled_property_disabled (GstObject *object, const gchar * property_name, gboolean disabled);
|
||||||
|
|
||||||
gboolean gst_object_set_control_source (GstObject *object, const gchar * property_name, GstControlSource *csource);
|
gboolean gst_object_set_control_source (GstObject *object, const gchar * property_name, GstControlSource *csource);
|
||||||
GstControlSource * gst_object_get_control_source (GstObject *object, const gchar * property_name);
|
GstControlSource * gst_object_get_control_source (GstObject *object, const gchar * property_name);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||||
|
|
||||||
|
@ -80,7 +82,6 @@ main (gint argc, gchar * argv[])
|
||||||
gint i, j;
|
gint i, j;
|
||||||
GstElement *src, *sink;
|
GstElement *src, *sink;
|
||||||
GstElement *bin;
|
GstElement *bin;
|
||||||
GstController *ctrl;
|
|
||||||
GstInterpolationControlSource *csource;
|
GstInterpolationControlSource *csource;
|
||||||
GValue freq = { 0, };
|
GValue freq = { 0, };
|
||||||
GstClockTime bt, ct;
|
GstClockTime bt, ct;
|
||||||
|
@ -109,15 +110,15 @@ main (gint argc, gchar * argv[])
|
||||||
|
|
||||||
tick = BLOCK_SIZE * GST_SECOND / 44100;
|
tick = BLOCK_SIZE * GST_SECOND / 44100;
|
||||||
|
|
||||||
/* add a controller to the source */
|
/* select parameters to control */
|
||||||
if (!(ctrl = gst_controller_new (GST_OBJECT (src), "freq", NULL))) {
|
if (!gst_object_control_properties (GST_OBJECT (src), "freq", NULL)) {
|
||||||
GST_WARNING ("can't control source element");
|
GST_WARNING ("can't control source element");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create and configure control source */
|
/* create and configure control source */
|
||||||
csource = gst_interpolation_control_source_new ();
|
csource = gst_interpolation_control_source_new ();
|
||||||
gst_controller_set_control_source (ctrl, "freq",
|
gst_object_set_control_source (GST_OBJECT (src), "freq",
|
||||||
GST_CONTROL_SOURCE (csource));
|
GST_CONTROL_SOURCE (csource));
|
||||||
gst_interpolation_control_source_set_interpolation_mode (csource,
|
gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||||
GST_INTERPOLATE_LINEAR);
|
GST_INTERPOLATE_LINEAR);
|
||||||
|
@ -194,7 +195,6 @@ main (gint argc, gchar * argv[])
|
||||||
GST_TIME_ARGS (elapsed));
|
GST_TIME_ARGS (elapsed));
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
g_object_unref (G_OBJECT (ctrl));
|
|
||||||
gst_object_unref (G_OBJECT (bin));
|
gst_object_unref (G_OBJECT (bin));
|
||||||
res = 0;
|
res = 0;
|
||||||
Error:
|
Error:
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,6 @@ main (gint argc, gchar ** argv)
|
||||||
gint res = 1;
|
gint res = 1;
|
||||||
GstElement *src, *sink;
|
GstElement *src, *sink;
|
||||||
GstElement *bin;
|
GstElement *bin;
|
||||||
GstController *ctrl;
|
|
||||||
GstInterpolationControlSource *csource1, *csource2;
|
GstInterpolationControlSource *csource1, *csource2;
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
GstClockID clock_id;
|
GstClockID clock_id;
|
||||||
|
@ -50,7 +49,7 @@ main (gint argc, gchar ** argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* add a controller to the source */
|
/* add a controller to the source */
|
||||||
if (!(ctrl = gst_controller_new (GST_OBJECT (src), "freq", "volume", NULL))) {
|
if (!gst_object_control_properties (GST_OBJECT (src), "freq", "volume", NULL)) {
|
||||||
GST_WARNING ("can't control source element");
|
GST_WARNING ("can't control source element");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
@ -58,9 +57,9 @@ main (gint argc, gchar ** argv)
|
||||||
csource1 = gst_interpolation_control_source_new ();
|
csource1 = gst_interpolation_control_source_new ();
|
||||||
csource2 = gst_interpolation_control_source_new ();
|
csource2 = gst_interpolation_control_source_new ();
|
||||||
|
|
||||||
gst_controller_set_control_source (ctrl, "volume",
|
gst_object_set_control_source (GST_OBJECT (src), "volume",
|
||||||
GST_CONTROL_SOURCE (csource1));
|
GST_CONTROL_SOURCE (csource1));
|
||||||
gst_controller_set_control_source (ctrl, "freq",
|
gst_object_set_control_source (GST_OBJECT (src), "freq",
|
||||||
GST_CONTROL_SOURCE (csource2));
|
GST_CONTROL_SOURCE (csource2));
|
||||||
|
|
||||||
/* Set interpolation mode */
|
/* Set interpolation mode */
|
||||||
|
@ -101,7 +100,6 @@ main (gint argc, gchar ** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
g_object_unref (G_OBJECT (ctrl));
|
|
||||||
gst_clock_id_unref (clock_id);
|
gst_clock_id_unref (clock_id);
|
||||||
gst_object_unref (G_OBJECT (clock));
|
gst_object_unref (G_OBJECT (clock));
|
||||||
gst_object_unref (G_OBJECT (bin));
|
gst_object_unref (G_OBJECT (bin));
|
||||||
|
|
Loading…
Reference in a new issue