diff --git a/Makefile.am b/Makefile.am index e319295b68..2916ddd30a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,7 @@ SUBDIRS_DOCS = endif if BUILD_TESTS -SUBDIRS_TESTS = test tests testsuite +SUBDIRS_TESTS = else SUBDIRS_TESTS = endif @@ -47,7 +47,7 @@ EXTRA_DIST = gstreamer.spec.in gstreamer-config.in gstreamer.m4 \ gstreamer.pc.in gstreamer-uninstalled.pc.in \ configure.base autogen.sh \ LICENSE REQUIREMENTS ABOUT-NLS $(man_MANS) \ - idiottest.mak ltconfig.sh + idiottest.mak dist-hook: cp gstreamer.spec $(distdir) diff --git a/REQUIREMENTS b/REQUIREMENTS index 6c581ea30c..0795d02e34 100644 --- a/REQUIREMENTS +++ b/REQUIREMENTS @@ -79,9 +79,10 @@ CVS (using autogen.sh): Required tools: =============== -autoconf -automake v1.4 or better -libtool v1.3.5 or better +autoconf v2.13 or better, 2.52 prefered +automake v1.4 or better, 1.5 prefered +libtool v1.4 or better +pkgconfig 0.8.0 (http://www.freedesktop.org/software/pkgconfig/) Optional tools: =============== diff --git a/configure.base b/configure.base index 810d933565..7597efb68b 100644 --- a/configure.base +++ b/configure.base @@ -83,6 +83,9 @@ else HAVE_NASM="yes" fi +dnl Check for pkgconfig +AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, true, false) + dnl check for gtkdoc AC_CHECK_PROG(HAVE_GTK_DOC, gtkdoc-mkdb, true, false) AC_CHECK_PROG(HAVE_GTK_DOC, gtkdoc-scanobj, :, false) @@ -803,8 +806,12 @@ AC_ARG_ENABLE(profiling, esac], [USE_PROFILING=no]) dnl Default value -dnl Default value -GST_CONFIG_DIR=/etc/gstreamer +dnl default to building registry in the source tree if we are enabling plugin build dir +if test "x$PLUGINS_USE_BUILDDIR" = xyes; then + GST_CONFIG_DIR=$builddir +else + GST_CONFIG_DIR=/etc/gstreamer +fi AC_ARG_WITH(configdir, [ --with-configdir specify path to use for configdir], [case "${withval}" in @@ -1181,6 +1188,7 @@ libs/putbits/Makefile libs/idct/Makefile libs/audio/Makefile libs/bytestream/Makefile +libs/control/Makefile plugins/Makefile plugins/a52dec/Makefile plugins/aasink/Makefile @@ -1228,7 +1236,7 @@ plugins/rtp/Makefile plugins/rtp/rtpsend/Makefile plugins/mulaw/Makefile plugins/alaw/Makefile -plugins/ffmpeg/Makefile +dnl until ffmpeg is handled by configure plugins/ffmpeg/Makefile plugins/filters/Makefile plugins/filters/smooth/Makefile plugins/filters/median/Makefile @@ -1281,12 +1289,14 @@ plugins/gsm/Makefile plugins/1394/Makefile plugins/sdlsink/Makefile plugins/dv/Makefile +plugins/synthesis/Makefile +plugins/synthesis/sinesrc/Makefile gstplay/Makefile dnl components/bonobo-gstmediaplay/Makefile test/Makefile test/xml/Makefile test/bindings/Makefile -test/misc/Makefile +dnl someone should fix this test/misc/Makefile test/memchunk/Makefile test/events/Makefile tests/Makefile @@ -1296,7 +1306,7 @@ tests/muxing/Makefile testsuite/Makefile testsuite/capsnego/Makefile testsuite/refcounting/Makefile -testsuite/plugin/Makefile +dnl someone should fix this testsuite/plugin/Makefile tests/nego/Makefile examples/Makefile examples/autoplug/Makefile diff --git a/debian/README.Debian b/debian/README.Debian index 96407182ae..64d1a1302e 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -19,6 +19,7 @@ recommended plugins: optional plugins: + gstreamer-a52dec gstreamer-aa gstreamer-alsa gstreamer-arts @@ -35,10 +36,12 @@ optional plugins: gstreamer-jpeg gstreamer-lame gstreamer-mad + gstreamer-mikmod gstreamer-mpeg2dec gstreamer-mpg123 gstreamer-oss gstreamer-sdl + gstreamer-sid gstreamer-vorbis gstreamer-x diff --git a/debian/gstreamer-plugin-template.postinst b/debian/gstreamer-plugin-template.postinst index d1c4e4b602..9afaa890b3 100644 --- a/debian/gstreamer-plugin-template.postinst +++ b/debian/gstreamer-plugin-template.postinst @@ -3,8 +3,8 @@ set -e if [ "$1" = "configure" ]; then - gstreamer-register --gst-mask=0 - gstreamer-compprep --gst-mask=0 + gstreamer-register --gst-mask=0 || true + gstreamer-compprep --gst-mask=0 || true fi #DEBHELPER# diff --git a/debian/gstreamer-plugin-template.postrm b/debian/gstreamer-plugin-template.postrm index 95f4dac0cf..b8658f30e1 100644 --- a/debian/gstreamer-plugin-template.postrm +++ b/debian/gstreamer-plugin-template.postrm @@ -3,8 +3,8 @@ set -e if [ "$1" = "remove" ]; then - gstreamer-register --gst-mask=0 - gstreamer-compprep --gst-mask=0 + gstreamer-register --gst-mask=0 || true + gstreamer-compprep --gst-mask=0 || true fi #DEBHELPER# diff --git a/debian/gstreamer-runtime.postinst b/debian/gstreamer-runtime.postinst index d1c4e4b602..9afaa890b3 100644 --- a/debian/gstreamer-runtime.postinst +++ b/debian/gstreamer-runtime.postinst @@ -3,8 +3,8 @@ set -e if [ "$1" = "configure" ]; then - gstreamer-register --gst-mask=0 - gstreamer-compprep --gst-mask=0 + gstreamer-register --gst-mask=0 || true + gstreamer-compprep --gst-mask=0 || true fi #DEBHELPER# diff --git a/docs/gst/Makefile.am b/docs/gst/Makefile.am index 235a8040a3..a9b1fe9299 100644 --- a/docs/gst/Makefile.am +++ b/docs/gst/Makefile.am @@ -9,6 +9,9 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code (if it contains documentation). DOC_SOURCE_DIR=$(top_srcdir)/gst +# thomas +# there's something wrong with gstreamer-sections.txt not being in the dist +# maybe it doesn't resolve EXTRA_DIST = gstreamer.types.in gstreamer.hierarchy $(DOC_MODULE)-sections.txt $(DOC_MAIN_SGML_FILE) HTML_DIR=$(datadir)/gstreamer/html diff --git a/docs/gst/gstreamer.types.in b/docs/gst/gstreamer.types.in index 41ade6afbe..5020474c6e 100644 --- a/docs/gst/gstreamer.types.in +++ b/docs/gst/gstreamer.types.in @@ -16,7 +16,6 @@ gst_fakesink_get_type gst_disksrc_get_type @GST_HTTPSRC_GET_TYPE@ gst_fdsrc_get_type -gst_sinesrc_get_type gst_fdsink_get_type diff --git a/gst/Makefile.am b/gst/Makefile.am index da6c2c49b5..6e7583219a 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -67,8 +67,6 @@ libgst_la_SOURCES = \ gstcaps.c \ gstclock.c \ gstcpu.c \ - gstdparam.c \ - gstdparammanager.c \ gstelement.c \ gstelementfactory.c \ gstevent.c \ @@ -139,12 +137,11 @@ cothreads.o: $(srcdir)/cothreads.c $(srcdir)/cothreads.h $(srcdir)/gst_private.h # Generate both marshal files together. Makes dependency work easier. gstmarshal.h: gstmarshal.list glib-genmarshal --header --prefix=gst_marshal gstmarshal.list > gstmarshal.h - echo "#include \"glib-object.h\"" >gstmarshal.c - glib-genmarshal --body --prefix=gst_marshal gstmarshal.list >> gstmarshal.c gstmarshal.c: gstmarshal.list - glib-genmarshal --header --prefix=gst_marshal gstmarshal.list > gstmarshal.h echo "#include \"glib-object.h\"" >gstmarshal.c + echo "#include \"gstlog.h\"" >> gstmarshal.c + echo "#include \"gstmarshal.h\"" >> gstmarshal.c glib-genmarshal --body --prefix=gst_marshal gstmarshal.list >> gstmarshal.c ##### end built sources ##### @@ -172,8 +169,6 @@ libgstinclude_HEADERS = \ gstclock.h \ gstcpu.h \ gstdata.h \ - gstdparam.h \ - gstdparammanager.h \ gstelement.h \ gstevent.h \ gstextratypes.h \ @@ -201,6 +196,18 @@ noinst_HEADERS = \ gstarch.h \ gstpropsprivate.h +CFLAGS = \ + $(LIBGST_CFLAGS) \ + -D_GNU_SOURCE \ + -DG_LOG_DOMAIN=g_log_domain_gstreamer \ + -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" \ + \ + -W -Wpointer-arith -Wbad-function-cast \ + -Wcast-align -Wsign-compare \ + -Wmissing-prototypes -Wmissing-declarations \ + -Wnested-externs \ + -Winline -Wno-unused + CFLAGS = $(LIBGST_CFLAGS) -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" -Wall LIBS = $(LIBGST_LIBS) LDFLAGS = "" diff --git a/gst/autoplug/gststaticautoplugrender.c b/gst/autoplug/gststaticautoplugrender.c index 94b5295ffd..0c71fffc08 100644 --- a/gst/autoplug/gststaticautoplugrender.c +++ b/gst/autoplug/gststaticautoplugrender.c @@ -187,7 +187,7 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) if (state == GST_STATE_PLAYING) gst_element_set_state (GST_ELEMENT (gst_element_get_parent (src)), GST_STATE_PAUSED); - if ((connected = gst_pad_connect (pad, sinkpad))) { + if ((connected = gst_pad_try_connect (pad, sinkpad))) { if (state == GST_STATE_PLAYING) gst_element_set_state (GST_ELEMENT (gst_element_get_parent (src)), GST_STATE_PLAYING); break; diff --git a/gst/cothreads.h b/gst/cothreads.h index d33a45f7e2..013ecd6767 100644 --- a/gst/cothreads.h +++ b/gst/cothreads.h @@ -66,7 +66,7 @@ struct _cothread_state { }; -cothread_context* cothread_init(); +cothread_context* cothread_init (void); cothread_state* cothread_create (cothread_context *ctx); void cothread_setfunc (cothread_state *thread, cothread_func func, int argc, char **argv); diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am index 3902ca30c4..f50e4f75b4 100644 --- a/gst/elements/Makefile.am +++ b/gst/elements/Makefile.am @@ -25,7 +25,6 @@ libgstelements_la_SOURCES = \ gstpipefilter.c \ gsttee.c \ gstaggregator.c \ - gstsinesrc.c \ $(GSTHTTPSRC) noinst_HEADERS = \ diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c index 799c632029..bdd540d49e 100644 --- a/gst/elements/gstelements.c +++ b/gst/elements/gstelements.c @@ -32,7 +32,6 @@ #include "gstfdsrc.h" #include "gstmultidisksrc.h" #include "gstpipefilter.h" -#include "gstsinesrc.h" #include "gsttee.h" #include "gstaggregator.h" @@ -64,7 +63,6 @@ static struct _elements_entry _elements[] = { { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL }, { "multidisksrc", gst_multidisksrc_get_type, &gst_multidisksrc_details, NULL }, { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, - { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, gst_sinesrc_factory_init }, { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, { "aggregator", gst_aggregator_get_type, &gst_aggregator_details, gst_aggregator_factory_init }, @@ -87,13 +85,20 @@ plugin_init (GModule *module, GstPlugin *plugin) factory = gst_elementfactory_new (_elements[i].name, (_elements[i].type) (), _elements[i].details); - if (factory != NULL) { - gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); - if (_elements[i].factoryinit) { - _elements[i].factoryinit (factory); + + if (!factory) + { + g_warning ("gst_elementfactory_new failed for `%s'", + _elements[i].name); + continue; } -// g_print("added factory '%s'\n",_elements[i].name); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + if (_elements[i].factoryinit) { + _elements[i].factoryinit (factory); } +// g_print("added factory '%s'\n",_elements[i].name); + i++; } diff --git a/gst/gobject2gtk.c b/gst/gobject2gtk.c index 7d3f9be8eb..72165d39c8 100644 --- a/gst/gobject2gtk.c +++ b/gst/gobject2gtk.c @@ -2,6 +2,7 @@ /* Modified by Jamie Gennis 06-2001 */ #include #include +#include "gstlog.h" #include "gobject2gtk.h" @@ -126,16 +127,16 @@ g2g_object_class_find_property(GObjectClass *class, const gchar *name) //fprintf(stderr,"class name is %s\n",gtk_type_name(class->type)); - gtk_object_arg_get_info(class->type,name,&info); + // the return value NULL if no error + if (gtk_object_arg_get_info(class->type,name,&info) != NULL) { + return NULL; + } + spec = g_new0(GParamSpec,1); - if (info) { - spec->name = (gchar *) name; - spec->value_type = info->type; - spec->flags = info->arg_flags; - } else { - spec->value_type = GTK_TYPE_NONE; - } + spec->name = (gchar *) name; + spec->value_type = info->type; + spec->flags = info->arg_flags; return spec; } diff --git a/gst/gobject2gtk.h b/gst/gobject2gtk.h index 87e22c1632..6201c12a78 100644 --- a/gst/gobject2gtk.h +++ b/gst/gobject2gtk.h @@ -23,6 +23,9 @@ GSList *g_slist_delete_link (GSList *list, GSList *llink); typedef struct _GObject GObject; typedef struct _GObjectClass GObjectClass; +#define g_string_printf g_string_sprintf +#define g_string_printfa g_string_sprintfa + #define g_object_ref(obj) gtk_object_ref((GtkObject *)(obj)) #define g_object_unref(obj) gtk_object_unref((GtkObject *)(obj)) @@ -79,6 +82,7 @@ typedef struct _GObjectClass GObjectClass; #define gst_marshal_VOID__VOID gtk_marshal_NONE__NONE #define gst_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL #define gst_marshal_VOID__INT gtk_marshal_NONE__INT +#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT #define gst_marshal_VOID__STRING gtk_marshal_NONE__STRING #define gst_marshal_VOID__POINTER gtk_marshal_NONE__POINTER #define gst_marshal_VOID__OBJECT gtk_marshal_NONE__POINTER @@ -241,7 +245,7 @@ struct _GParamSpec { }; #define g_value_init(value,t) ((value)->type = (t)) -#define g_value_copy gtk_arg_copy +#define g_value_copy(src_val,dest_val) (dest_val = gtk_arg_copy(src_val,dest_val)) #define g_value_unset(val) #define g_object_class_install_property g2g_object_class_install_property diff --git a/gst/gst.c b/gst/gst.c index 0eb794e0bd..8ecacbacfc 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -53,6 +53,18 @@ static void load_plugin_func (gpointer data, gpointer user_data); static GSList *preload_plugins = NULL; +const gchar *g_log_domain_gstreamer = "GStreamer"; + +static void +debug_log_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + g_log_default_handler(log_domain, log_level, message, user_data); + g_on_error_query(NULL); +} + /** * gst_init: * @argc: pointer to application's argc @@ -64,6 +76,7 @@ static GSList *preload_plugins = NULL; void gst_init (int *argc, char **argv[]) { + GLogLevelFlags llf; #ifndef GST_DISABLE_TRACE GstTrace *gst_trace; #endif @@ -92,6 +105,9 @@ gst_init (int *argc, char **argv[]) exit (0); // FIXME! } + llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL; + g_log_set_handler(g_log_domain_gstreamer, llf, debug_log_handler, NULL); + GST_INFO (GST_CAT_GST_INIT, "Initializing GStreamer Core Library"); gst_object_get_type (); diff --git a/gst/gst.h b/gst/gst.h index 9216029c4a..032d5d2c57 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -49,8 +49,6 @@ #include #include #include -#include -#include #include #include diff --git a/gst/gstautoplug.c b/gst/gstautoplug.c index af7736d268..612cd4b9ce 100644 --- a/gst/gstautoplug.c +++ b/gst/gstautoplug.c @@ -61,6 +61,7 @@ GType gst_autoplug_get_type(void) sizeof(GstAutoplug), 4, (GInstanceInitFunc)gst_autoplug_init, + NULL }; autoplug_type = g_type_register_static (GST_TYPE_OBJECT, "GstAutoplug", &autoplug_info, G_TYPE_FLAG_ABSTRACT); } @@ -194,6 +195,7 @@ gst_autoplugfactory_get_type (void) sizeof(GstAutoplugFactory), 0, (GInstanceInitFunc) gst_autoplugfactory_init, + NULL }; autoplugfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, "GstAutoplugFactory", &autoplugfactory_info, 0); diff --git a/gst/gstbin.c b/gst/gstbin.c index 561328e5c0..4396fe3da4 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -37,7 +37,7 @@ GstElementDetails gst_bin_details = { }; -static void gst_bin_real_destroy (GObject *object); +static void gst_bin_dispose (GObject *object); static GstElementStateReturn gst_bin_change_state (GstElement *element); static GstElementStateReturn gst_bin_change_state_norecurse (GstBin *bin); @@ -87,6 +87,7 @@ gst_bin_get_type (void) sizeof(GstBin), 8, (GInstanceInitFunc)gst_bin_init, + NULL }; bin_type = g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0); } @@ -122,8 +123,7 @@ gst_bin_class_init (GstBinClass *klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state); -// FIXME -// gobject_class->destroy = GST_DEBUG_FUNCPTR (gst_bin_real_destroy); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose); } static void @@ -170,7 +170,7 @@ gst_bin_reset_element_sched (GstElement *element, GstSchedule *sched) // GST_SCHEDULE_ADD_ELEMENT (sched, element); } -void +static void gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) { GList *children; @@ -211,7 +211,7 @@ gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) } -void +static void gst_bin_unset_element_sched (GstElement *element) { GList *children; @@ -475,13 +475,13 @@ gst_bin_set_state_type (GstBin *bin, } static void -gst_bin_real_destroy (GObject *object) +gst_bin_dispose (GObject *object) { GstBin *bin = GST_BIN (object); GList *children, *orig; GstElement *child; - GST_DEBUG (GST_CAT_REFCOUNTING,"destroy()\n"); + GST_DEBUG (GST_CAT_REFCOUNTING,"dispose\n"); if (bin->children) { orig = children = g_list_copy (bin->children); @@ -500,9 +500,7 @@ gst_bin_real_destroy (GObject *object) g_cond_free (bin->eoscond); -// FIXME!!! -// if (G_OBJECT_CLASS (parent_class)->destroy) -// G_OBJECT_CLASS (parent_class)->destroy (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } /** diff --git a/gst/gstdparam.c b/gst/gstdparam.c deleted file mode 100644 index c18ec58eb1..0000000000 --- a/gst/gstdparam.c +++ /dev/null @@ -1,187 +0,0 @@ -/* GStreamer - * Copyright (C) 2001 Steve Baker - * - * gstdparam.c: Dynamic Parameter functionality - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gst_private.h" - -#include "gstdparam.h" - -static void gst_dparam_class_init (GstDParamClass *klass); -static void gst_dparam_base_class_init (GstDParamClass *klass); -static void gst_dparam_init (GstDParam *dparam); - -static void gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp); -static 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), - (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_value_array(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_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; - 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(GValue*,values_length + 1); - - 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[x] = value; - 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; -} - -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[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; -} - - diff --git a/gst/gstdparammanager.c b/gst/gstdparammanager.c deleted file mode 100644 index a05bfe66c9..0000000000 --- a/gst/gstdparammanager.c +++ /dev/null @@ -1,459 +0,0 @@ -/* GStreamer - * Copyright (C) 2001 Steve Baker - * - * gstdparammanager.c: Dynamic Parameter group functionality - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gst_private.h" - -#include "gstdparammanager.h" -#include - - -static void gst_dpman_base_class_init (GstDParamManagerClass *klass); -static void gst_dpman_class_init (GstDParamManagerClass *klass); -static void gst_dpman_init (GstDParamManager *dpman); -static void gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman); -static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman); -static guint gst_dpman_first_countdown_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp); -static guint gst_dpman_first_countdown_noop(GstDParamManager *dpman, guint frames, gint64 timestamp); -static guint gst_dpman_countdown_noop(GstDParamManager *dpman, guint frame_count); - -GType -gst_dpman_get_type (void) -{ - static GType dpman_type = 0; - - if (!dpman_type) { - static const GTypeInfo dpman_info = { - sizeof(GstDParamManagerClass), - (GBaseInitFunc)gst_dpman_base_class_init, - NULL, - (GClassInitFunc)gst_dpman_class_init, - NULL, - NULL, - sizeof(GstDParamManager), - 0, - (GInstanceInitFunc)gst_dpman_init, - }; - dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParamManager", &dpman_info, 0); - } - return dpman_type; -} - -static void -gst_dpman_base_class_init (GstDParamManagerClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass*) klass; - -} - -static void -gst_dpman_class_init (GstDParamManagerClass *klass) -{ - GstObjectClass *gstobject_class; - GObjectClass *gobject_class; - - gstobject_class = (GstObjectClass*) klass; - gobject_class = (GObjectClass*) klass; - - klass->modes = g_hash_table_new(g_str_hash,g_str_equal); - - gst_dpman_register_mode (klass, "synchronous", - gst_dpman_first_countdown_synchronous, gst_dpman_countdown_noop, NULL, NULL); - gst_dpman_register_mode (klass, "asynchronous", - gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL); - gst_dpman_register_mode (klass, "disabled", - gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL); - -} - -static void -gst_dpman_init (GstDParamManager *dpman) -{ - GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal); - GST_DPMAN_DPARAMS_LIST(dpman) = NULL; - GST_DPMAN_NAME(dpman) = NULL; - GST_DPMAN_PARENT(dpman) = NULL; - GST_DPMAN_MODE_NAME(dpman) = NULL; - GST_DPMAN_MODE(dpman) = NULL; - GST_DPMAN_MODE_DATA(dpman) = NULL; - GST_DPMAN_RATE(dpman) = 0; -} - -/** - * gst_dpman_new: - * @name: name of the GstDParamManager instance - * @parent: element which created this instance - * - * Returns: a new instance of GstDParamManager - */ -GstDParamManager* -gst_dpman_new (gchar *name, GstElement *parent) -{ - GstDParamManager *dpman; - - g_return_val_if_fail (name != NULL, NULL); - - dpman = 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: - * @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/gstelement.c b/gst/gstelement.c index 874bf8ef2e..332c91be6e 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -56,8 +56,7 @@ static void gst_element_set_property (GObject *object, guint prop_id, static void gst_element_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static void gst_element_shutdown (GObject *object); -static void gst_element_real_destroy (GObject *object); +static void gst_element_dispose (GObject *object); static GstElementStateReturn gst_element_change_state (GstElement *element); @@ -84,6 +83,7 @@ GType gst_element_get_type (void) sizeof(GstElement), 0, (GInstanceInitFunc)gst_element_init, + NULL }; _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT); } @@ -140,9 +140,7 @@ gst_element_class_init (GstElementClass *klass) gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_get_property); -// gobject_class->shutdown = GST_DEBUG_FUNCPTR(gst_element_shutdown); -// FIXME! -// gobject_class->destroy = GST_DEBUG_FUNCPTR(gst_element_real_destroy); + gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_element_dispose); #ifndef GST_DISABLE_LOADSAVE gstobject_class->save_thyself = GST_DEBUG_FUNCPTR(gst_element_save_thyself); @@ -940,36 +938,23 @@ GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(GST_ELEMENT_PARENT(element)),GST_ELEM } static void -gst_element_shutdown (GObject *object) -{ - GstElement *element = GST_ELEMENT (object); - - GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "shutdown\n"); - - if (GST_IS_BIN (GST_OBJECT_PARENT (element))) - gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (element)), element); - -// if (G_OBJECT_CLASS (parent_class)->shutdown) -// G_OBJECT_CLASS (parent_class)->shutdown (G_OBJECT (object)); -} - -static void -gst_element_real_destroy (GObject *object) +gst_element_dispose (GObject *object) { GstElement *element = GST_ELEMENT (object); GList *pads; GstPad *pad; + + GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose\n"); + + if (GST_IS_BIN (GST_OBJECT_PARENT (element))) + gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (element)), element); - GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "destroy\n"); if (element->pads) { GList *orig; orig = pads = g_list_copy (element->pads); while (pads) { pad = GST_PAD (pads->data); - //gst_object_destroy (GST_OBJECT (pad)); - gst_object_ref (GST_OBJECT (pad)); - gst_element_remove_pad (element, pad); gst_object_unref (GST_OBJECT (pad)); pads = g_list_next (pads); } @@ -981,9 +966,7 @@ gst_element_real_destroy (GObject *object) element->numsrcpads = 0; element->numsinkpads = 0; -// FIXME! -// if (G_OBJECT_CLASS (parent_class)->destroy) -// G_OBJECT_CLASS (parent_class)->destroy (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } /* @@ -1142,9 +1125,9 @@ gst_element_restore_thyself (xmlNodePtr self, GstObject *parent) // first get the needed tags to construct the element while (children) { if (!strcmp (children->name, "name")) { - name = g_strdup (xmlNodeGetContent (children)); + name = xmlNodeGetContent (children); } else if (!strcmp (children->name, "type")) { - type = g_strdup (xmlNodeGetContent (children)); + type = xmlNodeGetContent (children); } children = children->next; } @@ -1171,10 +1154,10 @@ gst_element_restore_thyself (xmlNodePtr self, GstObject *parent) while (child) { if (!strcmp (child->name, "name")) { - name = g_strdup (xmlNodeGetContent (child)); + name = xmlNodeGetContent (child); } else if (!strcmp (child->name, "value")) { - value = g_strdup (xmlNodeGetContent (child)); + value = xmlNodeGetContent (child); } child = child->next; } diff --git a/gst/gstelement.h b/gst/gstelement.h index d7ceb7a914..1d05451878 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -30,7 +30,6 @@ #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -123,7 +122,6 @@ 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; @@ -149,8 +147,6 @@ struct _GstElement { guint16 numsinkpads; GList *pads; GstPad *select_pad; - - GstDParamManager *dpman; }; struct _GstElementClass { @@ -262,6 +258,8 @@ struct _GstElementFactory { GType type; /* unique GType of element */ + guint details_dynamic : 1; + GstElementDetails *details; /* pointer to details struct */ GList *padtemplates; diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 43a5d18c9f..0f4dde38c0 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -57,6 +57,7 @@ gst_elementfactory_get_type (void) sizeof(GstElementFactory), 0, (GInstanceInitFunc) gst_elementfactory_init, + NULL }; elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, "GstElementFactory", &elementfactory_info, 0); @@ -138,6 +139,25 @@ gst_elementfactory_get_list (void) return _gst_elementfactories; } +static void +gst_element_details_free (GstElementDetails *dp) +{ + g_return_if_fail (dp); + + if (dp->longname) + g_free (dp->longname); + if (dp->klass) + g_free (dp->klass); + if (dp->description) + g_free (dp->description); + if (dp->version) + g_free (dp->version); + if (dp->author) + g_free (dp->author); + if (dp->copyright) + g_free (dp->copyright); + g_free (dp); +} /** * gst_elementfactory_new: @@ -157,19 +177,31 @@ gst_elementfactory_new (const gchar *name, GType type, GstElementFactory *factory; g_return_val_if_fail(name != NULL, NULL); - g_return_val_if_fail(type != 0, NULL); + g_return_val_if_fail (type, NULL); + g_return_val_if_fail (details, NULL); factory = gst_elementfactory_find (name); - if (!factory) { - factory = GST_ELEMENTFACTORY (g_object_new (GST_TYPE_ELEMENTFACTORY, NULL)); - } - gst_object_set_name (GST_OBJECT (factory), name); - factory->type = type; - if (factory->details) - g_free (factory->details); + if (!factory) + factory = GST_ELEMENTFACTORY (g_object_new (GST_TYPE_ELEMENTFACTORY, NULL)); + + if (factory->details_dynamic) + { + gst_element_details_free (factory->details); + factory->details_dynamic = FALSE; + } + factory->details = details; + if (!factory->type) + factory->type = type; + else if (factory->type != type) +/* FIXME: g_critical is glib-2.0, not glib-1.2 + g_critical ("`%s' requested type change (!)", name); +*/ + g_warning ("`%s' requested type change (!)", name); + gst_object_set_name (GST_OBJECT (factory), name); + return factory; } @@ -194,12 +226,20 @@ gst_elementfactory_create (GstElementFactory *factory, g_return_val_if_fail(factory != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - GST_DEBUG (GST_CAT_ELEMENTFACTORY,"creating element from factory \"%s\" with name \"%s\"\n", - GST_OBJECT_NAME (factory), name); + GST_DEBUG (GST_CAT_ELEMENTFACTORY,"creating element from factory \"%s\" with name \"%s\" and type %d\n", + GST_OBJECT_NAME (factory), name, factory->type); gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory)); - g_return_val_if_fail(factory->type != 0, NULL); + if (factory->type == 0) + { +/* FIXME: g_critical is glib-2.0, not glib-1.2 + g_critical ("Factory for `%s' has no type", +*/ + g_warning ("Factory for `%s' has no type", + gst_object_get_name (GST_OBJECT (factory))); + return NULL; + } // create an instance of the element element = GST_ELEMENT(g_object_new(factory->type,NULL)); @@ -275,7 +315,9 @@ gst_elementfactory_add_padtemplate (GstElementFactory *factory, g_return_if_fail(templ != NULL); padtemplates = factory->padtemplates; - + + gst_object_ref (GST_OBJECT (templ)); + while (padtemplates) { GstPadTemplate *oldtempl = GST_PADTEMPLATE (padtemplates->data); @@ -383,12 +425,18 @@ gst_elementfactory_save_thyself (GstObject *object, g_return_val_if_fail(factory != NULL, NULL); - xmlNewChild(parent,NULL,"longname", factory->details->longname); - xmlNewChild(parent,NULL,"class", factory->details->klass); - xmlNewChild(parent,NULL,"description", factory->details->description); - xmlNewChild(parent,NULL,"version", factory->details->version); - xmlNewChild(parent,NULL,"author", factory->details->author); - xmlNewChild(parent,NULL,"copyright", factory->details->copyright); + if (factory->details) + { + xmlNewChild(parent,NULL,"longname", factory->details->longname); + xmlNewChild(parent,NULL,"class", factory->details->klass); + xmlNewChild(parent,NULL,"description", factory->details->description); + xmlNewChild(parent,NULL,"version", factory->details->version); + xmlNewChild(parent,NULL,"author", factory->details->author); + xmlNewChild(parent,NULL,"copyright", factory->details->copyright); + } + else + g_warning ("elementfactory `%s' is missing details", + object->name); pads = factory->padtemplates; if (pads) { @@ -410,6 +458,8 @@ gst_elementfactory_restore_thyself (GstObject *object, xmlNodePtr parent) { GstElementFactory *factory = GST_ELEMENTFACTORY (object); xmlNodePtr children = parent->xmlChildrenNode; + + factory->details_dynamic = TRUE; factory->details = g_new0(GstElementDetails, 1); factory->padtemplates = NULL; diff --git a/gst/gstextratypes.c b/gst/gstextratypes.c index 162bdb50a1..032f9efb9e 100644 --- a/gst/gstextratypes.c +++ b/gst/gstextratypes.c @@ -41,6 +41,7 @@ gst_extra_get_filename_type (void) 0, //sizeof(GstElement), 0, NULL, + NULL }; filename_type = g_type_register_static (G_TYPE_STRING, "GstFilename", &filename_info, 0); } diff --git a/gst/gstlog.h b/gst/gstlog.h index cba96eb924..0e9817445e 100644 --- a/gst/gstlog.h +++ b/gst/gstlog.h @@ -23,6 +23,8 @@ #ifndef __GST_LOG_H__ #define __GST_LOG_H__ +extern const char *g_log_domain_gstreamer; + /* information messages */ #define GST_SHOW_INFO #ifdef GST_SHOW_INFO diff --git a/gst/gstobject.c b/gst/gstobject.c index 4ca9a03587..70d81227c3 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -57,8 +57,7 @@ static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 }; static void gst_object_class_init (GstObjectClass *klass); static void gst_object_init (GstObject *object); -static void gst_object_real_destroy (GObject *object); -static void gst_object_shutdown (GObject *object); +static void gst_object_dispose (GObject *object); static void gst_object_finalize (GObject *object); static GObjectClass *parent_class = NULL; @@ -78,6 +77,7 @@ gst_object_get_type (void) sizeof (GstObject), 32, (GInstanceInitFunc) gst_object_init, + NULL }; _gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT); } @@ -110,8 +110,7 @@ gst_object_class_init (GstObjectClass *klass) // FIXME!!! // klass->signal_object = g_object_new(gst_signal_object_get_type (,NULL)); -// gobject_class->shutdown = gst_object_shutdown; -// gobject_class->destroy = gst_object_real_destroy; + gobject_class->dispose = gst_object_dispose; gobject_class->finalize = gst_object_finalize; } @@ -142,7 +141,6 @@ gst_object_ref (GstObject *object) G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count+1); g_object_ref (G_OBJECT (object)); - return object; } #define gst_object_ref gst_object_ref @@ -201,29 +199,19 @@ gst_object_destroy (GstObject *object) * invocations. */ gst_object_ref (object); -// G_OBJECT_GET_CLASS (object)->shutdown (G_OBJECT (object)); + G_OBJECT_GET_CLASS (object)->dispose (G_OBJECT (object)); gst_object_unref (object); } } static void -gst_object_shutdown (GObject *object) +gst_object_dispose (GObject *object) { - GST_DEBUG (GST_CAT_REFCOUNTING, "shutdown '%s'\n",GST_OBJECT_NAME(object)); + GST_DEBUG (GST_CAT_REFCOUNTING, "dispose '%s'\n",GST_OBJECT_NAME(object)); GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED); -// parent_class->shutdown (object); -} + GST_OBJECT_PARENT (object) = NULL; -/* finilize is called when the object has to free its resources */ -static void -gst_object_real_destroy (GObject *g_object) -{ - GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(g_object)); - - GST_OBJECT_PARENT (g_object) = NULL; - -// FIXME!! -// parent_class->destroy (g_object); + parent_class->dispose (object); } /* finilize is called when the object has to free its resources */ @@ -342,6 +330,8 @@ gst_object_unparent (GstObject *object) if (object->parent == NULL) return; + GST_DEBUG (GST_CAT_REFCOUNTING, "unparent '%s'\n",GST_OBJECT_NAME(object)); + object->parent = NULL; gst_object_unref (object); } @@ -608,6 +598,7 @@ gst_signal_object_get_type (void) sizeof(GstSignalObject), 16, (GInstanceInitFunc)gst_signal_object_init, + NULL }; signal_object_type = g_type_register_static(G_TYPE_OBJECT, "GstSignalObject", &signal_object_info, 0); } diff --git a/gst/gstpad.c b/gst/gstpad.c index b5c9d4d011..c5c985d025 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -24,6 +24,7 @@ #include "gst_private.h" #include "gstpad.h" +#include "gstutils.h" #include "gstelement.h" #include "gsttype.h" #include "gstbin.h" @@ -55,6 +56,7 @@ gst_pad_get_type(void) sizeof(GstPad), 32, (GInstanceInitFunc)gst_pad_init, + NULL }; _gst_pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0); } @@ -101,7 +103,7 @@ static void gst_real_pad_init (GstRealPad *pad); static void gst_real_pad_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_real_pad_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static void gst_real_pad_destroy (GObject *object); +static void gst_real_pad_dispose (GObject *object); static void gst_pad_push_func (GstPad *pad, GstBuffer *buf); @@ -123,6 +125,7 @@ gst_real_pad_get_type(void) { sizeof(GstRealPad), 32, (GInstanceInitFunc)gst_real_pad_init, + NULL }; _gst_real_pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0); } @@ -140,8 +143,7 @@ gst_real_pad_class_init (GstRealPadClass *klass) real_pad_parent_class = g_type_class_ref(GST_TYPE_PAD); -// FIXME! -// gobject_class->destroy = GST_DEBUG_FUNCPTR(gst_real_pad_destroy); + gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_real_pad_dispose); gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_real_pad_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_real_pad_get_property); @@ -284,10 +286,10 @@ gst_pad_new_from_template (GstPadTemplate *templ, g_return_val_if_fail (templ != NULL, NULL); pad = gst_pad_new (name, templ->direction); + gst_object_ref (GST_OBJECT (templ)); - gst_object_sink (GST_OBJECT (templ)); GST_PAD_PADTEMPLATE(pad) = templ; - + return pad; } @@ -552,11 +554,36 @@ gst_pad_disconnect (GstPad *srcpad, * * Connects the source pad to the sink pad. * + * You shouldn't use this API in a real application because the + * failure mode dumps diagnostics to stderr. A professional + * application should never fail, or use gst_pad_try_connect and + * check the return code. + */ +void +gst_pad_connect (GstPad *srcpad, + GstPad *sinkpad) +{ + if (!gst_pad_try_connect (srcpad, sinkpad)) +/* FIXME: g_critical is glib-2.0, not glib-1.2 + g_critical ("couldn't connect %s:%s and %s:%s", +*/ + g_warning ("couldn't connect %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (srcpad), + GST_DEBUG_PAD_NAME (sinkpad)); +} + +/** + * gst_pad_try_connect: + * @srcpad: the source pad to connect + * @sinkpad: the sink pad to connect + * + * Connects the source pad to the sink pad. + * * Returns: TRUE if the pad could be connected */ gboolean -gst_pad_connect (GstPad *srcpad, - GstPad *sinkpad) +gst_pad_try_connect (GstPad *srcpad, + GstPad *sinkpad) { GstRealPad *realsrc, *realsink; gboolean negotiated = FALSE; @@ -994,21 +1021,27 @@ gst_pad_get_bufferpool (GstPad *pad) } static void -gst_real_pad_destroy (GObject *object) +gst_real_pad_dispose (GObject *object) { GstPad *pad = GST_PAD (object); + + GST_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s\n", GST_DEBUG_PAD_NAME(pad)); - GST_DEBUG (GST_CAT_REFCOUNTING, "destroy %s:%s\n", GST_DEBUG_PAD_NAME(pad)); - - if (GST_PAD (pad)->padtemplate) + if (GST_PAD (pad)->padtemplate){ + GST_DEBUG (GST_CAT_REFCOUNTING, "unreffing padtemplate'%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_PAD (pad)->padtemplate))); gst_object_unref (GST_OBJECT (GST_PAD (pad)->padtemplate)); - - if (GST_PAD_PEER (pad)) + } + + if (GST_PAD_PEER (pad)){ + GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_PAD (GST_PAD_PEER (pad))))); gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad))); - - if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) + } + + if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){ + GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad))))); gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad); - + } + // FIXME we should destroy the ghostpads, because they are nothing without the real pad if (GST_REAL_PAD (pad)->ghostpads) { GList *orig, *ghostpads; @@ -1018,18 +1051,17 @@ gst_real_pad_destroy (GObject *object) while (ghostpads) { GstPad *ghostpad = GST_PAD (ghostpads->data); - if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) + if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){ + GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n", GST_OBJECT_NAME(GST_OBJECT_PARENT (ghostpad))); gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), ghostpad); - + } ghostpads = g_list_next (ghostpads); } g_list_free (orig); g_list_free (GST_REAL_PAD(pad)->ghostpads); } -// FIXME !! -// if (G_OBJECT_CLASS (real_pad_parent_class)->destroy) -// G_OBJECT_CLASS (real_pad_parent_class)->destroy (object); + G_OBJECT_CLASS (real_pad_parent_class)->dispose (object); } @@ -1058,7 +1090,7 @@ gst_pad_load_and_connect (xmlNodePtr self, pad = gst_element_get_pad (GST_ELEMENT (parent), xmlNodeGetContent (field)); } else if (!strcmp(field->name, "peer")) { - peer = g_strdup (xmlNodeGetContent (field)); + peer = xmlNodeGetContent (field); } field = field->next; } @@ -1424,7 +1456,9 @@ gst_pad_push (GstPad *pad, GstBuffer *buf) GST_DEBUG_FUNCPTR_NAME (peer->chainhandler), GST_DEBUG_PAD_NAME (((GstPad*)peer))); (peer->chainhandler) (((GstPad*)peer), buf); } else - GST_DEBUG (GST_CAT_DATAFLOW, "no chainhandler\n"); + { + GST_DEBUG (GST_CAT_DATAFLOW, "no chainhandler\n"); + } } #endif @@ -1445,7 +1479,15 @@ gst_pad_pull (GstPad *pad) GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad)); g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL); - g_return_val_if_fail (peer != NULL, NULL); + + if (!peer) + { +/* FIXME: g_critical is glib-2.0, not glib-1.2 + g_critical ("gst_pad_pull but %s:%s is unconnected", GST_DEBUG_PAD_NAME(pad)); +*/ + g_warning ("gst_pad_pull but %s:%s is unconnected", GST_DEBUG_PAD_NAME(pad)); + return NULL; + } if (peer->gethandler) { GST_DEBUG (GST_CAT_DATAFLOW,"calling gethandler %s of peer pad %s:%s\n", @@ -1610,6 +1652,7 @@ gst_padtemplate_get_type (void) sizeof(GstPadTemplate), 32, (GInstanceInitFunc)gst_padtemplate_init, + NULL }; padtemplate_type = g_type_register_static(GST_TYPE_OBJECT, "GstPadTemplate", &padtemplate_info, 0); } @@ -1858,6 +1901,7 @@ gst_ghost_pad_get_type(void) { sizeof(GstGhostPad), 8, (GInstanceInitFunc)gst_ghost_pad_init, + NULL }; _gst_ghost_pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0); } diff --git a/gst/gstpad.h b/gst/gstpad.h index c1d63b043b..70f0a39647 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -374,7 +374,8 @@ GstPad* gst_pad_get_peer (GstPad *pad); GstBufferPool* gst_pad_get_bufferpool (GstPad *pad); -gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad); +gboolean gst_pad_try_connect (GstPad *srcpad, GstPad *sinkpad); +void gst_pad_connect (GstPad *srcpad, GstPad *sinkpad); void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad); gboolean gst_pad_renegotiate (GstPad *pad); @@ -442,6 +443,9 @@ xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr pare GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent); #endif +xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad, + GstElement *bin, + xmlNodePtr parent); #ifdef __cplusplus } diff --git a/gst/gstparse.c b/gst/gstparse.c index a0f3fe12f5..b7e519175a 100644 --- a/gst/gstparse.c +++ b/gst/gstparse.c @@ -88,9 +88,11 @@ dynamic_connect (GstElement *element, GstPad *newpad, gpointer data) static gchar * gst_parse_unique_name(gchar *type,gst_parse_priv *priv) { + gpointer tmp; gint count; - count = GPOINTER_TO_INT(g_hash_table_lookup(priv->elementcounts,type)); + tmp = g_hash_table_lookup (priv->elementcounts,type); + count = GPOINTER_TO_INT (tmp); count++; g_hash_table_insert(priv->elementcounts,type,GINT_TO_POINTER(count)); @@ -233,6 +235,7 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr argname = arg; pos[0] = '\0'; argval = pos+1; + GST_DEBUG(0,"attempting to set argument '%s' to '%s' on element '%s'\n", argname,argval,GST_ELEMENT_NAME(previous)); gst_util_set_object_arg (G_OBJECT(previous), argname, argval); @@ -361,7 +364,7 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr } } - if (!sinkpads) GST_DEBUG(0,"can't find a sink pad for %s\n", gst_element_get_name (previous)); + if (!sinkpads) GST_DEBUG(0,"can't find a sink pad for element\n"); else GST_DEBUG(0,"have sink pad %s:%s\n",GST_DEBUG_PAD_NAME(GST_PARSE_LISTPAD(sinkpads))); if (!srcpads && sinkpads && previous) { @@ -375,8 +378,10 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr srcpadname, GST_DEBUG_PAD_NAME(GST_PARSE_LISTPAD(sinkpads))); - g_signal_connect (G_OBJECT (previous), "new_pad", dynamic_connect, connect); - g_signal_connect (G_OBJECT (previous), "new_ghost_pad", dynamic_connect, connect); + g_signal_connect (G_OBJECT (previous), "new_pad", + G_CALLBACK (dynamic_connect), connect); + g_signal_connect (G_OBJECT (previous), "new_ghost_pad", + G_CALLBACK (dynamic_connect), connect); } else { for (j=0; (jsched; @@ -951,7 +952,7 @@ gst_schedule_chain_destroy (GstScheduleChain *chain) GST_INFO (GST_CAT_SCHEDULING, "destroyed chain %p, now are %d chains in sched %p",chain,sched->num_chains,sched); } -void +static void gst_schedule_chain_add_element (GstScheduleChain *chain, GstElement *element) { GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to chain %p", GST_ELEMENT_NAME (element),chain); @@ -964,7 +965,7 @@ gst_schedule_chain_add_element (GstScheduleChain *chain, GstElement *element) chain->num_elements++; } -void +static void gst_schedule_chain_enable_element (GstScheduleChain *chain, GstElement *element) { GST_INFO (GST_CAT_SCHEDULING, "enabling element \"%s\" in chain %p", GST_ELEMENT_NAME (element),chain); @@ -979,7 +980,7 @@ gst_schedule_chain_enable_element (GstScheduleChain *chain, GstElement *element) gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain); } -void +static void gst_schedule_chain_disable_element (GstScheduleChain *chain, GstElement *element) { GST_INFO (GST_CAT_SCHEDULING, "disabling element \"%s\" in chain %p", GST_ELEMENT_NAME (element),chain); @@ -995,7 +996,7 @@ gst_schedule_chain_disable_element (GstScheduleChain *chain, GstElement *element // gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain); } -void +static void gst_schedule_chain_remove_element (GstScheduleChain *chain, GstElement *element) { GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from chain %p", GST_ELEMENT_NAME (element),chain); @@ -1017,7 +1018,7 @@ gst_schedule_chain_remove_element (GstScheduleChain *chain, GstElement *element) element->sched = NULL; } -void +static void gst_schedule_chain_elements (GstSchedule *sched, GstElement *element1, GstElement *element2) { GList *chains; @@ -1103,7 +1104,7 @@ GST_ELEMENT_SCHED(srcelement),GST_ELEMENT_SCHED(sinkelement)); } // find the chain within the schedule that holds the element, if any -GstScheduleChain * +static GstScheduleChain * gst_schedule_find_chain (GstSchedule *sched, GstElement *element) { GList *chains; @@ -1125,7 +1126,7 @@ gst_schedule_find_chain (GstSchedule *sched, GstElement *element) return NULL; } -void +static void gst_schedule_chain_recursive_add (GstScheduleChain *chain, GstElement *element) { GList *pads; diff --git a/gst/gstthread.c b/gst/gstthread.c index a1cdc2bba5..27ae96c6d7 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -61,7 +61,7 @@ enum { static void gst_thread_class_init (GstThreadClass *klass); static void gst_thread_init (GstThread *thread); -static void gst_thread_real_destroy (GObject *object); +static void gst_thread_dispose (GObject *object); static void gst_thread_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_thread_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); @@ -95,6 +95,7 @@ gst_thread_get_type(void) { sizeof(GstThread), 4, (GInstanceInitFunc)gst_thread_init, + NULL }; thread_type = g_type_register_static(GST_TYPE_BIN, "GstThread", &thread_info, 0); } @@ -120,8 +121,7 @@ gst_thread_class_init (GstThreadClass *klass) g_param_spec_boolean("create_thread", "Create Thread", "Whether to create a thread.", TRUE,G_PARAM_READWRITE)); -// FIXME! -// gobject_class->destroy = gst_thread_real_destroy; + gobject_class->dispose = gst_thread_dispose; #ifndef GST_DISABLE_LOADSAVE gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_thread_save_thyself); @@ -161,21 +161,20 @@ gst_thread_init (GstThread *thread) } static void -gst_thread_real_destroy (GObject *object) +gst_thread_dispose (GObject *object) { GstThread *thread = GST_THREAD (object); - GST_DEBUG (GST_CAT_REFCOUNTING,"destroy()\n"); + GST_DEBUG (GST_CAT_REFCOUNTING,"dispose\n"); g_mutex_free (thread->lock); g_cond_free (thread->cond); -// FIXME! -// if (G_OBJECT_CLASS (parent_class)->destroy) -// G_OBJECT_CLASS (parent_class)->destroy (object); + G_OBJECT_CLASS (parent_class)->dispose (object); gst_object_destroy (GST_OBJECT (GST_ELEMENT_SCHED (thread))); gst_object_unref (GST_OBJECT (GST_ELEMENT_SCHED (thread))); + } static void @@ -256,7 +255,6 @@ gst_thread_change_state (GstElement *element) gboolean stateset = GST_STATE_SUCCESS; gint transition; pthread_t self = pthread_self(); - GstElement *peerelement; g_return_val_if_fail (GST_IS_THREAD(element), FALSE); // GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME(element)); @@ -394,10 +392,15 @@ gst_thread_change_state (GstElement *element) GList *pads = GST_ELEMENT_PADS(e); while (pads) { + GstRealPad *peer; + GstElement *peerelement; GstPad *p = GST_PAD(pads->data); pads = g_list_next(pads); - peerelement = GST_PAD_PARENT(GST_PAD_PEER(p)); + peer = GST_PAD_PEER(p); + if (!peer) continue; + + peerelement = GST_PAD_PARENT(peer); if (!peerelement) continue; // deal with case where there's no peer if (!GST_FLAG_IS_SET(peerelement,GST_ELEMENT_DECOUPLED)) { diff --git a/gst/gsttrace.c b/gst/gsttrace.c index fb0c7b1a23..6aad091253 100644 --- a/gst/gsttrace.c +++ b/gst/gsttrace.c @@ -30,6 +30,7 @@ #include "gst_private.h" +#include "gstlog.h" #include "gsttrace.h" diff --git a/gst/gsttype.c b/gst/gsttype.c index 99bee4c2d8..feeac26506 100644 --- a/gst/gsttype.c +++ b/gst/gsttype.c @@ -69,6 +69,7 @@ gst_typefactory_get_type (void) sizeof(GstTypeFactory), 0, (GInstanceInitFunc) gst_typefactory_init, + NULL }; typefactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, "GstTypeFactory", &typefactory_info, 0); diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index 09894e0de1..44a557ee3d 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -81,6 +81,7 @@ gst_typefind_get_type (void) sizeof(GstTypeFind), 0, (GInstanceInitFunc)gst_typefind_init, + NULL }; typefind_type = g_type_register_static (GST_TYPE_ELEMENT, "GstTypeFind", &typefind_info, 0); } diff --git a/gst/gstutils.c b/gst/gstutils.c index 7681ad3e11..f38f39caa9 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -28,6 +28,8 @@ #include "gstextratypes.h" +#define ZERO(mem) memset(&mem, 0, sizeof(mem)) + /** * gst_util_get_int_arg: * @object: the object to query @@ -40,8 +42,9 @@ gint gst_util_get_int_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_INT); g_object_get_property(G_OBJECT(object),argname,&value); @@ -60,8 +63,9 @@ gst_util_get_int_arg (GObject *object, const gchar *argname) gint gst_util_get_bool_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_BOOLEAN); g_object_get_property(G_OBJECT(object),argname,&value); @@ -80,8 +84,9 @@ gst_util_get_bool_arg (GObject *object, const gchar *argname) glong gst_util_get_long_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_LONG); g_object_get_property(G_OBJECT(object),argname,&value); @@ -100,8 +105,9 @@ gst_util_get_long_arg (GObject *object, const gchar *argname) gfloat gst_util_get_float_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_FLOAT); g_object_get_property(G_OBJECT(object),argname,&value); @@ -120,8 +126,9 @@ gst_util_get_float_arg (GObject *object, const gchar *argname) gdouble gst_util_get_double_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_DOUBLE); g_object_get_property(G_OBJECT(object),argname,&value); @@ -140,12 +147,13 @@ gst_util_get_double_arg (GObject *object, const gchar *argname) const gchar* gst_util_get_string_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_STRING); g_object_get_property(G_OBJECT(object),argname,&value); - return g_value_get_string(&value); + return g_value_get_string(&value); // memleak? } /** @@ -160,8 +168,9 @@ gst_util_get_string_arg (GObject *object, const gchar *argname) gpointer gst_util_get_pointer_arg (GObject *object, const gchar *argname) { - GValue value = {0, }; + GValue value; + ZERO (value); g_value_init (&value, G_TYPE_POINTER); g_object_get_property(G_OBJECT(object),argname,&value); @@ -315,3 +324,217 @@ gst_util_set_object_arg (GObject *object, const gchar *name, const gchar *valu } } } + +// ----------------------------------------------------- +// +// The following code will be moved out of the main +// gstreamer library someday. +// + +#include "gstpad.h" +#include "gsttype.h" +#include "gstprops.h" +#include "gstpropsprivate.h" + +static void string_append_indent (GString *str, gint count) +{ + gint xx; + for (xx=0; xx < count; xx++) + g_string_append_c (str, ' '); +} + +static void +gst_print_props (GString *buf, gint indent, + GList *props, gboolean showname) +{ + GList *elem; + guint width = 0; + + if (showname) + for (elem = props; elem; elem = g_list_next (elem)) + { + GstPropsEntry *prop = elem->data; + const gchar *name = g_quark_to_string (prop->propid); + + if (width < strlen (name)) + width = strlen (name); + } + + for (elem = props; elem; elem = g_list_next (elem)) + { + GstPropsEntry *prop = elem->data; + + string_append_indent (buf, indent); + if (showname) + { + const gchar *name = g_quark_to_string (prop->propid); + + g_string_append (buf, name); + string_append_indent (buf, 2 + width - strlen (name)); + } + + switch (prop->propstype) { + case GST_PROPS_INT_ID: + g_string_printfa (buf, "%d (int)\n", prop->data.int_data); + break; + case GST_PROPS_INT_RANGE_ID: + g_string_printfa (buf, "%d - %d (int)\n", + prop->data.int_range_data.min, + prop->data.int_range_data.max); + break; + case GST_PROPS_FLOAT_ID: + g_string_printfa (buf, "%f (float)\n", prop->data.float_data); + break; + case GST_PROPS_FLOAT_RANGE_ID: + g_string_printfa (buf, "%f - %f (float)\n", + prop->data.float_range_data.min, + prop->data.float_range_data.max); + break; + case GST_PROPS_BOOL_ID: + g_string_printfa (buf, "%s\n", + prop->data.bool_data ? "TRUE" : "FALSE"); + break; + case GST_PROPS_STRING_ID: + g_string_printfa (buf, "\"%s\"\n", prop->data.string_data.string); + break; + case GST_PROPS_FOURCC_ID: + g_string_printfa (buf, "'%c%c%c%c' (fourcc)\n", + prop->data.fourcc_data & 0xff, + prop->data.fourcc_data>>8 & 0xff, + prop->data.fourcc_data>>16 & 0xff, + prop->data.fourcc_data>>24 & 0xff); + break; + case GST_PROPS_LIST_ID: + gst_print_props (buf, indent+2, prop->data.list_data.entries, FALSE); + break; + default: + g_string_printfa (buf, "unknown proptype %d\n", prop->propstype); + break; + } + } +} + +void gst_print_pad_caps (GString *buf, gint indent, GstPad *pad) +{ + GstRealPad *realpad; + GstCaps *caps; + + realpad = GST_PAD_REALIZE(pad); + caps = realpad->caps; + + if (!caps) + { + string_append_indent (buf, indent); + g_string_printf (buf, "%s:%s has no capabilities", + GST_DEBUG_PAD_NAME (pad)); + } + else + { + gint capx = 0; + + while (caps) { + GstType *type; + + string_append_indent (buf, indent); + g_string_printfa (buf, "Cap[%d]: %s\n", capx++, caps->name); + + type = gst_type_find_by_id (caps->id); + string_append_indent (buf, indent+2); + g_string_printfa (buf, "MIME type: %s\n", + type->mime? type->mime : "unknown/unknown"); + + if (caps->properties) + gst_print_props (buf, indent + 4, + caps->properties->properties, TRUE); + + caps = caps->next; + } + } +} + +void gst_print_element_args (GString *buf, gint indent, GstElement *element) +{ + gint num_properties; + gint px; + guint width; + + GParamSpec **property_specs = + g_object_class_list_properties (G_OBJECT_GET_CLASS (element), + &num_properties); + + width=0; + for (px=0; px < num_properties; px++) { + GParamSpec *param = property_specs[px]; + if (width < strlen (param->name)) + width = strlen (param->name); + } + + for (px=0; px < num_properties; px++) { + GParamSpec *param = property_specs[px]; + GValue value; + + ZERO (value); + + g_value_init (&value, param->value_type); + g_object_get_property (G_OBJECT (element), param->name, &value); + + string_append_indent (buf, indent); + g_string_append (buf, param->name); + string_append_indent (buf, 2 + width - strlen (param->name)); + + if (G_IS_PARAM_SPEC_ENUM (param)) { + GEnumValue *values; + +#ifdef USE_GLIB2 + values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values; +#else + values = gtk_type_enum_get_values (param->value_type); +#endif + + g_string_printfa (buf, "%s (%s)", + values [g_value_get_enum (&value)].value_nick, + g_type_name (G_VALUE_TYPE (&value))); + } + else + switch (G_VALUE_TYPE (&value)) { + case G_TYPE_STRING: + g_string_printfa (buf, "\"%s\"", g_value_get_string (&value)); + break; + case G_TYPE_BOOLEAN: + g_string_append (buf, g_value_get_boolean (&value)? "TRUE":"FALSE"); + break; + case G_TYPE_ULONG:{ + gulong val = g_value_get_ulong (&value); + g_string_printfa (buf, "%lu (0x%lx)", val, val); + break;} + case G_TYPE_LONG:{ + glong val = g_value_get_long (&value); + g_string_printfa (buf, "%ld (0x%lx)", val, val); + break;} + case G_TYPE_UINT:{ + guint val = g_value_get_uint (&value); + g_string_printfa (buf, "%u (0x%x)", val, val); + break;} + case G_TYPE_INT:{ + gint val = g_value_get_int (&value); + g_string_printfa (buf, "%d (0x%x)", val, val); + break;} + case G_TYPE_FLOAT: + g_string_printfa (buf, "%f", g_value_get_float (&value)); + break; + case G_TYPE_DOUBLE: + g_string_printfa (buf, "%f", g_value_get_double (&value)); + break; + default: + g_string_printfa (buf, "unknown value_type %d", G_VALUE_TYPE (&value)); + break; + } + + g_string_append_c (buf, '\n'); + + if (G_VALUE_TYPE (&value)) + g_value_unset (&value); + } + + g_free (property_specs); +} diff --git a/gst/gstutils.h b/gst/gstutils.h index daf2b2aa53..e7e1fa5f98 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -44,6 +44,10 @@ void gst_util_set_object_arg (GObject *object, const gchar *name, const gchar void gst_util_dump_mem (guchar *mem, guint size); + +void gst_print_pad_caps (GString *buf, gint indent, GstPad *pad); +void gst_print_element_args (GString *buf, gint indent, GstElement *element); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gst/gstxml.c b/gst/gstxml.c index 54d311c2a7..5d29e212b7 100644 --- a/gst/gstxml.c +++ b/gst/gstxml.c @@ -54,6 +54,7 @@ gst_xml_get_type(void) sizeof(GstXML), 0, (GInstanceInitFunc)gst_xml_init, + NULL }; xml_type = g_type_register_static (GST_TYPE_OBJECT, "GstXml", &xml_info, 0); } diff --git a/include/Makefile.am b/include/Makefile.am index 8253f453fb..8e8427c288 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,6 @@ noinst_HEADERS = \ mmx.h \ - sse.h \ - gstaudio.h + sse.h # This test needs to go here because this is the first makefile which the # install target gets run in. diff --git a/include/gstaudio.h b/include/gstaudio.h deleted file mode 100644 index a661159eab..0000000000 --- a/include/gstaudio.h +++ /dev/null @@ -1,84 +0,0 @@ -/* GStreamer - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000 Wim Taymans - * - * gstaudio.h: convenience macros for pad capabilities - * - * 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. - */ - -/* for people that are looking at this source: the purpose of these defines is - * to make GstCaps a bit easier, in that you don't have to know all of the - * properties that need to be defined. you can just use these macros. currently - * (8/01) the only plugins that use these are the passthrough, speed, volume, - * and [de]interleave plugins. so. these are for convenience only, and do not - * specify the 'limits' of gstreamer. you might also use these definitions as a - * base for making your own caps, if need be. - * - * for example, to make a source pad that can output mono streams of either - * float or int: - - template = gst_padtemplate_new - ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - gst_caps_append(gst_caps_new ("sink_int", "audio/raw", - GST_AUDIO_INT_PAD_TEMPLATE_PROPS), - gst_caps_new ("sink_float", "audio/raw", - GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS)), - NULL); - - srcpad = gst_pad_new_from_template(template,"src"); - - * Andy Wingo, 18 August 2001 */ - -#define GST_AUDIO_INT_PAD_TEMPLATE_PROPS \ - gst_props_new (\ - "format", GST_PROPS_STRING ("int"),\ - "law", GST_PROPS_INT (0),\ - "endianness", GST_PROPS_INT (G_BYTE_ORDER),\ - "signed", GST_PROPS_LIST (\ - GST_PROPS_BOOLEAN (TRUE),\ - GST_PROPS_BOOLEAN(FALSE)\ - ),\ - "width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ - "depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ - "rate", GST_PROPS_INT_RANGE (4000, 96000),\ - "channels", GST_PROPS_INT_RANGE (1, G_MAXINT),\ - NULL) - -#define GST_AUDIO_INT_MONO_PAD_TEMPLATE_PROPS \ - gst_props_new (\ - "format", GST_PROPS_STRING ("int"),\ - "law", GST_PROPS_INT (0),\ - "endianness", GST_PROPS_INT (G_BYTE_ORDER),\ - "signed", GST_PROPS_LIST (\ - GST_PROPS_BOOLEAN (TRUE),\ - GST_PROPS_BOOLEAN(FALSE)\ - ),\ - "width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ - "depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ - "rate", GST_PROPS_INT_RANGE (4000, 96000),\ - "channels", GST_PROPS_INT (1),\ - NULL) - -#define GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS \ - gst_props_new (\ - "format", GST_PROPS_STRING ("float"),\ - "layout", GST_PROPS_STRING ("gfloat"),\ - "intercept", GST_PROPS_FLOAT (0.0),\ - "slope", GST_PROPS_FLOAT (1.0),\ - "rate", GST_PROPS_INT_RANGE (4000, 96000),\ - "channels", GST_PROPS_INT (1),\ - NULL) diff --git a/libs/Makefile.am b/libs/Makefile.am index a7f69c30b9..581277f9d2 100644 --- a/libs/Makefile.am +++ b/libs/Makefile.am @@ -1,4 +1,3 @@ +SUBDIRS = riff getbits putbits idct audio bytestream control -SUBDIRS = riff getbits putbits idct audio bytestream - -DIST_SUBDIRS = riff getbits putbits audio idct bytestream +DIST_SUBDIRS = riff getbits putbits audio idct bytestream control diff --git a/libs/audio/gstaudio.h b/libs/audio/gstaudio.h index 7cced9acf2..09ef3ec796 100644 --- a/libs/audio/gstaudio.h +++ b/libs/audio/gstaudio.h @@ -18,13 +18,76 @@ * Boston, MA 02111-1307, USA. */ +#include + +/* for people that are looking at this source: the purpose of these defines is + * to make GstCaps a bit easier, in that you don't have to know all of the + * properties that need to be defined. you can just use these macros. currently + * (8/01) the only plugins that use these are the passthrough, speed, volume, + * and [de]interleave plugins. so. these are for convenience only, and do not + * specify the 'limits' of gstreamer. you might also use these definitions as a + * base for making your own caps, if need be. + * + * for example, to make a source pad that can output mono streams of either + * float or int: + + template = gst_padtemplate_new + ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + gst_caps_append(gst_caps_new ("sink_int", "audio/raw", + GST_AUDIO_INT_PAD_TEMPLATE_PROPS), + gst_caps_new ("sink_float", "audio/raw", + GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS)), + NULL); + + srcpad = gst_pad_new_from_template(template,"src"); + + * Andy Wingo, 18 August 2001 */ + +#define GST_AUDIO_INT_PAD_TEMPLATE_PROPS \ + gst_props_new (\ + "format", GST_PROPS_STRING ("int"),\ + "law", GST_PROPS_INT (0),\ + "endianness", GST_PROPS_INT (G_BYTE_ORDER),\ + "signed", GST_PROPS_LIST (\ + GST_PROPS_BOOLEAN (TRUE),\ + GST_PROPS_BOOLEAN(FALSE)\ + ),\ + "width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ + "depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ + "rate", GST_PROPS_INT_RANGE (4000, 96000),\ + "channels", GST_PROPS_INT_RANGE (1, G_MAXINT),\ + NULL) + +#define GST_AUDIO_INT_MONO_PAD_TEMPLATE_PROPS \ + gst_props_new (\ + "format", GST_PROPS_STRING ("int"),\ + "law", GST_PROPS_INT (0),\ + "endianness", GST_PROPS_INT (G_BYTE_ORDER),\ + "signed", GST_PROPS_LIST (\ + GST_PROPS_BOOLEAN (TRUE),\ + GST_PROPS_BOOLEAN(FALSE)\ + ),\ + "width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ + "depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\ + "rate", GST_PROPS_INT_RANGE (4000, 96000),\ + "channels", GST_PROPS_INT (1),\ + NULL) + +#define GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS \ + gst_props_new (\ + "format", GST_PROPS_STRING ("float"),\ + "layout", GST_PROPS_STRING ("gfloat"),\ + "intercept", GST_PROPS_FLOAT (0.0),\ + "slope", GST_PROPS_FLOAT (1.0),\ + "rate", GST_PROPS_INT_RANGE (4000, 96000),\ + "channels", GST_PROPS_INT (1),\ + NULL) + /* * this library defines and implements some helper functions for audio * handling */ -#include - /* get byte size of audio frame (based on caps of pad */ int gst_audio_frame_byte_size (GstPad* pad); @@ -43,3 +106,4 @@ long gst_audio_highest_sample_value (GstPad* pad); /* check if the buffer size is a whole multiple of the frame size */ gboolean gst_audio_is_buffer_framed (GstPad* pad, GstBuffer* buf); + diff --git a/libs/control/Makefile.am b/libs/control/Makefile.am new file mode 100644 index 0000000000..bb721257f1 --- /dev/null +++ b/libs/control/Makefile.am @@ -0,0 +1,21 @@ +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 diff --git a/libs/control/gstcontrol.c b/libs/control/gstcontrol.c new file mode 100644 index 0000000000..9be50955ae --- /dev/null +++ b/libs/control/gstcontrol.c @@ -0,0 +1,22 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * 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" diff --git a/libs/control/gstcontrol.h b/libs/control/gstcontrol.h new file mode 100644 index 0000000000..764f37bdd7 --- /dev/null +++ b/libs/control/gstcontrol.h @@ -0,0 +1,41 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#include + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_CONTROL_H__ */ diff --git a/libs/control/gstdparam.c b/libs/control/gstdparam.c new file mode 100644 index 0000000000..665b66d2a8 --- /dev/null +++ b/libs/control/gstdparam.c @@ -0,0 +1,368 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparam.c: Dynamic Parameter functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#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; +} diff --git a/gst/gstdparam.h b/libs/control/gstdparam.h similarity index 80% rename from gst/gstdparam.h rename to libs/control/gstdparam.h index e7dbb4eff2..72d5fad3a9 100644 --- a/gst/gstdparam.h +++ b/libs/control/gstdparam.h @@ -29,8 +29,9 @@ 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(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)) @@ -38,12 +39,16 @@ extern "C" { #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)) @@ -75,7 +80,7 @@ typedef enum { typedef struct _GstDParam GstDParam; typedef struct _GstDParamClass GstDParamClass; -typedef struct _GstDParamModel GstDParamModel; +typedef struct _GstDParamSpec GstDParamSpec; typedef GValue** (*GstDParamInsertPointFunction) (GstDParam *dparam, guint64 timestamp); typedef void (*GstDParamRemovePointFunction) (GstDParam *dparam, GValue** point); @@ -97,10 +102,13 @@ struct _GstDParam { 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 { @@ -109,10 +117,27 @@ struct _GstDParamClass { /* 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 (); -void gst_dparam_set_parent (GstDParam *dparam, GstObject *parent); +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 } diff --git a/libs/control/gstdparammanager.c b/libs/control/gstdparammanager.c new file mode 100644 index 0000000000..efba3735a2 --- /dev/null +++ b/libs/control/gstdparammanager.c @@ -0,0 +1,760 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparammanager.c: Dynamic Parameter group functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gstdparammanager.h" +#include +#include + +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; +} + diff --git a/gst/gstdparammanager.h b/libs/control/gstdparammanager.h similarity index 54% rename from gst/gstdparammanager.h rename to libs/control/gstdparammanager.h index 06fa76cb26..e8799e6313 100644 --- a/gst/gstdparammanager.h +++ b/libs/control/gstdparammanager.h @@ -23,7 +23,8 @@ #define __GST_DPMAN_H__ #include -#include +#include +#include #ifdef __cplusplus extern "C" { @@ -45,17 +46,23 @@ extern "C" { #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 _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 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); +typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data); struct _GstDParamManager { GstObject object; @@ -64,7 +71,7 @@ struct _GstDParamManager { GSList *dparams_list; gchar *mode_name; - GstDpmMode* mode; + GstDPMMode* mode; gpointer mode_data; gint64 timestamp; @@ -78,58 +85,76 @@ struct _GstDParamManagerClass { /* signal callbacks */ }; -struct _GstDpmMode { - GstDpmModeFirstCountdownFunction firstcountdownfunc; - GstDpmModeCountdownFunction countdownfunc; - GstDpmModeSetupFunction setupfunc; - GstDpmModeTeardownFunction teardownfunc; +struct _GstDPMMode { + GstDPMModePreProcessFunction preprocessfunc; + GstDPMModeProcessFunction processfunc; + GstDPMModeSetupFunction setupfunc; + GstDPMModeTeardownFunction teardownfunc; }; struct _GstDParamWrapper { - gchar *dparam_name; + GstDParamSpec* spec; GValue *value; GstDParam *dparam; - GstDpmUpdateFunction update_func; + GstDPMUpdateMethod update_method; gpointer update_data; + GstDPMUpdateFunction update_func; }; -#define GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman) (((dpman)->mode)->firstcountdownfunc) -#define GST_DPMAN_COUNTDOWNFUNC(dpman) (((dpman)->mode)->countdownfunc) +#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_FIRST_COUNTDOWN(dpman, buffer_size, timestamp) \ - (GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman)(dpman, buffer_size, timestamp)) +#define GST_DPMAN_PREPROCESS(dpman, buffer_size, timestamp) \ + (GST_DPMAN_PREPROCESSFUNC(dpman)(dpman, buffer_size, timestamp)) -#define GST_DPMAN_COUNTDOWN(dpman, frame_countdown, frame_count) \ +#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_COUNTDOWNFUNC(dpman)(dpman, frame_count))) - + (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 (GstDParamManager *dpman, - gchar *dparam_name, - GType type, - GstDpmUpdateFunction update_func, - gpointer update_data); +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, - GstDpmModeFirstCountdownFunction firstcountdownfunc, - GstDpmModeCountdownFunction countdownfunc, - GstDpmModeSetupFunction setupfunc, - GstDpmModeTeardownFunction teardownfunc); + GstDPMModePreProcessFunction preprocessfunc, + GstDPMModeProcessFunction processfunc, + GstDPMModeSetupFunction setupfunc, + GstDPMModeTeardownFunction teardownfunc); #ifdef __cplusplus } diff --git a/libs/control/gstdplinearinterp.c b/libs/control/gstdplinearinterp.c new file mode 100644 index 0000000000..24441650ee --- /dev/null +++ b/libs/control/gstdplinearinterp.c @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * 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; +} diff --git a/libs/control/gstdplinearinterp.h b/libs/control/gstdplinearinterp.h new file mode 100644 index 0000000000..fa1a7dc31c --- /dev/null +++ b/libs/control/gstdplinearinterp.h @@ -0,0 +1,61 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * 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 +#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__ */ diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am index 3902ca30c4..f50e4f75b4 100644 --- a/plugins/elements/Makefile.am +++ b/plugins/elements/Makefile.am @@ -25,7 +25,6 @@ libgstelements_la_SOURCES = \ gstpipefilter.c \ gsttee.c \ gstaggregator.c \ - gstsinesrc.c \ $(GSTHTTPSRC) noinst_HEADERS = \ diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index 799c632029..bdd540d49e 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -32,7 +32,6 @@ #include "gstfdsrc.h" #include "gstmultidisksrc.h" #include "gstpipefilter.h" -#include "gstsinesrc.h" #include "gsttee.h" #include "gstaggregator.h" @@ -64,7 +63,6 @@ static struct _elements_entry _elements[] = { { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL }, { "multidisksrc", gst_multidisksrc_get_type, &gst_multidisksrc_details, NULL }, { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, - { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, gst_sinesrc_factory_init }, { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, { "aggregator", gst_aggregator_get_type, &gst_aggregator_details, gst_aggregator_factory_init }, @@ -87,13 +85,20 @@ plugin_init (GModule *module, GstPlugin *plugin) factory = gst_elementfactory_new (_elements[i].name, (_elements[i].type) (), _elements[i].details); - if (factory != NULL) { - gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); - if (_elements[i].factoryinit) { - _elements[i].factoryinit (factory); + + if (!factory) + { + g_warning ("gst_elementfactory_new failed for `%s'", + _elements[i].name); + continue; } -// g_print("added factory '%s'\n",_elements[i].name); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + if (_elements[i].factoryinit) { + _elements[i].factoryinit (factory); } +// g_print("added factory '%s'\n",_elements[i].name); + i++; } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index fdf8bfec54..08cc5f8a60 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -121,6 +121,7 @@ gst_queue_get_type(void) sizeof(GstQueue), 4, (GInstanceInitFunc)gst_queue_init, + NULL }; queue_type = g_type_register_static (GST_TYPE_ELEMENT, "GstQueue", &queue_info, 0); } diff --git a/test/Makefile.am b/test/Makefile.am index c4b5afa1df..2613c070e0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,8 +3,9 @@ if HAVE_GNOME GNOME_PROGS = spectrum wave mp1parse videotest aviparse \ videotest2 video2mp1 dvshow dv2mp1 \ - mpeg2parse mpeg2parse2 mpeg2parse3 \ + mpeg2parse2 mpeg2parse3 \ mp2tomp1v2 main sinesliders testspeed +sinesliders_LDADD = ../libs/control/libgstcontrol.la else GNOME_PROGS = endif diff --git a/test/mpeg2parse.c b/test/mpeg2parse.c deleted file mode 100644 index e010e7383c..0000000000 --- a/test/mpeg2parse.c +++ /dev/null @@ -1,229 +0,0 @@ - -#include -#include - -void eof(GstElement *src) { - g_print("have eos, quitting\n"); - exit(0); -} - -gboolean idle_func(gpointer data) { - gst_bin_iterate(GST_BIN(data)); - return TRUE; -} - -GstElement *merge_subtitles; - -void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { - GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *show; - GstElement *audio_queue, *video_queue; - GstElement *audio_thread, *video_thread; - - GtkWidget *appwindow; - - g_print("***** a new pad %s was created\n", gst_pad_get_name(pad)); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED); - - // connect to audio pad - //if (0) { - if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0) { - gst_plugin_load("ac3parse"); - gst_plugin_load("ac3dec"); - // construct internal pipeline elements - parse_audio = gst_elementfactory_make("ac3parse","parse_audio"); - g_return_if_fail(parse_audio != NULL); - decode = gst_elementfactory_make("ac3dec","decode_audio"); - g_return_if_fail(decode != NULL); - play = gst_elementfactory_make("osssink","play_audio"); - g_return_if_fail(play != NULL); - - // create the thread and pack stuff into it - audio_thread = gst_thread_new("audio_thread"); - g_return_if_fail(audio_thread != NULL); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play)); - - // set up pad connections - gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), - gst_element_get_pad(parse_audio,"sink"),"sink"); - gst_pad_connect(gst_element_get_pad(parse_audio,"src"), - gst_element_get_pad(decode,"sink")); - gst_pad_connect(gst_element_get_pad(decode,"src"), - gst_element_get_pad(play,"sink")); - - // construct queue and connect everything in the main pipelie - audio_queue = gst_elementfactory_make("queue","audio_queue"); - gtk_object_set(GTK_OBJECT(audio_queue),"max_level",30,NULL); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_queue)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_thread)); - gst_pad_connect(pad, - gst_element_get_pad(audio_queue,"sink")); - gst_pad_connect(gst_element_get_pad(audio_queue,"src"), - gst_element_get_pad(audio_thread,"sink")); - - // set up thread state and kick things off - gtk_object_set(GTK_OBJECT(audio_thread),"create_thread",TRUE,NULL); - g_print("setting to READY state\n"); - gst_element_set_state(GST_ELEMENT(audio_thread),GST_STATE_READY); - } else if (strncmp(gst_pad_get_name(pad), "subtitle_stream_4", 17) == 0) { - gst_pad_connect(pad, - gst_element_get_pad(merge_subtitles,"subtitle")); - - } else if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) { - gst_plugin_load("mp3parse"); - gst_plugin_load("mpg123"); - // construct internal pipeline elements - parse_audio = gst_elementfactory_make("mp3parse","parse_audio"); - g_return_if_fail(parse_audio != NULL); - decode = gst_elementfactory_make("mpg123","decode_audio"); - g_return_if_fail(decode != NULL); - play = gst_elementfactory_make("osssink","play_audio"); - g_return_if_fail(play != NULL); - - // create the thread and pack stuff into it - audio_thread = gst_thread_new("audio_thread"); - g_return_if_fail(audio_thread != NULL); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play)); - - // set up pad connections - gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), - gst_element_get_pad(parse_audio,"sink"),"sink"); - gst_pad_connect(gst_element_get_pad(parse_audio,"src"), - gst_element_get_pad(decode,"sink")); - gst_pad_connect(gst_element_get_pad(decode,"src"), - gst_element_get_pad(play,"sink")); - - // construct queue and connect everything in the main pipelie - audio_queue = gst_elementfactory_make("queue","audio_queue"); - gtk_object_set(GTK_OBJECT(audio_queue),"max_level",30,NULL); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_queue)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_thread)); - gst_pad_connect(pad, - gst_element_get_pad(audio_queue,"sink")); - gst_pad_connect(gst_element_get_pad(audio_queue,"src"), - gst_element_get_pad(audio_thread,"sink")); - - // set up thread state and kick things off - gtk_object_set(GTK_OBJECT(audio_thread),"create_thread",TRUE,NULL); - g_print("setting to READY state\n"); - gst_element_set_state(GST_ELEMENT(audio_thread),GST_STATE_READY); - } else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) { - //} else if (0) { - - gst_plugin_load("mp1videoparse"); - gst_plugin_load("mpeg2play"); - gst_plugin_load("mpeg2subt"); - gst_plugin_load("videosink"); - // construct internal pipeline elements - parse_video = gst_elementfactory_make("mp1videoparse","parse_video"); - g_return_if_fail(parse_video != NULL); - decode_video = gst_elementfactory_make("mpeg2play","decode_video"); - g_return_if_fail(decode_video != NULL); - merge_subtitles = gst_elementfactory_make("mpeg2subt","merge_subtitles"); - g_return_if_fail(merge_subtitles != NULL); - show = gst_elementfactory_make("videosink","show"); - //gtk_object_set(GTK_OBJECT(show),"xv_enabled",FALSE,NULL); - g_return_if_fail(show != NULL); - //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL); - - appwindow = gnome_app_new("MPEG player","MPEG player"); - gnome_app_set_contents(GNOME_APP(appwindow), - gst_util_get_pointer_arg(GTK_OBJECT(show),"widget")); - gtk_widget_show_all(appwindow); - - // create the thread and pack stuff into it - video_thread = gst_thread_new("video_thread"); - g_return_if_fail(video_thread != NULL); - gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(parse_video)); - gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(decode_video)); - gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(merge_subtitles)); - gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(show)); - - // set up pad connections - gst_element_add_ghost_pad(GST_ELEMENT(video_thread), - gst_element_get_pad(parse_video,"sink"),"sink"); - gst_pad_connect(gst_element_get_pad(parse_video,"src"), - gst_element_get_pad(decode_video,"sink")); - gst_pad_connect(gst_element_get_pad(decode_video,"src"), - gst_element_get_pad(merge_subtitles,"video")); - gst_pad_connect(gst_element_get_pad(merge_subtitles,"src"), - gst_element_get_pad(show,"sink")); - - // construct queue and connect everything in the main pipeline - video_queue = gst_elementfactory_make("queue","video_queue"); - gtk_object_set(GTK_OBJECT(video_queue),"max_level",30,NULL); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_queue)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_thread)); - gst_pad_connect(pad, - gst_element_get_pad(video_queue,"sink")); - gst_pad_connect(gst_element_get_pad(video_queue,"src"), - gst_element_get_pad(video_thread,"sink")); - - // set up thread state and kick things off - gtk_object_set(GTK_OBJECT(video_thread),"create_thread",TRUE,NULL); - g_print("setting to READY state\n"); - gst_element_set_state(GST_ELEMENT(video_thread),GST_STATE_READY); - } - g_print("\n"); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING); -} - -int main(int argc,char *argv[]) { - GstPipeline *pipeline; - GstElement *src, *parse; - - g_print("have %d args\n",argc); - - g_thread_init(NULL); - gtk_init(&argc,&argv); - gst_init(&argc,&argv); - gnome_init("MPEG2 Video player","0.0.1",argc,argv); - gst_plugin_load("mpeg2parse"); - //gst_plugin_load("mpeg1parse"); - - pipeline = GST_PIPELINE(gst_pipeline_new("pipeline")); - g_return_val_if_fail(pipeline != NULL, -1); - - if (strstr(argv[1],"video_ts")) { - src = gst_elementfactory_make("dvdsrc","src"); - g_print("using DVD source\n"); - } else - src = gst_elementfactory_make("disksrc","src"); - - g_return_val_if_fail(src != NULL, -1); - gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL); - if (argc >= 3) { - gtk_object_set(GTK_OBJECT(src),"bytesperread",atoi(argv[2]),NULL); - g_print("block size is %d\n",atoi(argv[2])); - } - g_print("should be using file '%s'\n",argv[1]); - - parse = gst_elementfactory_make("mpeg2parse","parse"); - //parse = gst_elementfactory_make("mpeg1parse","parse"); - g_return_val_if_fail(parse != NULL, -1); - - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(src)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(parse)); - - gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mpeg2parse_newpad, pipeline); - - gtk_signal_connect(GTK_OBJECT(src),"eos",GTK_SIGNAL_FUNC(eof),NULL); - - gst_pad_connect(gst_element_get_pad(src,"src"), - gst_element_get_pad(parse,"sink")); - - g_print("setting to READY state\n"); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_READY); - gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING); - - gtk_idle_add(idle_func,pipeline); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return 0; -} diff --git a/test/sinesliders.c b/test/sinesliders.c index 71402bb41c..aaab8bbb60 100644 --- a/test/sinesliders.c +++ b/test/sinesliders.c @@ -1,7 +1,8 @@ #include +#include #include #include -#include +#include static gint quit_live(GtkWidget *window, GdkEventAny *e, gpointer data) { gtk_main_quit(); @@ -13,6 +14,20 @@ static gint quit_live(GtkWidget *window, GdkEventAny *e, gpointer data) { // gtk_object_set(GTK_OBJECT(element),"volume",adj->value,NULL); //} +static void dynparm_log_value_changed(GtkAdjustment *adj,GstDParam *dparam) { + GValue **point; + g_return_if_fail(dparam != NULL); + g_return_if_fail(GST_IS_DPARAM (dparam)); + + point = GST_DPARAM_GET_POINT(dparam, 0LL); + + GST_DPARAM_LOCK(dparam); + g_print("setting value from %f to %f\n", g_value_get_float(point[0]), (gfloat)exp(adj->value)); + g_value_set_float(point[0], (gfloat)exp(adj->value)); + GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + GST_DPARAM_UNLOCK(dparam); +} + static void dynparm_value_changed(GtkAdjustment *adj,GstDParam *dparam) { GValue **point; g_return_if_fail(dparam != NULL); @@ -38,25 +53,15 @@ int main(int argc,char *argv[]) { GstElement *thread, *sinesrc, *osssink; GstDParamManager *dpman; - GstDParam *volume, *freq; + GstDParam *volume; + GstDParam *freq; + GstDParamSpec *spec; + + GValue **vals; gtk_init(&argc,&argv); gst_init(&argc,&argv); - /***** set up the GUI *****/ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_signal_connect(window,"delete_event",GTK_SIGNAL_FUNC(quit_live),NULL); - hbox = gtk_hbox_new(TRUE,0); - gtk_container_add(GTK_CONTAINER(window),hbox); - - volume_adj = (GtkAdjustment*)gtk_adjustment_new(1.0, 0.0, 1.0, 0.01, 0.01, 0.01); - volume_slider = gtk_vscale_new(volume_adj); - gtk_box_pack_start(GTK_BOX(hbox),volume_slider,TRUE,TRUE,0); - - freq_adj = (GtkAdjustment*)gtk_adjustment_new(440.0, 0.0, 2000.0, 1.0, 5.0, 5.0); - freq_slider = gtk_vscale_new(freq_adj); - gtk_box_pack_start(GTK_BOX(hbox),freq_slider,TRUE,TRUE,0); - /***** construct the pipeline *****/ g_print("creating elements\n"); @@ -66,17 +71,67 @@ int main(int argc,char *argv[]) { gst_bin_add(GST_BIN(thread),sinesrc); gst_bin_add(GST_BIN(thread),osssink); gst_element_connect(sinesrc,"src",osssink,"sink"); - gtk_object_set(GTK_OBJECT(sinesrc),"GstSineSrc::buffersize",64,NULL); + g_object_set(G_OBJECT(osssink),"fragment",0x00180008,NULL); + g_object_set(G_OBJECT(sinesrc),"buffersize",64,NULL); - dpman = GST_ELEMENT_DPARAM_MANAGER(sinesrc); - volume = gst_dparam_new(); - freq = gst_dparam_new(); + dpman = gst_dpman_get_manager (sinesrc); + freq = gst_dparam_smooth_new(G_TYPE_FLOAT); + vals = GST_DPARAM_GET_POINT(freq, 0LL); + + g_value_set_float(vals[0], 10.0); + + // this defines the maximum slope that this + // param can change. This says that in 50ms + // the value can change by a maximum of one semitone + // (the log of one semitone is 0.693) + g_value_set_float(vals[1], 0.693); + g_value_set_float(vals[2], 50000000.0); + + // set the default update period to 0.5ms, or 2000Hz + GST_DPARAM_DEFAULT_UPDATE_PERIOD(freq) = 2000000LL; + + volume = gst_dparam_smooth_new(G_TYPE_FLOAT); + vals = GST_DPARAM_GET_POINT(volume, 0LL); + + // this defines the maximum slope that this + // param can change. This says that in 10ms + // the value can change by a maximum of 0.2 + g_value_set_float(vals[1], 0.2); + g_value_set_float(vals[2], 10000000.0); + + // set the default update period to 0.5ms, or 2000Hz + GST_DPARAM_DEFAULT_UPDATE_PERIOD(volume) = 2000000LL; + g_assert(gst_dpman_attach_dparam (dpman, "volume", volume)); g_assert(gst_dpman_attach_dparam (dpman, "freq", freq)); gst_dpman_set_mode(dpman, "synchronous"); + /***** set up the GUI *****/ + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(window), 80, 400); + g_signal_connect(window,"delete_event",GTK_SIGNAL_FUNC(quit_live),NULL); + hbox = gtk_hbox_new(TRUE,0); + gtk_container_add(GTK_CONTAINER(window),hbox); + + spec = gst_dpman_get_dparam_spec (dpman, "volume"); + volume_adj = (GtkAdjustment*)gtk_adjustment_new(g_value_get_float(spec->default_val), + g_value_get_float(spec->min_val), + g_value_get_float(spec->max_val), 0.1, 0.01, 0.01); + volume_slider = gtk_vscale_new(volume_adj); + gtk_scale_set_digits(GTK_SCALE(volume_slider), 2); + gtk_box_pack_start(GTK_BOX(hbox),volume_slider,TRUE,TRUE,0); + + spec = gst_dpman_get_dparam_spec (dpman, "freq"); + freq_adj = (GtkAdjustment*)gtk_adjustment_new((gfloat)log(g_value_get_float(spec->default_val)), + (gfloat)log(g_value_get_float(spec->min_val)), + (gfloat)log(g_value_get_float(spec->max_val)), 0.1, 0.01, 0.01); + freq_slider = gtk_vscale_new(freq_adj); + gtk_scale_set_digits(GTK_SCALE(freq_slider), 2); + gtk_box_pack_start(GTK_BOX(hbox),freq_slider,TRUE,TRUE,0); + + /***** set up the handlers and such *****/ //gtk_signal_connect(volume_adj,"value-changed",GTK_SIGNAL_FUNC(volume_changed),sinesrc); g_signal_connect(volume_adj,"value-changed", @@ -84,7 +139,7 @@ int main(int argc,char *argv[]) { volume); g_signal_connect(freq_adj,"value-changed", - GTK_SIGNAL_FUNC(dynparm_value_changed), + GTK_SIGNAL_FUNC(dynparm_log_value_changed), freq); gtk_adjustment_value_changed(volume_adj); gtk_adjustment_value_changed(freq_adj); diff --git a/tests/autoplug.c b/tests/autoplug.c index 1d9e8d1176..df720b5529 100644 --- a/tests/autoplug.c +++ b/tests/autoplug.c @@ -18,7 +18,7 @@ main (int argc, char *argv[]) osssink = gst_elementfactory_make ("osssink", "osssink"); g_assert (osssink != NULL); - videosink = gst_elementfactory_make ("videosink", "videosink"); + videosink = gst_elementfactory_make ("xvideosink", "videosink"); g_assert (videosink != NULL); testcaps = gst_caps_new ("test_caps", diff --git a/tools/.gitignore b/tools/.gitignore index beeec25e2a..7cc47e8a66 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -11,4 +11,5 @@ gstreamer-register gstreamer-inspect gstreamer-compprep gstreamer-complete +gstreamer-guilaunch *.xml diff --git a/tools/Makefile.am b/tools/Makefile.am index 3488808a82..bef06f9476 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -11,7 +11,14 @@ else GST_LOADSAVE_SRC = gstreamer-compprep endif +if USE_GLIB2 +GST_GUI_LAUNCH = +else +GST_GUI_LAUNCH = gstreamer-guilaunch +endif + bin_PROGRAMS = gstreamer-launch \ + $(GST_GUI_LAUNCH) \ $(GST_REGISTRY_SRC) \ gstreamer-inspect \ $(GST_LOADSAVE_SRC) \ diff --git a/tools/gstreamer-guilaunch.c b/tools/gstreamer-guilaunch.c new file mode 100644 index 0000000000..ef8745333b --- /dev/null +++ b/tools/gstreamer-guilaunch.c @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +GtkWidget *start_but, *pause_but, *parse_but, *status; +GtkWidget *window; +GstElement *pipeline; +typedef void (*found_handler) (GstElement *element, gint xid, void *priv); + +static gint quit_live(GtkWidget *window, GdkEventAny *e, gpointer data) { + gtk_main_quit(); + return FALSE; +} + +gboolean +idle_func (gpointer data) +{ + return gst_bin_iterate (GST_BIN (pipeline)); +} + +void +load_history(GtkWidget *pipe_combo) +{ + + int history_fd; + struct stat statbuf; + gchar *map, *current, *next, *entry; + gchar *history_filename; + gint num_entries = 0, entries_limit = 50; + GList *history = NULL; + FILE *history_file; + + history_filename = g_strdup_printf("%s/.gstreamer-guilaunch.history", g_get_home_dir()); + + + if ((history_fd = open(history_filename, O_RDONLY)) > -1){ + fstat(history_fd, &statbuf); + map = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, history_fd, 0); + + // scan it once to find out how many entries there are + current = map; + while (current){ + if ((next = strstr(current, "\n"))){ + num_entries++; + current = next + 1; + } + else { + current = NULL; + } + } + + current = map; + while (current){ + if ((next = strstr(current, "\n"))){ + + // show entries_limit of the newest entries + if (num_entries-- < entries_limit){ + entry = g_strndup(current, next - current); + history = g_list_prepend(history, entry); + } + current = next + 1; + } + else { + current = NULL; + } + } + close(history_fd); + munmap(map, statbuf.st_size); + } + gtk_combo_set_popdown_strings(GTK_COMBO(pipe_combo), history); + + history_file = fopen(history_filename, "a"); + if (history_file == NULL){ + perror("couldn't open history file"); + } + gtk_object_set_data(GTK_OBJECT(pipe_combo), "history", history); + gtk_object_set_data(GTK_OBJECT(pipe_combo), "history_file", history_file); +} + +void +debug_toggle_callback(GtkWidget *widget, gpointer mode_ptr){ + guint32 debug_mode = GPOINTER_TO_INT(mode_ptr); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){ + gst_info_enable_category(debug_mode); + gst_debug_enable_category(debug_mode); + } + else { + gst_info_disable_category(debug_mode); + gst_debug_disable_category(debug_mode); + } +} + +void +debug_select_callback(GtkWidget *widget, GSList *debug_list) +{ + gchar *name = gtk_object_get_data(GTK_OBJECT(widget), "name"); + gboolean select = (strstr(name, "deselect all") == NULL); + while (debug_list){ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(debug_list->data), select); + debug_list = g_slist_next(debug_list); + } +} + +void +build_debug_page(GtkWidget *notebook) +{ + guint32 debug_mode; + GtkWidget *debug_box, *debug_buts, *debug_but, *scrolled; + GSList *debug_list = NULL; + + scrolled = gtk_scrolled_window_new(NULL,NULL); + + debug_box = gtk_vbox_new(TRUE, 0); + debug_buts = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(debug_box),debug_buts,TRUE,TRUE,0); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), debug_box); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, gtk_label_new("Debug")); + + for (debug_mode = 0 ; (debug_mode < GST_CAT_MAX_CATEGORY) && + (gst_get_category_name(debug_mode) != NULL); debug_mode++){ + GtkWidget *debug_enable = gtk_check_button_new_with_label (gst_get_category_name(debug_mode)); + + debug_list = g_slist_append(debug_list, debug_enable); + + gtk_box_pack_start(GTK_BOX(debug_box),debug_enable,TRUE,TRUE,0); + gtk_signal_connect (GTK_OBJECT (debug_enable), "toggled", + GTK_SIGNAL_FUNC (debug_toggle_callback), GINT_TO_POINTER(debug_mode)); + } + + debug_but = gtk_button_new_with_label("select all"); + gtk_box_pack_start(GTK_BOX(debug_buts),debug_but,TRUE,TRUE,0); + gtk_object_set_data(GTK_OBJECT(debug_but), "name", "select all"); + gtk_signal_connect (GTK_OBJECT (debug_but), "clicked", + GTK_SIGNAL_FUNC (debug_select_callback), debug_list); + + debug_but = gtk_button_new_with_label("deselect all"); + gtk_box_pack_start(GTK_BOX(debug_buts),debug_but,TRUE,TRUE,0); + gtk_object_set_data(GTK_OBJECT(debug_but), "name", "deselect all"); + gtk_signal_connect (GTK_OBJECT (debug_but), "clicked", + GTK_SIGNAL_FUNC (debug_select_callback), debug_list); + + +} + +void +arg_search (GstBin *bin, gchar *argname, found_handler handler, void *priv) +{ + GList *children; + GValue *value; + GParamSpec **property_specs; + + value = g_new0(GValue,1); + g_value_init (value, G_TYPE_INT); + children = gst_bin_get_list(bin); + + while (children) { + GstElement *child; + + child = GST_ELEMENT (children->data); + children = g_list_next (children); + + if (GST_IS_BIN (child)) arg_search (GST_BIN (child), argname, handler, priv); + else { + gint num_properties,i; + + property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS (child), &num_properties); + + for (i=0;iname,argname)) { + g_object_get_property(G_OBJECT(child),argname,value); + + (handler)(child, g_value_get_int(value) ,priv); + } + } + } + } + g_free(value); +} + +void +handle_have_size (GstElement *element,int width,int height) +{ + g_print("setting window size\n"); + gtk_widget_set_usize(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(element), "gtk_socket")),width,height); + gtk_widget_show_all(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(element), "vid_window"))); +} + +void +xid_handler (GstElement *element, gint xid, void *priv) +{ + GtkWidget *gtk_socket, *vid_window; + + g_print("handling xid %d\n", xid); + vid_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_socket = gtk_socket_new (); + gtk_widget_show(gtk_socket); + + gtk_container_add(GTK_CONTAINER(vid_window),gtk_socket); + + gtk_widget_realize(gtk_socket); + gtk_socket_steal (GTK_SOCKET (gtk_socket), xid); + + gtk_object_set(GTK_OBJECT(vid_window),"allow_grow",TRUE,NULL); + gtk_object_set(GTK_OBJECT(vid_window),"allow_shrink",TRUE,NULL); + + gtk_signal_connect (GTK_OBJECT (element), "have_size", + GTK_SIGNAL_FUNC (handle_have_size), element); + gtk_object_set_data(GTK_OBJECT(element), "vid_window", vid_window); + gtk_object_set_data(GTK_OBJECT(element), "gtk_socket", gtk_socket); +} + +void +parse_callback( GtkWidget *widget, + GtkWidget *pipe_combo) +{ + GList *history = (GList*)gtk_object_get_data(GTK_OBJECT(pipe_combo), "history"); + FILE *history_file = (FILE*)gtk_object_get_data(GTK_OBJECT(pipe_combo), "history_file"); + + gchar *try_pipe = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(pipe_combo)->entry)); + gchar *write_pipe = g_strdup_printf("%s\n", try_pipe); + + fwrite(write_pipe, sizeof(gchar), strlen(write_pipe), history_file); + fflush(history_file); + + if (pipeline){ + g_print("unreffing\n"); + gst_object_unref (GST_OBJECT (pipeline)); + } + g_print ("trying pipeline: %s\n", try_pipe); + + pipeline = gst_pipeline_new ("launch"); + gst_parse_launch (try_pipe, GST_BIN (pipeline)); + gtk_widget_set_sensitive(GTK_WIDGET(start_but), TRUE); + + history = g_list_prepend(history, try_pipe); + gtk_combo_set_popdown_strings(GTK_COMBO(pipe_combo), history); + g_free(write_pipe); +} + +void +start_callback( GtkWidget *widget, + gpointer data ) +{ + GtkWidget *pipe_combo = gtk_object_get_data(GTK_OBJECT(widget), "pipe_combo"); + gchar *try_pipe = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(pipe_combo)->entry)); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){ + gtk_widget_set_sensitive(GTK_WIDGET(pause_but), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_but), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(parse_but), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(pipe_combo), FALSE); + gtk_label_set_text(GTK_LABEL(status), "playing"); + + arg_search(GST_BIN(pipeline),"xid",xid_handler,NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + g_idle_add(idle_func,pipeline); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(pause_but), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_but), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(parse_but), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(pipe_combo), TRUE); + gst_element_set_state (pipeline, GST_STATE_NULL); + gtk_label_set_text(GTK_LABEL(status), "stopped"); + + g_idle_remove_by_data(pipeline); + } +} + +void +pause_callback( GtkWidget *widget, + gpointer data ) +{ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gtk_label_set_text(GTK_LABEL(status), "paused"); + } + else { + gst_element_set_state (pipeline, GST_STATE_PLAYING); + gtk_label_set_text(GTK_LABEL(status), "playing"); + } +} + +int main(int argc,char *argv[]) { + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *parse_line, *pipe_combo, *notebook; + + gst_init(&argc,&argv); + + /***** set up the GUI *****/ + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect(window,"delete_event",GTK_SIGNAL_FUNC(quit_live),NULL); + vbox = gtk_vbox_new(FALSE,0); + gtk_container_add(GTK_CONTAINER(window),vbox); + + parse_line = gtk_hbox_new(FALSE, 3); + gtk_box_pack_start(GTK_BOX(vbox),parse_line,FALSE,FALSE,0); + + pipe_combo = gtk_combo_new(); + gtk_combo_set_value_in_list(GTK_COMBO(pipe_combo), FALSE, FALSE); + load_history(pipe_combo); + + parse_but = gtk_button_new_with_label("Parse"); + gtk_box_pack_start(GTK_BOX(parse_line),pipe_combo,TRUE,TRUE,0); + gtk_box_pack_start(GTK_BOX(parse_line),parse_but,FALSE,FALSE,0); + + start_but = gtk_toggle_button_new_with_label("Play"); + pause_but = gtk_toggle_button_new_with_label("Pause"); + + gtk_box_pack_start(GTK_BOX(parse_line),start_but,FALSE,FALSE,0); + gtk_box_pack_start(GTK_BOX(parse_line),pause_but,FALSE,FALSE,0); + + gtk_widget_set_sensitive(GTK_WIDGET(start_but), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(pause_but), FALSE); + + gtk_signal_connect (GTK_OBJECT (start_but), "clicked", + GTK_SIGNAL_FUNC (start_callback), NULL); + gtk_signal_connect (GTK_OBJECT (pause_but), "clicked", + GTK_SIGNAL_FUNC (pause_callback), NULL); + gtk_signal_connect (GTK_OBJECT (parse_but), "clicked", + GTK_SIGNAL_FUNC (parse_callback), pipe_combo); + + gtk_object_set_data(GTK_OBJECT(start_but), "pipe_combo", pipe_combo); + + notebook = gtk_notebook_new(); + gtk_box_pack_start(GTK_BOX(vbox),notebook,TRUE,TRUE,0); + + build_debug_page(notebook); + + status = gtk_label_new("stopped"); + gtk_box_pack_start(GTK_BOX(vbox),status,FALSE,FALSE,0); + + gtk_widget_show_all(window); + gtk_main(); + + return 0; +}