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")
gst/types/Makefile
gst/meta/Makefile
gst/elements/Makefile
+gst/autoplug/Makefile
libs/Makefile
libs/riff/Makefile
libs/colorspace/Makefile
</para>
-<!-- ##### MACRO GST_AUTOPLUG_MAX_COST ##### -->
-<para>
-The maximum cost of a certain connection.
-</para>
-
-
-
-<!-- ##### USER_FUNCTION GstAutoplugCostFunction ##### -->
-<para>
-Calculate the cost between two elements.
-</para>
-
-@src: the source element
-@dest: the destination element
-@data: optional user data
-@Returns: the cost for a connection between the two elements
-
-
-<!-- ##### USER_FUNCTION GstAutoplugListFunction ##### -->
-<para>
-Get a list of all elements. These elements will be used in autoplugging.
-</para>
-
-@data: user data
-@Returns: a GList of elements
-
-
-<!-- ##### FUNCTION gst_autoplug_caps ##### -->
-<para>
-
-</para>
-
-@srccaps:
-@sinkcaps:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_autoplug_pads ##### -->
+<!-- ##### FUNCTION gst_autoplug_caps_list ##### -->
<para>
</para>
+@autoplug:
@srcpad:
@sinkpad:
+@Varargs:
@Returns:
-
-
-<!-- ##### FUNCTION gst_autoplug_caps_list ##### -->
-<para>
-
-</para>
-
+<!-- # Unused Parameters # -->
@srccaps:
@sinkcaps:
-@Returns:
@offset: the offset of the region to get
@len: the length of the region to get
@Returns: a #GstBuffer
+<!-- # Unused Parameters # -->
+@size: the size of the region to get
<!-- ##### USER_FUNCTION GstPadQoSFunction ##### -->
@Returns:
-<!-- ##### FUNCTION gst_pipeline_add_sink ##### -->
-<para>
-
-</para>
-
-@pipeline:
-@sink:
-
-
-<!-- ##### FUNCTION gst_pipeline_add_src ##### -->
-<para>
-
-</para>
-
-@pipeline:
-@src:
-
-
-<!-- ##### FUNCTION gst_pipeline_autoplug ##### -->
-<para>
-
-</para>
-
-@pipeline:
-@Returns:
-
-
<!-- ##### MACRO gst_pipeline_destroy ##### -->
<para>
Destroys the pipeline.
@numtypes:
@elements:
@numelements:
+@autopluggers:
+@numautopluggers:
@loaded:
<!-- ##### STRUCT GstPluginElement ##### -->
@Returns:
-<!-- ##### FUNCTION gst_plugin_find_elementfactory ##### -->
-<para>
-
-</para>
-
-@name:
-@Returns:
-
-
<!-- ##### FUNCTION gst_plugin_load_elementfactory ##### -->
<para>
</para>
-<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Short_Description ##### -->
-Asynchronous disk reader. (asyncdisksrc)
-
-
<!-- ##### FUNCTION gst_src_signal_eos ##### -->
<para>
@klass:
+<<<<<<< gstreamer-unused.sgml
<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Title ##### -->
GstAsyncDiskSrc
<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
+=======
+<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
+>>>>>>> 1.23.2.3
<para>
</para>
</para>
+<<<<<<< gstreamer-unused.sgml
<!-- ##### ENUM GstSrcFlags ##### -->
<para>
Flags for the GstSrc element
<!-- ##### MACRO GST_HTTPSRC ##### -->
+=======
+<!-- ##### ENUM GstSrcFlags ##### -->
+<para>
+Flags for the GstSrc element
+</para>
+
+@GST_SRC_ASYNC: Indicates that this src is asynchronous
+@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
+
+
+<!-- ##### MACRO GST_HTTPSRC ##### -->
+>>>>>>> 1.23.2.3
<para>
</para>
--- /dev/null
+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
+
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.
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
-----------------
- 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
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
-
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);
};
(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 */
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 \
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);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PAD))
struct _GstEditorPad {
- GtkObject object;
+ GtkObject object;
/* parent element */
GstEditorElement *parent;
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;
// 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, ...);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PADTEMPLATE))
struct _GstEditorPadTemplate {
- GtkObject object;
+ GtkObject object;
/* parent element */
GstEditorElement *parent;
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;
// 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, ...);
exit(-1);
}
-
-
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline)));
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
// hmmmm hack? FIXME
GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER);
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"));
g_print("cannot autoplug pipeline\n");
exit(-1);
}
+ */
gst_bin_add(GST_BIN(pipeline), thread);
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
//gst_bin_remove(GST_BIN(pipeline), disksrc);
# cheap trick to build . first...
-SUBDIRS = . types meta elements
+SUBDIRS = . types meta elements autoplug
lib_LTLIBRARIES = libgst.la
--- /dev/null
+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)
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gst.h>
+
+#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; i<numsinks; i++) {
+ if (factory != (GstElementFactory *) (factories[i]->data)) {
+ 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; i<numsinks; i++) {
+ factories[i] = g_list_next (factories[i]);
+ }
+
+ have_common = TRUE;
+ }
+
+differ:
+
+ // loop over all the sink elements
+ for (i = 0; i < numsinks; i++) {
+ GstElement *thesrcelement = srcelement;
+ GstElement *thebin = GST_ELEMENT(result);
+
+ while (factories[i]) {
+ // fase 4: add other elements...
+ GstElementFactory *factory;
+ GstElement *element;
+
+ factory = (GstElementFactory *)(factories[i]->data);
+
+ 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);
+}
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gstautoplug.h>
+
+#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__ */
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gst.h>
+
+#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; i<numsinks; i++) {
+ if (factory != (GstElementFactory *) (factories[i]->data)) {
+ 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; i<numsinks; i++) {
+ factories[i] = g_list_next (factories[i]);
+ }
+
+ have_common = TRUE;
+ }
+
+differ:
+
+ // loop over all the sink elements
+ for (i = 0; i < numsinks; i++) {
+ GstElement *thesrcelement = srcelement;
+ GstElement *thebin = GST_ELEMENT(result);
+ GstElement *sinkelement;
+ gboolean use_thread;
+
+ sinkelement = GST_ELEMENT (endelements->data);
+ 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);
+}
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gstautoplug.h>
+
+#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__ */
+
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
- * 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
};
-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;
}
static void
-gst_disksrc_class_init (GstDiskSrcClass *klass)
+gst_disksrc_class_init (GstDiskSrcClass *klass)
{
GtkObjectClass *gtkobject_class;
GstElementClass *gstelement_class;
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_);
}
-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) {
}
}
-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) {
* 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;
/* deal with EOF state */
if (src->curoffset >= src->size) {
- gst_element_signal_eos (GST_ELEMENT (src));
+ gst_pad_set_eos (pad);
return NULL;
}
* 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;
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;
}
/* 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);
}
/* 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));
}
-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);
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;
}
}
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
- * 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
{ "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;
#include "gst_private.h"
#include "gstautoplug.h"
+#include "gstplugin.h"
-static void gst_autoplug_class_init (GstAutoplugClass *klass);
-static void gst_autoplug_init (GstAutoplug *autoplug);
+GList* _gst_autoplugfactories;
-static GList* gst_autoplug_func (gpointer src, gpointer sink,
- GstAutoplugListFunction list_function,
- GstAutoplugCostFunction cost_function,
- gpointer data);
+enum {
+ NEW_OBJECT,
+ LAST_SIGNAL
+};
-struct _gst_autoplug_node
-{
- gpointer iNode;
- gpointer iPrev;
- gint iDist;
+enum {
+ ARG_0,
+ /* FILL ME */
};
-typedef struct _gst_autoplug_node gst_autoplug_node;
+static void gst_autoplug_class_init (GstAutoplugClass *klass);
+static void gst_autoplug_init (GstAutoplug *autoplug);
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 void gst_autoplug_init(GstAutoplug *autoplug) {
+void
+_gst_autoplug_initialize (void)
+{
+ _gst_autoplugfactories = NULL;
}
-static gboolean
-gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
+void
+gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object)
{
- GList *srctemps, *desttemps;
+ gtk_signal_emit (GTK_OBJECT (autoplug), gst_autoplug_signals[NEW_OBJECT], object);
+}
- srctemps = src->padtemplates;
- while (srctemps) {
- GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
+GstElement*
+gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...)
+{
+ GstAutoplugClass *oclass;
+ GstElement *element = NULL;
+ va_list args;
- desttemps = dest->padtemplates;
+ va_start (args, sinkcaps);
- while (desttemps) {
- GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
+ oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
+ if (oclass->autoplug_to_caps)
+ element = (oclass->autoplug_to_caps) (autoplug, srccaps, sinkcaps, args);
- 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;
- }
- }
+ va_end (args);
- 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;
+ return element;
}
-static GList*
-gst_autoplug_elementfactory_get_list (gpointer data)
+GstElement*
+gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...)
{
- return gst_elementfactory_get_list ();
-}
+ GstAutoplugClass *oclass;
+ GstElement *element = NULL;
+ va_list args;
-typedef struct {
- GList *src;
- GList *sink;
-} caps_struct;
+ va_start (args, target);
-#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
+ oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
+ if (oclass->autoplug_to_renderers)
+ element = (oclass->autoplug_to_renderers) (autoplug, srccaps, target, args);
-static guint
-gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
-{
- caps_struct *caps = (caps_struct *)data;
- gboolean res;
+ va_end (args);
- 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;
+ return element;
}
+
/**
- * gst_autoplug_caps:
- * @srccaps: the source caps
- * @sinkcaps: the sink caps
+ * 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
*
- * Perform autoplugging between the two given caps.
+ * Create a new autoplugfactory with the given parameters
*
- * Returns: a list of elementfactories that can connect
- * the two caps
+ * Returns: a new #GstAutoplugFactory.
*/
-GList*
-gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps)
+GstAutoplugFactory*
+gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type)
{
- caps_struct caps;
+ GstAutoplugFactory *factory;
+
+ g_return_val_if_fail(name != NULL, NULL);
- caps.src = g_list_prepend (NULL,srccaps);
- caps.sink = g_list_prepend (NULL,sinkcaps);
+ factory = g_new0(GstAutoplugFactory, 1);
- GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
+ factory->name = g_strdup(name);
+ factory->longdesc = g_strdup (longdesc);
+ factory->type = type;
- return gst_autoplug_func (caps.src, caps.sink,
- gst_autoplug_elementfactory_get_list,
- gst_autoplug_caps_find_cost,
- &caps);
+ _gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
+
+ return factory;
}
/**
- * gst_autoplug_caps_list:
- * @srccaps: the source caps list
- * @sinkcaps: the sink caps list
- *
- * Perform autoplugging between the two given caps lists.
+ * gst_autoplugfactory_destroy:
+ * @autoplug: factory to destroy
*
- * Returns: a list of elementfactories that can connect
- * the two caps lists
+ * Removes the autoplug from the global list.
*/
-GList*
-gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps)
+void
+gst_autoplugfactory_destroy (GstAutoplugFactory *autoplug)
{
- caps_struct caps;
-
- caps.src = srccaps;
- caps.sink = sinkcaps;
+ g_return_if_fail (autoplug != NULL);
- GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps list structures");
+ _gst_autoplugfactories = g_list_remove (_gst_autoplugfactories, autoplug);
- 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_pads:
- * @srcpad: the source pad
- * @sinkpad: the sink pad
+ * gst_autoplug_find:
+ * @name: name of autoplugger to find
*
- * Perform autoplugging between the two given pads.
+ * Search for an autoplugger of the given name.
*
- * Returns: a list of elementfactories that can connect
- * the two pads
+ * Returns: #GstAutoplug if found, NULL otherwise
*/
-GList*
-gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad)
+GstAutoplugFactory*
+gst_autoplugfactory_find (const gchar *name)
{
- caps_struct caps;
+ GList *walk;
+ GstAutoplugFactory *factory;
+
+ g_return_val_if_fail(name != NULL, NULL);
- caps.src = gst_pad_get_caps_list(srcpad);
- caps.sink = gst_pad_get_caps_list(sinkpad);
+ GST_DEBUG (0,"gstautoplug: find \"%s\"\n", name);
- GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
+ walk = _gst_autoplugfactories;
+ while (walk) {
+ factory = (GstAutoplugFactory *)(walk->data);
+ if (!strcmp (name, factory->name))
+ return factory;
+ walk = g_list_next (walk);
+ }
- return gst_autoplug_func (caps.src, caps.sink,
- gst_autoplug_elementfactory_get_list,
- gst_autoplug_caps_find_cost,
- &caps);
+ return NULL;
}
-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;
+/**
+ * gst_autoplugfactory_get_list:
+ *
+ * Get the global list of elementfactories.
+ *
+ * Returns: GList of type #GstElementFactory
+ */
+GList*
+gst_autoplugfactory_get_list (void)
+{
+ return _gst_autoplugfactories;
}
-static GList*
-construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
+GstAutoplug*
+gst_autoplugfactory_create (GstAutoplugFactory *factory)
{
- GstElementFactory *current;
- GList *factories = NULL;
+ GstAutoplug *new = NULL;
- current = rgnNodes[find_factory(rgnNodes, factory)].iPrev;
+ g_return_val_if_fail (factory != NULL, NULL);
- GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)");
+ if (factory->type == 0){
+ factory = gst_plugin_load_autoplugfactory (factory->name);
+ }
+ g_return_val_if_fail (factory != NULL, NULL);
+ g_return_val_if_fail (factory->type != 0, NULL);
- while (current != NULL)
- {
- gpointer next = NULL;
+ new = GST_AUTOPLUG (gtk_type_new (factory->type));
- 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;
+ return new;
}
-static GList*
-gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
+GstAutoplug*
+gst_autoplugfactory_make (const gchar *name)
{
- gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
+ GstAutoplugFactory *factory;
+
+ g_return_val_if_fail (name != NULL, NULL);
- node->iNode = iNode;
- node->iDist = iDist;
- node->iPrev = iPrev;
+ factory = gst_autoplugfactory_find (name);
- queue = g_list_append (queue, node);
+ if (factory == NULL)
+ return NULL;
- return queue;
+ return gst_autoplugfactory_create (factory);;
}
-static GList*
-gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
+xmlNodePtr
+gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent)
{
- GList *head;
- gst_autoplug_node *node;
+ g_return_val_if_fail(factory != NULL, NULL);
- 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);
- }
+ xmlNewChild(parent,NULL,"name",factory->name);
+ xmlNewChild(parent,NULL,"longdesc", factory->longdesc);
- return head;
+ return parent;
}
-static GList*
-gst_autoplug_func (gpointer src, gpointer sink,
- GstAutoplugListFunction list_function,
- GstAutoplugCostFunction cost_function,
- gpointer data)
+GstAutoplugFactory*
+gst_autoplugfactory_load_thyself (xmlNodePtr parent)
{
- gst_autoplug_node *rgnNodes;
- GList *queue = NULL;
- gpointer iNode, iPrev;
- gint iDist, i, iCost;
+ GstAutoplugFactory *factory = g_new0(GstAutoplugFactory, 1);
+ xmlNodePtr children = parent->xmlChildrenNode;
- 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;
+ while (children) {
+ if (!strcmp(children->name, "name")) {
+ factory->name = xmlNodeGetContent(children);
}
- else {
- rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST;
+ if (!strcmp(children->name, "longdesc")) {
+ factory->longdesc = xmlNodeGetContent(children);
}
-
- factories = g_list_next (factories);
+ children = children->next;
}
- 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);
- }
- }
+ _gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
- return construct_path (rgnNodes, sink);
+ return factory;
}
#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) \
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);
+};
+
+typedef struct _GstAutoplugFactory GstAutoplugFactory;
+
+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);
+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);
-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);
+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__ */
GstBin *bin;
GList *children;
GstElement *child;
+ GstElementStateReturn ret;
GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME (element));
break;
}
+ case GST_STATE_READY_TO_NULL:
+ GST_FLAG_UNSET (bin, GST_BIN_FLAG_MANAGER);
default:
break;
}
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;
}
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);
}
// 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++;
}
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);
}
#include "gstpropsprivate.h"
-void
-_gst_caps_initialize (void)
+void
+_gst_caps_initialize (void)
{
}
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;
}
gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
{
GstCaps *caps;
-
+
caps = gst_caps_new (name, mime);
caps->properties = props;
* gst_caps_register:
* @factory: the factory to register
*
- * Register the factory.
+ * Register the factory.
*
* Returns: the registered capability
*/
tag = (*factory)[i++];
g_return_val_if_fail (tag != NULL, NULL);
-
+
typeid = get_type_for_mime ((gchar *)tag);
caps = g_new0 (GstCaps, 1);
*
* Returns: the name of the caps
*/
-const gchar*
+const gchar*
gst_caps_get_name (GstCaps *caps)
{
g_return_val_if_fail (caps != NULL, NULL);
/**
* 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.
gst_caps_set_name (GstCaps *caps, const gchar *name)
{
g_return_if_fail (caps != NULL);
-
+
if (caps->name)
g_free (caps->name);
*
* Returns: the mime type of the caps
*/
-const gchar*
+const gchar*
gst_caps_get_mime (GstCaps *caps)
{
GstType *type;
type = gst_type_find_by_id (caps->id);
- if (type)
+ if (type)
return type->mime;
- else
+ else
return "unknown/unknown";
}
*
* Returns: the type id of the caps
*/
-guint16
+guint16
gst_caps_get_type_id (GstCaps *caps)
{
g_return_val_if_fail (caps != NULL, 0);
/**
* 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;
}
/**
g_return_val_if_fail (caps->properties == NULL, caps);
caps->properties = props;
-
+
return caps;
}
{
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);
*
* Returns: a new XML node pointer
*/
-xmlNodePtr
+xmlNodePtr
gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
{
xmlNodePtr subtree;
*
* Returns: a new capability
*/
-GstCaps*
+GstCaps*
gst_caps_load_thyself (xmlNodePtr parent)
{
GstCaps *caps = g_new0 (GstCaps, 1);
};
/* 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);
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__ */
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;
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);
}
}
child = child->next;
}
-
gst_util_set_object_arg (GTK_OBJECT (element), name, value);
}
children = children->next;
#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;
/* global list of registered elementfactories */
GList* _gst_elementfactories;
-void
-_gst_elementfactory_initialize (void)
+void
+_gst_elementfactory_initialize (void)
{
_gst_elementfactories = NULL;
}
*
* 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);
* Returns: #GstElementFactory if found, NULL otherwise
*/
GstElementFactory*
-gst_elementfactory_find (const gchar *name)
+gst_elementfactory_find (const gchar *name)
{
GList *walk;
GstElementFactory *factory;
* Returns: GList of type #GstElementFactory
*/
GList*
-gst_elementfactory_get_list (void)
+gst_elementfactory_get_list (void)
{
return _gst_elementfactories;
}
*/
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;
*/
GstElement *
gst_elementfactory_create (GstElementFactory *factory,
- const gchar *name)
+ const gchar *name)
{
GstElement *element;
GstElementClass *oclass;
* 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;
/**
* 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;
/**
* 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;
}
if (!strcmp(children->name, "padtemplate")) {
GstPadTemplate *template;
-
+
template = gst_padtemplate_load_thyself (children);
gst_elementfactory_add_padtemplate (factory, template);
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)) {
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 {
static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
-
static GstObject *pad_parent_class = NULL;
GtkType
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
{
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));
{
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);
* 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:
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);
{
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;
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);
}
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;
}
}
-
-
-
-
-
-
-
/***** ghost pads *****/
static void gst_ghost_pad_class_init (GstGhostPadClass *klass);
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);
#include "gst_private.h"
#include "gstpipeline.h"
-#include "gstthread.h"
-#include "gstutils.h"
-#include "gsttype.h"
-#include "gstautoplug.h"
GstElementDetails gst_pipeline_details = {
};
-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 };
}
static void
-gst_pipeline_class_init (GstPipelineClass *klass)
+gst_pipeline_class_init (GstPipelineClass *klass)
{
GstElementClass *gstelement_class;
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;
}
* 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)
-{
- 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)
+static void
+gst_pipeline_prepare (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; i<numsinks; i++) {
- if (!factories[i] || (factory != (GstElementFactory *)(factories[i]->data))) {
- 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_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\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)) {
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));
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))
-
-void gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src);
-void gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink);
-
-gboolean gst_pipeline_autoplug (GstPipeline *pipeline);
+#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(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__ */
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");
plugin->numelements = 0;
plugin->types = NULL;
plugin->numtypes = 0;
+ plugin->autopluggers = NULL;
+ plugin->numautopluggers = 0;
plugin->loaded = TRUE;
return plugin;
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;
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
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:
*
* Returns; a GList of GstPlugin elements
*/
GList*
-gst_plugin_get_list(void)
+gst_plugin_get_list (void)
{
return _gst_plugins;
}
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;
}
{
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++;
}
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);
}
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;
+}
#include <gst/gsttype.h>
#include <gst/gstelement.h>
+#include <gst/gstautoplug.h>
-typedef struct _GstPlugin GstPlugin;
-typedef struct _GstPluginElement GstPluginElement;
+typedef struct _GstPlugin GstPlugin;
+typedef struct _GstPluginElement GstPluginElement;
struct _GstPlugin {
gchar *name; /* name of the plugin */
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 */
};
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__ */
sscanf (prop, "%08x", &entry->data.fourcc_data);
g_free (prop);
}
+ else {
+ g_free (entry);
+ entry = NULL;
+ }
return entry;
}
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;
}
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)));
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 */
*
* Returns: the new type id
*/
-guint16
-gst_type_register (GstTypeFactory *factory)
+guint16
+gst_type_register (GstTypeFactory *factory)
{
guint16 id;
GstType *type;
// 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);
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;
*
* 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);
}
*
* 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");
* Returns: the type
*/
GstType*
-gst_type_find_by_id (guint16 id)
+gst_type_find_by_id (guint16 id)
{
GList *walk = _gst_types;
GstType *type;
* Returns: a list of GstTypes
*/
GList*
-gst_type_get_list (void)
+gst_type_get_list (void)
{
return _gst_types;
}
*
* 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) {
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;
* Returns: the new typefactory
*/
GstTypeFactory*
-gst_typefactory_load_thyself (xmlNodePtr parent)
+gst_typefactory_load_thyself (xmlNodePtr parent)
{
GstTypeFactory *factory = g_new0 (GstTypeFactory, 1);
/* 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);
/* 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__ */
};
-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) {
(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;
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) {
}
}
-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) {
}
}
-static void
-gst_typefind_chain (GstPad *pad, GstBuffer *buf)
+static void
+gst_typefind_chain (GstPad *pad, GstBuffer *buf)
{
GstTypeFind *typefind;
GList *type_list;
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;
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;
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;
/* 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;
}
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);
+ }
+}
+
+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;
}
-GstPlayReturn
-gst_play_set_uri (GstPlay *play,
- const guchar *uri)
+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) {
- }
+ priv = (GstPlayPrivate *)play->priv;
- 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->bin), new_element);
+
+ gst_element_connect (priv->src, "src", new_element, "sink");
- gst_bin_add (GST_BIN (priv->thread), priv->pipeline);
+ 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) {
}
}
-void
-gst_play_play (GstPlay *play)
+void
+gst_play_play (GstPlay *play)
{
GstPlayPrivate *priv;
play->state);
}
-void
-gst_play_pause (GstPlay *play)
+void
+gst_play_pause (GstPlay *play)
{
GstPlayPrivate *priv;
play->state);
}
-void
-gst_play_stop (GstPlay *play)
+void
+gst_play_stop (GstPlay *play)
{
GstPlayPrivate *priv;
play->state);
}
-gulong
-gst_play_get_media_size (GstPlay *play)
+gulong
+gst_play_get_media_size (GstPlay *play)
{
GstPlayPrivate *priv;
return gst_util_get_long_arg (GTK_OBJECT (priv->src), "size");
}
-gulong
+gulong
gst_play_get_media_offset (GstPlay *play)
{
GstPlayPrivate *priv;
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);
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;
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);
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;
return current_time;
}
-gboolean
+gboolean
gst_play_media_can_seek (GstPlay *play)
{
GstPlayPrivate *priv;
return priv->can_seek;
}
-void
-gst_play_media_seek (GstPlay *play,
+void
+gst_play_media_seek (GstPlay *play,
gulong offset)
{
GstPlayPrivate *priv;
}
-static void
+static void
gst_play_set_arg (GtkObject *object,
GtkArg *arg,
- guint id)
+ guint id)
{
GstPlay *play;
}
}
-static void
+static void
gst_play_get_arg (GtkObject *object,
GtkArg *arg,
- guint id)
+ guint id)
{
GstPlay *play;
GstPlayPrivate *priv;
typedef enum {
GST_PLAY_OK,
GST_PLAY_UNKNOWN_MEDIA,
+ GST_PLAY_CANNOT_PLAY,
GST_PLAY_ERROR,
} GstPlayReturn;
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;
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
- * 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
};
-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;
}
static void
-gst_disksrc_class_init (GstDiskSrcClass *klass)
+gst_disksrc_class_init (GstDiskSrcClass *klass)
{
GtkObjectClass *gtkobject_class;
GstElementClass *gstelement_class;
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_);
}
-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) {
}
}
-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) {
* 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;
/* deal with EOF state */
if (src->curoffset >= src->size) {
- gst_element_signal_eos (GST_ELEMENT (src));
+ gst_pad_set_eos (pad);
return NULL;
}
* 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;
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;
}
/* 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);
}
/* 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));
}
-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);
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;
}
}
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
- * 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
{ "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;
// 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) {
// 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);
.deps
.libs
*.xml
-
+*.gst
init
loadall
simplefake
load
padfactory
tee
+autoplug2
+autoplug3
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)
#include <gst/gst.h>
-static GList*
-autoplug_caps (gchar *mime1, gchar *mime2)
+static void
+new_object_added (GstAutoplug *autoplug, GstObject *object)
{
- GstCaps *caps1, *caps2;
-
- caps1 = gst_caps_new ("tescaps1", mime1);
- caps2 = gst_caps_new ("tescaps2", mime2);
-
- return gst_autoplug_caps (caps1, caps2);
+ g_print ("added new object \"%s\"\n", gst_object_get_name (object));
}
-static void
-dump_factories (GList *factories)
+int
+main (int argc, char *argv[])
{
- g_print ("dumping factories\n");
+ GstElement *element;
+ GstElement *videosink, *audiosink;
+ GstAutoplug *autoplugger;
+ GList *testcaps;
- while (factories) {
- GstElementFactory *factory = (GstElementFactory *)factories->data;
+ gst_init(&argc,&argv);
- g_print ("factory: \"%s\"\n", factory->name);
+ audiosink = gst_elementfactory_make ("audiosink", "audiosink");
+ g_assert (audiosink != NULL);
+ videosink = gst_elementfactory_make ("videosink", "videosink");
+ g_assert (videosink != NULL);
- factories = g_list_next (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)));
-int main(int argc,char *argv[])
-{
- GList *factories;
+ autoplugger = gst_autoplugfactory_make ("static");
- gst_init(&argc,&argv);
+ 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);
- factories = autoplug_caps ("audio/mp3", "audio/raw");
- dump_factories (factories);
-
- factories = autoplug_caps ("video/mpeg", "audio/raw");
- dump_factories (factories);
-
- 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);
-
- 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);
+ xmlDocDump (stdout, gst_xml_write (element));
exit (0);
}
--- /dev/null
+#include <gst/gst.h>
+
+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);
+}
--- /dev/null
+#include <gst/gst.h>
+
+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);
+}
exit(-1);
}
-
-
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline)));
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
// hmmmm hack? FIXME
GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER);
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"));
g_print("cannot autoplug pipeline\n");
exit(-1);
}
+ */
gst_bin_add(GST_BIN(pipeline), thread);
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);
g_print("unable to handle stream\n");
exit(-1);
}
+ */
//gst_bin_remove(GST_BIN(pipeline), disksrc);
g_free(longprefix);
break;
default:
- printf("\n");
+ printf("unknown props %d\n", prop->propstype);
}
}
}
}
-/*
-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;
}
}
-
-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);
printf("\n");
if (plugin->numelements) {
+ GList *factories;
+ GstElementFactory *factory;
+
printf("Element Factories:\n");
factories = gst_plugin_get_factory_list(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");
}
// 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 {