[gst-cvs] CVS: gstreamer/libs/control Makefile.am,NONE,1.2.2.1 gstcontrol.c,NONE,1.1.2.1 gstcontrol.h,NONE,1.2.2.1 gstdparam.c,NONE,1.1.2.1 gstdparam.h,NONE,1.1.2.1 gstdparammanager.c,NONE,1.1.2.1 gstdparammanager.h,NONE,1.1.2.1 gstdplinearinterp.c,NONE,1.2.2.1 gstdplinearinterp.h,NONE,1.2.2.1

Erik Walthinsen omegahacker at users.sourceforge.net
Wed Oct 17 01:52:16 PDT 2001


Update of /cvsroot/gstreamer/gstreamer/libs/control
In directory usw-pr-cvs1:/tmp/cvs-serv20849/libs/control

Added Files:
      Tag: BRANCH-EVENTS1
	Makefile.am gstcontrol.c gstcontrol.h gstdparam.c gstdparam.h 
	gstdparammanager.c gstdparammanager.h gstdplinearinterp.c 
	gstdplinearinterp.h 
Log Message:
merge from HEAD on 20011016

--- NEW FILE: Makefile.am ---
filterdir = $(libdir)/gst

filter_LTLIBRARIES = libgstcontrol.la

libgstcontrol_la_SOURCES = \
    gstcontrol.c \
    gstdparammanager.c \
    gstdparam.c \
    gstdplinearinterp.c
    

libgstcontrolincludedir = $(includedir)/gst/libs/control
libgstcontrolinclude_HEADERS = \
    gstcontrol.h \
    gstdparammanager.h \
    gstdparam.h \
    gstdplinearinterp.h

libgstcontrol_la_LIBADD = -lm

CFLAGS += -O2 $(FOMIT_FRAME_POINTER) -finline-functions -ffast-math

--- NEW FILE: gstcontrol.c ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at yahoo.co.uk>
 *
 * gstcontrol.c: GStreamer control utility library
 *
 * 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 "gstcontrol.h"

--- NEW FILE: gstcontrol.h ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at yahoo.co.uk>
 *
 * gstcontrol.h: GStreamer control utility library
 *
 * 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_CONTROL_H__
#define __GST_CONTROL_H__

#include <gst/gstobject.h>
#include <gst/gstprops.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <libs/control/gstdparammanager.h>
#include <libs/control/gstdparam.h>

#include <libs/control/gstdplinearinterp.h>

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GST_CONTROL_H__ */

--- NEW FILE: gstdparam.c ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at 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 <math.h>
#include <string.h>
#include <gst/gstinfo.h>

#include "gstdparam.h"
#include "gstdparammanager.h"

static void gst_dparam_class_init (GstDParamClass *klass);
static void gst_dparam_init (GstDParam *dparam);

static void gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp);
static GValue** 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),
			NULL,
			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_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;
	GST_DPARAM_TYPE(dparam) = 0;
	GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)=0LL;
	GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)=0LL;
	GST_DPARAM_READY_FOR_UPDATE(dparam)=FALSE;
	dparam->lock = g_mutex_new ();
}

/**
 * gst_dparam_new:
 * @type: the type that this dparam will store
 *
 * Returns: a new instance of GstDParam
 */
GstDParam* 
gst_dparam_new (GType type)
{
	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_value_array(type, 0);	
	GST_DPARAM_TYPE(dparam) = type;
	
	return dparam;
}

/**
 * gst_dparam_attach
 * @dparam: GstDParam instance
 * @parent: the GstDParamManager that this dparam belongs to
 *
 */
void
gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec)
{
	
	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 (GST_IS_DPMAN (parent));
	g_return_if_fail ((gpointer)dparam != (gpointer)parent);
	g_return_if_fail (value != NULL);
	g_return_if_fail (spec != NULL);
	g_return_if_fail (GST_DPARAM_TYPE(dparam) == G_VALUE_TYPE(value));
	
	GST_DPARAM_NAME(dparam) = spec->dparam_name;
	GST_DPARAM_VALUE(dparam) = value;
	GST_DPARAM_SPEC(dparam) = spec;
	gst_object_set_parent (GST_OBJECT (dparam), parent);
}

/**
 * gst_dparam_new_value_array
 * @type: the type of the first GValue in the array
 * @...: the type of other GValues in the array
 *
 * 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 array of GValues
 */
GValue**
gst_dparam_new_value_array(GType type, ...)
{
	GValue **point;
	GValue *value;
	guint x;
	guint values_length = 0;
	va_list var_args;
	GType each_type;

	va_start (var_args, type);
	each_type = type;
	while (each_type){
		values_length++;
		each_type = va_arg (var_args, GType);
	}
	va_end (var_args);
	
	point = g_new0(GValue*,values_length + 1);

	va_start (var_args, type);
	each_type = type;
	for (x=0 ; x < values_length ; x++){
		value = g_new0(GValue,1);
		if (each_type != G_TYPE_NONE){
			g_value_init(value, each_type);
		}
		point[x] = value;
		each_type = va_arg (var_args, GType);
	}
	point[values_length] = NULL;
	va_end (var_args);
	
	GST_DEBUG(GST_CAT_PARAMS, "array with %d values created\n", values_length);

	return point;
}

void
gst_dparam_set_value_from_string(GValue *value, const gchar *value_str)
{

	g_return_if_fail(value != NULL);
	g_return_if_fail(value_str != NULL);
	
	GST_DEBUG(GST_CAT_PARAMS, "parsing '%s' to type %s\n", value_str, g_type_name(G_VALUE_TYPE(value)));

	switch (G_VALUE_TYPE(value)) {
		case G_TYPE_STRING:
			g_value_set_string(value, g_strdup(value_str));
			break;
		case G_TYPE_ENUM: 
		case G_TYPE_INT: {
			gint i;
			sscanf (value_str, "%d", &i);
			g_value_set_int(value, i);
			break;
		}
		case G_TYPE_UINT: {
			guint i;
			sscanf (value_str, "%u", &i);
			g_value_set_uint(value, i);
			break;
		}
		case G_TYPE_LONG: {
			glong i;
			sscanf (value_str, "%ld", &i);
			g_value_set_long(value, i);
			break;
		}
		case G_TYPE_ULONG: {
			gulong i;
			sscanf (value_str, "%lu", &i);
			g_value_set_ulong(value, i);
			break;
		}
		case G_TYPE_BOOLEAN: {
			gboolean i = FALSE;
			if (!strncmp ("true", value_str, 4)) i = TRUE;
			g_value_set_boolean(value, i);
			break;
		}
		case G_TYPE_CHAR: {
			gchar i;
			sscanf (value_str, "%c", &i);
			g_value_set_char(value, i);
			break;
		}
		case G_TYPE_UCHAR: {
			guchar i;
			sscanf (value_str, "%c", &i);
			g_value_set_uchar(value, i);
			break;
		}
		case G_TYPE_FLOAT: {
			gfloat i;
			sscanf (value_str, "%f", &i);
			g_value_set_float(value, i);
			break;
		}
		case G_TYPE_DOUBLE: {
			gfloat i;
			sscanf (value_str, "%g", &i);
			g_value_set_double(value, (gdouble)i);
			break;
		}
		default:
	  		break;
	}
}

static void
gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp)
{
	GST_DPARAM_LOCK(dparam);
	GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE;
	GST_DEBUG(GST_CAT_PARAMS, "updating value for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
	g_value_copy(dparam->point[0], GST_DPARAM_VALUE(dparam));
	GST_DPARAM_UNLOCK(dparam);
}

static GValue** 
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;
}

/**********************
 * GstDParamSmooth
 **********************/

static void gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp);
static GValue** gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp);

/**
 * gst_dparam_smooth_new:
 * @type: the type that this dparam will store
 *
 * Returns: a new instance of GstDParamSmooth
 */
GstDParam* 
gst_dparam_smooth_new (GType type)
{
	GstDParam *dparam;

	dparam = g_object_new (gst_dparam_get_type (), NULL);
	
	dparam->do_update_func = gst_dparam_do_update_smooth;
	dparam->get_point_func = gst_dparam_get_point_smooth;
	
	dparam->point = gst_dparam_new_value_array(type, type, G_TYPE_FLOAT, 0);	
	GST_DPARAM_TYPE(dparam) = type;
	
	return dparam;
}

static void
gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp)
{
	gint64 time_diff;
	gfloat time_ratio;
	
	time_diff = MIN(GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam), 
	                timestamp - GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam));
	                
	time_ratio = (gfloat)time_diff / g_value_get_float(dparam->point[2]);

	GST_DPARAM_LOCK(dparam);

	GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam);  
	while(GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp){
		GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) += GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam);
	}
	GST_DEBUG(GST_CAT_PARAMS, "last:%lld current:%lld next:%lld\n",
	                           GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam), timestamp, GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam));

	
	switch (G_VALUE_TYPE(GST_DPARAM_VALUE(dparam))){
		case G_TYPE_FLOAT: {
			gfloat current, target, max_change, current_diff, final_val;
			
			target = g_value_get_float(dparam->point[0]);
			current = g_value_get_float(GST_DPARAM_VALUE(dparam));
			max_change = time_ratio * g_value_get_float(dparam->point[1]);

			GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f max_change:%f \n", 
			                           target, current, max_change);
			                           
			if (dparam->spec->is_log){
				gfloat current_log;
				current_log = log(current);
				current_diff = ABS(current_log - log(target));
				if (current_diff > max_change)
					final_val = (target < current) ? exp(current_log-max_change) : exp(current_log+max_change);
				else
					final_val = target;
			} 
			else {
				current_diff = ABS (current - target);
				if (current_diff > max_change)
					final_val = (target < current) ? current-max_change : current+max_change;
				else
					final_val = target;									
			}

			GST_DPARAM_READY_FOR_UPDATE(dparam) = (current_diff > max_change);
			g_value_set_float(GST_DPARAM_VALUE(dparam), final_val);
			
			break;
		}
		default:
			break;
	}

		                           
	//GST_DEBUG(GST_CAT_PARAMS, "smooth update for %s(%p): %f\n",
	//                           GST_DPARAM_NAME (dparam),dparam, g_value_get_float(GST_DPARAM_VALUE(dparam)));

	GST_DPARAM_UNLOCK(dparam);
}

static GValue** 
gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp)
{
	GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
	return dparam->point;
}

--- NEW FILE: gstdparam.h ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at 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_SPEC(dparam)				 ((dparam)->spec)
#define GST_DPARAM_TYPE(dparam)				 ((dparam)->type)

#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_DEFAULT_UPDATE_PERIOD(dparam)	((dparam)->default_update_period)
#define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)	((dparam)->next_update_timestamp)
#define GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)	((dparam)->last_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 _GstDParamSpec GstDParamSpec;

typedef GValue** (*GstDParamInsertPointFunction) (GstDParam *dparam, guint64 timestamp);
typedef void (*GstDParamRemovePointFunction) (GstDParam *dparam, GValue** point);
typedef GValue** (*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;
	GstDParamSpec *spec;
	GValue **point;
	GType type;
	gint64 last_update_timestamp;
	gint64 next_update_timestamp;
	gint64 default_update_period;
	gboolean ready_for_update;
};

struct _GstDParamClass {
	GstObjectClass parent_class;

	/* signal callbacks */
};

struct _GstDParamSpec {
	gchar *dparam_name;
	gchar *unit_name;
	GValue *min_val;
	GValue *max_val;
	GValue *default_val;
	gboolean is_log;
	gboolean is_rate;
};

GType gst_dparam_get_type (void);
GstDParam* gst_dparam_new (GType type);
void gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec);
GValue** gst_dparam_new_value_array(GType type, ...);
void gst_dparam_set_value_from_string(GValue *value, const gchar *value_str);

/**********************
 * GstDParamSmooth
 **********************/

GstDParam* gst_dparam_smooth_new (GType type);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GST_DPARAM_H__ */

--- NEW FILE: gstdparammanager.c ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at 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 "gstdparammanager.h"
#include <gst/gstelement.h>
#include <gst/gstinfo.h>

static GHashTable *_element_registry;

static void gst_dpman_class_init (GstDParamManagerClass *klass);
static void gst_dpman_init (GstDParamManager *dpman);
static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method);
static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name);
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_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp);
static guint gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp);
static guint gst_dpman_process_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),
			NULL,
			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_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);
	_element_registry = g_hash_table_new(NULL,NULL);

	gst_dpman_register_mode (klass, "synchronous", 
	                       gst_dpman_preprocess_synchronous, gst_dpman_process_noop, NULL, NULL);
	gst_dpman_register_mode (klass, "asynchronous", 
	                       gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL);
	gst_dpman_register_mode (klass, "disabled", 
	                       gst_dpman_preprocess_noop, gst_dpman_process_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 = g_object_new (gst_dpman_get_type (), NULL);
	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_callback:
 * @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_callback (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 (update_func != NULL, FALSE);

	dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_CALLBACK);

	g_return_val_if_fail (dpwrap != NULL, FALSE);

	GST_DEBUG(GST_CAT_PARAMS,"adding required callback dparam '%s' of type %s\n", dparam_name, g_type_name(type));

	dpwrap->update_func = update_func;
	dpwrap->update_data = update_data;

	return TRUE;	
}

/**
 * gst_dpman_add_required_dparam_direct:
 * @dpman: GstDParamManager instance
 * @dparam_name: a parameter name unique to this GstDParamManager
 * @type: the GValue type that this parameter will store
 * @update_data: pointer to the member to be updated
 *
 * Returns: true if it was successfully added
 */
gboolean 
gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, 
                                        gchar *dparam_name, 
                                        GType type, 
                                        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 (update_data != NULL, FALSE);

	dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_DIRECT);

	g_return_val_if_fail (dpwrap != NULL, FALSE);

	GST_DEBUG(GST_CAT_PARAMS,"adding required direct dparam '%s' of type %s\n", dparam_name, g_type_name(type));

	dpwrap->update_data = update_data;

	return TRUE;	
}

/**
 * gst_dpman_add_required_dparam_array:
 * @dpman: GstDParamManager instance
 * @dparam_name: a parameter name unique to this GstDParamManager
 * @type: the GValue type that this parameter will store
 * @update_data: pointer to where the array will be stored
 *
 * Returns: true if it was successfully added
 */
gboolean 
gst_dpman_add_required_dparam_array (GstDParamManager *dpman, 
                                        gchar *dparam_name, 
                                        GType type, 
                                        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 (update_data != NULL, FALSE);

	dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_ARRAY);

	g_return_val_if_fail (dpwrap != NULL, FALSE);

	GST_DEBUG(GST_CAT_PARAMS,"adding required array dparam '%s' of type %s\n", dparam_name, g_type_name(type));

	dpwrap->update_data = update_data;

	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 = gst_dpman_get_wrapper(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 = gst_dpman_get_wrapper(dpman, dparam_name);

	g_return_val_if_fail(dpwrap != NULL, FALSE);
	g_return_val_if_fail(dpwrap->value != NULL, FALSE);

	dpwrap->dparam = dparam;
	gst_dparam_attach(dparam, GST_OBJECT(dpman), dpwrap->value, dpwrap->spec);

	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 = gst_dpman_get_wrapper(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_get_dparam_type:
 * @dpman: GstDParamManager instance
 * @name: the name of dparam
 *
 * Returns: the type that this dparam requires/uses
 */
GType
gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name)
{
	GstDParamWrapper* dpwrap;

	g_return_val_if_fail (dpman != NULL, 0);
	g_return_val_if_fail (GST_IS_DPMAN (dpman), 0);
	g_return_val_if_fail (name != NULL, 0);
	
	dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
	g_return_val_if_fail (dpwrap != NULL, 0);
	
	return G_VALUE_TYPE(dpwrap->value);
}

GstDParamSpec**
gst_dpman_list_dparam_specs(GstDParamManager *dpman)
{
	GstDParamWrapper* dpwrap;
	GSList *dpwraps;
	GstDParamSpec** dparam_specs;
	guint x = 0;

	g_return_val_if_fail (dpman != NULL, NULL);
	g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
	
	dpwraps = GST_DPMAN_DPARAMS_LIST(dpman);

	dparam_specs = g_new0(GstDParamSpec*, g_slist_length(dpwraps) + 1);
	
	while (dpwraps){
		dpwrap = (GstDParamWrapper*)dpwraps->data;
		dparam_specs[x++] = dpwrap->spec;
		dpwraps = g_slist_next(dpwraps);
	}
	return dparam_specs;
}

GstDParamSpec*
gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_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 (dparam_name != NULL, NULL);

	dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
	return dpwrap->spec;
}

void
gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name)
{
	
}

/**
 * gst_dpman_register_mode
 * @klass: GstDParamManagerClass class instance
 * @modename: the unique name of the new mode
 * @preprocessfunc: the function which will be called before each buffer is processed
 * @processfunc: 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, 
                         GstDPMModePreProcessFunction preprocessfunc,
                         GstDPMModeProcessFunction processfunc,
                         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->preprocessfunc = preprocessfunc;
	mode->processfunc = processfunc;
	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));

	g_hash_table_insert(_element_registry, parent, dpman);
	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_get_manager
 * @parent: the element that the desired GstDParamManager belongs to
 *
 * Returns: the GstDParamManager which belongs to this element or NULL
 * if it doesn't exist
 */
GstDParamManager *
gst_dpman_get_manager (GstElement *parent)
{
	GstDParamManager *dpman;
	g_return_val_if_fail (parent != NULL, NULL);
	g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
	
	dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent);
	g_return_val_if_fail (dpman != NULL, NULL);
	return 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 GstDParamWrapper* 
gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name)
{
	g_return_val_if_fail (dpman != NULL, NULL);
	g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
	g_return_val_if_fail (dparam_name != NULL, NULL);
	
	return g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
}

static GstDParamWrapper* 
gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method)
{
	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 (dparam_name != NULL, NULL);

	g_return_val_if_fail(gst_dpman_get_wrapper(dpman, dparam_name) == NULL, NULL);

	dpwrap = g_new0(GstDParamWrapper,1);
	dpwrap->update_method = update_method;
	dpwrap->value = g_new0(GValue,1);
	g_value_init(dpwrap->value, type);
	
	dpwrap->spec = g_new0(GstDParamSpec,1);
	dpwrap->spec->dparam_name = dparam_name;
	dpwrap->spec->min_val = g_new0(GValue,1);
	dpwrap->spec->max_val = g_new0(GValue,1);
	dpwrap->spec->default_val = g_new0(GValue,1);
	g_value_init(dpwrap->spec->min_val, type);
	g_value_init(dpwrap->spec->max_val, type);
	g_value_init(dpwrap->spec->default_val, 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 dpwrap;	
}


static void 
gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman)
{
	GSList *dwraps;
	GstDParam *dparam;
	GstDParamWrapper *dpwrap;

	g_return_if_fail (dpman != NULL);
	g_return_if_fail (GST_IS_DPMAN (dpman));
	
	if (state == GST_STATE_PLAYING){
		GST_DEBUG(GST_CAT_PARAMS, "initialising params\n");
			
		// 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;
				if (dparam->spec){
					g_value_copy(dparam->spec->default_val, GST_DPARAM_VALUE(dparam));
				}
			}
			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_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp)
{
	GSList *dwraps;
   	GstDParam *dparam;
	GstDParamWrapper *dpwrap;
	guint x;

	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))){
		              	
		    // this will make dpwrap->value contain the latest value.
		    // now we just need to get it to the element
			GST_DPARAM_DO_UPDATE(dparam, timestamp);
			
			switch (dpwrap->update_method) {
				
				// direct method - set the value directly in the struct of the element
				case GST_DPMAN_DIRECT:
					GST_DEBUG(GST_CAT_PARAMS, "doing direct update\n");
					switch (G_VALUE_TYPE(dpwrap->value)){
						case G_TYPE_CHAR:
							*(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
							break;
						case G_TYPE_UCHAR:
							*(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
							break;
						case G_TYPE_BOOLEAN:
							*(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
							break;
						case G_TYPE_INT:
							*(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
							break;
						case G_TYPE_UINT:
							*(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
							break;
						case G_TYPE_LONG:
							*(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
							break;
						case G_TYPE_ULONG:
							*(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
							break;
						case G_TYPE_FLOAT:
							*(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
							break;
						case G_TYPE_DOUBLE:
							*(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
							break;
						case G_TYPE_POINTER:
							*(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
							break;
						default:
							break;
					}
					break;

				// callback method - call the element's callback so it can do what it likes
				case GST_DPMAN_CALLBACK:
					GST_DEBUG(GST_CAT_PARAMS, "doing callback update\n");
					GST_DPMAN_DO_UPDATE(dpwrap);
					break;
					
				// array method - generate an array of the right size 
				// with each value being the same (in synchronous update mode)
				case GST_DPMAN_ARRAY:
					GST_DEBUG(GST_CAT_PARAMS, "doing array update\n");
					switch (G_VALUE_TYPE(dpwrap->value)){
						case G_TYPE_CHAR:
							(gchar*)dpwrap->update_data = g_new(gchar, frames);
							*(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gchar*)dpwrap->update_data)[x] = *(gchar*)dpwrap->update_data;
							break;
						case G_TYPE_UCHAR:
							(guchar*)dpwrap->update_data = g_new(guchar, frames);
							*(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((guchar*)dpwrap->update_data)[x] = *(guchar*)dpwrap->update_data;
							break;
						case G_TYPE_BOOLEAN:
							(gboolean*)dpwrap->update_data = g_new(gboolean, frames);
							*(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gboolean*)dpwrap->update_data)[x] = *(gboolean*)dpwrap->update_data;
							break;
						case G_TYPE_INT:
							(gint*)dpwrap->update_data = g_new(gint, frames);
							*(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gint*)dpwrap->update_data)[x] = *(gint*)dpwrap->update_data;
							break;
						case G_TYPE_UINT:
							(guint*)dpwrap->update_data = g_new(guint, frames);
							*(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((guint*)dpwrap->update_data)[x] = *(guint*)dpwrap->update_data;
							break;
						case G_TYPE_LONG:
							(glong*)dpwrap->update_data = g_new(glong, frames);
							*(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((glong*)dpwrap->update_data)[x] = *(glong*)dpwrap->update_data;
							break;
						case G_TYPE_ULONG:
							(gulong*)dpwrap->update_data = g_new(gulong, frames);
							*(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gulong*)dpwrap->update_data)[x] = *(gulong*)dpwrap->update_data;
							break;
						case G_TYPE_FLOAT:
							(gfloat*)dpwrap->update_data = g_new(gfloat, frames);
							*(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gfloat*)dpwrap->update_data)[x] = *(gfloat*)dpwrap->update_data;
							break;
						case G_TYPE_DOUBLE:
							(gdouble*)dpwrap->update_data = g_new(gdouble, frames);
							*(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gdouble*)dpwrap->update_data)[x] = *(gdouble*)dpwrap->update_data;
							break;
						case G_TYPE_POINTER:
							(gpointer*)dpwrap->update_data = g_new(gpointer, frames);
							*(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
							for (x = 1 ; x < frames ; x++)
								((gpointer*)dpwrap->update_data)[x] = *(gpointer*)dpwrap->update_data;
							break;
						default:
							break;
					}
					break;
				default:
					break;
			}
		}
		dwraps = g_slist_next(dwraps);
	}
	return frames;
}

static guint 
gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp)
{
	return frames;
}

static guint 
gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count)
{
	return 0;
}


--- NEW FILE: gstdparammanager.h ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at 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/gstprops.h>
#include <libs/control/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 enum {
  GST_DPMAN_CALLBACK,
  GST_DPMAN_DIRECT,
  GST_DPMAN_ARRAY,
} GstDPMUpdateMethod;

typedef struct _GstDParamManager GstDParamManager;
typedef struct _GstDParamManagerClass GstDParamManagerClass;
typedef struct _GstDPMMode GstDPMMode;
typedef struct _GstDParamWrapper GstDParamWrapper;

typedef guint (*GstDPMModePreProcessFunction) (GstDParamManager *dpman, guint frames, gint64 timestamp);
typedef guint (*GstDPMModeProcessFunction) (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 {
	GstDPMModePreProcessFunction preprocessfunc;
	GstDPMModeProcessFunction processfunc;
	GstDPMModeSetupFunction setupfunc;
	GstDPMModeTeardownFunction teardownfunc;
};

struct _GstDParamWrapper {
	GstDParamSpec* spec;
	GValue *value;
	GstDParam *dparam;
	GstDPMUpdateMethod update_method;
	gpointer update_data;
	GstDPMUpdateFunction update_func;
};

#define GST_DPMAN_PREPROCESSFUNC(dpman)		(((dpman)->mode)->preprocessfunc)
#define GST_DPMAN_PROCESSFUNC(dpman)		(((dpman)->mode)->processfunc)
#define GST_DPMAN_SETUPFUNC(dpman)		(((dpman)->mode)->setupfunc)
#define GST_DPMAN_TEARDOWNFUNC(dpman)		(((dpman)->mode)->teardownfunc)

#define GST_DPMAN_PREPROCESS(dpman, buffer_size, timestamp) \
				(GST_DPMAN_PREPROCESSFUNC(dpman)(dpman, buffer_size, timestamp))

#define GST_DPMAN_PROCESS(dpman, frame_count) \
				(GST_DPMAN_PROCESSFUNC(dpman)(dpman, frame_count))

#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \
				(frame_countdown-- || \
				(frame_countdown = GST_DPMAN_PROCESS(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);
GstDParamManager* gst_dpman_get_manager (GstElement *parent);

gboolean gst_dpman_add_required_dparam_callback (GstDParamManager *dpman, 
                                                gchar *dparam_name, 
                                                GType type, 
                                                GstDPMUpdateFunction update_func, 
                                                gpointer update_data);
gboolean gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, 
                                               gchar *dparam_name, 
                                               GType type, 
                                               gpointer update_data);
gboolean gst_dpman_add_required_dparam_array (GstDParamManager *dpman, 
                                              gchar *dparam_name, 
                                              GType type, 
                                              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);
GType gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name);

GstDParamSpec** gst_dpman_list_dparam_specs(GstDParamManager *dpman);
GstDParamSpec* gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name);
void gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_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, 
                           GstDPMModePreProcessFunction preprocessfunc,
                           GstDPMModeProcessFunction processfunc,
                           GstDPMModeSetupFunction setupfunc,
                           GstDPMModeTeardownFunction teardownfunc);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GST_DPMAN_H__ */

--- NEW FILE: gstdplinearinterp.c ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at yahoo.co.uk>
 *
 * gstdplinearinterp.c: linear interpolation dynamic parameter
 *
 * 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 "gstdplinearinterp.h"

static void gst_dp_linint_class_init (GstDParamClass *klass);
static void gst_dp_linint_base_class_init (GstDParamClass *klass);
static void gst_dp_linint_init (GstDParam *dp_linint);

GType 
gst_dp_linint_get_type(void) {
	static GType dp_linint_type = 0;

	if (!dp_linint_type) {
		static const GTypeInfo dp_linint_info = {
			sizeof(GstDParamClass),
			(GBaseInitFunc)gst_dp_linint_base_class_init,
			NULL,
			(GClassInitFunc)gst_dp_linint_class_init,
			NULL,
			NULL,
			sizeof(GstDParam),
			0,
			(GInstanceInitFunc)gst_dp_linint_init,
		};
		dp_linint_type = g_type_register_static(GST_TYPE_DPARAM, "GstDParamLinInterp", &dp_linint_info, 0);
	}
	return dp_linint_type;
}

static void
gst_dp_linint_base_class_init (GstDParamClass *klass)
{

}

static void
gst_dp_linint_class_init (GstDParamClass *klass)
{

}

static void
gst_dp_linint_init (GstDParam *dp_linint)
{
	g_return_if_fail (dp_linint != NULL);
}

/**
 * gst_dp_linint_new:
 * @type: the type that this dp_linint will store
 *
 * Returns: a new instance of GstDParam
 */
GstDParam* 
gst_dp_linint_new (GType type)
{
	GstDParam *dparam;
	GstDParamLinInterp *dp_linint;

	dp_linint = g_object_new (gst_dp_linint_get_type (), NULL);
	dparam = GST_DPARAM(dp_linint);
	
	return dparam;
}

--- NEW FILE: gstdplinearinterp.h ---
/* GStreamer
 * Copyright (C) 2001 Steve Baker <stevebaker_org at yahoo.co.uk>
 *
 * gstdplinearinterp.h: linear interpolation dynamic parameter
 *
 * 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_DP_LININT_H__
#define __GST_DP_LININT_H__

#include <gst/gstobject.h>
#include "gstdparam.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


#define GST_TYPE_DP_LININT			(gst_dp_linint_get_type ())
#define GST_DP_LININT(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DP_LININT,GstDParamLinInterp))
#define GST_DP_LININT_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DP_LININT,GstDParamLinInterp))
#define GST_IS_DP_LININT(obj)			(G_TYPE_CHECK_INSTANCE_TYPE	((obj), GST_TYPE_DP_LININT))
#define GST_IS_DP_LININT_CLASS(obj)		(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DP_LININT))

typedef struct _GstDParamLinInterp GstDParamLinInterp;
typedef struct _GstDParamLinInterpClass GstDParamLinInterpClass;

struct _GstDParamLinInterp {
	GstDParam		dparam;

};

struct _GstDParamLinInterpClass {
	GstDParamClass parent_class;

	/* signal callbacks */
};

GType gst_dp_linint_get_type (void);
GstDParam* gst_dp_linint_new (GType type);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GST_DP_LININT_H__ */





More information about the Gstreamer-commits mailing list