dparams have arrived. see previous mail for an intro
authorSteve Baker <steve@stevebaker.org>
Mon, 10 Sep 2001 16:28:43 +0000 (16:28 +0000)
committerSteve Baker <steve@stevebaker.org>
Mon, 10 Sep 2001 16:28:43 +0000 (16:28 +0000)
Original commit message from CVS:
dparams have arrived. see previous mail for an intro

gst/Makefile.am
gst/elements/gstsinesrc.c
gst/elements/gstsinesrc.h
gst/gst.h
gst/gstdparam.c [new file with mode: 0644]
gst/gstdparam.h [new file with mode: 0644]
gst/gstdparammanager.c [new file with mode: 0644]
gst/gstdparammanager.h [new file with mode: 0644]
gst/gstelement.h
plugins/elements/gstsinesrc.c
plugins/elements/gstsinesrc.h

index 08c2a81..39cdcee 100644 (file)
@@ -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         \
index 83d340e..e10db30 100644 (file)
@@ -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 
index 390d12b..58e03fd 100644 (file)
@@ -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;
index 2addc92..948e25a 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -49,6 +49,8 @@
 #include <gst/gstxml.h>
 #include <gst/cothreads.h>
 #include <gst/gstscheduler.h>
+#include <gst/gstdparam.h>
+#include <gst/gstdparammanager.h>
 #include <gst/gsttimecache.h>
 
 #include <gst/gstparse.h>
diff --git a/gst/gstdparam.c b/gst/gstdparam.c
new file mode 100644 (file)
index 0000000..8f14555
--- /dev/null
@@ -0,0 +1,190 @@
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 (file)
index 0000000..f19fc4f
--- /dev/null
@@ -0,0 +1,128 @@
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 <gst/gstobject.h>
+#include <gst/gstprops.h>
+
+#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 (file)
index 0000000..0c74e30
--- /dev/null
@@ -0,0 +1,459 @@
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 <gst/gstelement.h>
+
+
+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 (file)
index 0000000..25091c3
--- /dev/null
@@ -0,0 +1,138 @@
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 <gst/gstobject.h>
+#include <gst/gstdparam.h>
+
+#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__ */
index 945ab35..41a7cbf 100644 (file)
@@ -37,6 +37,7 @@
 #include <gst/gstpad.h>
 #include <gst/cothreads.h>
 #include <gst/gstpluginfeature.h>
+#include <gst/gstdparammanager.h>
 
 #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 {
index 83d340e..e10db30 100644 (file)
@@ -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 
index 390d12b..58e03fd 100644 (file)
@@ -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;