diff --git a/configure.in b/configure.in index 0344b85838..4eacd91bf8 100644 --- a/configure.in +++ b/configure.in @@ -597,6 +597,7 @@ AM_CONDITIONAL(HAVE_LIBSHOUT, test "x$HAVE_LIBSHOUT" = "xyes") AM_CONDITIONAL(HAVE_LIBESD, test "x$HAVE_LIBESD" = "xyes") AM_CONDITIONAL(HAVE_LIBASOUND, test "x$HAVE_LIBASOUND" = "xyes") AM_CONDITIONAL(HAVE_MPEG2DEC, test "x$HAVE_MPEG2DEC" = "xyes") +AM_CONDITIONAL(HAVE_LIBXMMS, test "x$HAVE_LIBXMMS" = "xyes") @@ -680,6 +681,7 @@ gst/Makefile gst/types/Makefile gst/meta/Makefile gst/elements/Makefile +gst/autoplug/Makefile libs/Makefile libs/riff/Makefile libs/colorspace/Makefile diff --git a/docs/gst/tmpl/gstautoplug.sgml b/docs/gst/tmpl/gstautoplug.sgml index 2ea069b281..0fe0ed4306 100644 --- a/docs/gst/tmpl/gstautoplug.sgml +++ b/docs/gst/tmpl/gstautoplug.sgml @@ -15,60 +15,18 @@ to convert a certain GstCaps to another one. - - -The maximum cost of a certain connection. - - - - - - -Calculate the cost between two elements. - - -@src: the source element -@dest: the destination element -@data: optional user data -@Returns: the cost for a connection between the two elements - - - - -Get a list of all elements. These elements will be used in autoplugging. - - -@data: user data -@Returns: a GList of elements - - - - - - - -@srccaps: -@sinkcaps: -@Returns: - - - - - - - -@srcpad: -@sinkpad: -@Returns: - - +@autoplug: +@srcpad: +@sinkpad: +@Varargs: +@Returns: + @srccaps: @sinkcaps: -@Returns: diff --git a/docs/gst/tmpl/gstpad.sgml b/docs/gst/tmpl/gstpad.sgml index db45773d2d..5a5dd33144 100644 --- a/docs/gst/tmpl/gstpad.sgml +++ b/docs/gst/tmpl/gstpad.sgml @@ -133,6 +133,8 @@ a start/stop timecode pair. @offset: the offset of the region to get @len: the length of the region to get @Returns: a #GstBuffer + +@size: the size of the region to get diff --git a/docs/gst/tmpl/gstpipeline.sgml b/docs/gst/tmpl/gstpipeline.sgml index da53a47805..f486cfb193 100644 --- a/docs/gst/tmpl/gstpipeline.sgml +++ b/docs/gst/tmpl/gstpipeline.sgml @@ -38,33 +38,6 @@ pipeline figure out what plugins to use. @Returns: - - - - - -@pipeline: -@sink: - - - - - - - -@pipeline: -@src: - - - - - - - -@pipeline: -@Returns: - - Destroys the pipeline. diff --git a/docs/gst/tmpl/gstplugin.sgml b/docs/gst/tmpl/gstplugin.sgml index b281b08a9f..b4b87637e0 100644 --- a/docs/gst/tmpl/gstplugin.sgml +++ b/docs/gst/tmpl/gstplugin.sgml @@ -27,6 +27,8 @@ GStreamer is extensible so GstElements can be loaded at r @numtypes: @elements: @numelements: +@autopluggers: +@numautopluggers: @loaded: @@ -203,15 +205,6 @@ by the loader at statup. @Returns: - - - - - -@name: -@Returns: - - diff --git a/docs/gst/tmpl/gstreamer-unused.sgml b/docs/gst/tmpl/gstreamer-unused.sgml index 1740957e0d..5f5ff9c6ea 100644 --- a/docs/gst/tmpl/gstreamer-unused.sgml +++ b/docs/gst/tmpl/gstreamer-unused.sgml @@ -780,10 +780,6 @@ Query whether this object has multiple input pads. - -Asynchronous disk reader. (asyncdisksrc) - - @@ -1383,11 +1379,15 @@ The start point of a filter graph @klass: +<<<<<<< gstreamer-unused.sgml GstAsyncDiskSrc +======= + +>>>>>>> 1.23.2.3 @@ -2009,6 +2009,7 @@ GstFilter +<<<<<<< gstreamer-unused.sgml Flags for the GstSrc element @@ -2024,6 +2025,18 @@ Flags for the GstSrc element +======= + + +Flags for the GstSrc element + + +@GST_SRC_ASYNC: Indicates that this src is asynchronous +@GST_SRC_FLAG_LAST: subclasses can use this to number their flags + + + +>>>>>>> 1.23.2.3 diff --git a/docs/random/hierarchy b/docs/random/hierarchy new file mode 100644 index 0000000000..fc854aff72 --- /dev/null +++ b/docs/random/hierarchy @@ -0,0 +1,149 @@ +Face it, the plugins/ directory hierarchy is crap. We want to propose a +better layout for it now. Some things to consider: + + - Elements have a klass member in the factory that is used to + denote the functional type of the element. For example, the + mp3 encoder has a klass of Filter/Encoder/Audio + + - The plugins can be grouped together by the media type they + operate on or by the way they work (decoder/encoder) + +In GStreamer all plugins are techically filters, the only way they +can be considered sources or sinks (input/output) elements is +by the absence of src/sink pads. At first sight the source/filter/ +sink distinction is quite useless because most of the plugins +will go into the filters category anyway. + +We don't want to make the hierarchy too deep, yet provide a +clean way to ask for a mp3 decoder element.. + +Anyway this is a rough proposal to fire off the discussions... + +Wim + +Source + Disk + disksrc + fdsrc + multifilesrc + Network + HTTPsrc + RTPsrc + CDDA + cdparanoia + XMMS + .. + DVD + dvdsrc + Audio + ASLA + OSS + Capture + v4lsrc + firewire + +Demuxer + AVI + MPEG1 + MPEG2 + QT + +Muxer + AVI + MPEG1 + QT + +Aggregator + +Tee + gsttee + +Connection + queue + CORBA + +Parser + MPEG1 + MPEG2 + AC3 + +Mixer + Audio + Merge + Video + Subtitles + Merge + +Filters + Audio + ladspa + resample + Video + colorspace + +Effect + Audio + stereo + volume + delay + chorus + Video + median + smooth + XMMS + +Decoder + MPEG1 + MPEG2 + MP3 + mpg123 + xing + win32 + AU + WAV + JPEG + AC3 + ac3dec + RTJPEG + vorbis + +Encoder + MPEG1 + MPEG2 + MP3 + lame + mpegaudio + win32 + JPEG + AU + WAV + RTJPEG + Vorbis + +Visualisation + Video + histogram + Audio + smoothwave + spectrum + synaesthesia + vumeter + XMMS + +Sink + Disk + filesink + multifilesink + Network + ICECASTsink + FTPsink + RTPsink + XMMS + ESD + Video + videosink + SDLsink + Audio + OSSsink + ALSAsink + diff --git a/docs/random/wtay/autoplug2 b/docs/random/wtay/autoplug2 index 1c0f6f808c..c56f9b1f54 100644 --- a/docs/random/wtay/autoplug2 +++ b/docs/random/wtay/autoplug2 @@ -42,22 +42,26 @@ any intermediate steps to accomplish this conversion. The API for the user apps should be no more then this: - GstElement* gst_autoplug_construct (GstAutoplug *autoplug, - GstCaps *incaps, - GstCaps *outcaps, ...); + GstElement* gst_autoplug_caps_list (GstAutoplug *autoplug, + GList *incaps, + GList *outcaps, ...); autoplug is a reference to the autoplug implementation - incaps is a GstCaps handle for the source pad, the last set - of arguments is a va_list of destination caps. + incaps is a GList of GstCaps* for the source pad, the last set + of arguments is a va_list of destination caps lists. A handle to the autoplugger implementation can be obtained with - GList* gst_autoplug_get_list (void); + GList* gst_autoplugfactory_get_list (void); which will return a GList* of autopluggers. - GstAutoplug* gst_autoplug_get ("name"); + GstAutoplug* gst_autoplugfactory_make ("name"); + +or + + GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *autoplug); is used to get an autoplugger. @@ -72,11 +76,12 @@ overriding various methods. the autoplugger can be registered with: gst_plugin_add_autoplugger (GstPlugin *plugin, - GstAutoplug *autoplug); + GstAutoplugFactory *autoplug); This will allow us to only load the autoplugger when needed. + 4) implementation ----------------- @@ -108,11 +113,9 @@ properties: - name, description, more text to identify the autoplugger. - - a class method autoplug_construct that has to be implemented by + - a class method autoplug_caps_list that has to be implemented by the real autoplugger. - - possible PadTemplates that this autoplugger can handle well? - optionally, the core autoplugger code can provide convenience functions to implement custom autopluggers. The shortest path algorithm with pluggable weighting and list functions come to @@ -124,8 +127,9 @@ A possible use case would be to let gstmediaplay perform an autoplug on the media stream and insert a custom sound/video effect in the pipeline when an appropriate element is created. +the "new_object" signal will be fired by the autoplugger whenever +a new object has been created. This signal can be caught by the +user app to perform an introspection on the newly created object. + -comments? -Wim - diff --git a/editor/gsteditor.h b/editor/gsteditor.h index 105e18087a..e67667e8a4 100644 --- a/editor/gsteditor.h +++ b/editor/gsteditor.h @@ -155,14 +155,14 @@ struct _GstEditorElement { struct _GstEditorElementClass { GnomeCanvasGroupClass parent_class; - void (*name_changed) (GstEditorElement *element); - void (*position_changed) (GstEditorElement *element); - void (*size_changed) (GstEditorElement *element); - void (*realize) (GstEditorElement *element); - gint (*event) (GnomeCanvasItem *item,GdkEvent *event, - GstEditorElement *element); - gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event, - GstEditorElement *element); + void (*name_changed) (GstEditorElement *element); + void (*position_changed) (GstEditorElement *element); + void (*size_changed) (GstEditorElement *element); + void (*realize) (GstEditorElement *element); + gint (*event) (GnomeCanvasItem *item,GdkEvent *event, + GstEditorElement *element); + gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event, + GstEditorElement *element); }; @@ -188,11 +188,11 @@ const gchar *gst_editor_element_get_name(GstEditorElement *element); (GTK_CHECK_TYPE((obj),GST_TYPE_EDITOR_BIN)) #define GST_IS_EDITOR_BIN_CLASS(obj) \ (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_BIN)) - + struct _GstEditorBin { GstEditorElement element; - /* lists of GUI elements and connections */ + /* lists of GUI elements and connections */ GList *elements, *connections; /* connection state */ @@ -213,11 +213,11 @@ struct _GstEditorBinClass { GtkType gst_editor_bin_get_type(); GstEditorBin* gst_editor_bin_new (GstBin *bin, const gchar *first_arg_name,...); -void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element); - -void gst_editor_bin_connection_drag (GstEditorBin *bin, - gdouble wx,gdouble wy); -void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad); +void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element); + +void gst_editor_bin_connection_drag (GstEditorBin *bin, + gdouble wx,gdouble wy); +void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad); #define GST_TYPE_EDITOR_CANVAS \ @@ -246,8 +246,8 @@ struct _GstEditorCanvasClass { GstEditorCanvas* gst_editor_canvas_new (void); GstEditorCanvas* gst_editor_canvas_new_with_bin (GstEditorBin *bin); -void gst_editor_canvas_set_bin (GstEditorCanvas *canvas, - GstEditorBin *element); +void gst_editor_canvas_set_bin (GstEditorCanvas *canvas, + GstEditorBin *element); GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas); @@ -263,7 +263,7 @@ GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas); (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PAD)) struct _GstEditorPad { - GtkObject object; + GtkObject object; /* parent element */ GstEditorElement *parent; @@ -291,7 +291,7 @@ struct _GstEditorPad { gdouble width,height; // actual size gdouble boxwidth,boxheight; // size of pad box gboolean resize; // does it need resizing? - + /* interaction state */ gboolean dragging,resizing,moved; gdouble dragx,dragy; @@ -300,13 +300,13 @@ struct _GstEditorPad { // GnomeCanvasItem *connection; // can't use //GstEditorConnection }; - + struct _GstEditorPadClass { GtkObjectClass parent_class; void (*realize) (GstEditorPad *pad); }; - + GtkType gst_editor_pad_get_type(); GstEditorPad *gst_editor_pad_new(GstEditorElement *parent,GstPad *pad, const gchar *first_arg_name, ...); @@ -329,7 +329,7 @@ void gst_editor_pad_repack(GstEditorPad *pad); (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PADTEMPLATE)) struct _GstEditorPadTemplate { - GtkObject object; + GtkObject object; /* parent element */ GstEditorElement *parent; @@ -361,7 +361,7 @@ struct _GstEditorPadTemplate { gdouble width,height; // actual size gdouble boxwidth,boxheight; // size of padtemplate box gboolean resize; // does it need resizing? - + /* interaction state */ gboolean dragging,resizing,moved; gdouble dragx,dragy; @@ -370,13 +370,13 @@ struct _GstEditorPadTemplate { // GnomeCanvasItem *connection; // can't use //GstEditorConnection }; - + struct _GstEditorPadTemplateClass { GtkObjectClass parent_class; void (*realize) (GstEditorPadTemplate *padtemplate); }; - + GtkType gst_editor_padtemplate_get_type(); GstEditorPadTemplate *gst_editor_padtemplate_new(GstEditorElement *parent,GstPadTemplate *padtemplate, const gchar *first_arg_name, ...); diff --git a/examples/autoplug/autoplug.c b/examples/autoplug/autoplug.c index 4a3453552c..4e37b5d999 100644 --- a/examples/autoplug/autoplug.c +++ b/examples/autoplug/autoplug.c @@ -31,8 +31,6 @@ int main(int argc,char *argv[]) exit(-1); } - - /* create a new bin to hold the elements */ pipeline = gst_pipeline_new("pipeline"); g_assert(pipeline != NULL); @@ -59,6 +57,7 @@ int main(int argc,char *argv[]) gtk_widget_show_all(appwindow); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), videosink); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -67,6 +66,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline))); diff --git a/examples/helloworld2/helloworld2.c b/examples/helloworld2/helloworld2.c index 90de5139d5..8b70518eda 100644 --- a/examples/helloworld2/helloworld2.c +++ b/examples/helloworld2/helloworld2.c @@ -41,6 +41,7 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -48,6 +49,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ // hmmmm hack? FIXME GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER); diff --git a/examples/queue2/queue2.c b/examples/queue2/queue2.c index a3662b14e6..706acc073f 100644 --- a/examples/queue2/queue2.c +++ b/examples/queue2/queue2.c @@ -46,11 +46,12 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue); gst_bin_add(GST_BIN(thread), audiosink); - + gst_pad_connect(gst_element_get_pad(queue,"src"), gst_element_get_pad(audiosink,"sink")); @@ -58,6 +59,7 @@ int main(int argc,char *argv[]) g_print("cannot autoplug pipeline\n"); exit(-1); } + */ gst_bin_add(GST_BIN(pipeline), thread); diff --git a/examples/thread/thread.c b/examples/thread/thread.c index 533c38a6f7..b8bc00e1de 100644 --- a/examples/thread/thread.c +++ b/examples/thread/thread.c @@ -45,6 +45,7 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -52,6 +53,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ //gst_bin_remove(GST_BIN(pipeline), disksrc); diff --git a/gst/Makefile.am b/gst/Makefile.am index d25c9f9468..c5f4e9310e 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -1,5 +1,5 @@ # cheap trick to build . first... -SUBDIRS = . types meta elements +SUBDIRS = . types meta elements autoplug lib_LTLIBRARIES = libgst.la diff --git a/gst/autoplug/Makefile.am b/gst/autoplug/Makefile.am new file mode 100644 index 0000000000..0ddb2a8a74 --- /dev/null +++ b/gst/autoplug/Makefile.am @@ -0,0 +1,12 @@ +filterdir = $(libdir)/gst + +filter_LTLIBRARIES = libgststaticautoplug.la libgststaticautoplugrender.la + +libgststaticautoplug_la_SOURCES = \ + gststaticautoplug.c + +libgststaticautoplugrender_la_SOURCES = \ + gststaticautoplugrender.c + +libgststaticautoplug_la_LDFLAGS = -version-info $(GSTREAMER_LIBVERSION) +libgststaticautoplugrender_la_LDFLAGS = -version-info $(GSTREAMER_LIBVERSION) diff --git a/gst/autoplug/gststaticautoplug.c b/gst/autoplug/gststaticautoplug.c new file mode 100644 index 0000000000..a39ac579fe --- /dev/null +++ b/gst/autoplug/gststaticautoplug.c @@ -0,0 +1,619 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gststaticautoplug.c: A static Autoplugger of pipelines + * + * 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 "gststaticautoplug.h" + +#include + +#define GST_AUTOPLUG_MAX_COST 999999 + +typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data); +typedef GList* (*GstAutoplugListFunction) (gpointer data); + + +static void gst_static_autoplug_class_init (GstStaticAutoplugClass *klass); +static void gst_static_autoplug_init (GstStaticAutoplug *autoplug); + +static GList* gst_autoplug_func (gpointer src, gpointer sink, + GstAutoplugListFunction list_function, + GstAutoplugCostFunction cost_function, + gpointer data); + + + +static GstElement* gst_static_autoplug_to_caps (GstAutoplug *autoplug, + GList *srccaps, GList *sinkcaps, va_list args); + +static GstAutoplugClass *parent_class = NULL; + +GtkType gst_static_autoplug_get_type(void) +{ + static GtkType static_autoplug_type = 0; + + if (!static_autoplug_type) { + static const GtkTypeInfo static_autoplug_info = { + "GstStaticAutoplug", + sizeof(GstElement), + sizeof(GstElementClass), + (GtkClassInitFunc)gst_static_autoplug_class_init, + (GtkObjectInitFunc)gst_static_autoplug_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + static_autoplug_type = gtk_type_unique (GST_TYPE_AUTOPLUG, &static_autoplug_info); + } + return static_autoplug_type; +} + +static void +gst_static_autoplug_class_init(GstStaticAutoplugClass *klass) +{ + GstAutoplugClass *gstautoplug_class; + + gstautoplug_class = (GstAutoplugClass*) klass; + + parent_class = gtk_type_class(GST_TYPE_AUTOPLUG); + + gstautoplug_class->autoplug_to_caps = gst_static_autoplug_to_caps; +} + +static void gst_static_autoplug_init(GstStaticAutoplug *autoplug) { +} + +GstPlugin* +plugin_init (GModule *module) +{ + GstPlugin *plugin; + GstAutoplugFactory *factory; + + plugin = gst_plugin_new("gststaticautoplug"); + g_return_val_if_fail(plugin != NULL,NULL); + + gst_plugin_set_longname (plugin, "A static autoplugger"); + + factory = gst_autoplugfactory_new ("static", + "A static autoplugger, it constructs the complete element before running it", + gst_static_autoplug_get_type ()); + + if (factory != NULL) { + gst_plugin_add_autoplugger (plugin, factory); + } + return plugin; +} + +static gboolean +gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest) +{ + GList *srctemps, *desttemps; + + srctemps = src->padtemplates; + + while (srctemps) { + GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data; + + desttemps = dest->padtemplates; + + while (desttemps) { + GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data; + + if (srctemp->direction == GST_PAD_SRC && + desttemp->direction == GST_PAD_SINK) { + if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) { + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, + "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name); + return TRUE; + } + } + + desttemps = g_list_next (desttemps); + } + srctemps = g_list_next (srctemps); + } + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, + "factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name); + return FALSE; +} + +static gboolean +gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) +{ + GList *sinkpads; + gboolean connected = FALSE; + + GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n", + GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); + + sinkpads = gst_element_get_pad_list(sink); + while (sinkpads) { + GstPad *sinkpad = (GstPad *)sinkpads->data; + + // if we have a match, connect the pads + if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK && + !GST_PAD_CONNECTED(sinkpad)) + { + if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) { + gst_pad_connect(pad, sinkpad); + GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad), + GST_ELEMENT_NAME(src)); + GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad), + GST_ELEMENT_NAME(sink)); + connected = TRUE; + break; + } + else { + GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad)); + } + } + sinkpads = g_list_next(sinkpads); + } + + if (!connected) { + GST_DEBUG (0,"gstpipeline: no path to sinks for type\n"); + } + return connected; +} + +typedef struct { + GstElement *result; + GList *endcap; + gint i; +} dynamic_pad_struct; + +static void +autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) +{ + dynamic_pad_struct *info = (dynamic_pad_struct *)data; + GList *pads = gst_element_get_pad_list (element); + + GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element), + GST_PAD_NAME (pad)); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + pads = g_list_next (pads); + + if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) { + gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i)); + GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad)); + break; + } + } +} + +static void +gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink) +{ + GList *srcpads; + gboolean connected = FALSE; + + srcpads = gst_element_get_pad_list(src); + + while (srcpads && !connected) { + GstPad *srcpad = (GstPad *)srcpads->data; + + if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) + connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink); + + srcpads = g_list_next(srcpads); + } + + if (!connected) { + GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n", + GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); + gtk_signal_connect(GTK_OBJECT(src),"new_pad", + GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink); + } +} + +static GList* +gst_autoplug_elementfactory_get_list (gpointer data) +{ + return gst_elementfactory_get_list (); +} + +typedef struct { + GList *src; + GList *sink; +} caps_struct; + +#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink) + +static guint +gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) +{ + caps_struct *caps = (caps_struct *)data; + gboolean res; + + if (IS_CAPS (src) && IS_CAPS (dest)) { + res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res); + } + else if (IS_CAPS (src)) { + res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res); + } + else if (IS_CAPS (dest)) { + res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res); + } + else { + res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest); + } + + if (res) + return 1; + else + return GST_AUTOPLUG_MAX_COST; +} + +static GstElement* +gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args) +{ + caps_struct caps; + GList *capslist; + GstElement *result = NULL, *srcelement = NULL; + GList **factories; + GList *chains = NULL; + GList *endcaps = NULL; + guint numsinks = 0, i; + gboolean have_common = FALSE; + + capslist = sinkcaps; + + /* + * We first create a list of elements that are needed + * to convert the srcpad caps to the different sinkpad caps. + * and add the list of elementfactories to a list (chains). + */ + caps.src = srccaps; + + while (capslist) { + GList *elements; + + caps.sink = capslist; + + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures"); + + elements = gst_autoplug_func (caps.src, caps.sink, + gst_autoplug_elementfactory_get_list, + gst_autoplug_caps_find_cost, + &caps); + + if (elements) { + chains = g_list_append (chains, elements); + endcaps = g_list_append (endcaps, capslist); + numsinks++; + } + else { + } + + capslist = va_arg (args, GList *); + } + + /* + * If no list could be found the pipeline cannot be autoplugged and + * we return a NULL element + */ + if (numsinks == 0) + return NULL; + + /* + * We now have a list of lists. We will turn this into an array + * of lists, this will make it much more easy to manipulate it + * in the next steps. + */ + factories = g_new0 (GList *, numsinks); + + for (i = 0; chains; i++) { + GList *elements = (GList *) chains->data; + + factories[i] = elements; + + chains = g_list_next (chains); + } + //FIXME, free the list + + result = gst_bin_new ("autoplug_bin"); + + /* + * We now hav a list of lists that is probably like: + * + * ! + * A -> B -> C + * ! + * A -> D -> E + * + * we now try to find the common elements (A) and add them to + * the bin. We remove them from both lists too. + */ + while (factories[0]) { + GstElementFactory *factory; + GstElement *element; + + // fase 3: add common elements + factory = (GstElementFactory *) (factories[0]->data); + + // check to other paths for matching elements (factories) + for (i=1; idata)) { + goto differ; + } + } + + GST_DEBUG (0,"common factory \"%s\"\n", factory->name); + + element = gst_elementfactory_create (factory, factory->name); + gst_bin_add (GST_BIN(result), element); + + if (srcelement != NULL) { + gst_autoplug_pads_autoplug (srcelement, element); + } + // this is the first element, find a good ghostpad + else { + GList *pads; + + pads = gst_element_get_pad_list (element); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + + if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) { + gst_element_add_ghost_pad (result, pad, "sink"); + break; + } + + pads = g_list_next (pads); + } + } + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); + + srcelement = element; + + // advance the pointer in all lists + for (i=0; idata); + + GST_DEBUG (0,"factory \"%s\"\n", factory->name); + element = gst_elementfactory_create(factory, factory->name); + + GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element)); + gst_bin_add(GST_BIN(thebin), element); + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); + + gst_autoplug_pads_autoplug(thesrcelement, element); + + // this element is now the new source element + thesrcelement = element; + + factories[i] = g_list_next(factories[i]); + } + /* + * we're at the last element in the chain, + * find a suitable pad to turn into a ghostpad + */ + { + GList *endcap = (GList *)(endcaps->data); + GList *pads = gst_element_get_pad_list (thesrcelement); + gboolean have_pad = FALSE; + endcaps = g_list_next (endcaps); + + GST_DEBUG (0,"attempting to create a ghostpad for %s\n", GST_ELEMENT_NAME (thesrcelement)); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + pads = g_list_next (pads); + + if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) { + gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i)); + have_pad = TRUE; + break; + } + } + if (!have_pad) { + dynamic_pad_struct *data = g_new0(dynamic_pad_struct, 1); + + data->result = result; + data->endcap = endcap; + data->i = i; + + GST_DEBUG (0,"delaying the creation of a ghostpad for %s\n", GST_ELEMENT_NAME (thesrcelement)); + gtk_signal_connect (GTK_OBJECT (thesrcelement), "new_pad", + autoplug_dynamic_pad, data); + gtk_signal_connect (GTK_OBJECT (thesrcelement), "new_ghost_pad", + autoplug_dynamic_pad, data); + } + } + } + + return result; +} + +/* + * shortest path algorithm + * + */ +struct _gst_autoplug_node +{ + gpointer iNode; + gpointer iPrev; + gint iDist; +}; + +typedef struct _gst_autoplug_node gst_autoplug_node; + +static gint +find_factory (gst_autoplug_node *rgnNodes, gpointer factory) +{ + gint i=0; + + while (rgnNodes[i].iNode) { + if (rgnNodes[i].iNode == factory) return i; + i++; + } + return 0; +} + +static GList* +construct_path (gst_autoplug_node *rgnNodes, gpointer factory) +{ + GstElementFactory *current; + GList *factories = NULL; + + current = rgnNodes[find_factory(rgnNodes, factory)].iPrev; + + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)"); + + while (current != NULL) + { + gpointer next = NULL; + + next = rgnNodes[find_factory(rgnNodes, current)].iPrev; + if (next) { + factories = g_list_prepend (factories, current); + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name); + } + current = next; + } + return factories; +} + +static GList* +gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev) +{ + gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node)); + + node->iNode = iNode; + node->iDist = iDist; + node->iPrev = iPrev; + + queue = g_list_append (queue, node); + + return queue; +} + +static GList* +gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev) +{ + GList *head; + gst_autoplug_node *node; + + head = g_list_first (queue); + + if (head) { + node = (gst_autoplug_node *)head->data; + *iNode = node->iNode; + *iPrev = node->iPrev; + *iDist = node->iDist; + head = g_list_remove (queue, node); + } + + return head; +} + +static GList* +gst_autoplug_func (gpointer src, gpointer sink, + GstAutoplugListFunction list_function, + GstAutoplugCostFunction cost_function, + gpointer data) +{ + gst_autoplug_node *rgnNodes; + GList *queue = NULL; + gpointer iNode, iPrev; + gint iDist, i, iCost; + + GList *elements = g_list_copy (list_function(data)); + GList *factories; + guint num_factories; + + elements = g_list_append (elements, sink); + elements = g_list_append (elements, src); + + factories = elements; + + num_factories = g_list_length (factories); + + rgnNodes = g_new0 (gst_autoplug_node, num_factories+1); + + for (i=0; i< num_factories; i++) { + gpointer fact = factories->data; + + rgnNodes[i].iNode = fact; + rgnNodes[i].iPrev = NULL; + + if (fact == src) { + rgnNodes[i].iDist = 0; + } + else { + rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST; + } + + factories = g_list_next (factories); + } + rgnNodes[num_factories].iNode = NULL; + + queue = gst_autoplug_enqueue (queue, src, 0, NULL); + + while (g_list_length (queue) > 0) { + GList *factories2 = elements; + + queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev); + + for (i=0; i< num_factories; i++) { + gpointer current = factories2->data; + + iCost = cost_function (iNode, current, data); + if (iCost != GST_AUTOPLUG_MAX_COST) { + if ((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) || + (rgnNodes[i].iDist > (iCost + iDist))) { + rgnNodes[i].iDist = iDist + iCost; + rgnNodes[i].iPrev = iNode; + + queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode); + } + } + + factories2 = g_list_next (factories2); + } + } + + return construct_path (rgnNodes, sink); +} + diff --git a/gst/autoplug/gststaticautoplug.h b/gst/autoplug/gststaticautoplug.h new file mode 100644 index 0000000000..9a99097975 --- /dev/null +++ b/gst/autoplug/gststaticautoplug.h @@ -0,0 +1,64 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstautoplug.h: Header for autoplugging functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_STATIC_AUTOPLUG_H__ +#define __GST_STATIC_AUTOPLUG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GST_TYPE_STATIC_AUTOPLUG \ + (gst_static_autoplug_get_type()) +#define GST_STATIC_AUTOPLUG(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_STATIC_AUTOPLUG,GstStaticAutoplug)) +#define GST_STATIC_AUTOPLUG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_STATIC_AUTOPLUG,GstStaticAutoplugClass)) +#define GST_IS_STATIC_AUTOPLUG(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_STATIC_AUTOPLUG)) +#define GST_IS_STATIC_AUTOPLUG_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_STATIC_AUTOPLUG)) + +typedef struct _GstStaticAutoplug GstStaticAutoplug; +typedef struct _GstStaticAutoplugClass GstStaticAutoplugClass; + +struct _GstStaticAutoplug { + GstAutoplug object; +}; + +struct _GstStaticAutoplugClass { + GstAutoplugClass parent_class; +}; + + +GtkType gst_static_autoplug_get_type (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_STATIC_AUTOPLUG_H__ */ + diff --git a/gst/autoplug/gststaticautoplugrender.c b/gst/autoplug/gststaticautoplugrender.c new file mode 100644 index 0000000000..5533d69178 --- /dev/null +++ b/gst/autoplug/gststaticautoplugrender.c @@ -0,0 +1,650 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gststaticautoplug.c: A static Autoplugger of pipelines + * + * 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 "gststaticautoplugrender.h" + +#include + +#define GST_AUTOPLUG_MAX_COST 999999 + +typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data); +typedef GList* (*GstAutoplugListFunction) (gpointer data); + + +static void gst_static_autoplug_render_class_init (GstStaticAutoplugRenderClass *klass); +static void gst_static_autoplug_render_init (GstStaticAutoplugRender *autoplug); + +static GList* gst_autoplug_func (gpointer src, gpointer sink, + GstAutoplugListFunction list_function, + GstAutoplugCostFunction cost_function, + gpointer data); + + + +static GstElement* gst_static_autoplug_to_render (GstAutoplug *autoplug, + GList *srccaps, GstElement *target, va_list args); + +static GstAutoplugClass *parent_class = NULL; + +GtkType gst_static_autoplug_render_get_type(void) +{ + static GtkType static_autoplug_type = 0; + + if (!static_autoplug_type) { + static const GtkTypeInfo static_autoplug_info = { + "GstStaticAutoplugRender", + sizeof(GstElement), + sizeof(GstElementClass), + (GtkClassInitFunc)gst_static_autoplug_render_class_init, + (GtkObjectInitFunc)gst_static_autoplug_render_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + static_autoplug_type = gtk_type_unique (GST_TYPE_AUTOPLUG, &static_autoplug_info); + } + return static_autoplug_type; +} + +static void +gst_static_autoplug_render_class_init(GstStaticAutoplugRenderClass *klass) +{ + GstAutoplugClass *gstautoplug_class; + + gstautoplug_class = (GstAutoplugClass*) klass; + + parent_class = gtk_type_class(GST_TYPE_AUTOPLUG); + + gstautoplug_class->autoplug_to_renderers = gst_static_autoplug_to_render; +} + +static void gst_static_autoplug_render_init(GstStaticAutoplugRender *autoplug) { +} + +GstPlugin* +plugin_init (GModule *module) +{ + GstPlugin *plugin; + GstAutoplugFactory *factory; + + plugin = gst_plugin_new("gststaticautoplugrender"); + g_return_val_if_fail(plugin != NULL,NULL); + + gst_plugin_set_longname (plugin, "A static autoplugger"); + + factory = gst_autoplugfactory_new ("staticrender", + "A static autoplugger, it constructs the complete element before running it", + gst_static_autoplug_render_get_type ()); + + if (factory != NULL) { + gst_plugin_add_autoplugger (plugin, factory); + } + return plugin; +} + +static gboolean +gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest) +{ + GList *srctemps, *desttemps; + + srctemps = src->padtemplates; + + while (srctemps) { + GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data; + + desttemps = dest->padtemplates; + + while (desttemps) { + GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data; + + if (srctemp->direction == GST_PAD_SRC && + desttemp->direction == GST_PAD_SINK) { + if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) { + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, + "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name); + return TRUE; + } + } + + desttemps = g_list_next (desttemps); + } + srctemps = g_list_next (srctemps); + } + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, + "factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name); + return FALSE; +} + +static gboolean +gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) +{ + GList *sinkpads; + gboolean connected = FALSE; + + GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n", + GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); + + sinkpads = gst_element_get_pad_list(sink); + while (sinkpads) { + GstPad *sinkpad = (GstPad *)sinkpads->data; + + // if we have a match, connect the pads + if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK && + !GST_PAD_CONNECTED(sinkpad)) + { + if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) { + gst_pad_connect(pad, sinkpad); + GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad), + GST_ELEMENT_NAME(src)); + GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad), + GST_ELEMENT_NAME(sink)); + connected = TRUE; + break; + } + else { + GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad)); + } + } + sinkpads = g_list_next(sinkpads); + } + + if (!connected) { + GST_DEBUG (0,"gstpipeline: no path to sinks for type\n"); + } + return connected; +} + +typedef struct { + GstElement *result; + GList *endcap; + gint i; +} dynamic_pad_struct; + +static void +autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) +{ + dynamic_pad_struct *info = (dynamic_pad_struct *)data; + GList *pads = gst_element_get_pad_list (element); + + GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element), + GST_PAD_NAME (pad)); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + pads = g_list_next (pads); + + if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) { + gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i)); + GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad)); + break; + } + } +} + +static void +gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink) +{ + GList *srcpads; + gboolean connected = FALSE; + + srcpads = gst_element_get_pad_list(src); + + while (srcpads && !connected) { + GstPad *srcpad = (GstPad *)srcpads->data; + + if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) + connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink); + + srcpads = g_list_next(srcpads); + } + + if (!connected) { + GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n", + GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); + gtk_signal_connect(GTK_OBJECT(src),"new_pad", + GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink); + gtk_signal_connect(GTK_OBJECT(src),"new_ghost_pad", + GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink); + } +} + +static GList* +gst_autoplug_elementfactory_get_list (gpointer data) +{ + return gst_elementfactory_get_list (); +} + +typedef struct { + GList *src; + GList *sink; +} caps_struct; + +#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink) + +static guint +gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) +{ + caps_struct *caps = (caps_struct *)data; + gboolean res; + + if (IS_CAPS (src) && IS_CAPS (dest)) { + res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res); + } + else if (IS_CAPS (src)) { + res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res); + } + else if (IS_CAPS (dest)) { + res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest); + //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res); + } + else { + res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest); + } + + if (res) + return 1; + else + return GST_AUTOPLUG_MAX_COST; +} + +static GstElement* +gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args) +{ + caps_struct caps; + GstElement *targetelement; + GstElement *result = NULL, *srcelement = NULL; + GList **factories; + GList *chains = NULL; + GList *endelements = NULL; + guint numsinks = 0, i; + gboolean have_common = FALSE; + + targetelement = target; + + /* + * We first create a list of elements that are needed + * to convert the srcpad caps to the different sinkpad caps. + * and add the list of elementfactories to a list (chains). + */ + caps.src = srccaps; + + while (targetelement) { + GList *elements; + GstPad *pad; + + pad = GST_PAD (gst_element_get_pad_list (targetelement)->data); + + caps.sink = gst_pad_get_caps_list (pad); + + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures"); + + elements = gst_autoplug_func (caps.src, caps.sink, + gst_autoplug_elementfactory_get_list, + gst_autoplug_caps_find_cost, + &caps); + + if (elements) { + chains = g_list_append (chains, elements); + endelements = g_list_append (endelements, targetelement); + numsinks++; + } + else { + } + + targetelement = va_arg (args, GstElement *); + } + + /* + * If no list could be found the pipeline cannot be autoplugged and + * we return a NULL element + */ + if (numsinks == 0) + return NULL; + + /* + * We now have a list of lists. We will turn this into an array + * of lists, this will make it much more easy to manipulate it + * in the next steps. + */ + factories = g_new0 (GList *, numsinks); + + for (i = 0; chains; i++) { + GList *elements = (GList *) chains->data; + + factories[i] = elements; + + chains = g_list_next (chains); + } + //FIXME, free the list + + result = gst_bin_new ("autoplug_bin"); + + /* + * We now hav a list of lists that is probably like: + * + * ! + * A -> B -> C + * ! + * A -> D -> E + * + * we now try to find the common elements (A) and add them to + * the bin. We remove them from both lists too. + */ + while (factories[0]) { + GstElementFactory *factory; + GstElement *element; + + // fase 3: add common elements + factory = (GstElementFactory *) (factories[0]->data); + + // check to other paths for matching elements (factories) + for (i=1; idata)) { + goto differ; + } + } + + GST_DEBUG (0,"common factory \"%s\"\n", factory->name); + + element = gst_elementfactory_create (factory, factory->name); + gst_bin_add (GST_BIN(result), element); + + if (srcelement != NULL) { + gst_autoplug_pads_autoplug (srcelement, element); + } + // this is the first element, find a good ghostpad + else { + GList *pads; + + pads = gst_element_get_pad_list (element); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + + if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) { + gst_element_add_ghost_pad (result, pad, "sink"); + break; + } + + pads = g_list_next (pads); + } + } + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); + + srcelement = element; + + // advance the pointer in all lists + for (i=0; idata); + endelements = g_list_next (endelements); + + use_thread = have_common; + + while (factories[i] || sinkelement) { + // fase 4: add other elements... + GstElementFactory *factory; + GstElement *element; + + if (factories[i]) { + factory = (GstElementFactory *)(factories[i]->data); + + GST_DEBUG (0,"factory \"%s\"\n", factory->name); + element = gst_elementfactory_create(factory, factory->name); + } + else { + element = sinkelement; + sinkelement = NULL; + } + + // this element suggests the use of a thread, so we set one up... + if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) { + GstElement *queue; + GList *sinkpads; + GstPad *srcpad, *sinkpad; + + use_thread = FALSE; + + GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element)); + + // create a new queue and add to the previous bin + queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL)); + GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element)); + gst_bin_add(GST_BIN(thebin), queue); + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (queue)); + + // this will be the new bin for all following elements + thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL)); + + srcpad = gst_element_get_pad(queue, "src"); + + sinkpads = gst_element_get_pad_list(element); + while (sinkpads) { + sinkpad = (GstPad *)sinkpads->data; + + // FIXME connect matching pads, not just the first one... + if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK && + !GST_PAD_CONNECTED(sinkpad)) { + GList *caps = gst_pad_get_caps_list (sinkpad); + + // the queue has the type of the elements it connects + gst_pad_set_caps_list (srcpad, caps); + gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps); + break; + } + sinkpads = g_list_next(sinkpads); + } + gst_autoplug_pads_autoplug(thesrcelement, queue); + + GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element)); + gst_bin_add(GST_BIN(thebin), element); + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); + GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin)); + gst_bin_add(GST_BIN(result), thebin); + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (thebin)); + thesrcelement = queue; + } + // no thread needed, easy case + else { + GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element)); + gst_bin_add(GST_BIN(thebin), element); + gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); + } + gst_autoplug_pads_autoplug(thesrcelement, element); + + // this element is now the new source element + thesrcelement = element; + + factories[i] = g_list_next(factories[i]); + } + } + + return result; +} + +/* + * shortest path algorithm + * + */ +struct _gst_autoplug_node +{ + gpointer iNode; + gpointer iPrev; + gint iDist; +}; + +typedef struct _gst_autoplug_node gst_autoplug_node; + +static gint +find_factory (gst_autoplug_node *rgnNodes, gpointer factory) +{ + gint i=0; + + while (rgnNodes[i].iNode) { + if (rgnNodes[i].iNode == factory) return i; + i++; + } + return 0; +} + +static GList* +construct_path (gst_autoplug_node *rgnNodes, gpointer factory) +{ + GstElementFactory *current; + GList *factories = NULL; + + current = rgnNodes[find_factory(rgnNodes, factory)].iPrev; + + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)"); + + while (current != NULL) + { + gpointer next = NULL; + + next = rgnNodes[find_factory(rgnNodes, current)].iPrev; + if (next) { + factories = g_list_prepend (factories, current); + GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name); + } + current = next; + } + return factories; +} + +static GList* +gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev) +{ + gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node)); + + node->iNode = iNode; + node->iDist = iDist; + node->iPrev = iPrev; + + queue = g_list_append (queue, node); + + return queue; +} + +static GList* +gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev) +{ + GList *head; + gst_autoplug_node *node; + + head = g_list_first (queue); + + if (head) { + node = (gst_autoplug_node *)head->data; + *iNode = node->iNode; + *iPrev = node->iPrev; + *iDist = node->iDist; + head = g_list_remove (queue, node); + } + + return head; +} + +static GList* +gst_autoplug_func (gpointer src, gpointer sink, + GstAutoplugListFunction list_function, + GstAutoplugCostFunction cost_function, + gpointer data) +{ + gst_autoplug_node *rgnNodes; + GList *queue = NULL; + gpointer iNode, iPrev; + gint iDist, i, iCost; + + GList *elements = g_list_copy (list_function(data)); + GList *factories; + guint num_factories; + + elements = g_list_append (elements, sink); + elements = g_list_append (elements, src); + + factories = elements; + + num_factories = g_list_length (factories); + + rgnNodes = g_new0 (gst_autoplug_node, num_factories+1); + + for (i=0; i< num_factories; i++) { + gpointer fact = factories->data; + + rgnNodes[i].iNode = fact; + rgnNodes[i].iPrev = NULL; + + if (fact == src) { + rgnNodes[i].iDist = 0; + } + else { + rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST; + } + + factories = g_list_next (factories); + } + rgnNodes[num_factories].iNode = NULL; + + queue = gst_autoplug_enqueue (queue, src, 0, NULL); + + while (g_list_length (queue) > 0) { + GList *factories2 = elements; + + queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev); + + for (i=0; i< num_factories; i++) { + gpointer current = factories2->data; + + iCost = cost_function (iNode, current, data); + if (iCost != GST_AUTOPLUG_MAX_COST) { + if ((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) || + (rgnNodes[i].iDist > (iCost + iDist))) { + rgnNodes[i].iDist = iDist + iCost; + rgnNodes[i].iPrev = iNode; + + queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode); + } + } + + factories2 = g_list_next (factories2); + } + } + + return construct_path (rgnNodes, sink); +} + diff --git a/gst/autoplug/gststaticautoplugrender.h b/gst/autoplug/gststaticautoplugrender.h new file mode 100644 index 0000000000..351d4cdcaf --- /dev/null +++ b/gst/autoplug/gststaticautoplugrender.h @@ -0,0 +1,64 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstautoplug.h: Header for autoplugging functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_STATIC_AUTOPLUG_RENDER_H__ +#define __GST_STATIC_AUTOPLUG_RENDER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GST_TYPE_STATIC_AUTOPLUG_RENDER \ + (gst_static_autoplug_render_get_type()) +#define GST_STATIC_AUTOPLUG_RENDER(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_STATIC_AUTOPLUG_RENDER,GstStaticAutoplugRender)) +#define GST_STATIC_AUTOPLUG_RENDER_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_STATIC_AUTOPLUG_RENDER,GstStaticAutoplugRenderClass)) +#define GST_IS_STATIC_AUTOPLUG_RENDER(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_STATIC_AUTOPLUG_RENDER)) +#define GST_IS_STATIC_AUTOPLUG_RENDER_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_STATIC_AUTOPLUG_RENDER)) + +typedef struct _GstStaticAutoplugRender GstStaticAutoplugRender; +typedef struct _GstStaticAutoplugRenderClass GstStaticAutoplugRenderClass; + +struct _GstStaticAutoplugRender { + GstAutoplug object; +}; + +struct _GstStaticAutoplugRenderClass { + GstAutoplugClass parent_class; +}; + + +GtkType gst_static_autoplug_render_get_type (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_STATIC_AUTOPLUG_H__ */ + diff --git a/gst/elements/gstdisksrc.c b/gst/elements/gstdisksrc.c index 9eebbd4bf6..9e81eb9b73 100644 --- a/gst/elements/gstdisksrc.c +++ b/gst/elements/gstdisksrc.c @@ -2,7 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * - * gstdisksrc.c: + * gstdisksrc.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -56,23 +56,23 @@ enum { }; -static void gst_disksrc_class_init (GstDiskSrcClass *klass); -static void gst_disksrc_init (GstDiskSrc *disksrc); +static void gst_disksrc_class_init (GstDiskSrcClass *klass); +static void gst_disksrc_init (GstDiskSrc *disksrc); -static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id); -static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id); static GstBuffer * gst_disksrc_get (GstPad *pad); static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len); -static GstElementStateReturn gst_disksrc_change_state (GstElement *element); +static GstElementStateReturn gst_disksrc_change_state (GstElement *element); static GstElementClass *parent_class = NULL; //static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 }; GtkType -gst_disksrc_get_type(void) +gst_disksrc_get_type(void) { static GtkType disksrc_type = 0; @@ -93,7 +93,7 @@ gst_disksrc_get_type(void) } static void -gst_disksrc_class_init (GstDiskSrcClass *klass) +gst_disksrc_class_init (GstDiskSrcClass *klass) { GtkObjectClass *gtkobject_class; GstElementClass *gstelement_class; @@ -118,8 +118,8 @@ gst_disksrc_class_init (GstDiskSrcClass *klass) gstelement_class->change_state = gst_disksrc_change_state; } -static void -gst_disksrc_init (GstDiskSrc *disksrc) +static void +gst_disksrc_init (GstDiskSrc *disksrc) { // GST_FLAG_SET (disksrc, GST_SRC_); @@ -139,14 +139,14 @@ gst_disksrc_init (GstDiskSrc *disksrc) } -static void -gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) { GstDiskSrc *src; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_DISKSRC (object)); - + src = GST_DISKSRC (object); switch(id) { @@ -176,14 +176,14 @@ gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) } } -static void -gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) { GstDiskSrc *src; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_DISKSRC (object)); - + src = GST_DISKSRC (object); switch (id) { @@ -212,7 +212,7 @@ gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) * Push a new buffer from the disksrc at the current offset. */ static GstBuffer * -gst_disksrc_get (GstPad *pad) +gst_disksrc_get (GstPad *pad) { GstDiskSrc *src; GstBuffer *buf; @@ -223,7 +223,7 @@ gst_disksrc_get (GstPad *pad) /* deal with EOF state */ if (src->curoffset >= src->size) { - gst_element_signal_eos (GST_ELEMENT (src)); + gst_pad_set_eos (pad); return NULL; } @@ -269,7 +269,7 @@ gst_disksrc_get (GstPad *pad) * Push a new buffer from the disksrc of given size at given offset. */ static GstBuffer * -gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len) +gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len) { GstDiskSrc *src; GstBuffer *buf; @@ -281,10 +281,10 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l g_return_val_if_fail (GST_IS_DISKSRC (src), NULL); g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL); - + /* deal with EOF state */ if (offset >= src->size) { - gst_element_signal_eos (GST_ELEMENT (src)); + gst_pad_set_eos (pad); return NULL; } @@ -312,8 +312,8 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l /* open the file and mmap it, necessary to go to READY state */ -static -gboolean gst_disksrc_open_file (GstDiskSrc *src) +static +gboolean gst_disksrc_open_file (GstDiskSrc *src) { g_return_val_if_fail (!GST_FLAG_IS_SET (src ,GST_DISKSRC_OPEN), FALSE); @@ -343,8 +343,8 @@ gboolean gst_disksrc_open_file (GstDiskSrc *src) } /* unmap and close the file */ -static void -gst_disksrc_close_file (GstDiskSrc *src) +static void +gst_disksrc_close_file (GstDiskSrc *src) { g_return_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN)); @@ -365,8 +365,8 @@ gst_disksrc_close_file (GstDiskSrc *src) } -static GstElementStateReturn -gst_disksrc_change_state (GstElement *element) +static GstElementStateReturn +gst_disksrc_change_state (GstElement *element) { g_return_val_if_fail (GST_IS_DISKSRC (element), GST_STATE_FAILURE); @@ -375,7 +375,7 @@ gst_disksrc_change_state (GstElement *element) gst_disksrc_close_file (GST_DISKSRC (element)); } else { if (!GST_FLAG_IS_SET (element, GST_DISKSRC_OPEN)) { - if (!gst_disksrc_open_file (GST_DISKSRC (element))) + if (!gst_disksrc_open_file (GST_DISKSRC (element))) return GST_STATE_FAILURE; } } diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c index 193592ac85..62b5a9288f 100644 --- a/gst/elements/gstelements.c +++ b/gst/elements/gstelements.c @@ -2,7 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * - * gstelements.c: + * gstelements.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -61,13 +61,13 @@ static struct _elements_entry _elements[] = { { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, #if HAVE_LIBGHTTP - { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, #endif /* HAVE_LIBGHTTP */ - + { NULL, 0 }, }; -GstPlugin *plugin_init (GModule *module) +GstPlugin *plugin_init (GModule *module) { GstPlugin *plugin; GstElementFactory *factory; diff --git a/gst/gstautoplug.c b/gst/gstautoplug.c index 4a088a5344..3f74b25bb1 100644 --- a/gst/gstautoplug.c +++ b/gst/gstautoplug.c @@ -24,337 +24,268 @@ #include "gst_private.h" #include "gstautoplug.h" +#include "gstplugin.h" + +GList* _gst_autoplugfactories; + +enum { + NEW_OBJECT, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; static void gst_autoplug_class_init (GstAutoplugClass *klass); static void gst_autoplug_init (GstAutoplug *autoplug); -static GList* gst_autoplug_func (gpointer src, gpointer sink, - GstAutoplugListFunction list_function, - GstAutoplugCostFunction cost_function, - gpointer data); - -struct _gst_autoplug_node -{ - gpointer iNode; - gpointer iPrev; - gint iDist; -}; - -typedef struct _gst_autoplug_node gst_autoplug_node; - static GstObjectClass *parent_class = NULL; +static guint gst_autoplug_signals[LAST_SIGNAL] = { 0 }; -GtkType gst_autoplug_get_type(void) { +GtkType gst_autoplug_get_type(void) +{ static GtkType autoplug_type = 0; if (!autoplug_type) { static const GtkTypeInfo autoplug_info = { "GstAutoplug", - sizeof(GstElement), - sizeof(GstElementClass), + sizeof(GstAutoplug), + sizeof(GstAutoplugClass), (GtkClassInitFunc)gst_autoplug_class_init, (GtkObjectInitFunc)gst_autoplug_init, (GtkArgSetFunc)NULL, (GtkArgGetFunc)NULL, (GtkClassInitFunc)NULL, }; - autoplug_type = gtk_type_unique(GST_TYPE_AUTOPLUG,&autoplug_info); + autoplug_type = gtk_type_unique (GST_TYPE_OBJECT, &autoplug_info); } return autoplug_type; } static void -gst_autoplug_class_init(GstAutoplugClass *klass) { +gst_autoplug_class_init(GstAutoplugClass *klass) +{ + GtkObjectClass *gtkobject_class; + GstObjectClass *gstobject_class; + + gtkobject_class = (GtkObjectClass*) klass; + gstobject_class = (GstObjectClass*) klass; + parent_class = gtk_type_class(GST_TYPE_OBJECT); + + gst_autoplug_signals[NEW_OBJECT] = + gtk_signal_new ("new_object", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstAutoplugClass, new_object), + gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, + GST_TYPE_OBJECT); + + gtk_object_class_add_signals (gtkobject_class, gst_autoplug_signals, LAST_SIGNAL); } -static void gst_autoplug_init(GstAutoplug *autoplug) { -} - -static gboolean -gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest) +static void gst_autoplug_init(GstAutoplug *autoplug) { - GList *srctemps, *desttemps; - - srctemps = src->padtemplates; - - while (srctemps) { - GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data; - - desttemps = dest->padtemplates; - - while (desttemps) { - GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data; - - if (srctemp->direction == GST_PAD_SRC && - desttemp->direction == GST_PAD_SINK) { - if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) { - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name); - return TRUE; - } - } - - desttemps = g_list_next (desttemps); - } - srctemps = g_list_next (srctemps); - } - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name); - return FALSE; } -static GList* -gst_autoplug_elementfactory_get_list (gpointer data) +void +_gst_autoplug_initialize (void) { - return gst_elementfactory_get_list (); + _gst_autoplugfactories = NULL; } -typedef struct { - GList *src; - GList *sink; -} caps_struct; - -#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink) - -static guint -gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) +void +gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object) { - caps_struct *caps = (caps_struct *)data; - gboolean res; + gtk_signal_emit (GTK_OBJECT (autoplug), gst_autoplug_signals[NEW_OBJECT], object); +} - if (IS_CAPS (src) && IS_CAPS (dest)) { - res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest); - //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res); - } - else if (IS_CAPS (src)) { - res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src); - //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res); - } - else if (IS_CAPS (dest)) { - res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest); - //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res); - } - else { - res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest); - } - if (res) - return 1; - else - return GST_AUTOPLUG_MAX_COST; +GstElement* +gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...) +{ + GstAutoplugClass *oclass; + GstElement *element = NULL; + va_list args; + + va_start (args, sinkcaps); + + oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass); + if (oclass->autoplug_to_caps) + element = (oclass->autoplug_to_caps) (autoplug, srccaps, sinkcaps, args); + + va_end (args); + + return element; +} + +GstElement* +gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...) +{ + GstAutoplugClass *oclass; + GstElement *element = NULL; + va_list args; + + va_start (args, target); + + oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass); + if (oclass->autoplug_to_renderers) + element = (oclass->autoplug_to_renderers) (autoplug, srccaps, target, args); + + va_end (args); + + return element; +} + + +/** + * gst_autoplugfactory_new: + * @name: name of autoplugfactory to create + * @longdesc: long description of autoplugfactory to create + * @type: the gtk type of the GstAutoplug element of this factory + * + * Create a new autoplugfactory with the given parameters + * + * Returns: a new #GstAutoplugFactory. + */ +GstAutoplugFactory* +gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type) +{ + GstAutoplugFactory *factory; + + g_return_val_if_fail(name != NULL, NULL); + + factory = g_new0(GstAutoplugFactory, 1); + + factory->name = g_strdup(name); + factory->longdesc = g_strdup (longdesc); + factory->type = type; + + _gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory); + + return factory; } /** - * gst_autoplug_caps: - * @srccaps: the source caps - * @sinkcaps: the sink caps + * gst_autoplugfactory_destroy: + * @autoplug: factory to destroy * - * Perform autoplugging between the two given caps. - * - * Returns: a list of elementfactories that can connect - * the two caps + * Removes the autoplug from the global list. */ -GList* -gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps) +void +gst_autoplugfactory_destroy (GstAutoplugFactory *autoplug) { - caps_struct caps; + g_return_if_fail (autoplug != NULL); - caps.src = g_list_prepend (NULL,srccaps); - caps.sink = g_list_prepend (NULL,sinkcaps); + _gst_autoplugfactories = g_list_remove (_gst_autoplugfactories, autoplug); - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures"); - - return gst_autoplug_func (caps.src, caps.sink, - gst_autoplug_elementfactory_get_list, - gst_autoplug_caps_find_cost, - &caps); + // we don't free the struct bacause someone might have a handle to it.. } /** - * gst_autoplug_caps_list: - * @srccaps: the source caps list - * @sinkcaps: the sink caps list + * gst_autoplug_find: + * @name: name of autoplugger to find * - * Perform autoplugging between the two given caps lists. + * Search for an autoplugger of the given name. * - * Returns: a list of elementfactories that can connect - * the two caps lists + * Returns: #GstAutoplug if found, NULL otherwise */ -GList* -gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps) +GstAutoplugFactory* +gst_autoplugfactory_find (const gchar *name) { - caps_struct caps; + GList *walk; + GstAutoplugFactory *factory; - caps.src = srccaps; - caps.sink = sinkcaps; + g_return_val_if_fail(name != NULL, NULL); - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps list structures"); + GST_DEBUG (0,"gstautoplug: find \"%s\"\n", name); - return gst_autoplug_func (caps.src, caps.sink, - gst_autoplug_elementfactory_get_list, - gst_autoplug_caps_find_cost, - &caps); + walk = _gst_autoplugfactories; + while (walk) { + factory = (GstAutoplugFactory *)(walk->data); + if (!strcmp (name, factory->name)) + return factory; + walk = g_list_next (walk); + } + + return NULL; } /** - * gst_autoplug_pads: - * @srcpad: the source pad - * @sinkpad: the sink pad + * gst_autoplugfactory_get_list: * - * Perform autoplugging between the two given pads. + * Get the global list of elementfactories. * - * Returns: a list of elementfactories that can connect - * the two pads + * Returns: GList of type #GstElementFactory */ GList* -gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad) +gst_autoplugfactory_get_list (void) { - caps_struct caps; - - caps.src = gst_pad_get_caps_list(srcpad); - caps.sink = gst_pad_get_caps_list(sinkpad); - - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures"); - - return gst_autoplug_func (caps.src, caps.sink, - gst_autoplug_elementfactory_get_list, - gst_autoplug_caps_find_cost, - &caps); + return _gst_autoplugfactories; } -static gint -find_factory (gst_autoplug_node *rgnNodes, gpointer factory) -{ - gint i=0; - while (rgnNodes[i].iNode) { - if (rgnNodes[i].iNode == factory) return i; - i++; +GstAutoplug* +gst_autoplugfactory_create (GstAutoplugFactory *factory) +{ + GstAutoplug *new = NULL; + + g_return_val_if_fail (factory != NULL, NULL); + + if (factory->type == 0){ + factory = gst_plugin_load_autoplugfactory (factory->name); } - return 0; + g_return_val_if_fail (factory != NULL, NULL); + g_return_val_if_fail (factory->type != 0, NULL); + + new = GST_AUTOPLUG (gtk_type_new (factory->type)); + + return new; } -static GList* -construct_path (gst_autoplug_node *rgnNodes, gpointer factory) +GstAutoplug* +gst_autoplugfactory_make (const gchar *name) { - GstElementFactory *current; - GList *factories = NULL; + GstAutoplugFactory *factory; - current = rgnNodes[find_factory(rgnNodes, factory)].iPrev; + g_return_val_if_fail (name != NULL, NULL); - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)"); + factory = gst_autoplugfactory_find (name); - while (current != NULL) - { - gpointer next = NULL; + if (factory == NULL) + return NULL; - next = rgnNodes[find_factory(rgnNodes, current)].iPrev; - if (next) { - factories = g_list_prepend (factories, current); - GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name); + return gst_autoplugfactory_create (factory);; +} + +xmlNodePtr +gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent) +{ + g_return_val_if_fail(factory != NULL, NULL); + + xmlNewChild(parent,NULL,"name",factory->name); + xmlNewChild(parent,NULL,"longdesc", factory->longdesc); + + return parent; +} + +GstAutoplugFactory* +gst_autoplugfactory_load_thyself (xmlNodePtr parent) +{ + GstAutoplugFactory *factory = g_new0(GstAutoplugFactory, 1); + xmlNodePtr children = parent->xmlChildrenNode; + + while (children) { + if (!strcmp(children->name, "name")) { + factory->name = xmlNodeGetContent(children); } - current = next; - } - return factories; -} - -static GList* -gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev) -{ - gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node)); - - node->iNode = iNode; - node->iDist = iDist; - node->iPrev = iPrev; - - queue = g_list_append (queue, node); - - return queue; -} - -static GList* -gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev) -{ - GList *head; - gst_autoplug_node *node; - - head = g_list_first (queue); - - if (head) { - node = (gst_autoplug_node *)head->data; - *iNode = node->iNode; - *iPrev = node->iPrev; - *iDist = node->iDist; - head = g_list_remove (queue, node); - } - - return head; -} - -static GList* -gst_autoplug_func (gpointer src, gpointer sink, - GstAutoplugListFunction list_function, - GstAutoplugCostFunction cost_function, - gpointer data) -{ - gst_autoplug_node *rgnNodes; - GList *queue = NULL; - gpointer iNode, iPrev; - gint iDist, i, iCost; - - GList *elements = g_list_copy (list_function(data)); - GList *factories; - guint num_factories; - - elements = g_list_append (elements, sink); - elements = g_list_append (elements, src); - - factories = elements; - - num_factories = g_list_length (factories); - - rgnNodes = g_new0 (gst_autoplug_node, num_factories+1); - - for (i=0; i< num_factories; i++) { - gpointer fact = factories->data; - - rgnNodes[i].iNode = fact; - rgnNodes[i].iPrev = NULL; - - if (fact == src) { - rgnNodes[i].iDist = 0; - } - else { - rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST; - } - - factories = g_list_next (factories); - } - rgnNodes[num_factories].iNode = NULL; - - queue = gst_autoplug_enqueue (queue, src, 0, NULL); - - while (g_list_length (queue) > 0) { - GList *factories2 = elements; - - queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev); - - for (i=0; i< num_factories; i++) { - gpointer current = factories2->data; - - iCost = cost_function (iNode, current, data); - if (iCost != GST_AUTOPLUG_MAX_COST) { - if((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) || - (rgnNodes[i].iDist > (iCost + iDist))) { - rgnNodes[i].iDist = iDist + iCost; - rgnNodes[i].iPrev = iNode; - - queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode); - } - } - - factories2 = g_list_next (factories2); + if (!strcmp(children->name, "longdesc")) { + factory->longdesc = xmlNodeGetContent(children); } + children = children->next; } - return construct_path (rgnNodes, sink); + _gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory); + + return factory; } diff --git a/gst/gstautoplug.h b/gst/gstautoplug.h index c646c24d61..14d96d55d3 100644 --- a/gst/gstautoplug.h +++ b/gst/gstautoplug.h @@ -31,7 +31,7 @@ extern "C" { #endif /* __cplusplus */ #define GST_TYPE_AUTOPLUG \ - (gst_object_get_type()) + (gst_autoplug_get_type()) #define GST_AUTOPLUG(obj) \ (GTK_CHECK_CAST((obj),GST_TYPE_AUTOPLUG,GstAutoplug)) #define GST_AUTOPLUG_CLASS(klass) \ @@ -44,30 +44,66 @@ extern "C" { typedef struct _GstAutoplug GstAutoplug; typedef struct _GstAutoplugClass GstAutoplugClass; -#define GST_AUTOPLUG_MAX_COST 999999 +typedef enum { + GST_AUTOPLUG_TO_CAPS = GST_OBJECT_FLAG_LAST, + GST_AUTOPLUG_TO_RENDERER, -typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data); -typedef GList* (*GstAutoplugListFunction) (gpointer data); + GST_AUTOPLUG_FLAG_LAST = GST_OBJECT_FLAG_LAST + 8, +} GstAutoplugFlags; + struct _GstAutoplug { - GtkObject object; + GstObject object; }; struct _GstAutoplugClass { - GtkObjectClass parent_class; + GstObjectClass parent_class; + + /* signal callbacks */ + void (*new_object) (GstAutoplug *autoplug, GstObject *object); + + /* perform the autoplugging */ + GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args); + GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args); }; -GtkType gst_autoplug_get_type (void); +typedef struct _GstAutoplugFactory GstAutoplugFactory; -GList* gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps); -GList* gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps); -GList* gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad); +struct _GstAutoplugFactory { + gchar *name; /* name of autoplugger */ + gchar *longdesc; /* long description of the autoplugger (well, don't overdo it..) */ + GtkType type; /* unique GtkType of the autoplugger */ +}; +GtkType gst_autoplug_get_type (void); + +void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object); + +GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...); +GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, + GstElement *target, ...); + + +/* + * creating autopluggers + * + */ +GstAutoplugFactory* gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type); +void gst_autoplugfactory_destroy (GstAutoplugFactory *factory); + +GstAutoplugFactory* gst_autoplugfactory_find (const gchar *name); +GList* gst_autoplugfactory_get_list (void); + +GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *factory); +GstAutoplug* gst_autoplugfactory_make (const gchar *name); + +xmlNodePtr gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent); +GstAutoplugFactory* gst_autoplugfactory_load_thyself (xmlNodePtr parent); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* __GST_AUTOPLUG_H__ */ +#endif /* __GST_AUTOPLUG_H__ */ diff --git a/gst/gstbin.c b/gst/gstbin.c index d33078b023..dc0331e07e 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -234,6 +234,7 @@ gst_bin_change_state (GstElement *element) GstBin *bin; GList *children; GstElement *child; + GstElementStateReturn ret; GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME (element)); @@ -265,6 +266,8 @@ gst_bin_change_state (GstElement *element) break; } + case GST_STATE_READY_TO_NULL: + GST_FLAG_UNSET (bin, GST_BIN_FLAG_MANAGER); default: break; } @@ -289,9 +292,9 @@ gst_bin_change_state (GstElement *element) children = g_list_next (children); } // g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin))); + ret = gst_bin_change_state_norecurse (bin); - - return gst_bin_change_state_norecurse (bin); + return ret; } @@ -587,7 +590,7 @@ gst_bin_create_plan (GstBin *bin) static void gst_bin_received_eos (GstElement *element, GstBin *bin) { - GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d\n", GST_ELEMENT_NAME (element), + GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d", GST_ELEMENT_NAME (element), bin->num_eos_providers); GST_LOCK (bin); @@ -756,7 +759,9 @@ gst_bin_create_plan_func (GstBin *bin) } // else it's not ours and we need to wait for EOS notifications else { - gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin); + GST_DEBUG (0,"setting up EOS signal from \"%s\" to \"%s\"\n", elementname, + gst_element_get_name (GST_ELEMENT(bin)->manager)); + gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, GST_ELEMENT(bin)->manager); bin->eos_providers = g_list_prepend (bin->eos_providers, element); bin->num_eos_providers++; } @@ -869,7 +874,7 @@ gst_bin_iterate_func (GstBin *bin) if (bin->num_eos_providers) { GST_LOCK (bin); GST_DEBUG (0,"waiting for eos providers\n"); - g_cond_wait (bin->eoscond, GST_OBJECT(bin)->lock); + g_cond_wait (bin->eoscond, GST_GET_LOCK(bin)); GST_DEBUG (0,"num eos providers %d\n", bin->num_eos_providers); GST_UNLOCK (bin); } diff --git a/gst/gstcaps.c b/gst/gstcaps.c index f8bfcb3e66..ebdaccc301 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -29,8 +29,8 @@ #include "gstpropsprivate.h" -void -_gst_caps_initialize (void) +void +_gst_caps_initialize (void) { } @@ -67,12 +67,12 @@ gst_caps_new (const gchar *name, const gchar *mime) GstCaps *caps; g_return_val_if_fail (mime != NULL, NULL); - + caps = g_new0 (GstCaps, 1); caps->name = g_strdup (name); caps->id = get_type_for_mime (mime); caps->properties = NULL; - + return caps; } @@ -90,7 +90,7 @@ GstCaps* gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props) { GstCaps *caps; - + caps = gst_caps_new (name, mime); caps->properties = props; @@ -101,7 +101,7 @@ gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props) * gst_caps_register: * @factory: the factory to register * - * Register the factory. + * Register the factory. * * Returns: the registered capability */ @@ -140,7 +140,7 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter) tag = (*factory)[i++]; g_return_val_if_fail (tag != NULL, NULL); - + typeid = get_type_for_mime ((gchar *)tag); caps = g_new0 (GstCaps, 1); @@ -163,7 +163,7 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter) * * Returns: the name of the caps */ -const gchar* +const gchar* gst_caps_get_name (GstCaps *caps) { g_return_val_if_fail (caps != NULL, NULL); @@ -173,7 +173,7 @@ gst_caps_get_name (GstCaps *caps) /** * gst_caps_set_name: - * @caps: the caps to set the name to + * @caps: the caps to set the name to * @name: the name to set * * Set the name of a caps. @@ -182,7 +182,7 @@ void gst_caps_set_name (GstCaps *caps, const gchar *name) { g_return_if_fail (caps != NULL); - + if (caps->name) g_free (caps->name); @@ -197,7 +197,7 @@ gst_caps_set_name (GstCaps *caps, const gchar *name) * * Returns: the mime type of the caps */ -const gchar* +const gchar* gst_caps_get_mime (GstCaps *caps) { GstType *type; @@ -206,9 +206,9 @@ gst_caps_get_mime (GstCaps *caps) type = gst_type_find_by_id (caps->id); - if (type) + if (type) return type->mime; - else + else return "unknown/unknown"; } @@ -236,7 +236,7 @@ gst_caps_set_mime (GstCaps *caps, const gchar *mime) * * Returns: the type id of the caps */ -guint16 +guint16 gst_caps_get_type_id (GstCaps *caps) { g_return_val_if_fail (caps != NULL, 0); @@ -247,16 +247,16 @@ gst_caps_get_type_id (GstCaps *caps) /** * gst_caps_set_type_id: * @caps: the caps to set the type id to - * @typeid: the type id to set + * @typeid: the type id to set * * Set the type id of the caps. */ void -gst_caps_set_type_id (GstCaps *caps, guint16 typeid) +gst_caps_set_type_id (GstCaps *caps, guint16 type_id) { g_return_if_fail (caps != NULL); - caps->id = typeid; + caps->id = type_id; } /** @@ -276,7 +276,7 @@ gst_caps_set_props (GstCaps *caps, GstProps *props) g_return_val_if_fail (caps->properties == NULL, caps); caps->properties = props; - + return caps; } @@ -310,7 +310,7 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps) { g_return_val_if_fail (fromcaps != NULL, FALSE); g_return_val_if_fail (tocaps != NULL, FALSE); - + if (fromcaps->id != tocaps->id) { GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n", fromcaps->id, tocaps->id); @@ -371,7 +371,7 @@ gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps) * * Returns: a new XML node pointer */ -xmlNodePtr +xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent) { xmlNodePtr subtree; @@ -397,7 +397,7 @@ gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent) * * Returns: a new capability */ -GstCaps* +GstCaps* gst_caps_load_thyself (xmlNodePtr parent) { GstCaps *caps = g_new0 (GstCaps, 1); diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 99634d462b..dffa1cd3d5 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -52,7 +52,7 @@ struct _GstCaps { }; /* initialize the subsystem */ -void _gst_caps_initialize (void); +void _gst_caps_initialize (void); GstCaps* gst_caps_new (const gchar *name, const gchar *mime); GstCaps* gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props); @@ -60,21 +60,21 @@ GstCaps* gst_caps_register (GstCapsFactory *factory); GstCaps* gst_caps_register_count (GstCapsFactory *factory, guint *counter); const gchar* gst_caps_get_name (GstCaps *caps); -void gst_caps_set_name (GstCaps *caps, const gchar *name); +void gst_caps_set_name (GstCaps *caps, const gchar *name); const gchar* gst_caps_get_mime (GstCaps *caps); -void gst_caps_set_mime (GstCaps *caps, const gchar *mime); +void gst_caps_set_mime (GstCaps *caps, const gchar *mime); -guint16 gst_caps_get_type_id (GstCaps *caps); -void gst_caps_set_type_id (GstCaps *caps, guint16 /*typeid*/); +guint16 gst_caps_get_type_id (GstCaps *caps); +void gst_caps_set_type_id (GstCaps *caps, guint16 type_id); GstCaps* gst_caps_set_props (GstCaps *caps, GstProps *props); GstProps* gst_caps_get_props (GstCaps *caps); -gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps); -gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps); +gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps); +gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps); -xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent); -GstCaps* gst_caps_load_thyself (xmlNodePtr parent); +xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent); +GstCaps* gst_caps_load_thyself (xmlNodePtr parent); #endif /* __GST_CAPS_H__ */ diff --git a/gst/gstelement.c b/gst/gstelement.c index ef1c1b98a2..e8dc9ce5f6 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -519,7 +519,7 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ) g_return_val_if_fail (templ != NULL, NULL); templ_new = gst_element_get_padtemplate_by_compatible (element, templ); - if (templ_new != NULL) + if (templ_new != NULL) pad = gst_element_request_pad (element, templ_new); return pad; @@ -902,13 +902,15 @@ gst_element_save_thyself (GstObject *object, type = gtk_type_parent (type); } - pads = element->pads; + pads = GST_ELEMENT_PADS (element); + while (pads) { GstPad *pad = GST_PAD (pads->data); - xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL); // figure out if it's a direct pad or a ghostpad - if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) + if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) { + xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL); gst_object_save_thyself (GST_OBJECT (pad), padtag); + } pads = g_list_next (pads); } @@ -973,7 +975,6 @@ gst_element_load_thyself (xmlNodePtr self, GstObject *parent) } child = child->next; } - gst_util_set_object_arg (GTK_OBJECT (element), name, value); } children = children->next; diff --git a/gst/gstelement.h b/gst/gstelement.h index a88e216942..655d18fafe 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -122,6 +122,7 @@ typedef enum { #define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj)) #define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj)) +#define GST_ELEMENT_PADS(obj) ((obj)->pads) typedef struct _GstElement GstElement; typedef struct _GstElementClass GstElementClass; diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 6e31a0d6e2..eced12ed3e 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -30,8 +30,8 @@ /* global list of registered elementfactories */ GList* _gst_elementfactories; -void -_gst_elementfactory_initialize (void) +void +_gst_elementfactory_initialize (void) { _gst_elementfactories = NULL; } @@ -42,8 +42,8 @@ _gst_elementfactory_initialize (void) * * Removes the elementfactory from the global list. */ -void -gst_elementfactory_destroy (GstElementFactory *elementfactory) +void +gst_elementfactory_destroy (GstElementFactory *elementfactory) { g_return_if_fail (elementfactory != NULL); @@ -61,7 +61,7 @@ gst_elementfactory_destroy (GstElementFactory *elementfactory) * Returns: #GstElementFactory if found, NULL otherwise */ GstElementFactory* -gst_elementfactory_find (const gchar *name) +gst_elementfactory_find (const gchar *name) { GList *walk; GstElementFactory *factory; @@ -89,7 +89,7 @@ gst_elementfactory_find (const gchar *name) * Returns: GList of type #GstElementFactory */ GList* -gst_elementfactory_get_list (void) +gst_elementfactory_get_list (void) { return _gst_elementfactories; } @@ -108,12 +108,14 @@ gst_elementfactory_get_list (void) */ GstElementFactory* gst_elementfactory_new (const gchar *name, GtkType type, - GstElementDetails *details) + GstElementDetails *details) { - GstElementFactory *factory = g_new0(GstElementFactory, 1); + GstElementFactory *factory; g_return_val_if_fail(name != NULL, NULL); + factory = g_new0(GstElementFactory, 1); + factory->name = g_strdup(name); factory->type = type; factory->details = details; @@ -138,7 +140,7 @@ gst_elementfactory_new (const gchar *name, GtkType type, */ GstElement * gst_elementfactory_create (GstElementFactory *factory, - const gchar *name) + const gchar *name) { GstElement *element; GstElementClass *oclass; @@ -184,7 +186,7 @@ gst_elementfactory_create (GstElementFactory *factory, * Returns: new #GstElement */ GstElement* -gst_elementfactory_make (const gchar *factoryname, const gchar *name) +gst_elementfactory_make (const gchar *factoryname, const gchar *name) { GstElementFactory *factory; GstElement *element; @@ -338,15 +340,15 @@ gst_elementfactory_can_sink_caps (GstElementFactory *factory, /** * gst_elementfactory_save_thyself: * @factory: factory to save - * @parent: the parent xmlNodePtr + * @parent: the parent xmlNodePtr * * Saves the factory into an XML tree. - * + * * Returns: the new xmlNodePtr */ -xmlNodePtr -gst_elementfactory_save_thyself (GstElementFactory *factory, - xmlNodePtr parent) +xmlNodePtr +gst_elementfactory_save_thyself (GstElementFactory *factory, + xmlNodePtr parent) { GList *pads; @@ -377,14 +379,14 @@ gst_elementfactory_save_thyself (GstElementFactory *factory, /** * gst_elementfactory_load_thyself: - * @parent: the parent xmlNodePtr + * @parent: the parent xmlNodePtr * * Creates a new factory from an xmlNodePtr. - * + * * Returns: the new factory */ GstElementFactory * -gst_elementfactory_load_thyself (xmlNodePtr parent) +gst_elementfactory_load_thyself (xmlNodePtr parent) { GstElementFactory *factory = g_new0(GstElementFactory, 1); xmlNodePtr children = parent->xmlChildrenNode; @@ -415,7 +417,7 @@ gst_elementfactory_load_thyself (xmlNodePtr parent) } if (!strcmp(children->name, "padtemplate")) { GstPadTemplate *template; - + template = gst_padtemplate_load_thyself (children); gst_elementfactory_add_padtemplate (factory, template); diff --git a/gst/gstobject.c b/gst/gstobject.c index fe80744e27..c26744f8e0 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -370,13 +370,15 @@ gst_object_get_path_string (GstObject *object) GSList *parentage = NULL; GSList *parents; void *parent; - gchar *prevpath, *path = ""; + gchar *prevpath, *path; const char *component; gchar *separator = ""; gboolean free_component; parentage = g_slist_prepend (NULL, object); + path = g_strdup (""); + // first walk the object hierarchy to build a list of the parents do { if (GST_IS_OBJECT (object)) { @@ -397,9 +399,9 @@ gst_object_get_path_string (GstObject *object) parents = parentage; while (parents) { if (GST_IS_OBJECT (parents->data)) { - GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data)); + GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data)->klass); - component = GST_OBJECT_NAME (parents->data); + component = gst_object_get_name (parents->data); separator = oclass->path_string_separator; free_component = FALSE; } else { diff --git a/gst/gstpad.c b/gst/gstpad.c index 6946810fab..e613addae3 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -35,7 +35,6 @@ static void gst_pad_init (GstPad *pad); static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent); - static GstObject *pad_parent_class = NULL; GtkType @@ -593,6 +592,25 @@ gst_pad_get_parent (GstPad *pad) return GST_OBJECT_PARENT (pad); } +/** + * gst_pad_get_real_parent: + * @pad: the pad to get the parent from + * + * Get the real parent object of this pad. If the pad + * is a ghostpad, the actual owner of the real pad is + * returned, as opposed to the gst_pad_get_parent. + * + * Returns: the parent object + */ +GstObject* +gst_pad_get_real_parent (GstPad *pad) +{ + g_return_val_if_fail (pad != NULL, NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad))); +} + /** * gst_pad_add_ghost_pad: * @pad: the pad to set the ghost parent @@ -948,7 +966,7 @@ gst_pad_pull (GstPad *pad) { GstRealPad *peer = GST_RPAD_PEER(pad); - g_return_if_fail (peer != NULL); + g_return_val_if_fail (peer != NULL, NULL); GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad)); @@ -983,7 +1001,7 @@ gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len { GstRealPad *peer = GST_RPAD_PEER(pad); - g_return_if_fail (peer != NULL); + g_return_val_if_fail (peer != NULL, NULL); GST_DEBUG_ENTER("(%s:%s,%d,%lld,%lld)",GST_DEBUG_PAD_NAME(pad),type,offset,len); @@ -1003,6 +1021,65 @@ gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len * templates * */ +static void gst_padtemplate_class_init (GstPadTemplateClass *klass); +static void gst_padtemplate_init (GstPadTemplate *templ); + +enum { + TEMPL_PAD_CREATED, + /* FILL ME */ + TEMPL_LAST_SIGNAL +}; + +static GstObject *padtemplate_parent_class = NULL; +static guint gst_padtemplate_signals[TEMPL_LAST_SIGNAL] = { 0 }; + +GtkType +gst_padtemplate_get_type (void) +{ + static GtkType padtemplate_type = 0; + + if (!padtemplate_type) { + static const GtkTypeInfo padtemplate_info = { + "GstPadTemplate", + sizeof(GstPadTemplate), + sizeof(GstPadTemplateClass), + (GtkClassInitFunc)gst_padtemplate_class_init, + (GtkObjectInitFunc)gst_padtemplate_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + padtemplate_type = gtk_type_unique(GST_TYPE_OBJECT,&padtemplate_info); + } + return padtemplate_type; +} + +static void +gst_padtemplate_class_init (GstPadTemplateClass *klass) +{ + GtkObjectClass *gtkobject_class; + GstObjectClass *gstobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstobject_class = (GstObjectClass*)klass; + + padtemplate_parent_class = gtk_type_class(GST_TYPE_OBJECT); + + gst_padtemplate_signals[TEMPL_PAD_CREATED] = + gtk_signal_new ("pad_created", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstPadTemplateClass, pad_created), + gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, + GST_TYPE_PAD); + + gtk_object_class_add_signals (gtkobject_class, gst_padtemplate_signals, TEMPL_LAST_SIGNAL); + + gstobject_class->path_string_separator = "*"; +} + +static void +gst_padtemplate_init (GstPadTemplate *templ) +{ +} /** * gst_padtemplate_new: @@ -1022,7 +1099,7 @@ gst_padtemplate_new (GstPadFactory *factory) g_return_val_if_fail (factory != NULL, NULL); - new = g_new0 (GstPadTemplate, 1); + new = gtk_type_new (gst_padtemplate_get_type ()); tag = (*factory)[i++]; g_return_val_if_fail (tag != NULL, new); @@ -1063,7 +1140,9 @@ gst_padtemplate_create (gchar *name_template, { GstPadTemplate *new; - new = g_new0 (GstPadTemplate, 1); + g_return_val_if_fail (name_template != NULL, NULL); + + new = gtk_type_new (gst_padtemplate_get_type ()); new->name_template = name_template; new->direction = direction; @@ -1134,21 +1213,24 @@ GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent) { xmlNodePtr field = parent->xmlChildrenNode; - GstPadTemplate *factory = g_new0 (GstPadTemplate, 1); + GstPadTemplate *factory; + gchar *name_template = NULL; + GstPadDirection direction = GST_PAD_UNKNOWN; + GstPadPresence presence = GST_PAD_ALWAYS; + GList *caps = NULL; while (field) { if (!strcmp(field->name, "nametemplate")) { - factory->name_template = xmlNodeGetContent(field); + name_template = xmlNodeGetContent(field); } if (!strcmp(field->name, "direction")) { gchar *value = xmlNodeGetContent(field); - factory->direction = GST_PAD_UNKNOWN; if (!strcmp(value, "sink")) { - factory->direction = GST_PAD_SINK; + direction = GST_PAD_SINK; } else if (!strcmp(value, "src")) { - factory->direction = GST_PAD_SRC; + direction = GST_PAD_SRC; } g_free (value); } @@ -1156,21 +1238,24 @@ gst_padtemplate_load_thyself (xmlNodePtr parent) gchar *value = xmlNodeGetContent(field); if (!strcmp(value, "always")) { - factory->presence = GST_PAD_ALWAYS; + presence = GST_PAD_ALWAYS; } else if (!strcmp(value, "sometimes")) { - factory->presence = GST_PAD_SOMETIMES; + presence = GST_PAD_SOMETIMES; } else if (!strcmp(value, "request")) { - factory->presence = GST_PAD_REQUEST; + presence = GST_PAD_REQUEST; } g_free (value); } else if (!strcmp(field->name, "caps")) { - factory->caps = g_list_append(factory->caps, gst_caps_load_thyself (field)); + caps = g_list_append (caps, gst_caps_load_thyself (field)); } field = field->next; } + + factory = gst_padtemplate_create (name_template, direction, presence, caps); + return factory; } @@ -1271,13 +1356,6 @@ gst_pad_get_element_private (GstPad *pad) } - - - - - - - /***** ghost pads *****/ static void gst_ghost_pad_class_init (GstGhostPadClass *klass); diff --git a/gst/gstpad.h b/gst/gstpad.h index 8e1ed43cff..ef21617fdd 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -278,6 +278,7 @@ const gchar* gst_pad_get_name (GstPad *pad); void gst_pad_set_parent (GstPad *pad, GstObject *parent); GstObject* gst_pad_get_parent (GstPad *pad); +GstObject* gst_pad_get_real_parent (GstPad *pad); void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad); void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad); diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 065de192b2..f42d82bd2b 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -24,10 +24,6 @@ #include "gst_private.h" #include "gstpipeline.h" -#include "gstthread.h" -#include "gstutils.h" -#include "gsttype.h" -#include "gstautoplug.h" GstElementDetails gst_pipeline_details = { @@ -51,15 +47,13 @@ enum { }; -static void gst_pipeline_class_init (GstPipelineClass *klass); -static void gst_pipeline_init (GstPipeline *pipeline); +static void gst_pipeline_class_init (GstPipelineClass *klass); +static void gst_pipeline_init (GstPipeline *pipeline); -static GstElementStateReturn gst_pipeline_change_state (GstElement *element); +static GstElementStateReturn gst_pipeline_change_state (GstElement *element); -static void gst_pipeline_prepare (GstPipeline *pipeline); +static void gst_pipeline_prepare (GstPipeline *pipeline); -static void gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data); -static void gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink); static GstBinClass *parent_class = NULL; //static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; @@ -85,7 +79,7 @@ gst_pipeline_get_type (void) { } static void -gst_pipeline_class_init (GstPipelineClass *klass) +gst_pipeline_class_init (GstPipelineClass *klass) { GstElementClass *gstelement_class; @@ -96,14 +90,11 @@ gst_pipeline_class_init (GstPipelineClass *klass) gstelement_class->change_state = gst_pipeline_change_state; } -static void -gst_pipeline_init (GstPipeline *pipeline) +static void +gst_pipeline_init (GstPipeline *pipeline) { // we're a manager by default GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER); - - pipeline->src = NULL; - pipeline->sinks = NULL; } @@ -116,393 +107,25 @@ gst_pipeline_init (GstPipeline *pipeline) * Returns: newly created GstPipeline */ GstElement* -gst_pipeline_new (guchar *name) +gst_pipeline_new (guchar *name) { return gst_elementfactory_make ("pipeline", name); } -static void -gst_pipeline_prepare (GstPipeline *pipeline) +static void +gst_pipeline_prepare (GstPipeline *pipeline) { - GST_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\n", + GST_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\n", GST_ELEMENT_NAME(GST_ELEMENT(pipeline))); } -static void -gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data) -{ - GST_DEBUG (0,"GstPipeline: pipeline have type %p\n", (gboolean *)data); - - *(gboolean *)data = TRUE; -} - -static GstCaps* -gst_pipeline_typefind (GstPipeline *pipeline, GstElement *element) -{ - gboolean found = FALSE; - GstElement *typefind; - GstCaps *caps = NULL; - - GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n", - GST_ELEMENT_NAME(element), &found); - - typefind = gst_elementfactory_make ("typefind", "typefind"); - g_return_val_if_fail (typefind != NULL, FALSE); - - gtk_signal_connect (GTK_OBJECT (typefind), "have_type", - GTK_SIGNAL_FUNC (gst_pipeline_have_type), &found); - - gst_pad_connect (gst_element_get_pad (element, "src"), - gst_element_get_pad (typefind, "sink")); - - gst_bin_add (GST_BIN (pipeline), typefind); - - //gst_bin_create_plan (GST_BIN (pipeline)); - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); - - // keep pushing buffers... the have_type signal handler will set the found flag - while (!found) { - gst_bin_iterate (GST_BIN (pipeline)); - } - - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); - - if (found) { - caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps"); - - gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps)); - } - - gst_pad_disconnect (gst_element_get_pad (element, "src"), - gst_element_get_pad (typefind, "sink")); - gst_bin_remove (GST_BIN (pipeline), typefind); - gst_object_unref (GST_OBJECT (typefind)); - - return caps; -} - -static gboolean -gst_pipeline_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) -{ - GList *sinkpads; - gboolean connected = FALSE; - - GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n", - GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); - - sinkpads = gst_element_get_pad_list(sink); - while (sinkpads) { - GstPad *sinkpad = (GstPad *)sinkpads->data; - - // if we have a match, connect the pads - if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK && - !GST_PAD_CONNECTED(sinkpad)) - { - if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) { - gst_pad_connect(pad, sinkpad); - GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad), - GST_ELEMENT_NAME(src)); - GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad), - GST_ELEMENT_NAME(sink)); - connected = TRUE; - break; - } - else { - GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad)); - } - } - sinkpads = g_list_next(sinkpads); - } - - if (!connected) { - GST_DEBUG (0,"gstpipeline: no path to sinks for type\n"); - } - return connected; -} - -static void -gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink) -{ - GList *srcpads; - gboolean connected = FALSE; - - srcpads = gst_element_get_pad_list(src); - - while (srcpads && !connected) { - GstPad *srcpad = (GstPad *)srcpads->data; - - if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) - connected = gst_pipeline_pads_autoplug_func (src, srcpad, sink); - - srcpads = g_list_next(srcpads); - } - - if (!connected) { - GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n", - GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); - gtk_signal_connect(GTK_OBJECT(src),"new_pad", - GTK_SIGNAL_FUNC(gst_pipeline_pads_autoplug_func), sink); - } -} - -/** - * gst_pipeline_add_src: - * @pipeline: the pipeline to add the src to - * @src: the src to add to the pipeline - * - * Adds a src element to the pipeline. This element - * will be used as a src for autoplugging. If you add more - * than one src element, the previously added element will - * be removed. - */ -void -gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src) -{ - g_return_if_fail (pipeline != NULL); - g_return_if_fail (GST_IS_PIPELINE (pipeline)); - g_return_if_fail (src != NULL); - g_return_if_fail (GST_IS_ELEMENT (src)); - - if (pipeline->src) { - printf("gstpipeline: *WARNING* removing previously added element \"%s\"\n", - GST_ELEMENT_NAME(pipeline->src)); - gst_bin_remove(GST_BIN(pipeline), pipeline->src); - } - pipeline->src = src; - gst_bin_add(GST_BIN(pipeline), src); -} - -/** - * gst_pipeline_add_sink: - * @pipeline: the pipeline to add the sink to - * @sink: the sink to add to the pipeline - * - * Adds a sink element to the pipeline. This element - * will be used as a sink for autoplugging. - */ -void -gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink) -{ - g_return_if_fail (pipeline != NULL); - g_return_if_fail (GST_IS_PIPELINE (pipeline)); - g_return_if_fail (sink != NULL); - g_return_if_fail (GST_IS_ELEMENT (sink)); - - pipeline->sinks = g_list_prepend (pipeline->sinks, sink); - //gst_bin_add(GST_BIN(pipeline), sink); -} - -/** - * gst_pipeline_autoplug: - * @pipeline: the pipeline to autoplug - * - * Constructs a complete pipeline by automatically - * detecting the plugins needed. - * - * Returns: a gboolean indicating success or failure. - */ -gboolean -gst_pipeline_autoplug (GstPipeline *pipeline) -{ - GList *elements; - GstElement *element, *srcelement = NULL, *sinkelement= NULL; - GList **factories; - GList **base_factories; - GstElementFactory *factory; - GstCaps *src_caps = 0; - guint i, numsinks; - gboolean use_thread = FALSE, have_common = FALSE; - GList *sinkstart; - - g_return_val_if_fail(pipeline != NULL, FALSE); - g_return_val_if_fail(GST_IS_PIPELINE(pipeline), FALSE); - - GST_DEBUG (0,"GstPipeline: autopluging pipeline \"%s\"\n", - GST_ELEMENT_NAME(GST_ELEMENT(pipeline))); - - - // fase 1, run typedetect on the source if needed... - if (!pipeline->src) { - GST_DEBUG (0,"GstPipeline: no source detected, can't autoplug pipeline \"%s\"\n", - GST_ELEMENT_NAME(GST_ELEMENT(pipeline))); - return FALSE; - } - - GST_DEBUG (0,"GstPipeline: source \"%s\" has no MIME type, running typefind...\n", - GST_ELEMENT_NAME(pipeline->src)); - - src_caps = gst_pipeline_typefind(pipeline, pipeline->src); - - if (src_caps) { - GST_DEBUG (0,"GstPipeline: source \"%s\" type found %d\n", GST_ELEMENT_NAME(pipeline->src), - src_caps->id); - } - else { - GST_DEBUG (0,"GstPipeline: source \"%s\" has no type\n", GST_ELEMENT_NAME(pipeline->src)); - return FALSE; - } - - srcelement = pipeline->src; - - elements = pipeline->sinks; - - sinkstart = g_list_copy (elements); - - numsinks = g_list_length(elements); - factories = g_new0(GList *, numsinks); - base_factories = g_new0(GList *, numsinks); - - i = 0; - // fase 2, loop over all the sinks.. - while (elements) { - GstPad *pad; - - element = GST_ELEMENT(elements->data); - - pad = (GstPad *)gst_element_get_pad_list (element)->data; - - base_factories[i] = factories[i] = gst_autoplug_caps_list (g_list_append(NULL,src_caps), -gst_pad_get_caps_list(pad)); - // if we have a succesfull connection, proceed - if (factories[i] != NULL) { - i++; - } - else { - sinkstart = g_list_remove (sinkstart, element); - } - - elements = g_list_next(elements); - } - - while (factories[0]) { - // fase 3: add common elements - factory = (GstElementFactory *)(factories[0]->data); - - // check to other paths for mathing elements (factories) - for (i=1; idata))) { - goto differ; - } - factories[i] = g_list_next(factories[i]); - } - factory = (GstElementFactory *)(factories[0]->data); - - GST_DEBUG (0,"common factory \"%s\"\n", factory->name); - - element = gst_elementfactory_create(factory, factory->name); - gst_bin_add(GST_BIN(pipeline), element); - - gst_pipeline_pads_autoplug(srcelement, element); - - srcelement = element; - - factories[0] = g_list_next(factories[0]); - - have_common = TRUE; - } - -differ: - // loop over all the sink elements - elements = sinkstart; - - i = 0; - while (elements) { - GstElement *thesrcelement = srcelement; - GstElement *thebin = GST_ELEMENT(pipeline); - - if (g_list_length(base_factories[i]) == 0) goto next; - - sinkelement = (GstElement *)elements->data; - - use_thread = have_common; - - while (factories[i] || sinkelement) { - // fase 4: add other elements... - - if (factories[i]) { - factory = (GstElementFactory *)(factories[i]->data); - GST_DEBUG (0,"factory \"%s\"\n", factory->name); - element = gst_elementfactory_create(factory, factory->name); - factories[i] = g_list_next(factories[i]); - } - // we have arived to the final sink element - else { - element = sinkelement; - sinkelement = NULL; - } - - // this element suggests the use of a thread, so we set one up... - if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) { - GstElement *queue; - GList *sinkpads; - GstPad *srcpad, *sinkpad; - - use_thread = FALSE; - - GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element)); - - // create a new queue and add to the previous bin - queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL)); - GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element)); - gst_bin_add(GST_BIN(thebin), queue); - - // this will be the new bin for all following elements - thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL)); - - srcpad = gst_element_get_pad(queue, "src"); - - sinkpads = gst_element_get_pad_list(element); - while (sinkpads) { - sinkpad = (GstPad *)sinkpads->data; - - // FIXME connect matching pads, not just the first one... - if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK && - !GST_PAD_CONNECTED(sinkpad)) { - GList *caps = gst_pad_get_caps_list (sinkpad); - - // the queue has the type of the elements it connects - gst_pad_set_caps_list (srcpad, caps); - gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps); - break; - } - sinkpads = g_list_next(sinkpads); - } - gst_pipeline_pads_autoplug(thesrcelement, queue); - - GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element)); - gst_bin_add(GST_BIN(thebin), element); - GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin)); - gst_bin_add(GST_BIN(pipeline), thebin); - thesrcelement = queue; - } - // no thread needed, easy case - else { - GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element)); - gst_bin_add(GST_BIN(thebin), element); - } - gst_pipeline_pads_autoplug(thesrcelement, element); - - // this element is now the new source element - thesrcelement = element; - } -next: - elements = g_list_next(elements); - i++; - } - return TRUE; - - GST_DEBUG (0,"GstPipeline: unable to autoplug pipeline \"%s\"\n", - GST_ELEMENT_NAME(GST_ELEMENT(pipeline))); - return FALSE; -} - -static GstElementStateReturn -gst_pipeline_change_state (GstElement *element) +static GstElementStateReturn +gst_pipeline_change_state (GstElement *element) { GstPipeline *pipeline; g_return_val_if_fail (GST_IS_PIPELINE (element), FALSE); - + pipeline = GST_PIPELINE (element); switch (GST_STATE_TRANSITION (pipeline)) { @@ -513,22 +136,21 @@ gst_pipeline_change_state (GstElement *element) default: break; } - + if (GST_ELEMENT_CLASS (parent_class)->change_state) return GST_ELEMENT_CLASS (parent_class)->change_state (element); - + return GST_STATE_SUCCESS; } - /** * gst_pipeline_iterate: * @pipeline: #GstPipeline to iterate * * Cause the pipeline's contents to be run through one full 'iteration'. */ -void -gst_pipeline_iterate (GstPipeline *pipeline) +void +gst_pipeline_iterate (GstPipeline *pipeline) { g_return_if_fail (pipeline != NULL); g_return_if_fail (GST_IS_PIPELINE(pipeline)); diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index 5ab0afe101..3c13978e63 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -50,30 +50,22 @@ typedef struct _GstPipelineClass GstPipelineClass; struct _GstPipeline { GstBin bin; - - GstElement *src; /* we only allow one src element */ - GList *sinks; /* and multiple sinks */ }; struct _GstPipelineClass { GstBinClass parent_class; }; -GtkType gst_pipeline_get_type (void); +GtkType gst_pipeline_get_type (void); GstElement* gst_pipeline_new (guchar *name); -#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline)) +#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline)) -void gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src); -void gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink); - -gboolean gst_pipeline_autoplug (GstPipeline *pipeline); - -void gst_pipeline_iterate (GstPipeline *pipeline); +void gst_pipeline_iterate (GstPipeline *pipeline); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* __GST_PIPELINE_H__ */ +#endif /* __GST_PIPELINE_H__ */ diff --git a/gst/gstplugin.c b/gst/gstplugin.c index bea40e7cb0..557232a27c 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -82,6 +82,8 @@ _gst_plugin_initialize (void) PLUGINS_SRCDIR "/gst/elements"); _gst_plugin_paths = g_list_prepend (_gst_plugin_paths, PLUGINS_SRCDIR "/gst/types"); + _gst_plugin_paths = g_list_prepend (_gst_plugin_paths, + PLUGINS_SRCDIR "/gst/autoplug"); #endif /* PLUGINS_USE_SRCDIR */ doc = xmlParseFile (GST_CONFIG_DIR"/reg.xml"); @@ -407,6 +409,8 @@ gst_plugin_new (const gchar *name) plugin->numelements = 0; plugin->types = NULL; plugin->numtypes = 0; + plugin->autopluggers = NULL; + plugin->numautopluggers = 0; plugin->loaded = TRUE; return plugin; @@ -541,15 +545,7 @@ gst_plugin_find (const gchar *name) return NULL; } -/** - * gst_plugin_find_elementfactory: - * @name: name of elementfactory to find - * - * Find a registered elementfactory by name. - * - * Returns: @GstElementFactory if found, NULL if not - */ -GstElementFactory* +static GstElementFactory* gst_plugin_find_elementfactory (const gchar *name) { GList *plugins, *factories; @@ -621,6 +617,77 @@ gst_plugin_load_elementfactory (const gchar *name) return factory; } +static GstAutoplugFactory* +gst_plugin_find_autoplugfactory (const gchar *name) +{ + GList *plugins, *factories; + GstAutoplugFactory *factory; + + g_return_val_if_fail(name != NULL, NULL); + + plugins = _gst_plugins; + while (plugins) { + factories = ((GstPlugin *)(plugins->data))->autopluggers; + while (factories) { + factory = (GstAutoplugFactory*)(factories->data); + if (!strcmp(factory->name, name)) + return (GstAutoplugFactory*)(factory); + factories = g_list_next(factories); + } + plugins = g_list_next(plugins); + } + + return NULL; +} +/** + * gst_plugin_load_autoplugfactory: + * @name: name of autoplugfactory to load + * + * Load a registered autoplugfactory by name. + * + * Returns: @GstAutoplugFactory if loaded, NULL if not + */ +GstAutoplugFactory* +gst_plugin_load_autoplugfactory (const gchar *name) +{ + GList *plugins, *factories; + GstAutoplugFactory *factory = NULL; + GstPlugin *plugin; + + g_return_val_if_fail(name != NULL, NULL); + + plugins = _gst_plugins; + while (plugins) { + plugin = (GstPlugin *)plugins->data; + factories = plugin->autopluggers; + + while (factories) { + factory = (GstAutoplugFactory*)(factories->data); + + if (!strcmp(factory->name,name)) { + if (!plugin->loaded) { + gchar *filename = g_strdup (plugin->filename); + gchar *pluginname = g_strdup (plugin->name); + + GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded autoplugfactory %s from plugin %s",name,plugin->name); + gst_plugin_remove(plugin); + if (!gst_plugin_load_absolute(filename)) { + GST_DEBUG (0,"gstplugin: error loading autoplug factory %s from plugin %s\n", name, pluginname); + } + g_free (pluginname); + g_free (filename); + } + factory = gst_plugin_find_autoplugfactory(name); + return factory; + } + factories = g_list_next(factories); + } + plugins = g_list_next(plugins); + } + + return factory; +} + /** * gst_plugin_load_typefactory: * @mime: name of typefactory to load @@ -708,6 +775,24 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory) gst_type_register (factory); } +/** + * gst_plugin_add_type: + * @plugin: plugin to add type to + * @factory: the typefactory to add + * + * Add a typefactory to the list of those provided by the plugin. + */ +void +gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory) +{ + g_return_if_fail (plugin != NULL); + g_return_if_fail (factory != NULL); + +// g_print("adding factory to plugin\n"); + plugin->autopluggers = g_list_prepend (plugin->autopluggers, factory); + plugin->numautopluggers++; +} + /** * gst_plugin_get_list: * @@ -716,7 +801,7 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory) * Returns; a GList of GstPlugin elements */ GList* -gst_plugin_get_list(void) +gst_plugin_get_list (void) { return _gst_plugins; } @@ -733,34 +818,45 @@ xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent) { xmlNodePtr tree, subtree; - GList *plugins = NULL, *elements = NULL, *types = NULL; + GList *plugins = NULL, *elements = NULL, *types = NULL, *autopluggers = NULL; - plugins = gst_plugin_get_list(); + plugins = gst_plugin_get_list (); while (plugins) { GstPlugin *plugin = (GstPlugin *)plugins->data; - tree = xmlNewChild(parent,NULL,"plugin",NULL); - xmlNewChild(tree,NULL,"name",plugin->name); - xmlNewChild(tree,NULL,"longname",plugin->longname); - xmlNewChild(tree,NULL,"filename",plugin->filename); + + tree = xmlNewChild (parent, NULL, "plugin", NULL); + xmlNewChild (tree, NULL, "name", plugin->name); + xmlNewChild (tree, NULL, "longname", plugin->longname); + xmlNewChild (tree, NULL, "filename", plugin->filename); + types = plugin->types; while (types) { GstTypeFactory *factory = (GstTypeFactory *)types->data; - subtree = xmlNewChild(tree,NULL,"typefactory",NULL); + subtree = xmlNewChild(tree, NULL, "typefactory", NULL); - gst_typefactory_save_thyself(factory, subtree); + gst_typefactory_save_thyself (factory, subtree); - types = g_list_next(types); + types = g_list_next (types); } elements = plugin->elements; while (elements) { GstElementFactory *factory = (GstElementFactory *)elements->data; - subtree = xmlNewChild(tree,NULL,"elementfactory",NULL); + subtree = xmlNewChild (tree, NULL, "elementfactory", NULL); - gst_elementfactory_save_thyself(factory, subtree); + gst_elementfactory_save_thyself (factory, subtree); - elements = g_list_next(elements); + elements = g_list_next (elements); } - plugins = g_list_next(plugins); + autopluggers = plugin->autopluggers; + while (autopluggers) { + GstAutoplugFactory *factory = (GstAutoplugFactory *)autopluggers->data; + subtree = xmlNewChild (tree, NULL, "autoplugfactory", NULL); + + gst_autoplugfactory_save_thyself (factory, subtree); + + autopluggers = g_list_next (autopluggers); + } + plugins = g_list_next (plugins); } return parent; } @@ -776,43 +872,50 @@ gst_plugin_load_thyself (xmlNodePtr parent) { xmlNodePtr kinderen; gint elementcount = 0; + gint autoplugcount = 0; gint typecount = 0; gchar *pluginname; kinderen = parent->xmlChildrenNode; // Dutch invasion :-) while (kinderen) { - if (!strcmp(kinderen->name, "plugin")) { + if (!strcmp (kinderen->name, "plugin")) { xmlNodePtr field = kinderen->xmlChildrenNode; GstPlugin *plugin = g_new0 (GstPlugin, 1); + plugin->elements = NULL; plugin->types = NULL; plugin->loaded = FALSE; while (field) { - if (!strcmp(field->name, "name")) { - pluginname = xmlNodeGetContent(field); - if (gst_plugin_find(pluginname)) { - g_free(pluginname); - g_free(plugin); + if (!strcmp (field->name, "name")) { + pluginname = xmlNodeGetContent (field); + if (gst_plugin_find (pluginname)) { + g_free (pluginname); + g_free (plugin); plugin = NULL; break; } else { plugin->name = pluginname; } } - else if (!strcmp(field->name, "longname")) { - plugin->longname = xmlNodeGetContent(field); + else if (!strcmp (field->name, "longname")) { + plugin->longname = xmlNodeGetContent (field); } - else if (!strcmp(field->name, "filename")) { - plugin->filename = xmlNodeGetContent(field); + else if (!strcmp (field->name, "filename")) { + plugin->filename = xmlNodeGetContent (field); } - else if (!strcmp(field->name, "elementfactory")) { - GstElementFactory *factory = gst_elementfactory_load_thyself(field); + else if (!strcmp (field->name, "elementfactory")) { + GstElementFactory *factory = gst_elementfactory_load_thyself (field); gst_plugin_add_factory (plugin, factory); elementcount++; } - else if (!strcmp(field->name, "typefactory")) { - GstTypeFactory *factory = gst_typefactory_load_thyself(field); + else if (!strcmp (field->name, "autoplugfactory")) { + GstAutoplugFactory *factory = gst_autoplugfactory_load_thyself (field); + gst_plugin_add_autoplugger (plugin, factory); + autoplugcount++; + } + else if (!strcmp (field->name, "typefactory")) { + GstTypeFactory *factory = gst_typefactory_load_thyself (field); gst_plugin_add_type (plugin, factory); elementcount++; typecount++; @@ -822,13 +925,14 @@ gst_plugin_load_thyself (xmlNodePtr parent) } if (plugin) { - _gst_plugins = g_list_prepend(_gst_plugins, plugin); + _gst_plugins = g_list_prepend (_gst_plugins, plugin); } } kinderen = kinderen->next; } - GST_INFO (GST_CAT_PLUGIN_LOADING,"added %d registered factories and %d types",elementcount,typecount); + GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d registered factories, %d autopluggers and %d types", + elementcount, autoplugcount, typecount); } @@ -863,3 +967,19 @@ gst_plugin_get_type_list (GstPlugin *plugin) return plugin->types; } + +/** + * gst_plugin_get_autoplug_list: + * @plugin: the plugin to get the autoplugfactories from + * + * get a list of all the autoplugfactories that this plugin provides + * + * Returns: a GList of factories + */ +GList* +gst_plugin_get_autoplug_list (GstPlugin *plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->autopluggers; +} diff --git a/gst/gstplugin.h b/gst/gstplugin.h index c171ada41b..299d10edc1 100644 --- a/gst/gstplugin.h +++ b/gst/gstplugin.h @@ -36,10 +36,11 @@ #include #include +#include -typedef struct _GstPlugin GstPlugin; -typedef struct _GstPluginElement GstPluginElement; +typedef struct _GstPlugin GstPlugin; +typedef struct _GstPluginElement GstPluginElement; struct _GstPlugin { gchar *name; /* name of the plugin */ @@ -50,6 +51,8 @@ struct _GstPlugin { gint numtypes; GList *elements; /* list of elements provided */ gint numelements; + GList *autopluggers; /* list of autopluggers provided */ + gint numautopluggers; gboolean loaded; /* if the plugin is in memory */ }; @@ -57,40 +60,41 @@ struct _GstPlugin { typedef GstPlugin* (*GstPluginInitFunc) (GModule *module); -void _gst_plugin_initialize (void); +void _gst_plugin_initialize (void); GstPlugin* gst_plugin_new (const gchar *name); void gst_plugin_add_path (const gchar *path); const gchar* gst_plugin_get_name (GstPlugin *plugin); -void gst_plugin_set_name (GstPlugin *plugin, const gchar *name); +void gst_plugin_set_name (GstPlugin *plugin, const gchar *name); const gchar* gst_plugin_get_longname (GstPlugin *plugin); -void gst_plugin_set_longname (GstPlugin *plugin, const gchar *longname); +void gst_plugin_set_longname (GstPlugin *plugin, const gchar *longname); const gchar* gst_plugin_get_filename (GstPlugin *plugin); -gboolean gst_plugin_is_loaded (GstPlugin *plugin); +gboolean gst_plugin_is_loaded (GstPlugin *plugin); GList* gst_plugin_get_type_list (GstPlugin *plugin); GList* gst_plugin_get_factory_list (GstPlugin *plugin); +GList* gst_plugin_get_autoplug_list (GstPlugin *plugin); void gst_plugin_load_all (void); gboolean gst_plugin_load (const gchar *name); gboolean gst_plugin_load_absolute (const gchar *name); gboolean gst_library_load (const gchar *name); -void gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory); -void gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory); +void gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory); +void gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory); +void gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory); GstPlugin* gst_plugin_find (const gchar *name); GList* gst_plugin_get_list (void); -GstElementFactory* gst_plugin_find_elementfactory (const gchar *name); - GstElementFactory* gst_plugin_load_elementfactory (const gchar *name); -void gst_plugin_load_typefactory (const gchar *mime); +void gst_plugin_load_typefactory (const gchar *mime); +GstAutoplugFactory* gst_plugin_load_autoplugfactory (const gchar *name); -xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent); -void gst_plugin_load_thyself (xmlNodePtr parent); +xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent); +void gst_plugin_load_thyself (xmlNodePtr parent); #endif /* __GST_PLUGIN_H__ */ diff --git a/gst/gstprops.c b/gst/gstprops.c index a3e688b26f..d3ca3cf8b0 100644 --- a/gst/gstprops.c +++ b/gst/gstprops.c @@ -601,6 +601,10 @@ gst_props_load_thyself_func (xmlNodePtr field) sscanf (prop, "%08x", &entry->data.fourcc_data); g_free (prop); } + else { + g_free (entry); + entry = NULL; + } return entry; } @@ -634,7 +638,8 @@ gst_props_load_thyself (xmlNodePtr parent) while (subfield) { GstPropsEntry *subentry = gst_props_load_thyself_func (subfield); - entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry); + if (subentry) + entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry); subfield = subfield->next; } diff --git a/gst/gstthread.c b/gst/gstthread.c index 7a5e767f87..ca269b0032 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -254,7 +254,7 @@ gst_thread_change_state (GstElement *element) gst_thread_main_loop, thread); // wait for it to 'spin up' -// gst_thread_wait_thread (thread); + //gst_thread_wait_thread (thread); } else { GST_INFO (GST_CAT_THREAD, "gstthread: NOT starting thread \"%s\"", GST_ELEMENT_NAME (GST_ELEMENT (element))); diff --git a/gst/gsttype.c b/gst/gsttype.c index 84090e74d3..437da194df 100644 --- a/gst/gsttype.c +++ b/gst/gsttype.c @@ -43,10 +43,10 @@ struct _GstTypeFindInfo { GstPlugin *plugin; /* the plugin with this typefind function */ }; -static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv); +static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv); -void -_gst_type_initialize (void) +void +_gst_type_initialize (void) { _gst_types = NULL; _gst_maxtype = 1; /* type 0 is undefined */ @@ -60,8 +60,8 @@ _gst_type_initialize (void) * * Returns: the new type id */ -guint16 -gst_type_register (GstTypeFactory *factory) +guint16 +gst_type_register (GstTypeFactory *factory) { guint16 id; GstType *type; @@ -70,16 +70,17 @@ gst_type_register (GstTypeFactory *factory) // GST_INFO (GST_CAT_TYPES,"type register %s", factory->mime); id = gst_type_find_by_mime (factory->mime); - + if (!id) { type = g_new0 (GstType, 1); - type->id = _gst_maxtype++; - type->mime = factory->mime; - type->exts = factory->exts; - _gst_types = g_list_prepend (_gst_types, type); + type->id = _gst_maxtype++; + type->mime = factory->mime; + type->exts = factory->exts; + _gst_types = g_list_prepend (_gst_types, type); id = type->id; + GST_DEBUG (0,"gsttype: new mime type '%s', id %d\n", type->mime, type->id); } else { type = gst_type_find_by_id (id); @@ -96,8 +97,8 @@ gst_type_register (GstTypeFactory *factory) return id; } -static -guint16 gst_type_find_by_mime_func (const gchar *mime) +static +guint16 gst_type_find_by_mime_func (const gchar *mime) { GList *walk; GstType *type; @@ -142,8 +143,8 @@ guint16 gst_type_find_by_mime_func (const gchar *mime) * * Returns: the type id */ -guint16 -gst_type_find_by_mime (const gchar *mime) +guint16 +gst_type_find_by_mime (const gchar *mime) { return gst_type_find_by_mime_func (mime); } @@ -156,8 +157,8 @@ gst_type_find_by_mime (const gchar *mime) * * Returns: the type id */ -guint16 -gst_type_find_by_ext (const gchar *ext) +guint16 +gst_type_find_by_ext (const gchar *ext) { //FIXME g_warning ("gsttype: find_by_ext not implemented"); @@ -173,7 +174,7 @@ gst_type_find_by_ext (const gchar *ext) * Returns: the type */ GstType* -gst_type_find_by_id (guint16 id) +gst_type_find_by_id (guint16 id) { GList *walk = _gst_types; GstType *type; @@ -196,7 +197,7 @@ gst_type_find_by_id (guint16 id) * Returns: a list of GstTypes */ GList* -gst_type_get_list (void) +gst_type_get_list (void) { return _gst_types; } @@ -210,8 +211,8 @@ gst_type_get_list (void) * * Returns: the new xmlNodePtr */ -xmlNodePtr -gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent) +xmlNodePtr +gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent) { xmlNewChild (parent, NULL, "mime", factory->mime); if (factory->exts) { @@ -220,11 +221,11 @@ gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent) if (factory->typefindfunc) { xmlNewChild (parent, NULL, "typefind", NULL); } - + return parent; } -static GstCaps * +static GstCaps * gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv) { GstType *type = (GstType *)priv; @@ -263,7 +264,7 @@ gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv) * Returns: the new typefactory */ GstTypeFactory* -gst_typefactory_load_thyself (xmlNodePtr parent) +gst_typefactory_load_thyself (xmlNodePtr parent) { GstTypeFactory *factory = g_new0 (GstTypeFactory, 1); diff --git a/gst/gsttype.h b/gst/gsttype.h index 2e2ef0a129..68ab8ce686 100644 --- a/gst/gsttype.h +++ b/gst/gsttype.h @@ -52,14 +52,14 @@ struct _GstTypeFactory { /* initialize the subsystem */ -void _gst_type_initialize (void); +void _gst_type_initialize (void); /* create a new type, or find/merge an existing one */ -guint16 gst_type_register (GstTypeFactory *factory); +guint16 gst_type_register (GstTypeFactory *factory); /* look up a type by mime or extension */ -guint16 gst_type_find_by_mime (const gchar *mime); -guint16 gst_type_find_by_ext (const gchar *ext); +guint16 gst_type_find_by_mime (const gchar *mime); +guint16 gst_type_find_by_ext (const gchar *ext); /* get GstType by id */ GstType* gst_type_find_by_id (guint16 id); @@ -67,7 +67,7 @@ GstType* gst_type_find_by_id (guint16 id); /* get the list of registered types (returns list of GstType!) */ GList* gst_type_get_list (void); -xmlNodePtr gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent); +xmlNodePtr gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent); GstTypeFactory* gst_typefactory_load_thyself (xmlNodePtr parent); #endif /* __GST_TYPE_H__ */ diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index 8f8489d681..279a2fe766 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -52,19 +52,20 @@ enum { }; -static void gst_typefind_class_init (GstTypeFindClass *klass); -static void gst_typefind_init (GstTypeFind *typefind); +static void gst_typefind_class_init (GstTypeFindClass *klass); +static void gst_typefind_init (GstTypeFind *typefind); -static void gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id); -static void gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id); -static void gst_typefind_chain (GstPad *pad, GstBuffer *buf); +static void gst_typefind_chain (GstPad *pad, GstBuffer *buf); static GstElementClass *parent_class = NULL; static guint gst_typefind_signals[LAST_SIGNAL] = { 0 }; GtkType -gst_typefind_get_type(void) { +gst_typefind_get_type (void) +{ static GtkType typefind_type = 0; if (!typefind_type) { @@ -78,13 +79,13 @@ gst_typefind_get_type(void) { (GtkArgGetFunc)gst_typefind_get_arg, (GtkClassInitFunc)NULL, }; - typefind_type = gtk_type_unique(GST_TYPE_ELEMENT,&typefind_info); + typefind_type = gtk_type_unique (GST_TYPE_ELEMENT, &typefind_info); } return typefind_type; } static void -gst_typefind_class_init (GstTypeFindClass *klass) +gst_typefind_class_init (GstTypeFindClass *klass) { GtkObjectClass *gtkobject_class; @@ -107,22 +108,22 @@ gst_typefind_class_init (GstTypeFindClass *klass) gtkobject_class->get_arg = gst_typefind_get_arg; } -static void -gst_typefind_init (GstTypeFind *typefind) +static void +gst_typefind_init (GstTypeFind *typefind) { typefind->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); gst_element_add_pad (GST_ELEMENT (typefind), typefind->sinkpad); gst_pad_set_chain_function (typefind->sinkpad, gst_typefind_chain); } -static void -gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id) { GstTypeFind *typefind; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_TYPEFIND (object)); - + typefind = GST_TYPEFIND (object); switch(id) { @@ -131,14 +132,14 @@ gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id) } } -static void -gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id) { GstTypeFind *typefind; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_TYPEFIND (object)); - + typefind = GST_TYPEFIND (object); switch(id) { @@ -150,8 +151,8 @@ gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id) } } -static void -gst_typefind_chain (GstPad *pad, GstBuffer *buf) +static void +gst_typefind_chain (GstPad *pad, GstBuffer *buf) { GstTypeFind *typefind; GList *type_list; diff --git a/gstplay/gstplay.c b/gstplay/gstplay.c index 86aa6261b5..f0b7459dce 100644 --- a/gstplay/gstplay.c +++ b/gstplay/gstplay.c @@ -41,8 +41,8 @@ enum { static GtkObject *parent_class = NULL; static guint gst_play_signals[LAST_SIGNAL] = { 0 }; -GtkType -gst_play_get_type (void) +GtkType +gst_play_get_type (void) { static GtkType play_type = 0; @@ -62,8 +62,8 @@ gst_play_get_type (void) return play_type; } -static void -gst_play_class_init (GstPlayClass *klass) +static void +gst_play_class_init (GstPlayClass *klass) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; @@ -108,14 +108,13 @@ gst_play_class_init (GstPlayClass *klass) object_class->set_arg = gst_play_set_arg; object_class->get_arg = gst_play_get_arg; - widget_class->realize = gst_play_realize; + widget_class->realize = gst_play_realize; } -static void -gst_play_init (GstPlay *play) +static void +gst_play_init (GstPlay *play) { - GstPlayPrivate *priv = g_new0 (GstPlayPrivate, 1); play->priv = priv; @@ -123,25 +122,20 @@ gst_play_init (GstPlay *play) /* create a new bin to hold the elements */ priv->thread = gst_thread_new ("main_thread"); g_assert (priv->thread != NULL); - priv->pipeline = gst_pipeline_new ("main_pipeline"); - g_assert (priv->pipeline != NULL); + priv->bin = gst_bin_new ("main_bin"); + g_assert (priv->bin != NULL); - /* and an audio sink */ - priv->audio_play = gst_elementfactory_make ("audiosink","play_audio"); - g_return_if_fail (priv->audio_play != NULL); - gtk_signal_connect (GTK_OBJECT (priv->audio_play), "handoff", + priv->audio_element = gst_elementfactory_make ("audiosink", "play_audio"); + g_return_if_fail (priv->audio_element != NULL); + gtk_signal_connect (GTK_OBJECT (priv->audio_element), "handoff", GTK_SIGNAL_FUNC (gst_play_audio_handoff), play); - /* and a video sink */ - priv->video_show = gst_elementfactory_make ("videosink","show"); - g_return_if_fail (priv->video_show != NULL); - gtk_object_set (GTK_OBJECT (priv->video_show),"xv_enabled",FALSE,NULL); - gtk_signal_connect (GTK_OBJECT (priv->video_show), "frame_displayed", + priv->video_element = gst_elementfactory_make ("videosink", "show"); + g_return_if_fail (priv->video_element != NULL); + gtk_object_set (GTK_OBJECT (priv->video_element), "xv_enabled", FALSE, NULL); + gtk_signal_connect (GTK_OBJECT (priv->video_element), "frame_displayed", GTK_SIGNAL_FUNC (gst_play_frame_displayed), play); - gst_pipeline_add_sink (GST_PIPELINE (priv->pipeline), priv->audio_play); - gst_pipeline_add_sink (GST_PIPELINE (priv->pipeline), priv->video_show); - play->state = GST_PLAY_STOPPED; play->flags = 0; @@ -155,155 +149,258 @@ gst_play_init (GstPlay *play) } GstPlay * -gst_play_new () +gst_play_new () { return GST_PLAY (gtk_type_new (GST_TYPE_PLAY)); } -static void -gst_play_eos (GstElement *element, - GstPlay *play) +static void +gst_play_eos (GstElement *element, + GstPlay *play) { g_print("gstplay: eos reached\n"); gst_play_stop(play); } -static void -gst_play_frame_displayed (GstElement *element, - GstPlay *play) +static void +gst_play_frame_displayed (GstElement *element, + GstPlay *play) { + GstPlayPrivate *priv; + + priv = (GstPlayPrivate *)play->priv; + + gdk_threads_enter (); + gtk_widget_show (GTK_WIDGET (priv->video_widget)); + gdk_threads_leave (); + gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_FRAME_DISPLAYED], NULL); } -static void -gst_play_audio_handoff (GstElement *element, - GstPlay *play) +static void +gst_play_audio_handoff (GstElement *element, + GstPlay *play) { gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_AUDIO_PLAYED], NULL); } -static void -gst_play_object_introspect (GstElement *element, +static void +gst_play_object_introspect (GstObject *object, const gchar *property, GstElement **target) { gchar *info; GtkArgInfo *arg; + GstElement *element; - info = gtk_object_arg_get_info( GTK_OBJECT_TYPE(element), property, &arg); + if (!GST_IS_ELEMENT (object)) + return; + + element = GST_ELEMENT (object); + + info = gtk_object_arg_get_info (GTK_OBJECT_TYPE (element), property, &arg); if (info) { g_free(info); } else { *target = element; - g_print("gstplay: using element \"%s\" for %s property\n", + g_print("gstplay: using element \"%s\" for %s property\n", gst_element_get_name(element), property); } } /* Dumb introspection of the interface... - * this will change with glib 1.4 + * this will change with glib 1.4 * */ -static void -gst_play_object_added (GstElement *pipeline, - GstElement *element, - GstPlay *play) +static void +gst_play_object_added (GstAutoplug* autoplug, + GstObject *object, + GstPlay *play) { GstPlayPrivate *priv; - + g_return_if_fail (play != NULL); priv = (GstPlayPrivate *)play->priv; - if (GST_FLAG_IS_SET (element, GST_ELEMENT_NO_SEEK)) { + if (GST_FLAG_IS_SET (object, GST_ELEMENT_NO_SEEK)) { priv->can_seek = FALSE; } - if (GST_IS_BIN (element)) { - gtk_signal_connect (GTK_OBJECT (element), "object_added", gst_play_object_added, play); + if (GST_IS_BIN (object)) { + //gtk_signal_connect (GTK_OBJECT (object), "object_added", gst_play_object_added, play); } else { // first come first serve here... - if (!priv->offset_element) - gst_play_object_introspect (element, "offset", &priv->offset_element); - if (!priv->bit_rate_element) - gst_play_object_introspect (element, "bit_rate", &priv->bit_rate_element); + if (!priv->offset_element) + gst_play_object_introspect (object, "offset", &priv->offset_element); + if (!priv->bit_rate_element) + gst_play_object_introspect (object, "bit_rate", &priv->bit_rate_element); if (!priv->media_time_element) - gst_play_object_introspect (element, "media_time", &priv->media_time_element); + gst_play_object_introspect (object, "media_time", &priv->media_time_element); if (!priv->current_time_element) - gst_play_object_introspect (element, "current_time", &priv->current_time_element); + gst_play_object_introspect (object, "current_time", &priv->current_time_element); } } -GstPlayReturn -gst_play_set_uri (GstPlay *play, - const guchar *uri) +static void +gst_play_have_type (GstElement *sink, GstElement *sink2, gpointer data) +{ + GST_DEBUG (0,"GstPipeline: play have type %p\n", (gboolean *)data); + + *(gboolean *)data = TRUE; +} + +static GstCaps* +gst_play_typefind (GstBin *bin, GstElement *element) +{ + gboolean found = FALSE; + GstElement *typefind; + GstCaps *caps = NULL; + + GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n", + GST_ELEMENT_NAME(element), &found); + + typefind = gst_elementfactory_make ("typefind", "typefind"); + g_return_val_if_fail (typefind != NULL, FALSE); + + gtk_signal_connect (GTK_OBJECT (typefind), "have_type", + GTK_SIGNAL_FUNC (gst_play_have_type), &found); + + gst_pad_connect (gst_element_get_pad (element, "src"), + gst_element_get_pad (typefind, "sink")); + + gst_bin_add (bin, typefind); + + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); + + // push a buffer... the have_type signal handler will set the found flag + gst_bin_iterate (bin); + + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + + if (found) { + caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps"); + + gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps)); + } + + gst_pad_disconnect (gst_element_get_pad (element, "src"), + gst_element_get_pad (typefind, "sink")); + gst_bin_remove (bin, typefind); + gst_object_unref (GST_OBJECT (typefind)); + + return caps; +} + +static gboolean +connect_pads (GstElement *new_element, GstElement *target, gboolean add) +{ + GList *pads = gst_element_get_pad_list (new_element); + GstPad *targetpad = gst_element_get_pad (target, "sink"); + + while (pads) { + GstPad *pad = GST_PAD (pads->data); + + if (gst_pad_check_compatibility (pad, targetpad)) { + if (add) { + gst_bin_add (GST_BIN (gst_element_get_parent ( + GST_ELEMENT (gst_pad_get_real_parent (pad)))), + target); + } + gst_pad_connect (pad, targetpad); + return TRUE; + } + pads = g_list_next (pads); + } + return FALSE; +} + +GstPlayReturn +gst_play_set_uri (GstPlay *play, + const guchar *uri) { GstPlayPrivate *priv; + GstCaps *src_caps; + GstElement *new_element; + GstAutoplug *autoplug; g_return_val_if_fail (play != NULL, GST_PLAY_ERROR); g_return_val_if_fail (GST_IS_PLAY (play), GST_PLAY_ERROR); g_return_val_if_fail (uri != NULL, GST_PLAY_ERROR); - + priv = (GstPlayPrivate *)play->priv; - if (priv->src) { - } - - if (priv->uri) g_free (priv->uri); + if (priv->uri) + g_free (priv->uri); priv->uri = g_strdup (uri); - //priv->src = gst_elementfactory_make ("disksrc", "disk_src"); priv->src = gst_elementfactory_make ("disksrc", "disk_src"); //priv->src = gst_elementfactory_make ("dvdsrc", "disk_src"); + priv->offset_element = priv->src; + g_return_val_if_fail (priv->src != NULL, -1); - gtk_object_set (GTK_OBJECT (priv->src),"location",uri,NULL); - gtk_signal_connect (GTK_OBJECT (priv->src), "eos", GTK_SIGNAL_FUNC (gst_play_eos), play); + gtk_object_set (GTK_OBJECT (priv->src), "location", uri, NULL); - gtk_signal_connect (GTK_OBJECT (priv->pipeline), "object_added", gst_play_object_added, play); + gst_bin_add (GST_BIN (priv->bin), priv->src); - gst_pipeline_add_src (GST_PIPELINE (priv->pipeline),GST_ELEMENT (priv->src)); + src_caps = gst_play_typefind (GST_BIN (priv->bin), priv->src); - if (!gst_pipeline_autoplug (GST_PIPELINE (priv->pipeline))) { + if (!src_caps) { return GST_PLAY_UNKNOWN_MEDIA; } - if (GST_PAD_CONNECTED (gst_element_get_pad (priv->video_show, "sink"))) { - play->flags |= GST_PLAY_TYPE_VIDEO; - } - if (GST_PAD_CONNECTED (gst_element_get_pad (priv->audio_play, "sink"))) { - play->flags |= GST_PLAY_TYPE_AUDIO; + autoplug = gst_autoplugfactory_make ("staticrender"); + g_assert (autoplug != NULL); + + gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play); + + new_element = gst_autoplug_to_renderers (autoplug, + gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")), + priv->video_element, + priv->audio_element, + NULL); + + if (!new_element) { + return GST_PLAY_CANNOT_PLAY; } - // hmmmm hack? FIXME - GST_FLAG_UNSET (priv->pipeline, GST_BIN_FLAG_MANAGER); + gst_bin_remove (GST_BIN (priv->bin), priv->src); + gst_bin_add (GST_BIN (priv->thread), priv->src); - gst_bin_add (GST_BIN (priv->thread), priv->pipeline); + gst_bin_add (GST_BIN (priv->bin), new_element); + + gst_element_connect (priv->src, "src", new_element, "sink"); + + gst_bin_add (GST_BIN (priv->thread), priv->bin); + gtk_signal_connect (GTK_OBJECT (priv->thread), "eos", GTK_SIGNAL_FUNC (gst_play_eos), play); return GST_PLAY_OK; } -static void -gst_play_realize (GtkWidget *widget) +static void +gst_play_realize (GtkWidget *widget) { GstPlay *play; - GtkWidget *video_widget; GstPlayPrivate *priv; - + g_return_if_fail (GST_IS_PLAY (widget)); + g_print ("gst_play: realize\n"); play = GST_PLAY (widget); priv = (GstPlayPrivate *)play->priv; - video_widget = gst_util_get_widget_arg (GTK_OBJECT (priv->video_show),"widget"); + priv->video_widget = gst_util_get_widget_arg (GTK_OBJECT (priv->video_element), "widget"); - if (video_widget) { - gtk_container_add (GTK_CONTAINER (widget), video_widget); - gtk_widget_show (video_widget); + if (priv->video_widget) { + gtk_container_add (GTK_CONTAINER (widget), priv->video_widget); + } + else { + g_print ("oops, no video widget found\n"); } if (GTK_WIDGET_CLASS (parent_class)->realize) { @@ -311,8 +408,8 @@ gst_play_realize (GtkWidget *widget) } } -void -gst_play_play (GstPlay *play) +void +gst_play_play (GstPlay *play) { GstPlayPrivate *priv; @@ -333,8 +430,8 @@ gst_play_play (GstPlay *play) play->state); } -void -gst_play_pause (GstPlay *play) +void +gst_play_pause (GstPlay *play) { GstPlayPrivate *priv; @@ -353,8 +450,8 @@ gst_play_pause (GstPlay *play) play->state); } -void -gst_play_stop (GstPlay *play) +void +gst_play_stop (GstPlay *play) { GstPlayPrivate *priv; @@ -374,8 +471,8 @@ gst_play_stop (GstPlay *play) play->state); } -gulong -gst_play_get_media_size (GstPlay *play) +gulong +gst_play_get_media_size (GstPlay *play) { GstPlayPrivate *priv; @@ -387,7 +484,7 @@ gst_play_get_media_size (GstPlay *play) return gst_util_get_long_arg (GTK_OBJECT (priv->src), "size"); } -gulong +gulong gst_play_get_media_offset (GstPlay *play) { GstPlayPrivate *priv; @@ -397,15 +494,18 @@ gst_play_get_media_offset (GstPlay *play) priv = (GstPlayPrivate *)play->priv; - return gst_util_get_long_arg (GTK_OBJECT (priv->offset_element), "offset"); + if (priv->offset_element) + return gst_util_get_long_arg (GTK_OBJECT (priv->offset_element), "offset"); + else + return 0; } -gulong +gulong gst_play_get_media_total_time (GstPlay *play) { gulong total_time, bit_rate; GstPlayPrivate *priv; - + g_return_val_if_fail (play != NULL, 0); g_return_val_if_fail (GST_IS_PLAY (play), 0); @@ -419,7 +519,7 @@ gst_play_get_media_total_time (GstPlay *play) bit_rate = gst_util_get_long_arg (GTK_OBJECT (priv->bit_rate_element), "bit_rate"); - if (bit_rate) + if (bit_rate) total_time = (gst_play_get_media_size (play) * 8) / bit_rate; else total_time = 0; @@ -427,12 +527,12 @@ gst_play_get_media_total_time (GstPlay *play) return total_time; } -gulong +gulong gst_play_get_media_current_time (GstPlay *play) { gulong current_time, bit_rate; GstPlayPrivate *priv; - + g_return_val_if_fail (play != NULL, 0); g_return_val_if_fail (GST_IS_PLAY (play), 0); @@ -446,7 +546,7 @@ gst_play_get_media_current_time (GstPlay *play) bit_rate = gst_util_get_long_arg (GTK_OBJECT (priv->bit_rate_element), "bit_rate"); - if (bit_rate) + if (bit_rate) current_time = (gst_play_get_media_offset (play) * 8) / bit_rate; else current_time = 0; @@ -454,7 +554,7 @@ gst_play_get_media_current_time (GstPlay *play) return current_time; } -gboolean +gboolean gst_play_media_can_seek (GstPlay *play) { GstPlayPrivate *priv; @@ -467,8 +567,8 @@ gst_play_media_can_seek (GstPlay *play) return priv->can_seek; } -void -gst_play_media_seek (GstPlay *play, +void +gst_play_media_seek (GstPlay *play, gulong offset) { GstPlayPrivate *priv; @@ -482,10 +582,10 @@ gst_play_media_seek (GstPlay *play, } -static void +static void gst_play_set_arg (GtkObject *object, GtkArg *arg, - guint id) + guint id) { GstPlay *play; @@ -503,10 +603,10 @@ gst_play_set_arg (GtkObject *object, } } -static void +static void gst_play_get_arg (GtkObject *object, GtkArg *arg, - guint id) + guint id) { GstPlay *play; GstPlayPrivate *priv; diff --git a/gstplay/gstplay.h b/gstplay/gstplay.h index 7452a78826..fcaebf2f18 100644 --- a/gstplay/gstplay.h +++ b/gstplay/gstplay.h @@ -31,6 +31,7 @@ typedef enum { typedef enum { GST_PLAY_OK, GST_PLAY_UNKNOWN_MEDIA, + GST_PLAY_CANNOT_PLAY, GST_PLAY_ERROR, } GstPlayReturn; diff --git a/gstplay/gstplayprivate.h b/gstplay/gstplayprivate.h index 66b7b4dd9c..31e4e17f10 100644 --- a/gstplay/gstplayprivate.h +++ b/gstplay/gstplayprivate.h @@ -12,9 +12,9 @@ typedef struct _GstPlayPrivate GstPlayPrivate; struct _GstPlayPrivate { GstElement *thread; - GstElement *pipeline; - GstElement *audio_play; - GstElement *video_show; + GstElement *bin; + GstElement *video_element, *audio_element; + GtkWidget *video_widget; GstElement *src; guchar *uri; diff --git a/plugins/elements/gstdisksrc.c b/plugins/elements/gstdisksrc.c index 9eebbd4bf6..9e81eb9b73 100644 --- a/plugins/elements/gstdisksrc.c +++ b/plugins/elements/gstdisksrc.c @@ -2,7 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * - * gstdisksrc.c: + * gstdisksrc.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -56,23 +56,23 @@ enum { }; -static void gst_disksrc_class_init (GstDiskSrcClass *klass); -static void gst_disksrc_init (GstDiskSrc *disksrc); +static void gst_disksrc_class_init (GstDiskSrcClass *klass); +static void gst_disksrc_init (GstDiskSrc *disksrc); -static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id); -static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id); +static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id); static GstBuffer * gst_disksrc_get (GstPad *pad); static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len); -static GstElementStateReturn gst_disksrc_change_state (GstElement *element); +static GstElementStateReturn gst_disksrc_change_state (GstElement *element); static GstElementClass *parent_class = NULL; //static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 }; GtkType -gst_disksrc_get_type(void) +gst_disksrc_get_type(void) { static GtkType disksrc_type = 0; @@ -93,7 +93,7 @@ gst_disksrc_get_type(void) } static void -gst_disksrc_class_init (GstDiskSrcClass *klass) +gst_disksrc_class_init (GstDiskSrcClass *klass) { GtkObjectClass *gtkobject_class; GstElementClass *gstelement_class; @@ -118,8 +118,8 @@ gst_disksrc_class_init (GstDiskSrcClass *klass) gstelement_class->change_state = gst_disksrc_change_state; } -static void -gst_disksrc_init (GstDiskSrc *disksrc) +static void +gst_disksrc_init (GstDiskSrc *disksrc) { // GST_FLAG_SET (disksrc, GST_SRC_); @@ -139,14 +139,14 @@ gst_disksrc_init (GstDiskSrc *disksrc) } -static void -gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) { GstDiskSrc *src; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_DISKSRC (object)); - + src = GST_DISKSRC (object); switch(id) { @@ -176,14 +176,14 @@ gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id) } } -static void -gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) +static void +gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) { GstDiskSrc *src; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_DISKSRC (object)); - + src = GST_DISKSRC (object); switch (id) { @@ -212,7 +212,7 @@ gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id) * Push a new buffer from the disksrc at the current offset. */ static GstBuffer * -gst_disksrc_get (GstPad *pad) +gst_disksrc_get (GstPad *pad) { GstDiskSrc *src; GstBuffer *buf; @@ -223,7 +223,7 @@ gst_disksrc_get (GstPad *pad) /* deal with EOF state */ if (src->curoffset >= src->size) { - gst_element_signal_eos (GST_ELEMENT (src)); + gst_pad_set_eos (pad); return NULL; } @@ -269,7 +269,7 @@ gst_disksrc_get (GstPad *pad) * Push a new buffer from the disksrc of given size at given offset. */ static GstBuffer * -gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len) +gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len) { GstDiskSrc *src; GstBuffer *buf; @@ -281,10 +281,10 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l g_return_val_if_fail (GST_IS_DISKSRC (src), NULL); g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL); - + /* deal with EOF state */ if (offset >= src->size) { - gst_element_signal_eos (GST_ELEMENT (src)); + gst_pad_set_eos (pad); return NULL; } @@ -312,8 +312,8 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l /* open the file and mmap it, necessary to go to READY state */ -static -gboolean gst_disksrc_open_file (GstDiskSrc *src) +static +gboolean gst_disksrc_open_file (GstDiskSrc *src) { g_return_val_if_fail (!GST_FLAG_IS_SET (src ,GST_DISKSRC_OPEN), FALSE); @@ -343,8 +343,8 @@ gboolean gst_disksrc_open_file (GstDiskSrc *src) } /* unmap and close the file */ -static void -gst_disksrc_close_file (GstDiskSrc *src) +static void +gst_disksrc_close_file (GstDiskSrc *src) { g_return_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN)); @@ -365,8 +365,8 @@ gst_disksrc_close_file (GstDiskSrc *src) } -static GstElementStateReturn -gst_disksrc_change_state (GstElement *element) +static GstElementStateReturn +gst_disksrc_change_state (GstElement *element) { g_return_val_if_fail (GST_IS_DISKSRC (element), GST_STATE_FAILURE); @@ -375,7 +375,7 @@ gst_disksrc_change_state (GstElement *element) gst_disksrc_close_file (GST_DISKSRC (element)); } else { if (!GST_FLAG_IS_SET (element, GST_DISKSRC_OPEN)) { - if (!gst_disksrc_open_file (GST_DISKSRC (element))) + if (!gst_disksrc_open_file (GST_DISKSRC (element))) return GST_STATE_FAILURE; } } diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index 193592ac85..62b5a9288f 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -2,7 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * - * gstelements.c: + * gstelements.c: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -61,13 +61,13 @@ static struct _elements_entry _elements[] = { { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, #if HAVE_LIBGHTTP - { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, #endif /* HAVE_LIBGHTTP */ - + { NULL, 0 }, }; -GstPlugin *plugin_init (GModule *module) +GstPlugin *plugin_init (GModule *module) { GstPlugin *plugin; GstElementFactory *factory; diff --git a/test/mp1parse.c b/test/mp1parse.c index d49bdad0eb..641f4b4254 100644 --- a/test/mp1parse.c +++ b/test/mp1parse.c @@ -62,7 +62,6 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { // 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) { @@ -116,7 +115,6 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { // 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); diff --git a/tests/.gitignore b/tests/.gitignore index 8d0cd0b737..fc4f7a1ff4 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -6,7 +6,7 @@ Makefile.in .deps .libs *.xml - +*.gst init loadall simplefake @@ -24,3 +24,5 @@ markup load padfactory tee +autoplug2 +autoplug3 diff --git a/tests/Makefile.am b/tests/Makefile.am index f116e177bf..1d82923671 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = sched eos noinst_PROGRAMS = init loadall simplefake states caps queue registry \ -paranoia rip mp3encode autoplug props case4 markup load tee +paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 # we have nothing but apps here, we can do this safely LIBS += $(GST_LIBS) diff --git a/tests/autoplug.c b/tests/autoplug.c index f6dcb1be39..87913c6f4f 100644 --- a/tests/autoplug.c +++ b/tests/autoplug.c @@ -1,63 +1,45 @@ #include -static GList* -autoplug_caps (gchar *mime1, gchar *mime2) -{ - GstCaps *caps1, *caps2; - - caps1 = gst_caps_new ("tescaps1", mime1); - caps2 = gst_caps_new ("tescaps2", mime2); - - return gst_autoplug_caps (caps1, caps2); -} - static void -dump_factories (GList *factories) +new_object_added (GstAutoplug *autoplug, GstObject *object) { - g_print ("dumping factories\n"); - - while (factories) { - GstElementFactory *factory = (GstElementFactory *)factories->data; - - g_print ("factory: \"%s\"\n", factory->name); - - factories = g_list_next (factories); - } + g_print ("added new object \"%s\"\n", gst_object_get_name (object)); } -int main(int argc,char *argv[]) +int +main (int argc, char *argv[]) { - GList *factories; + GstElement *element; + GstElement *videosink, *audiosink; + GstAutoplug *autoplugger; + GList *testcaps; gst_init(&argc,&argv); - factories = autoplug_caps ("audio/mp3", "audio/raw"); - dump_factories (factories); + audiosink = gst_elementfactory_make ("audiosink", "audiosink"); + g_assert (audiosink != NULL); + videosink = gst_elementfactory_make ("videosink", "videosink"); + g_assert (videosink != NULL); - factories = autoplug_caps ("video/mpeg", "audio/raw"); - dump_factories (factories); + testcaps = g_list_append (NULL, + gst_caps_new_with_props ("test_caps", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))); - factories = gst_autoplug_caps ( - gst_caps_new_with_props( - "testcaps3", - "video/mpeg", - gst_props_new ( - "mpegversion", GST_PROPS_INT (1), - "systemstream", GST_PROPS_BOOLEAN (TRUE), - NULL)), - gst_caps_new("testcaps4","audio/raw")); - dump_factories (factories); + autoplugger = gst_autoplugfactory_make ("static"); - factories = gst_autoplug_caps ( - gst_caps_new_with_props( - "testcaps5", - "video/mpeg", - gst_props_new ( - "mpegversion", GST_PROPS_INT (1), - "systemstream", GST_PROPS_BOOLEAN (FALSE), - NULL)), - gst_caps_new("testcaps6", "video/raw")); - dump_factories (factories); + gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL); + + element = gst_autoplug_to_caps (autoplugger, testcaps, + gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")), + gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")), + NULL); + g_assert (element != NULL); + + xmlDocDump (stdout, gst_xml_write (element)); exit (0); } diff --git a/tests/autoplug2.c b/tests/autoplug2.c new file mode 100644 index 0000000000..64f0a9f58d --- /dev/null +++ b/tests/autoplug2.c @@ -0,0 +1,78 @@ +#include + +static GstElement* +autoplug_caps (GstAutoplug *autoplug, gchar *mime1, gchar *mime2) +{ + GList *caps1, *caps2; + + caps1 = g_list_append (NULL, gst_caps_new ("tescaps1", mime1)); + caps2 = g_list_append (NULL, gst_caps_new ("tescaps2", mime2)); + + return gst_autoplug_to_caps (autoplug, caps1, caps2, NULL); +} + +int +main (int argc, char *argv[]) +{ + GstElement *element; + GstAutoplug *autoplug; + + gst_init(&argc,&argv); + + autoplug = gst_autoplugfactory_make ("static"); + + element = autoplug_caps (autoplug, "audio/mp3", "audio/raw"); + xmlSaveFile ("autoplug2_1.gst", gst_xml_write (element)); + + element = autoplug_caps (autoplug, "video/mpeg", "audio/raw"); + xmlSaveFile ("autoplug2_2.gst", gst_xml_write (element)); + + element = gst_autoplug_to_caps (autoplug, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps3", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps4","audio/raw")), + NULL); + xmlSaveFile ("autoplug2_3.gst", gst_xml_write (element)); + + element = gst_autoplug_to_caps (autoplug, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps5", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (FALSE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps6", "video/raw")), + NULL); + xmlSaveFile ("autoplug2_4.gst", gst_xml_write (element)); + + element = gst_autoplug_to_caps (autoplug, + g_list_append (NULL, gst_caps_new( + "testcaps7", + "video/avi")), + g_list_append (NULL, gst_caps_new("testcaps8", "video/raw")), + g_list_append (NULL, gst_caps_new("testcaps9", "audio/raw")), + NULL); + xmlSaveFile ("autoplug2_5.gst", gst_xml_write (element)); + + element = gst_autoplug_to_caps (autoplug, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps10", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps10", "video/raw")), + g_list_append (NULL, gst_caps_new("testcaps11", "audio/raw")), + NULL); + xmlSaveFile ("autoplug2_6.gst", gst_xml_write (element)); + + exit (0); + exit (0); +} diff --git a/tests/autoplug3.c b/tests/autoplug3.c new file mode 100644 index 0000000000..d63726ddca --- /dev/null +++ b/tests/autoplug3.c @@ -0,0 +1,102 @@ +#include + +int +main (int argc, char *argv[]) +{ + GstElement *element; + GstElement *sink1, *sink2; + GstAutoplug *autoplug; + GstAutoplug *autoplug2; + + gst_init(&argc,&argv); + + sink1 = gst_elementfactory_make ("videosink", "videosink"); + sink2 = gst_elementfactory_make ("audiosink", "audiosink"); + + autoplug = gst_autoplugfactory_make ("staticrender"); + autoplug2 = gst_autoplugfactory_make ("static"); + + element = gst_autoplug_to_renderers (autoplug, + g_list_append (NULL, gst_caps_new ("mp3caps", "audio/mp3")), sink2, NULL); + xmlSaveFile ("autoplug3_1.gst", gst_xml_write (element)); + + element = gst_autoplug_to_renderers (autoplug, + g_list_append (NULL, gst_caps_new ("mpeg1caps", "video/mpeg")), sink1, NULL); + if (element) { + xmlSaveFile ("autoplug3_2.gst", gst_xml_write (element)); + } + + element = gst_autoplug_to_caps (autoplug2, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps3", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps4","audio/raw")), + NULL); + if (element) { + xmlSaveFile ("autoplug3_3.gst", gst_xml_write (element)); + } + + element = gst_autoplug_to_caps (autoplug2, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps5", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (FALSE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps6", "video/raw")), + NULL); + if (element) { + xmlSaveFile ("autoplug3_4.gst", gst_xml_write (element)); + } + + element = gst_autoplug_to_caps (autoplug2, + g_list_append (NULL, gst_caps_new( + "testcaps7", + "video/avi")), + g_list_append (NULL, gst_caps_new("testcaps8", "video/raw")), + g_list_append (NULL, gst_caps_new("testcaps9", "audio/raw")), + NULL); + if (element) { + xmlSaveFile ("autoplug3_5.gst", gst_xml_write (element)); + } + + element = gst_autoplug_to_caps (autoplug2, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps10", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))), + g_list_append (NULL, gst_caps_new("testcaps10", "video/raw")), + g_list_append (NULL, gst_caps_new("testcaps11", "audio/raw")), + NULL); + if (element) { + xmlSaveFile ("autoplug3_6.gst", gst_xml_write (element)); + } + + sink1 = gst_elementfactory_make ("videosink", "videosink"); + sink2 = gst_elementfactory_make ("audiosink", "audiosink"); + + element = gst_autoplug_to_renderers (autoplug, + g_list_append (NULL, gst_caps_new_with_props( + "testcaps10", + "video/mpeg", + gst_props_new ( + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (TRUE), + NULL))), + sink1, + sink2, + NULL); + if (element) { + xmlSaveFile ("autoplug3_7.gst", gst_xml_write (element)); + } + + exit (0); +} diff --git a/tests/old/examples/autoplug/autoplug.c b/tests/old/examples/autoplug/autoplug.c index 4a3453552c..4e37b5d999 100644 --- a/tests/old/examples/autoplug/autoplug.c +++ b/tests/old/examples/autoplug/autoplug.c @@ -31,8 +31,6 @@ int main(int argc,char *argv[]) exit(-1); } - - /* create a new bin to hold the elements */ pipeline = gst_pipeline_new("pipeline"); g_assert(pipeline != NULL); @@ -59,6 +57,7 @@ int main(int argc,char *argv[]) gtk_widget_show_all(appwindow); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), videosink); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -67,6 +66,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline))); diff --git a/tests/old/examples/helloworld2/helloworld2.c b/tests/old/examples/helloworld2/helloworld2.c index 90de5139d5..8b70518eda 100644 --- a/tests/old/examples/helloworld2/helloworld2.c +++ b/tests/old/examples/helloworld2/helloworld2.c @@ -41,6 +41,7 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -48,6 +49,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ // hmmmm hack? FIXME GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER); diff --git a/tests/old/examples/queue2/queue2.c b/tests/old/examples/queue2/queue2.c index a3662b14e6..706acc073f 100644 --- a/tests/old/examples/queue2/queue2.c +++ b/tests/old/examples/queue2/queue2.c @@ -46,11 +46,12 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue); gst_bin_add(GST_BIN(thread), audiosink); - + gst_pad_connect(gst_element_get_pad(queue,"src"), gst_element_get_pad(audiosink,"sink")); @@ -58,6 +59,7 @@ int main(int argc,char *argv[]) g_print("cannot autoplug pipeline\n"); exit(-1); } + */ gst_bin_add(GST_BIN(pipeline), thread); diff --git a/tests/old/examples/thread/thread.c b/tests/old/examples/thread/thread.c index 533c38a6f7..b8bc00e1de 100644 --- a/tests/old/examples/thread/thread.c +++ b/tests/old/examples/thread/thread.c @@ -45,6 +45,7 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ + /* gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); @@ -52,6 +53,7 @@ int main(int argc,char *argv[]) g_print("unable to handle stream\n"); exit(-1); } + */ //gst_bin_remove(GST_BIN(pipeline), disksrc); diff --git a/tools/gstreamer-inspect.c b/tools/gstreamer-inspect.c index a95392e9cb..f8d4ac3703 100644 --- a/tools/gstreamer-inspect.c +++ b/tools/gstreamer-inspect.c @@ -42,7 +42,7 @@ void print_prop(GstPropsEntry *prop,gboolean showname,gchar *pfx) { g_free(longprefix); break; default: - printf("\n"); + printf("unknown props %d\n", prop->propstype); } } @@ -59,30 +59,9 @@ void print_props(GstProps *properties,gchar *pfx) { } } -/* -struct _GstPropsEntry { - GQuark propid; - GstPropsId propstype; - - union { - // flat values - gboolean bool_data; - guint32 fourcc_data; - gint int_data; - - // structured values - struct { - GList *entries; - } list_data; - struct { - gint min; - gint max; - } int_range_data; - } data; -}; -*/ - -gint print_element_info(GstElementFactory *factory) { +gint +print_element_info (GstElementFactory *factory) +{ GstElement *element; GstObjectClass *gstobject_class; GstElementClass *gstelement_class; @@ -322,11 +301,9 @@ void print_element_list() { } } - -void print_plugin_info(GstPlugin *plugin) { - GList *factories; - GstElementFactory *factory; - +void +print_plugin_info (GstPlugin *plugin) +{ printf("Plugin Details:\n"); printf(" Name:\t\t%s\n",plugin->name); printf(" Long Name:\t%s\n",plugin->longname); @@ -334,6 +311,9 @@ void print_plugin_info(GstPlugin *plugin) { printf("\n"); if (plugin->numelements) { + GList *factories; + GstElementFactory *factory; + printf("Element Factories:\n"); factories = gst_plugin_get_factory_list(plugin); @@ -344,6 +324,36 @@ void print_plugin_info(GstPlugin *plugin) { printf(" %s: %s\n",factory->name,factory->details->longname); } } + if (plugin->numautopluggers) { + GList *factories; + GstAutoplugFactory *factory; + + printf("Autpluggers:\n"); + + factories = gst_plugin_get_autoplug_list(plugin); + while (factories) { + factory = (GstAutoplugFactory*)(factories->data); + factories = g_list_next(factories); + + printf(" %s: %s\n", factory->name, factory->longdesc); + } + } + if (plugin->numtypes) { + GList *factories; + GstTypeFactory *factory; + + printf("Types:\n"); + + factories = gst_plugin_get_type_list(plugin); + while (factories) { + factory = (GstTypeFactory*)(factories->data); + factories = g_list_next(factories); + + printf(" %s: %s\n", factory->mime, factory->exts); + if (factory->typefindfunc) + printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc)); + } + } printf("\n"); } @@ -357,7 +367,7 @@ int main(int argc,char *argv[]) { // if no arguments, print out list of elements if (argc == 1) { - print_element_list(); + print_element_list(); // else we try to get a factory } else {