Commit 9e24b85a authored by Wim Taymans's avatar Wim Taymans

Remove threadsafe properties. Fix elements because GObject complains when...

Remove threadsafe properties. Fix elements because GObject complains when installing a property before declaring a se...

Original commit message from CVS:
Remove threadsafe properties. Fix elements because GObject
complains when installing a property before declaring a
set/get_property handler.
Rearrange gstelement.h file, use STATE macros for state locks.
Free mutexes in the finalize method instead of dispose.
parent 1c956939
2005-03-08 Wim Taymans <wim@fluendo.com>
* gst/elements/gstaggregator.c: (gst_aggregator_class_init):
* gst/elements/gstfakesink.c: (gst_fakesink_class_init):
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init):
* gst/elements/gstfdsink.c: (gst_fdsink_class_init):
* gst/elements/gstfdsrc.c: (gst_fdsrc_class_init):
* gst/elements/gstfilesink.c: (gst_filesink_class_init):
* gst/elements/gstfilesrc.c: (gst_filesrc_class_init):
* gst/elements/gstidentity.c: (gst_identity_class_init):
* gst/elements/gstmd5sink.c: (gst_md5sink_class_init):
* gst/elements/gstmultifilesrc.c: (gst_multifilesrc_class_init):
* gst/elements/gstshaper.c: (gst_shaper_class_init):
* gst/elements/gststatistics.c: (gst_statistics_class_init):
* gst/elements/gsttee.c: (gst_tee_class_init), (gst_tee_getcaps),
(gst_tee_link):
* gst/gstelement.c: (gst_element_class_init),
(gst_element_base_class_init), (gst_element_init),
(gst_element_get_random_pad), (gst_element_wait_state_change),
(gst_element_change_state), (gst_element_dispose),
(gst_element_finalize), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstqueue.c: (gst_queue_class_init), (gst_queue_link_src):
* gst/gstthread.c: (gst_thread_class_init),
(gst_thread_release_children_locks), (gst_thread_change_state):
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_loopfunc_wrapper),
(gst_basic_scheduler_chain_wrapper),
(gst_basic_scheduler_src_wrapper),
(gst_basic_scheduler_remove_element):
* gst/schedulers/gstoptimalscheduler.c: (schedule_group):
Remove threadsafe properties. Fix elements because GObject
complains when installing a property before declaring a
set/get_property handler.
Rearrange gstelement.h file, use STATE macros for state locks.
Free mutexes in the finalize method instead of dispose.
2005-03-08 Wim Taymans <wim@fluendo.com>
* check/gst/gstobject.c: (START_TEST), (gst_object_suite):
......
......@@ -137,6 +137,9 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_aggregator_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_aggregator_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_PADS,
g_param_spec_int ("num_pads", "Num pads", "The number of source pads",
0, G_MAXINT, 0, G_PARAM_READABLE));
......@@ -152,8 +155,6 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
"The current state of the element", NULL, G_PARAM_READABLE));
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_aggregator_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_aggregator_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_aggregator_get_property);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
......
......@@ -138,6 +138,8 @@ gst_fakesink_class_init (GstFakeSinkClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesink_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesink_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SINKS,
g_param_spec_int ("num_sinks", "Number of sinks",
......@@ -169,9 +171,6 @@ gst_fakesink_class_init (GstFakeSinkClass * klass)
gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 2,
GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesink_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesink_get_property);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_fakesink_request_new_pad);
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesink_set_clock);
......
......@@ -214,6 +214,8 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
g_param_spec_int ("num-sources", "num-sources", "Number of sources",
......@@ -281,9 +283,6 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 2,
GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
......
......@@ -88,13 +88,12 @@ gst_fdsink_class_init (GstFdSinkClass * klass)
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_fdsink_set_property;
gobject_class->get_property = gst_fdsink_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
0, G_MAXINT, 1, G_PARAM_READWRITE));
gobject_class->set_property = gst_fdsink_set_property;
gobject_class->get_property = gst_fdsink_get_property;
}
static void
......
......@@ -103,6 +103,9 @@ gst_fdsrc_class_init (GstFdSrcClass * klass)
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_fdsrc_set_property;
gobject_class->get_property = gst_fdsrc_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
0, G_MAXINT, 0, G_PARAM_READWRITE));
......@@ -119,9 +122,6 @@ gst_fdsrc_class_init (GstFdSrcClass * klass)
G_STRUCT_OFFSET (GstFdSrcClass, timeout), NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gobject_class->set_property = gst_fdsrc_set_property;
gobject_class->get_property = gst_fdsrc_get_property;
gstelement_class->change_state = gst_fdsrc_change_state;
}
......
......@@ -145,6 +145,8 @@ gst_filesink_class_init (GstFileSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_filesink_set_property;
gobject_class->get_property = gst_filesink_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
g_param_spec_string ("location", "File Location",
......@@ -155,8 +157,6 @@ gst_filesink_class_init (GstFileSinkClass * klass)
G_STRUCT_OFFSET (GstFileSinkClass, handoff), NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gobject_class->set_property = gst_filesink_set_property;
gobject_class->get_property = gst_filesink_get_property;
gobject_class->dispose = gst_filesink_dispose;
}
static void
......
......@@ -214,6 +214,8 @@ gst_filesrc_class_init (GstFileSrcClass * klass)
gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_filesrc_set_property;
gobject_class->get_property = gst_filesrc_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
g_param_spec_int ("fd", "File-descriptor",
......@@ -235,8 +237,6 @@ gst_filesrc_class_init (GstFileSrcClass * klass)
"Touch data to force disk read", FALSE, G_PARAM_READWRITE));
gobject_class->dispose = gst_filesrc_dispose;
gobject_class->set_property = gst_filesrc_set_property;
gobject_class->get_property = gst_filesrc_get_property;
gstelement_class->change_state = gst_filesrc_change_state;
}
......
......@@ -138,6 +138,9 @@ gst_identity_class_init (GstIdentityClass * klass)
gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
g_param_spec_boolean ("loop-based", "Loop-based",
"Set to TRUE to use loop-based rather than chain-based scheduling",
......@@ -185,8 +188,6 @@ gst_identity_class_init (GstIdentityClass * klass)
GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_identity_set_clock);
gstelement_class->change_state =
......
......@@ -392,7 +392,6 @@ gst_md5sink_class_init (GstMD5SinkClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_md5sink_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MD5,
......
......@@ -107,6 +107,8 @@ gst_multifilesrc_class_init (GstMultiFileSrcClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = gst_multifilesrc_set_property;
gobject_class->get_property = gst_multifilesrc_get_property;
gst_multifilesrc_signals[NEW_FILE] =
g_signal_new ("new-file", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
......@@ -114,16 +116,11 @@ gst_multifilesrc_class_init (GstMultiFileSrcClass * klass)
g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATIONS, g_param_spec_pointer ("locations", "locations", "locations", G_PARAM_READWRITE)); /* CHECKME */
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAVENEWMEDIA,
g_param_spec_boolean ("newmedia", "newmedia",
"generate new media events?", FALSE, G_PARAM_READWRITE));
gobject_class->set_property = gst_multifilesrc_set_property;
gobject_class->get_property = gst_multifilesrc_get_property;
gstelement_class->change_state = gst_multifilesrc_change_state;
}
......
......@@ -127,6 +127,8 @@ gst_shaper_class_init (GstShaperClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_shaper_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_shaper_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_POLICY,
g_param_spec_enum ("policy", "Policy", "Shaper policy",
......@@ -138,9 +140,6 @@ gst_shaper_class_init (GstShaperClass * klass)
g_param_spec_string ("last-message", "last-message", "last-message",
NULL, G_PARAM_READABLE));
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_shaper_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_shaper_get_property);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_shaper_request_new_pad);
}
......
......@@ -124,6 +124,8 @@ gst_statistics_class_init (GstStatisticsClass * klass)
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_statistics_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_statistics_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFERS,
g_param_spec_int64 ("buffers", "buffers", "total buffers count",
......@@ -162,8 +164,6 @@ gst_statistics_class_init (GstStatisticsClass * klass)
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_statistics_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_statistics_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_statistics_get_property);
}
static void
......
......@@ -113,6 +113,8 @@ gst_tee_class_init (GstTeeClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tee_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tee_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_PADS,
g_param_spec_int ("num_pads", "num_pads", "num_pads",
......@@ -126,8 +128,6 @@ gst_tee_class_init (GstTeeClass * klass)
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tee_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tee_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tee_get_property);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
......
......@@ -64,11 +64,6 @@ static void gst_element_init (GstElement * element);
static void gst_element_base_class_init (gpointer g_class);
static void gst_element_base_class_finalize (gpointer g_class);
static void gst_element_real_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_element_real_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_element_dispose (GObject * object);
static void gst_element_finalize (GObject * object);
......@@ -207,11 +202,6 @@ gst_element_class_init (GstElementClass * klass)
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_element_real_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_element_real_get_property);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
......@@ -233,15 +223,8 @@ gst_element_class_init (GstElementClass * klass)
static void
gst_element_base_class_init (gpointer g_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_element_real_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_element_real_get_property);
memset (&element_class->details, 0, sizeof (GstElementDetails));
element_class->padtemplates = NULL;
}
......@@ -272,30 +255,10 @@ gst_element_init (GstElement * element)
element->sched = NULL;
element->clock = NULL;
element->sched_private = NULL;
element->state_mutex = g_mutex_new ();
element->state_lock = g_mutex_new ();
element->state_cond = g_cond_new ();
}
static void
gst_element_real_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
if (oclass->set_property)
(oclass->set_property) (object, prop_id, value, pspec);
}
static void
gst_element_real_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
if (oclass->get_property)
(oclass->get_property) (object, prop_id, value, pspec);
}
/**
* gst_element_default_error:
* @object: a #GObject that signalled the error.
......@@ -323,408 +286,6 @@ gst_element_default_error (GObject * object, GstObject * source, GError * error,
g_free (name);
}
typedef struct
{
const GParamSpec *pspec;
GValue value;
}
prop_value_t;
static void
element_set_property (GstElement * element, const GParamSpec * pspec,
const GValue * value)
{
prop_value_t *prop_value = g_new0 (prop_value_t, 1);
prop_value->pspec = pspec;
prop_value->value = *value;
g_async_queue_push (element->prop_value_queue, prop_value);
}
static void
element_get_property (GstElement * element, const GParamSpec * pspec,
GValue * value)
{
g_mutex_lock (element->property_mutex);
g_object_get_property ((GObject *) element, pspec->name, value);
g_mutex_unlock (element->property_mutex);
}
static void
gst_element_threadsafe_properties_pre_run (GstElement * element)
{
/* need to ref the object because we don't want to lose the object
* before the post run function is called */
gst_object_ref (GST_OBJECT (element));
GST_DEBUG ("locking element %s", GST_OBJECT_NAME (element));
g_mutex_lock (element->property_mutex);
gst_element_set_pending_properties (element);
}
static void
gst_element_threadsafe_properties_post_run (GstElement * element)
{
GST_DEBUG ("unlocking element %s", GST_OBJECT_NAME (element));
g_mutex_unlock (element->property_mutex);
gst_object_unref (GST_OBJECT (element));
}
/**
* gst_element_enable_threadsafe_properties:
* @element: a #GstElement to enable threadsafe properties on.
*
* Installs an asynchronous queue, a mutex and pre- and post-run functions on
* this element so that properties on the element can be set in a
* threadsafe way.
*/
void
gst_element_enable_threadsafe_properties (GstElement * element)
{
g_return_if_fail (GST_IS_ELEMENT (element));
GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
element->pre_run_func = gst_element_threadsafe_properties_pre_run;
element->post_run_func = gst_element_threadsafe_properties_post_run;
if (!element->prop_value_queue)
element->prop_value_queue = g_async_queue_new ();
if (!element->property_mutex)
element->property_mutex = g_mutex_new ();
}
/**
* gst_element_disable_threadsafe_properties:
* @element: a #GstElement to disable threadsafe properties on.
*
* Removes the threadsafe properties, post- and pre-run locks from
* this element.
*/
void
gst_element_disable_threadsafe_properties (GstElement * element)
{
g_return_if_fail (GST_IS_ELEMENT (element));
GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
//element->pre_run_func = NULL;
//element->post_run_func = NULL;
/* let's keep around that async queue */
}
/**
* gst_element_set_pending_properties:
* @element: a #GstElement to set the pending properties on.
*
* Sets all pending properties on the threadsafe properties enabled
* element.
*/
void
gst_element_set_pending_properties (GstElement * element)
{
prop_value_t *prop_value;
while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
g_object_set_property ((GObject *) element, prop_value->pspec->name,
&prop_value->value);
g_value_unset (&prop_value->value);
g_free (prop_value);
}
}
/* following 6 functions taken mostly from gobject.c */
/**
* gst_element_set:
* @element: a #GstElement to set properties on.
* @first_property_name: the first property to set.
* @...: value of the first property, and more properties to set, ending
* with NULL.
*
* Sets properties on an element. If the element uses threadsafe properties,
* they will be queued and set on the object when it is scheduled again.
*/
void
gst_element_set (GstElement * element, const gchar * first_property_name, ...)
{
va_list var_args;
g_return_if_fail (GST_IS_ELEMENT (element));
va_start (var_args, first_property_name);
gst_element_set_valist (element, first_property_name, var_args);
va_end (var_args);
}
/**
* gst_element_get:
* @element: a #GstElement to get properties of.
* @first_property_name: the first property to get.
* @...: pointer to a variable to store the first property in, as well as
* more properties to get, ending with NULL.
*
* Gets properties from an element. If the element uses threadsafe properties,
* the element will be locked before getting the given properties.
*/
void
gst_element_get (GstElement * element, const gchar * first_property_name, ...)
{
va_list var_args;
g_return_if_fail (GST_IS_ELEMENT (element));
va_start (var_args, first_property_name);
gst_element_get_valist (element, first_property_name, var_args);
va_end (var_args);
}
/**
* gst_element_set_valist:
* @element: a #GstElement to set properties on.
* @first_property_name: the first property to set.
* @var_args: the var_args list of other properties to get.
*
* Sets properties on an element. If the element uses threadsafe properties,
* the property change will be put on the async queue.
*/
void
gst_element_set_valist (GstElement * element, const gchar * first_property_name,
va_list var_args)
{
const gchar *name;
GObject *object;
g_return_if_fail (GST_IS_ELEMENT (element));
object = (GObject *) element;
GST_CAT_DEBUG (GST_CAT_PROPERTIES,
"setting valist of properties starting with %s on element %s",
first_property_name, gst_element_get_name (element));
if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
g_object_set_valist (object, first_property_name, var_args);
return;
}
g_object_ref (object);
name = first_property_name;
while (name) {
GValue value = { 0, };
GParamSpec *pspec;
gchar *error = NULL;
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
if (!pspec) {
g_warning ("%s: object class `%s' has no property named `%s'",
G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
break;
}
if (!(pspec->flags & G_PARAM_WRITABLE)) {
g_warning ("%s: property `%s' of object class `%s' is not writable",
G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
break;
}
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
G_VALUE_COLLECT (&value, var_args, 0, &error);
if (error) {
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
/* we purposely leak the value here, it might not be
* in a sane state if an error condition occoured
*/
break;
}
element_set_property (element, pspec, &value);
g_value_unset (&value);
name = va_arg (var_args, gchar *);
}
g_object_unref (object);
}
/**
* gst_element_get_valist:
* @element: a #GstElement to get properties of.
* @first_property_name: the first property to get.
* @var_args: the var_args list of other properties to get.
*
* Gets properties from an element. If the element uses threadsafe properties,
* the element will be locked before getting the given properties.
*/
void
gst_element_get_valist (GstElement * element, const gchar * first_property_name,
va_list var_args)
{
const gchar *name;
GObject *object;
g_return_if_fail (GST_IS_ELEMENT (element));
object = (GObject *) element;
if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
g_object_get_valist (object, first_property_name, var_args);
return;
}
g_object_ref (object);
name = first_property_name;
while (name) {
GValue value = { 0, };
GParamSpec *pspec;
gchar *error;
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
if (!pspec) {
g_warning ("%s: object class `%s' has no property named `%s'",
G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
break;
}
if (!(pspec->flags & G_PARAM_READABLE)) {
g_warning ("%s: property `%s' of object class `%s' is not readable",
G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
break;
}
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
element_get_property (element, pspec, &value);
G_VALUE_LCOPY (&value, var_args, 0, &error);
if (error) {
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
g_value_unset (&value);