From 750e6b8c97722f5b66cdc8c0393506d33cb88092 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 10 Sep 2001 16:28:43 +0000 Subject: [PATCH] dparams have arrived. see previous mail for an intro Original commit message from CVS: dparams have arrived. see previous mail for an intro --- gst/Makefile.am | 4 + gst/elements/gstsinesrc.c | 67 ++++-- gst/elements/gstsinesrc.h | 6 +- gst/gst.h | 2 + gst/gstdparam.c | 190 +++++++++++++++++ gst/gstdparam.h | 128 ++++++++++++ gst/gstdparammanager.c | 459 ++++++++++++++++++++++++++++++++++++++++++ gst/gstdparammanager.h | 138 +++++++++++++ gst/gstelement.h | 3 + plugins/elements/gstsinesrc.c | 67 ++++-- plugins/elements/gstsinesrc.h | 6 +- 11 files changed, 1036 insertions(+), 34 deletions(-) create mode 100644 gst/gstdparam.c create mode 100644 gst/gstdparam.h create mode 100644 gst/gstdparammanager.c create mode 100644 gst/gstdparammanager.h diff --git a/gst/Makefile.am b/gst/Makefile.am index 08c2a81..39cdcee 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -65,6 +65,8 @@ libgst_la_SOURCES = \ gstcaps.c \ gstclock.c \ gstcpu.c \ + gstdparam.c \ + gstdparammanager.c \ gstelement.c \ gstelementfactory.c \ gstextratypes.c \ @@ -165,6 +167,8 @@ libgstinclude_HEADERS = \ gstcaps.h \ gstclock.h \ gstcpu.h \ + gstdparam.h \ + gstdparammanager.h \ gstelement.h \ gstevent.h \ gstextratypes.h \ diff --git a/gst/elements/gstsinesrc.c b/gst/elements/gstsinesrc.c index 83d340e..e10db30 100644 --- a/gst/elements/gstsinesrc.c +++ b/gst/elements/gstsinesrc.c @@ -85,6 +85,8 @@ static void gst_sinesrc_get_property (GObject *object, guint prop_id, //static void gst_sinesrc_close_audio(GstSineSrc *src); //static gboolean gst_sinesrc_open_audio(GstSineSrc *src); +static void gst_sinesrc_update_volume(GValue *value, gpointer data); +static void gst_sinesrc_update_freq(GValue *value, gpointer data); static void gst_sinesrc_populate_sinetable (GstSineSrc *src); static inline void gst_sinesrc_update_table_inc (GstSineSrc *src); static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src); @@ -156,6 +158,9 @@ gst_sinesrc_class_init (GstSineSrcClass *klass) static void gst_sinesrc_init (GstSineSrc *src) { + GstElement *element = GST_ELEMENT(src); + GstDparamManager *dpman; + src->srcpad = gst_pad_new_from_template ( GST_PADTEMPLATE_GET (sinesrc_src_factory), "src"); gst_element_add_pad(GST_ELEMENT(src), src->srcpad); @@ -163,21 +168,30 @@ gst_sinesrc_init (GstSineSrc *src) gst_pad_set_get_function(src->srcpad, gst_sinesrc_get); - src->volume = 1.0; - gst_sinesrc_update_vol_scale(src); - src->format = 16; src->samplerate = 44100; - src->freq = 440.0; + src->newcaps = TRUE; src->table_pos = 0.0; src->table_size = 1024; - gst_sinesrc_populate_sinetable(src); - gst_sinesrc_update_table_inc(src); src->buffer_size=1024; src->seq = 0; + + dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src)); + gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src); + gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src); + + gst_dpman_set_rate_change_pad(dpman, src->srcpad); + + GST_ELEMENT_DPARAM_MANAGER(element) = dpman; + + gst_sinesrc_update_vol_scale(src); + + gst_sinesrc_populate_sinetable(src); + gst_sinesrc_update_table_inc(src); + } static GstPadNegotiateReturn @@ -201,8 +215,10 @@ gst_sinesrc_get(GstPad *pad) { GstSineSrc *src; GstBuffer *buf; + GstDparamManager *dpman; + gint16 *samples; - gint i; + gint i=0, frame_countdown; g_return_val_if_fail (pad != NULL, NULL); src = GST_SINESRC(gst_pad_get_parent (pad)); @@ -213,7 +229,10 @@ gst_sinesrc_get(GstPad *pad) GST_BUFFER_DATA(buf) = (gpointer) samples; GST_BUFFER_SIZE(buf) = 2 * src->buffer_size; - for (i=0 ; i < src->buffer_size; i++) { + dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src)); + frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL); + + while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) { src->table_lookup = (gint)(src->table_pos); src->table_lookup_next = src->table_lookup + 1; src->table_interp = src->table_pos - src->table_lookup; @@ -234,7 +253,7 @@ gst_sinesrc_get(GstPad *pad) // * src->vol_scale; //linear interpolation - samples[i] = ((src->table_interp + samples[i++] = ((src->table_interp *(src->table_data[src->table_lookup_next] -src->table_data[src->table_lookup] ) @@ -260,7 +279,7 @@ gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, G switch (prop_id) { case ARG_VOLUME: - src->volume = g_value_get_double (value); + src->volume = (gfloat)g_value_get_double (value); gst_sinesrc_update_vol_scale(src); break; case ARG_FORMAT: @@ -275,7 +294,7 @@ gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, G case ARG_FREQ: { if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2) break; - src->freq = g_value_get_double (value); + src->freq = (gfloat)g_value_get_double (value); gst_sinesrc_update_table_inc(src); break; case ARG_TABLESIZE: @@ -303,7 +322,7 @@ gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS switch (prop_id) { case ARG_VOLUME: - g_value_set_double (value, src->volume); + g_value_set_double (value, (gdouble)(src->volume)); break; case ARG_FORMAT: g_value_set_int (value, src->format); @@ -312,7 +331,7 @@ gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS g_value_set_int (value, src->samplerate); break; case ARG_FREQ: - g_value_set_double (value, src->freq); + g_value_set_double (value, (gdouble)(src->freq)); break; case ARG_TABLESIZE: g_value_set_int (value, src->table_size); @@ -364,6 +383,26 @@ gst_sinesrc_populate_sinetable (GstSineSrc *src) src->table_data = table; } +static void +gst_sinesrc_update_volume(GValue *value, gpointer data) +{ + GstSineSrc *src = (GstSineSrc*)data; + g_return_if_fail(GST_IS_SINESRC(src)); + + src->volume = g_value_get_float(value); + src->vol_scale = 32767.0 * src->volume; +} + +static void +gst_sinesrc_update_freq(GValue *value, gpointer data) +{ + GstSineSrc *src = (GstSineSrc*)data; + g_return_if_fail(GST_IS_SINESRC(src)); + + src->freq = g_value_get_float(value); + src->table_inc = src->table_size * src->freq / src->samplerate; +} + static inline void gst_sinesrc_update_table_inc (GstSineSrc *src) { @@ -373,7 +412,7 @@ gst_sinesrc_update_table_inc (GstSineSrc *src) static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src) { - src->vol_scale = 32767 * src->volume; + src->vol_scale = 32767.0 * src->volume; } static void diff --git a/gst/elements/gstsinesrc.h b/gst/elements/gstsinesrc.h index 390d12b..58e03fd 100644 --- a/gst/elements/gstsinesrc.h +++ b/gst/elements/gstsinesrc.h @@ -57,9 +57,9 @@ struct _GstSineSrc { GstPad *srcpad; /* parameters */ - gdouble volume; - gdouble vol_scale; - gdouble freq; + gfloat volume; + gfloat freq; + gfloat vol_scale; /* lookup table data */ gfloat *table_data; diff --git a/gst/gst.h b/gst/gst.h index 2addc92..948e25a 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include #include diff --git a/gst/gstdparam.c b/gst/gstdparam.c new file mode 100644 index 0000000..8f14555 --- /dev/null +++ b/gst/gstdparam.c @@ -0,0 +1,190 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparam.c: Dynamic Parameter functionality + * + * 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. + */ + +#include "gst_private.h" + +#include "gstdparam.h" + +static void gst_dparam_class_init (GstDparamClass *klass); +static void gst_dparam_base_class_init (GstDparamClass *klass); +static void gst_dparam_init (GstDparam *dparam); + +static void gst_dparam_do_update_realtime (GstDparam *dparam, gint64 timestamp); +static GstDparamPoint* gst_dparam_get_point_realtime (GstDparam *dparam, gint64 timestamp); + +GType +gst_dparam_get_type(void) { + static GType dparam_type = 0; + + if (!dparam_type) { + static const GTypeInfo dparam_info = { + sizeof(GstDparamClass), + (GBaseInitFunc)gst_dparam_base_class_init, + NULL, + (GClassInitFunc)gst_dparam_class_init, + NULL, + NULL, + sizeof(GstDparam), + 0, + (GInstanceInitFunc)gst_dparam_init, + }; + dparam_type = g_type_register_static(GST_TYPE_OBJECT, "GstDparam", &dparam_info, 0); + } + return dparam_type; +} + +static void +gst_dparam_base_class_init (GstDparamClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass*) klass; + +} + +static void +gst_dparam_class_init (GstDparamClass *klass) +{ + GObjectClass *gobject_class; + GstDparamClass *dparam_class; + GstObjectClass *gstobject_class; + + gobject_class = (GObjectClass*)klass; + dparam_class = (GstDparamClass*)klass; + gstobject_class = (GstObjectClass*) klass; + + //gstobject_class->save_thyself = gst_dparam_save_thyself; + +} + +static void +gst_dparam_init (GstDparam *dparam) +{ + g_return_if_fail (dparam != NULL); + GST_DPARAM_VALUE(dparam) = NULL; + dparam->lock = g_mutex_new (); +} + +/** + * gst_dparam_new: + * + * Returns: a new instance of GstDparam + */ +GstDparam* +gst_dparam_new () +{ + GstDparam *dparam; + + dparam = g_object_new (gst_dparam_get_type (), NULL); + dparam->do_update_func = gst_dparam_do_update_realtime; + dparam->get_point_func = gst_dparam_get_point_realtime; + + dparam->point = gst_dparam_new_point(0LL, G_TYPE_NONE, 0); + + return dparam; +} + +/** + * gst_dparam_set_parent + * @dparam: GstDparam instance + * @parent: the GstDparamManager that this dparam belongs to + * + */ +void +gst_dparam_set_parent (GstDparam *dparam, GstObject *parent) +{ + g_return_if_fail (dparam != NULL); + g_return_if_fail (GST_IS_DPARAM (dparam)); + g_return_if_fail (GST_DPARAM_PARENT (dparam) == NULL); + g_return_if_fail (parent != NULL); + g_return_if_fail (G_IS_OBJECT (parent)); + g_return_if_fail ((gpointer)dparam != (gpointer)parent); + + gst_object_set_parent (GST_OBJECT (dparam), parent); +} + +/** + * gst_dparam_new_point + * @timestamp: timestamp where this point will be placed (or 0LL if not relavent) + * @type: the type of the first GValue in the point + * @...: the type of other GValues in the point + * + * The list of types should be terminated with a 0. + * If the type of a value is not yet known then use G_TYPE_NONE . + * + * Returns: an newly created point containing an array of GValues + */ +GstDparamPoint* +gst_dparam_new_point(gint64 timestamp, GType type, ...) +{ + GstDparamPoint *point; + GValue *value; + guint x; + gint values_length = 0; + va_list var_args; + + va_start (var_args, type); + while (type){ + values_length++; + type = va_arg (var_args, GType); + } + va_end (var_args); + + point = g_new0(GstDparamPoint,1); + point->values = g_new0(GValue*,values_length + 1); + point->timestamp = timestamp; + + va_start (var_args, type); + for (x=0 ; x < values_length ; x++){ + value = g_new0(GValue,1); + if (type != G_TYPE_NONE){ + g_value_init(value, type); + } + point->values[x] = value; + type = va_arg (var_args, GType); + } + point->values[values_length] = NULL; + va_end (var_args); + + GST_DEBUG(GST_CAT_PARAMS, "point with %d values created\n", values_length); + + return point; +} + +static void +gst_dparam_do_update_realtime (GstDparam *dparam, gint64 timestamp) +{ + GST_DEBUG(GST_CAT_PARAMS, "updating point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam); + + GST_DPARAM_LOCK(dparam); + GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; + g_value_copy(dparam->point->values[0], GST_DPARAM_VALUE(dparam)); + GST_DPARAM_UNLOCK(dparam); +} + +static GstDparamPoint* +gst_dparam_get_point_realtime (GstDparam *dparam, gint64 timestamp) +{ + GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam); + return dparam->point; +} + + diff --git a/gst/gstdparam.h b/gst/gstdparam.h new file mode 100644 index 0000000..f19fc4f --- /dev/null +++ b/gst/gstdparam.h @@ -0,0 +1,128 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparam.h: Dynamic Parameter functionality + * + * 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_DPARAM_H__ +#define __GST_DPARAM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GST_TYPE_DPARAM (gst_dparam_get_type ()) +#define GST_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPARAM,GstDparam)) +#define GST_DPARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPARAM,GstDparam)) +#define GST_IS_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPARAM)) +#define GST_IS_DPARAM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPARAM)) + +#define GST_DPARAM_NAME(dparam) (GST_OBJECT_NAME(dparam)) +#define GST_DPARAM_PARENT(dparam) (GST_OBJECT_PARENT(dparam)) +#define GST_DPARAM_VALUE(dparam) ((dparam)->value) + +#define GST_DPARAM_LOCK(dparam) (g_mutex_lock((dparam)->lock)) +#define GST_DPARAM_UNLOCK(dparam) (g_mutex_unlock((dparam)->lock)) + +#define GST_DPARAM_READY_FOR_UPDATE(dparam) ((dparam)->ready_for_update) +#define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) ((dparam)->next_update_timestamp) + +#define GST_DPARAM_GET_POINT(dparam, timestamp) \ + ((dparam->get_point_func)(dparam, timestamp)) + +#define GST_DPARAM_FIND_POINT(dparam, timestamp, search_flag) \ + ((dparam->find_point_func)(dparam, data, search_flag)) + +#define GST_DPARAM_DO_UPDATE(dparam, timestamp) \ + ((dparam->do_update_func)(dparam, timestamp)) + +#define GST_DPARAM_INSERT_POINT(dparam, timestamp) \ + ((dparam->insert_point_func)(dparam, timestamp)) + +#define GST_DPARAM_REMOVE_POINT(dparam, data) \ + ((dparam->remove_point_func)(dparam, data)) + +typedef enum { + GST_DPARAM_CLOSEST, + GST_DPARAM_CLOSEST_AFTER, + GST_DPARAM_CLOSEST_BEFORE, + GST_DPARAM_EXACT, +} GstDparamSearchFlag; + +typedef enum { + GST_DPARAM_NOT_FOUND = 0, + GST_DPARAM_FOUND_EXACT, + GST_DPARAM_FOUND_CLOSEST, +} GstDparamSearchResult; + +typedef struct _GstDparam GstDparam; +typedef struct _GstDparamClass GstDparamClass; +typedef struct _GstDparamModel GstDparamModel; +typedef struct _GstDparamPoint GstDparamPoint; + +typedef GstDparamPoint* (*GstDparamInsertPointFunction) (GstDparam *dparam, guint64 timestamp); +typedef void (*GstDparamRemovePointFunction) (GstDparam *dparam, GstDparamPoint* point); +typedef GstDparamPoint* (*GstDparamGetPointFunction) (GstDparam *dparam, gint64 timestamp); +typedef GstDparamSearchResult (*GstDparamFindPointFunction) (GstDparam *dparam, gint64 *timestamp, GstDparamSearchFlag search_flag); + +typedef void (*GstDparamDoUpdateFunction) (GstDparam *dparam, gint64 timestamp); + +struct _GstDparam { + GstObject object; + + GstDparamGetPointFunction get_point_func; + GstDparamFindPointFunction find_point_func; + + GstDparamDoUpdateFunction do_update_func; + + GstDparamInsertPointFunction insert_point_func; + GstDparamRemovePointFunction remove_point_func; + + GMutex *lock; + GValue *value; + GstDparamPoint *point; + gint64 next_update_timestamp; + gboolean ready_for_update; + +}; + +struct _GstDparamClass { + GstObjectClass parent_class; + + /* signal callbacks */ +}; + +struct _GstDparamPoint { + GValue **values; + gint64 timestamp; +}; + + +GType gst_dparam_get_type (void); +GstDparam* gst_dparam_new (); +void gst_dparam_set_parent (GstDparam *dparam, GstObject *parent); +GstDparamPoint* gst_dparam_new_point(gint64 timestamp, GType type, ...); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_DPARAM_H__ */ diff --git a/gst/gstdparammanager.c b/gst/gstdparammanager.c new file mode 100644 index 0000000..0c74e30 --- /dev/null +++ b/gst/gstdparammanager.c @@ -0,0 +1,459 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparammanager.c: Dynamic Parameter group functionality + * + * 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. + */ + +#include "gst_private.h" + +#include "gstdparammanager.h" +#include + + +static void gst_dpman_base_class_init (GstDparamManagerClass *klass); +static void gst_dpman_class_init (GstDparamManagerClass *klass); +static void gst_dpman_init (GstDparamManager *dpman); +static void gst_dpman_state_change (GstElement *element, gint state, GstDparamManager *dpman); +static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDparamManager *dpman); +static guint gst_dpman_first_countdown_synchronous(GstDparamManager *dpman, guint frames, gint64 timestamp); +static guint gst_dpman_first_countdown_noop(GstDparamManager *dpman, guint frames, gint64 timestamp); +static guint gst_dpman_countdown_noop(GstDparamManager *dpman, guint frame_count); + +GType +gst_dpman_get_type (void) +{ + static GType dpman_type = 0; + + if (!dpman_type) { + static const GTypeInfo dpman_info = { + sizeof(GstDparamManagerClass), + (GBaseInitFunc)gst_dpman_base_class_init, + NULL, + (GClassInitFunc)gst_dpman_class_init, + NULL, + NULL, + sizeof(GstDparamManager), + 0, + (GInstanceInitFunc)gst_dpman_init, + }; + dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDparamManager", &dpman_info, 0); + } + return dpman_type; +} + +static void +gst_dpman_base_class_init (GstDparamManagerClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass*) klass; + +} + +static void +gst_dpman_class_init (GstDparamManagerClass *klass) +{ + GstObjectClass *gstobject_class; + GObjectClass *gobject_class; + + gstobject_class = (GstObjectClass*) klass; + gobject_class = (GObjectClass*) klass; + + klass->modes = g_hash_table_new(g_str_hash,g_str_equal); + + gst_dpman_register_mode (klass, "synchronous", + gst_dpman_first_countdown_synchronous, gst_dpman_countdown_noop, NULL, NULL); + gst_dpman_register_mode (klass, "asynchronous", + gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL); + gst_dpman_register_mode (klass, "disabled", + gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL); + +} + +static void +gst_dpman_init (GstDparamManager *dpman) +{ + GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal); + GST_DPMAN_DPARAMS_LIST(dpman) = NULL; + GST_DPMAN_NAME(dpman) = NULL; + GST_DPMAN_PARENT(dpman) = NULL; + GST_DPMAN_MODE_NAME(dpman) = NULL; + GST_DPMAN_MODE(dpman) = NULL; + GST_DPMAN_MODE_DATA(dpman) = NULL; + GST_DPMAN_RATE(dpman) = 0; +} + +/** + * gst_dpman_new: + * @name: name of the GstDparamManager instance + * @parent: element which created this instance + * + * Returns: a new instance of GstDparamManager + */ +GstDparamManager* +gst_dpman_new (gchar *name, GstElement *parent) +{ + GstDparamManager *dpman; + + g_return_val_if_fail (name != NULL, NULL); + + dpman = gtk_type_new (gst_dpman_get_type ()); + gst_object_set_name (GST_OBJECT (dpman), name); + gst_dpman_set_parent(dpman, parent); + + gst_dpman_set_mode(dpman, "disabled"); + + return dpman; +} + +/** + * gst_dpman_add_required_dparam: + * @dpman: GstDparamManager instance + * @dparam_name: a parameter name unique to this GstDparamManager + * @type: the GValue type that this parameter will store + * @update_func: callback to update the element with the new value + * @update_data: will be included in the call to update_func + * + * Returns: true if it was successfully added + */ +gboolean +gst_dpman_add_required_dparam (GstDparamManager *dpman, + gchar *dparam_name, + GType type, + GstDpmUpdateFunction update_func, + gpointer update_data) +{ + GstDparamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (dparam_name != NULL, FALSE); + g_return_val_if_fail (update_func != NULL, FALSE); + + g_return_val_if_fail(g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name) == NULL, FALSE); + + GST_DEBUG(GST_CAT_PARAMS,"adding required dparam: %s\n", dparam_name); + + dpwrap = g_new0(GstDparamWrapper,1); + dpwrap->dparam_name = dparam_name; + dpwrap->update_func = update_func; + dpwrap->update_data = update_data; + dpwrap->value = g_new0(GValue,1); + g_value_init(dpwrap->value, type); + + g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap); + GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap); + + return TRUE; +} + +/** + * gst_dpman_remove_required_dparam: + * @dpman: GstDparamManager instance + * @dparam_name: the name of an existing parameter + * + */ +void +gst_dpman_remove_required_dparam (GstDparamManager *dpman, gchar *dparam_name) +{ + GstDparamWrapper* dpwrap; + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (dparam_name != NULL); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name); + + g_return_if_fail(dpwrap != NULL); + g_return_if_fail(dpwrap->dparam == NULL); + + GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s\n", dparam_name); + + g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name); + GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap); + + g_free(dpwrap->value); + g_free(dpwrap); +} + +/** + * gst_dpman_attach_dparam: + * @dpman: GstDparamManager instance + * @dparam_name: a name previously added with gst_dpman_add_required_dparam + * @dparam: GstDparam instance to attach + * + * Returns: true if it was successfully attached + */ +gboolean +gst_dpman_attach_dparam (GstDparamManager *dpman, gchar *dparam_name, GstDparam *dparam) +{ + GstDparamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (dparam_name != NULL, FALSE); + g_return_val_if_fail (dparam != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE); + g_return_val_if_fail (dparam != NULL, FALSE); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name); + + g_return_val_if_fail(dpwrap != NULL, FALSE); + g_return_val_if_fail(dpwrap->value != NULL, FALSE); + + GST_DPARAM_VALUE(dparam) = dpwrap->value; + dpwrap->dparam = dparam; + gst_dparam_set_parent (dparam, GST_OBJECT(dpman)); + GST_DPARAM_NAME(dparam) = dparam_name; + + return TRUE; +} + +/** + * gst_dpman_dettach_dparam: + * @dpman: GstDparamManager instance + * @dparam_name: the name of a parameter with a previously attached GstDparam + * + */ +void +gst_dpman_dettach_dparam (GstDparamManager *dpman, gchar *dparam_name) +{ + GstDparamWrapper* dpwrap; + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (dparam_name != NULL); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name); + + g_return_if_fail(dpwrap); + + GST_DPARAM_VALUE(dpwrap->dparam) = NULL; + GST_DPARAM_NAME(dpwrap->dparam) = NULL; + gst_object_unparent (GST_OBJECT(dpwrap->dparam)); + + dpwrap->dparam = NULL; + +} + +/** + * gst_dpman_get_dparam: + * @dpman: GstDparamManager instance + * @name: the name of an existing dparam instance + * + * Returns: the dparam with the given name - or NULL otherwise + */ +GstDparam * +gst_dpman_get_dparam (GstDparamManager *dpman, gchar *name) +{ + GstDparamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + g_return_val_if_fail (name != NULL, NULL); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name); + g_return_val_if_fail (dpwrap != NULL, NULL); + + return dpwrap->dparam; +} + +/** + * gst_dpman_register_mode + * @klass: GstDparamManagerClass class instance + * @modename: the unique name of the new mode + * @firstcountdownfunc: the function which will be called before each buffer is processed + * @countdownfunc: the function which may be called throughout the processing of a buffer + * @setupfunc: the function which initialises the mode when activated + * @teardownfunc: the function which frees any resources the mode uses + * + */ +void +gst_dpman_register_mode (GstDparamManagerClass *klass, + gchar *modename, + GstDpmModeFirstCountdownFunction firstcountdownfunc, + GstDpmModeCountdownFunction countdownfunc, + GstDpmModeSetupFunction setupfunc, + GstDpmModeTeardownFunction teardownfunc) +{ + GstDpmMode *mode; + + g_return_if_fail (klass != NULL); + g_return_if_fail (modename != NULL); + g_return_if_fail (GST_IS_DPMAN_CLASS (klass)); + + mode = g_new0(GstDpmMode,1); + + mode->firstcountdownfunc = firstcountdownfunc; + mode->countdownfunc = countdownfunc; + mode->setupfunc = setupfunc; + mode->teardownfunc = teardownfunc; + + g_hash_table_insert(klass->modes, modename, mode); + GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered\n", modename); +} + +/** + * gst_dpman_set_mode + * @dpman: GstDparamManager instance + * @modename: the name of the mode to use + * + * Returns: TRUE if the mode was set, FALSE otherwise + */ +gboolean +gst_dpman_set_mode(GstDparamManager *dpman, gchar *modename) +{ + GstDpmMode *mode=NULL; + GstDparamManagerClass *oclass; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (modename != NULL, FALSE); + + oclass = (GstDparamManagerClass*)(G_OBJECT_GET_CLASS(dpman)); + + mode = g_hash_table_lookup(oclass->modes, modename); + g_return_val_if_fail (mode != NULL, FALSE); + GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename); + if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){ + GST_DPMAN_TEARDOWNFUNC(dpman)(dpman); + } + + GST_DPMAN_MODE(dpman) = mode; + + if (GST_DPMAN_SETUPFUNC(dpman)){ + GST_DPMAN_SETUPFUNC(dpman)(dpman); + } + + return TRUE; +} + +/** + * gst_dpman_set_parent + * @dpman: GstDparamManager instance + * @parent: the element that this GstDparamManager belongs to + * + */ +void +gst_dpman_set_parent (GstDparamManager *dpman, GstElement *parent) +{ + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (parent != NULL); + g_return_if_fail (GST_IS_ELEMENT (parent)); + + gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent)); + g_signal_connect(G_OBJECT(parent), "state_change", + G_CALLBACK (gst_dpman_state_change), dpman); +} + +/** + * gst_dpman_set_rate_change_pad + * @dpman: GstDparamManager instance + * @pad: the pad which may have a "rate" caps property + * + */ +void +gst_dpman_set_rate_change_pad(GstDparamManager *dpman, GstPad *pad) +{ + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + + g_signal_connect(G_OBJECT(pad), "caps_changed", + G_CALLBACK (gst_dpman_caps_changed), dpman); +} + +static void +gst_dpman_state_change (GstElement *element, gint state, GstDparamManager *dpman) +{ + GSList *dwraps; + GstDparam *dparam; + GstDparamWrapper *dpwrap; + + if (state == GST_STATE_PLAYING) return; + GST_DEBUG(GST_CAT_PARAMS, "initialising params\n"); + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + + // force all params to be updated + dwraps = GST_DPMAN_DPARAMS_LIST(dpman); + while (dwraps){ + dpwrap = (GstDparamWrapper*)dwraps->data; + dparam = dpwrap->dparam; + + if (dparam){ + GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + } + dwraps = g_slist_next(dwraps); + } +} + +static void +gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDparamManager *dpman) +{ + g_return_if_fail (caps != NULL); + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + + GST_DPMAN_RATE(dpman) = gst_caps_get_int (caps, "rate"); + + GST_DEBUG(GST_CAT_PARAMS, "got caps change %d\n", GST_DPMAN_RATE(dpman)); +} + +static guint +gst_dpman_first_countdown_synchronous(GstDparamManager *dpman, guint frames, gint64 timestamp) +{ + GSList *dwraps; + GstDparam *dparam; + GstDparamWrapper *dpwrap; + + g_return_val_if_fail (dpman != NULL, frames); + g_return_val_if_fail (GST_IS_DPMAN (dpman), frames); + + // now check whether any passive dparams are ready for an update + dwraps = GST_DPMAN_DPARAMS_LIST(dpman); + while (dwraps){ + dpwrap = (GstDparamWrapper*)dwraps->data; + dparam = dpwrap->dparam; + + if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) || + (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) < timestamp))){ + GST_DPARAM_DO_UPDATE(dparam, timestamp); + GST_DPMAN_DO_UPDATE(dpwrap); + } + dwraps = g_slist_next(dwraps); + } + + return frames; +} + +static guint +gst_dpman_first_countdown_noop(GstDparamManager *dpman, guint frames, gint64 timestamp) +{ + return frames; +} + +static guint +gst_dpman_countdown_noop(GstDparamManager *dpman, guint frame_count) +{ + return 0; +} + diff --git a/gst/gstdparammanager.h b/gst/gstdparammanager.h new file mode 100644 index 0000000..25091c3 --- /dev/null +++ b/gst/gstdparammanager.h @@ -0,0 +1,138 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparammanager.h: Dynamic Parameter group functionality + * + * 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_DPMAN_H__ +#define __GST_DPMAN_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GST_TYPE_DPMAN (gst_dpman_get_type ()) +#define GST_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPMAN,GstDparamManager)) +#define GST_DPMAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPMAN,GstDparamManager)) +#define GST_IS_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPMAN)) +#define GST_IS_DPMAN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPMAN)) + +#define GST_DPMAN_NAME(dpman) (GST_OBJECT_NAME(dpman)) +#define GST_DPMAN_PARENT(dpman) (GST_OBJECT_PARENT(dpman)) +#define GST_DPMAN_DPARAMS(dpman) ((dpman)->dparams) +#define GST_DPMAN_DPARAMS_LIST(dpman) ((dpman)->dparams_list) + +#define GST_DPMAN_MODE_NAME(dpman) ((dpman)->mode_name) +#define GST_DPMAN_MODE(dpman) ((dpman)->mode) +#define GST_DPMAN_MODE_DATA(dpman) ((dpman)->mode_data) +#define GST_DPMAN_RATE(dpman) ((dpman)->rate) + +typedef struct _GstDparamManager GstDparamManager; +typedef struct _GstDparamManagerClass GstDparamManagerClass; +typedef struct _GstDpmMode GstDpmMode; +typedef struct _GstDparamWrapper GstDparamWrapper; + +typedef guint (*GstDpmModeFirstCountdownFunction) (GstDparamManager *dpman, guint frames, gint64 timestamp); +typedef guint (*GstDpmModeCountdownFunction) (GstDparamManager *dpman, guint frame_count); +typedef void (*GstDpmModeSetupFunction) (GstDparamManager *dpman); +typedef void (*GstDpmModeTeardownFunction) (GstDparamManager *dpman); + +typedef void (*GstDpmUpdateFunction) (GValue *value, gpointer data); + +struct _GstDparamManager { + GstObject object; + + GHashTable *dparams; + GSList *dparams_list; + + gchar *mode_name; + GstDpmMode* mode; + gpointer mode_data; + + gint64 timestamp; + guint rate; +}; + +struct _GstDparamManagerClass { + GstObjectClass parent_class; + + GHashTable *modes; + /* signal callbacks */ +}; + +struct _GstDpmMode { + GstDpmModeFirstCountdownFunction firstcountdownfunc; + GstDpmModeCountdownFunction countdownfunc; + GstDpmModeSetupFunction setupfunc; + GstDpmModeTeardownFunction teardownfunc; +}; + +struct _GstDparamWrapper { + gchar *dparam_name; + GValue *value; + GstDparam *dparam; + GstDpmUpdateFunction update_func; + gpointer update_data; +}; + +#define GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman) (((dpman)->mode)->firstcountdownfunc) +#define GST_DPMAN_COUNTDOWNFUNC(dpman) (((dpman)->mode)->countdownfunc) +#define GST_DPMAN_SETUPFUNC(dpman) (((dpman)->mode)->setupfunc) +#define GST_DPMAN_TEARDOWNFUNC(dpman) (((dpman)->mode)->teardownfunc) + +#define GST_DPMAN_FIRST_COUNTDOWN(dpman, buffer_size, timestamp) \ + (GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman)(dpman, buffer_size, timestamp)) + +#define GST_DPMAN_COUNTDOWN(dpman, frame_countdown, frame_count) \ + (frame_countdown-- || \ + (frame_countdown = GST_DPMAN_COUNTDOWNFUNC(dpman)(dpman, frame_count))) + +#define GST_DPMAN_DO_UPDATE(dpwrap) ((dpwrap->update_func)(dpwrap->value, dpwrap->update_data)) + +GType gst_dpman_get_type (void); +GstDparamManager* gst_dpman_new (gchar *name, GstElement *parent); +void gst_dpman_set_parent (GstDparamManager *dpman, GstElement *parent); + +gboolean gst_dpman_add_required_dparam (GstDparamManager *dpman, + gchar *dparam_name, + GType type, + GstDpmUpdateFunction update_func, + gpointer update_data); +void gst_dpman_remove_required_dparam (GstDparamManager *dpman, gchar *dparam_name); +gboolean gst_dpman_attach_dparam (GstDparamManager *dpman, gchar *dparam_name, GstDparam *dparam); +void gst_dpman_dettach_dparam (GstDparamManager *dpman, gchar *dparam_name); +GstDparam* gst_dpman_get_dparam(GstDparamManager *dpman, gchar *name); + +void gst_dpman_set_rate_change_pad(GstDparamManager *dpman, GstPad *pad); + +gboolean gst_dpman_set_mode(GstDparamManager *dpman, gchar *modename); +void gst_dpman_register_mode (GstDparamManagerClass *klass, + gchar *modename, + GstDpmModeFirstCountdownFunction firstcountdownfunc, + GstDpmModeCountdownFunction countdownfunc, + GstDpmModeSetupFunction setupfunc, + GstDpmModeTeardownFunction teardownfunc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_DPMAN_H__ */ diff --git a/gst/gstelement.h b/gst/gstelement.h index 945ab35..41a7cbf 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -123,6 +124,7 @@ typedef enum { #define GST_ELEMENT_MANAGER(obj) (((GstElement*)(obj))->manager) #define GST_ELEMENT_SCHED(obj) (((GstElement*)(obj))->sched) #define GST_ELEMENT_PADS(obj) ((obj)->pads) +#define GST_ELEMENT_DPARAM_MANAGER(obj) ((obj)->dpman) //typedef struct _GstElement GstElement; //typedef struct _GstElementClass GstElementClass; @@ -148,6 +150,7 @@ struct _GstElement { GstElement *manager; GstSchedule *sched; + GstDparamManager *dpman; }; struct _GstElementClass { diff --git a/plugins/elements/gstsinesrc.c b/plugins/elements/gstsinesrc.c index 83d340e..e10db30 100644 --- a/plugins/elements/gstsinesrc.c +++ b/plugins/elements/gstsinesrc.c @@ -85,6 +85,8 @@ static void gst_sinesrc_get_property (GObject *object, guint prop_id, //static void gst_sinesrc_close_audio(GstSineSrc *src); //static gboolean gst_sinesrc_open_audio(GstSineSrc *src); +static void gst_sinesrc_update_volume(GValue *value, gpointer data); +static void gst_sinesrc_update_freq(GValue *value, gpointer data); static void gst_sinesrc_populate_sinetable (GstSineSrc *src); static inline void gst_sinesrc_update_table_inc (GstSineSrc *src); static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src); @@ -156,6 +158,9 @@ gst_sinesrc_class_init (GstSineSrcClass *klass) static void gst_sinesrc_init (GstSineSrc *src) { + GstElement *element = GST_ELEMENT(src); + GstDparamManager *dpman; + src->srcpad = gst_pad_new_from_template ( GST_PADTEMPLATE_GET (sinesrc_src_factory), "src"); gst_element_add_pad(GST_ELEMENT(src), src->srcpad); @@ -163,21 +168,30 @@ gst_sinesrc_init (GstSineSrc *src) gst_pad_set_get_function(src->srcpad, gst_sinesrc_get); - src->volume = 1.0; - gst_sinesrc_update_vol_scale(src); - src->format = 16; src->samplerate = 44100; - src->freq = 440.0; + src->newcaps = TRUE; src->table_pos = 0.0; src->table_size = 1024; - gst_sinesrc_populate_sinetable(src); - gst_sinesrc_update_table_inc(src); src->buffer_size=1024; src->seq = 0; + + dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src)); + gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src); + gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src); + + gst_dpman_set_rate_change_pad(dpman, src->srcpad); + + GST_ELEMENT_DPARAM_MANAGER(element) = dpman; + + gst_sinesrc_update_vol_scale(src); + + gst_sinesrc_populate_sinetable(src); + gst_sinesrc_update_table_inc(src); + } static GstPadNegotiateReturn @@ -201,8 +215,10 @@ gst_sinesrc_get(GstPad *pad) { GstSineSrc *src; GstBuffer *buf; + GstDparamManager *dpman; + gint16 *samples; - gint i; + gint i=0, frame_countdown; g_return_val_if_fail (pad != NULL, NULL); src = GST_SINESRC(gst_pad_get_parent (pad)); @@ -213,7 +229,10 @@ gst_sinesrc_get(GstPad *pad) GST_BUFFER_DATA(buf) = (gpointer) samples; GST_BUFFER_SIZE(buf) = 2 * src->buffer_size; - for (i=0 ; i < src->buffer_size; i++) { + dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src)); + frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL); + + while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) { src->table_lookup = (gint)(src->table_pos); src->table_lookup_next = src->table_lookup + 1; src->table_interp = src->table_pos - src->table_lookup; @@ -234,7 +253,7 @@ gst_sinesrc_get(GstPad *pad) // * src->vol_scale; //linear interpolation - samples[i] = ((src->table_interp + samples[i++] = ((src->table_interp *(src->table_data[src->table_lookup_next] -src->table_data[src->table_lookup] ) @@ -260,7 +279,7 @@ gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, G switch (prop_id) { case ARG_VOLUME: - src->volume = g_value_get_double (value); + src->volume = (gfloat)g_value_get_double (value); gst_sinesrc_update_vol_scale(src); break; case ARG_FORMAT: @@ -275,7 +294,7 @@ gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, G case ARG_FREQ: { if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2) break; - src->freq = g_value_get_double (value); + src->freq = (gfloat)g_value_get_double (value); gst_sinesrc_update_table_inc(src); break; case ARG_TABLESIZE: @@ -303,7 +322,7 @@ gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS switch (prop_id) { case ARG_VOLUME: - g_value_set_double (value, src->volume); + g_value_set_double (value, (gdouble)(src->volume)); break; case ARG_FORMAT: g_value_set_int (value, src->format); @@ -312,7 +331,7 @@ gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS g_value_set_int (value, src->samplerate); break; case ARG_FREQ: - g_value_set_double (value, src->freq); + g_value_set_double (value, (gdouble)(src->freq)); break; case ARG_TABLESIZE: g_value_set_int (value, src->table_size); @@ -364,6 +383,26 @@ gst_sinesrc_populate_sinetable (GstSineSrc *src) src->table_data = table; } +static void +gst_sinesrc_update_volume(GValue *value, gpointer data) +{ + GstSineSrc *src = (GstSineSrc*)data; + g_return_if_fail(GST_IS_SINESRC(src)); + + src->volume = g_value_get_float(value); + src->vol_scale = 32767.0 * src->volume; +} + +static void +gst_sinesrc_update_freq(GValue *value, gpointer data) +{ + GstSineSrc *src = (GstSineSrc*)data; + g_return_if_fail(GST_IS_SINESRC(src)); + + src->freq = g_value_get_float(value); + src->table_inc = src->table_size * src->freq / src->samplerate; +} + static inline void gst_sinesrc_update_table_inc (GstSineSrc *src) { @@ -373,7 +412,7 @@ gst_sinesrc_update_table_inc (GstSineSrc *src) static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src) { - src->vol_scale = 32767 * src->volume; + src->vol_scale = 32767.0 * src->volume; } static void diff --git a/plugins/elements/gstsinesrc.h b/plugins/elements/gstsinesrc.h index 390d12b..58e03fd 100644 --- a/plugins/elements/gstsinesrc.h +++ b/plugins/elements/gstsinesrc.h @@ -57,9 +57,9 @@ struct _GstSineSrc { GstPad *srcpad; /* parameters */ - gdouble volume; - gdouble vol_scale; - gdouble freq; + gfloat volume; + gfloat freq; + gfloat vol_scale; /* lookup table data */ gfloat *table_data; -- 2.7.4