Implemented the plugable autopluggers.

Original commit message from CVS:
Implemented the plugable autopluggers.
- one can aad an autoplugger to a plugin with gst_plugin_add_autoplugger
- the autopluggers can be queried using _get_list
- save/load autoplugger descriptions in the XML registry
- load the autoplugger only when needed
- a signal can be attached to the autoplugger to be notified of
new objects.
- improved the media player to use the new autoplugger
- updated gstreamer-inspect for the autoplugger and types
added EOS to the disksrc
fixed two bugs in properties loading (min/max, comment tags)
This commit is contained in:
Wim Taymans 2001-02-08 19:37:41 +00:00
parent 5a52fd4009
commit fe586de094
20 changed files with 612 additions and 702 deletions

View file

@ -656,6 +656,7 @@ gst/Makefile
gst/types/Makefile
gst/meta/Makefile
gst/elements/Makefile
gst/autoplug/Makefile
libs/Makefile
libs/riff/Makefile
libs/colorspace/Makefile

View file

@ -155,14 +155,14 @@ struct _GstEditorElement {
struct _GstEditorElementClass {
GnomeCanvasGroupClass parent_class;
void (*name_changed) (GstEditorElement *element);
void (*position_changed) (GstEditorElement *element);
void (*size_changed) (GstEditorElement *element);
void (*realize) (GstEditorElement *element);
gint (*event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
void (*name_changed) (GstEditorElement *element);
void (*position_changed) (GstEditorElement *element);
void (*size_changed) (GstEditorElement *element);
void (*realize) (GstEditorElement *element);
gint (*event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
};
@ -188,11 +188,11 @@ const gchar *gst_editor_element_get_name(GstEditorElement *element);
(GTK_CHECK_TYPE((obj),GST_TYPE_EDITOR_BIN))
#define GST_IS_EDITOR_BIN_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_BIN))
struct _GstEditorBin {
GstEditorElement element;
/* lists of GUI elements and connections */
/* lists of GUI elements and connections */
GList *elements, *connections;
/* connection state */
@ -213,11 +213,11 @@ struct _GstEditorBinClass {
GtkType gst_editor_bin_get_type();
GstEditorBin* gst_editor_bin_new (GstBin *bin, const gchar *first_arg_name,...);
void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element);
void gst_editor_bin_connection_drag (GstEditorBin *bin,
gdouble wx,gdouble wy);
void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad);
void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element);
void gst_editor_bin_connection_drag (GstEditorBin *bin,
gdouble wx,gdouble wy);
void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad);
#define GST_TYPE_EDITOR_CANVAS \
@ -246,8 +246,8 @@ struct _GstEditorCanvasClass {
GstEditorCanvas* gst_editor_canvas_new (void);
GstEditorCanvas* gst_editor_canvas_new_with_bin (GstEditorBin *bin);
void gst_editor_canvas_set_bin (GstEditorCanvas *canvas,
GstEditorBin *element);
void gst_editor_canvas_set_bin (GstEditorCanvas *canvas,
GstEditorBin *element);
GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas);
@ -263,7 +263,7 @@ GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PAD))
struct _GstEditorPad {
GtkObject object;
GtkObject object;
/* parent element */
GstEditorElement *parent;
@ -291,7 +291,7 @@ struct _GstEditorPad {
gdouble width,height; // actual size
gdouble boxwidth,boxheight; // size of pad box
gboolean resize; // does it need resizing?
/* interaction state */
gboolean dragging,resizing,moved;
gdouble dragx,dragy;
@ -300,13 +300,13 @@ struct _GstEditorPad {
// GnomeCanvasItem *connection; // can't use
//GstEditorConnection
};
struct _GstEditorPadClass {
GtkObjectClass parent_class;
void (*realize) (GstEditorPad *pad);
};
GtkType gst_editor_pad_get_type();
GstEditorPad *gst_editor_pad_new(GstEditorElement *parent,GstPad *pad,
const gchar *first_arg_name, ...);
@ -329,7 +329,7 @@ void gst_editor_pad_repack(GstEditorPad *pad);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PADTEMPLATE))
struct _GstEditorPadTemplate {
GtkObject object;
GtkObject object;
/* parent element */
GstEditorElement *parent;
@ -361,7 +361,7 @@ struct _GstEditorPadTemplate {
gdouble width,height; // actual size
gdouble boxwidth,boxheight; // size of padtemplate box
gboolean resize; // does it need resizing?
/* interaction state */
gboolean dragging,resizing,moved;
gdouble dragx,dragy;
@ -370,13 +370,13 @@ struct _GstEditorPadTemplate {
// GnomeCanvasItem *connection; // can't use
//GstEditorConnection
};
struct _GstEditorPadTemplateClass {
GtkObjectClass parent_class;
void (*realize) (GstEditorPadTemplate *padtemplate);
};
GtkType gst_editor_padtemplate_get_type();
GstEditorPadTemplate *gst_editor_padtemplate_new(GstEditorElement *parent,GstPadTemplate *padtemplate,
const gchar *first_arg_name, ...);

View file

@ -1,5 +1,5 @@
# cheap trick to build . first...
SUBDIRS = . types meta elements
SUBDIRS = . types meta elements autoplug
lib_LTLIBRARIES = libgst.la

View file

@ -32,7 +32,7 @@
GstElementDetails gst_disksrc_details = {
"hronous Disk Source",
"asynchronous Disk Source",
"Source/File",
"Read from arbitrary point in a file",
VERSION,

View file

@ -2,7 +2,7 @@
* 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
@ -48,27 +48,27 @@ struct _elements_entry {
};
static struct _elements_entry _elements[] = {
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL },
{ "asyncdisksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "identity", gst_identity_get_type, &gst_identity_details, NULL },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL },
{ "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL },
{ "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL },
{ "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init },
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL },
{ "asyncdisksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "identity", gst_identity_get_type, &gst_identity_details, NULL },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL },
{ "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL },
{ "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL },
{ "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;

View file

@ -24,570 +24,248 @@
#include "gst_private.h"
#include "gstautoplug.h"
#include "gstbin.h"
#include "gstplugin.h"
GList* _gst_autoplugfactories;
enum {
NEW_OBJECT,
LAST_SIGNAL
};
enum {
ARG_0,
/* FILL ME */
};
static void gst_autoplug_class_init (GstAutoplugClass *klass);
static void gst_autoplug_init (GstAutoplug *autoplug);
static GList* gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data);
struct _gst_autoplug_node
{
gpointer iNode;
gpointer iPrev;
gint iDist;
};
typedef struct _gst_autoplug_node gst_autoplug_node;
static GstObjectClass *parent_class = NULL;
static guint gst_autoplug_signals[LAST_SIGNAL] = { 0 };
GtkType gst_autoplug_get_type(void) {
GtkType gst_autoplug_get_type(void)
{
static GtkType autoplug_type = 0;
if (!autoplug_type) {
static const GtkTypeInfo autoplug_info = {
"GstAutoplug",
sizeof(GstElement),
sizeof(GstElementClass),
sizeof(GstAutoplug),
sizeof(GstAutoplugClass),
(GtkClassInitFunc)gst_autoplug_class_init,
(GtkObjectInitFunc)gst_autoplug_init,
(GtkArgSetFunc)NULL,
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
autoplug_type = gtk_type_unique(GST_TYPE_AUTOPLUG,&autoplug_info);
autoplug_type = gtk_type_unique (GTK_TYPE_OBJECT, &autoplug_info);
}
return autoplug_type;
}
static void
gst_autoplug_class_init(GstAutoplugClass *klass) {
parent_class = gtk_type_class(GST_TYPE_OBJECT);
}
static void gst_autoplug_init(GstAutoplug *autoplug) {
}
static gboolean
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
gst_autoplug_class_init(GstAutoplugClass *klass)
{
GList *srctemps, *desttemps;
GtkObjectClass *gtkobject_class;
srctemps = src->padtemplates;
gtkobject_class = (GtkObjectClass*) klass;
while (srctemps) {
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
parent_class = gtk_type_class(GTK_TYPE_OBJECT);
desttemps = dest->padtemplates;
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);
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;
gtk_object_class_add_signals (gtkobject_class, gst_autoplug_signals, LAST_SIGNAL);
}
static gboolean
gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
static void gst_autoplug_init(GstAutoplug *autoplug)
{
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_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
void
_gst_autoplug_initialize (void)
{
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);
}
_gst_autoplugfactories = NULL;
}
static GList*
gst_autoplug_elementfactory_get_list (gpointer data)
void
gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object)
{
return gst_elementfactory_get_list ();
gtk_signal_emit (GTK_OBJECT (autoplug), gst_autoplug_signals[NEW_OBJECT], object);
}
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)
GstElement*
gst_autoplug_caps_list (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, ...)
{
caps_struct *caps = (caps_struct *)data;
gboolean res;
GstAutoplugClass *oclass;
GstElement *element = NULL;
va_list 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);
}
va_start (args, sinkpad);
if (res)
return 1;
else
return GST_AUTOPLUG_MAX_COST;
oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
if (oclass->autoplug_caps_list)
element = (oclass->autoplug_caps_list) (autoplug, srcpad, sinkpad, args);
va_end (args);
return element;
}
/**
* gst_autoplugfactory_new:
* @name: name of autoplugfactory to create
* @longdesc: long description of autoplugfactory to create
* @type: the gtk type of the GstAutoplug element of this factory
*
* Create a new autoplugfactory with the given parameters
*
* Returns: a new #GstAutoplugFactory.
*/
GstAutoplugFactory*
gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type)
{
GstAutoplugFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
factory = g_new0(GstAutoplugFactory, 1);
factory->name = g_strdup(name);
factory->longdesc = g_strdup (longdesc);
factory->type = type;
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
return factory;
}
/**
* gst_autoplug_pads:
* @srcpad: the source pad
* @sinkpad: the sink pad
* gst_autoplugfactory_destroy:
* @autoplug: factory to destroy
*
* Perform autoplugging between the two given pads.
*
* Returns: a list of elementfactories that can connect
* the two pads
* Removes the autoplug from the global list.
*/
GstElement*
gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps, ...)
void
gst_autoplugfactory_destroy (GstAutoplugFactory *autoplug)
{
caps_struct caps;
va_list args;
GList *capslist;
GstElement *result = NULL, *srcelement = NULL;
GList **factories;
GList *chains = NULL;
GList *endcaps = NULL;
guint numsinks = 0, i;
gboolean have_common = FALSE;
g_return_if_fail (autoplug != NULL);
va_start (args, sinkcaps);
capslist = sinkcaps;
_gst_autoplugfactories = g_list_remove (_gst_autoplugfactories, autoplug);
/*
* 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;
// we don't free the struct bacause someone might have a handle to it..
}
while (capslist) {
GList *elements;
/**
* gst_autoplug_find:
* @name: name of autoplugger to find
*
* Search for an autoplugger of the given name.
*
* Returns: #GstAutoplug if found, NULL otherwise
*/
GstAutoplugFactory*
gst_autoplugfactory_find (const gchar *name)
{
GList *walk;
GstAutoplugFactory *factory;
caps.sink = capslist;
g_return_val_if_fail(name != NULL, NULL);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
GST_DEBUG (0,"gstautoplug: find \"%s\"\n", name);
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 *);
walk = _gst_autoplugfactories;
while (walk) {
factory = (GstAutoplugFactory *)(walk->data);
if (!strcmp (name, factory->name))
return factory;
walk = g_list_next (walk);
}
va_end (args);
/*
* If no list could be found the pipeline cannot be autoplugged and
* we return a NULL element
*/
if (numsinks == 0)
return NULL;
}
/**
* gst_autoplugfactory_get_list:
*
* Get the global list of elementfactories.
*
* Returns: GList of type #GstElementFactory
*/
GList*
gst_autoplugfactory_get_list (void)
{
return _gst_autoplugfactories;
}
GstAutoplug*
gst_autoplugfactory_create (GstAutoplugFactory *factory)
{
GstAutoplug *new = NULL;
g_return_val_if_fail (factory != NULL, NULL);
if (factory->type == 0){
factory = gst_plugin_load_autoplugfactory (factory->name);
}
g_return_val_if_fail (factory != NULL, NULL);
g_return_val_if_fail (factory->type != 0, NULL);
new = GST_AUTOPLUG (gtk_type_new (factory->type));
return new;
}
GstAutoplug*
gst_autoplugfactory_make (const gchar *name)
{
GstAutoplugFactory *factory;
g_return_val_if_fail (name != NULL, NULL);
factory = gst_autoplugfactory_find (name);
if (factory == NULL)
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);
}
}
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);
gboolean use_thread;
use_thread = have_common;
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);
// 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_autoplug_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(result), 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_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);
endcaps = g_list_next (endcaps);
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));
break;
}
}
}
}
return result;
return gst_autoplugfactory_create (factory);;
}
static gint
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
xmlNodePtr
gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent)
{
gint i=0;
g_return_val_if_fail(factory != NULL, NULL);
while (rgnNodes[i].iNode) {
if (rgnNodes[i].iNode == factory) return i;
i++;
}
return 0;
xmlNewChild(parent,NULL,"name",factory->name);
xmlNewChild(parent,NULL,"longdesc", factory->longdesc);
return parent;
}
static GList*
construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
GstAutoplugFactory*
gst_autoplugfactory_load_thyself (xmlNodePtr parent)
{
GstElementFactory *current;
GList *factories = NULL;
GstAutoplugFactory *factory = g_new0(GstAutoplugFactory, 1);
xmlNodePtr children = parent->xmlChildrenNode;
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);
while (children) {
if (!strcmp(children->name, "name")) {
factory->name = xmlNodeGetContent(children);
}
current = next;
}
return factories;
}
static GList*
gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
{
gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
node->iNode = iNode;
node->iDist = iDist;
node->iPrev = iPrev;
queue = g_list_append (queue, node);
return queue;
}
static GList*
gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
{
GList *head;
gst_autoplug_node *node;
head = g_list_first (queue);
if (head) {
node = (gst_autoplug_node *)head->data;
*iNode = node->iNode;
*iPrev = node->iPrev;
*iDist = node->iDist;
head = g_list_remove (queue, node);
if (!strcmp(children->name, "longdesc")) {
factory->longdesc = xmlNodeGetContent(children);
}
children = children->next;
}
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);
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
return factory;
}

View file

@ -31,7 +31,7 @@ extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_AUTOPLUG \
(gst_object_get_type())
(gst_autoplug_get_type())
#define GST_AUTOPLUG(obj) \
(GTK_CHECK_CAST((obj),GST_TYPE_AUTOPLUG,GstAutoplug))
#define GST_AUTOPLUG_CLASS(klass) \
@ -44,11 +44,6 @@ extern "C" {
typedef struct _GstAutoplug GstAutoplug;
typedef struct _GstAutoplugClass GstAutoplugClass;
#define GST_AUTOPLUG_MAX_COST 999999
typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data);
typedef GList* (*GstAutoplugListFunction) (gpointer data);
struct _GstAutoplug {
GtkObject object;
};
@ -57,19 +52,42 @@ struct _GstAutoplugClass {
GtkObjectClass parent_class;
/* signal callbacks */
void (*element_added) (GstAutoplug *eutoplug, GstElement *element);
void (*new_object) (GstAutoplug *autoplug, GstObject *object);
/* perform the autoplugging */
GstElement* (*autoplug_caps_list) (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, va_list args);
};
typedef struct _GstAutoplugFactory GstAutoplugFactory;
struct _GstAutoplugFactory {
gchar *name; /* name of element */
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);
GstElement* gst_autoplug_caps_list (GList *srcpad, GList *sinkpad, ...);
void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object);
GstElement* gst_autoplug_caps_list (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, ...);
/*
* creating autopluggers
*
*/
GstAutoplugFactory* gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type);
void gst_autoplugfactory_destroy (GstAutoplugFactory *factory);
GstAutoplugFactory* gst_autoplugfactory_find (const gchar *name);
GList* gst_autoplugfactory_get_list (void);
GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *factory);
GstAutoplug* gst_autoplugfactory_make (const gchar *name);
xmlNodePtr gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent);
GstAutoplugFactory* gst_autoplugfactory_load_thyself (xmlNodePtr parent);
#ifdef __cplusplus
}

View file

@ -30,8 +30,8 @@
/* global list of registered elementfactories */
GList* _gst_elementfactories;
void
_gst_elementfactory_initialize (void)
void
_gst_elementfactory_initialize (void)
{
_gst_elementfactories = NULL;
}
@ -42,8 +42,8 @@ _gst_elementfactory_initialize (void)
*
* Removes the elementfactory from the global list.
*/
void
gst_elementfactory_destroy (GstElementFactory *elementfactory)
void
gst_elementfactory_destroy (GstElementFactory *elementfactory)
{
g_return_if_fail (elementfactory != NULL);
@ -61,7 +61,7 @@ gst_elementfactory_destroy (GstElementFactory *elementfactory)
* Returns: #GstElementFactory if found, NULL otherwise
*/
GstElementFactory*
gst_elementfactory_find (const gchar *name)
gst_elementfactory_find (const gchar *name)
{
GList *walk;
GstElementFactory *factory;
@ -89,7 +89,7 @@ gst_elementfactory_find (const gchar *name)
* Returns: GList of type #GstElementFactory
*/
GList*
gst_elementfactory_get_list (void)
gst_elementfactory_get_list (void)
{
return _gst_elementfactories;
}
@ -108,12 +108,14 @@ gst_elementfactory_get_list (void)
*/
GstElementFactory*
gst_elementfactory_new (const gchar *name, GtkType type,
GstElementDetails *details)
GstElementDetails *details)
{
GstElementFactory *factory = g_new0(GstElementFactory, 1);
GstElementFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
factory = g_new0(GstElementFactory, 1);
factory->name = g_strdup(name);
factory->type = type;
factory->details = details;
@ -138,7 +140,7 @@ gst_elementfactory_new (const gchar *name, GtkType type,
*/
GstElement *
gst_elementfactory_create (GstElementFactory *factory,
const gchar *name)
const gchar *name)
{
GstElement *element;
GstElementClass *oclass;
@ -184,7 +186,7 @@ gst_elementfactory_create (GstElementFactory *factory,
* Returns: new #GstElement
*/
GstElement*
gst_elementfactory_make (const gchar *factoryname, const gchar *name)
gst_elementfactory_make (const gchar *factoryname, const gchar *name)
{
GstElementFactory *factory;
GstElement *element;
@ -338,15 +340,15 @@ gst_elementfactory_can_sink_caps (GstElementFactory *factory,
/**
* gst_elementfactory_save_thyself:
* @factory: factory to save
* @parent: the parent xmlNodePtr
* @parent: the parent xmlNodePtr
*
* Saves the factory into an XML tree.
*
*
* Returns: the new xmlNodePtr
*/
xmlNodePtr
gst_elementfactory_save_thyself (GstElementFactory *factory,
xmlNodePtr parent)
xmlNodePtr
gst_elementfactory_save_thyself (GstElementFactory *factory,
xmlNodePtr parent)
{
GList *pads;
@ -377,14 +379,14 @@ gst_elementfactory_save_thyself (GstElementFactory *factory,
/**
* gst_elementfactory_load_thyself:
* @parent: the parent xmlNodePtr
* @parent: the parent xmlNodePtr
*
* Creates a new factory from an xmlNodePtr.
*
*
* Returns: the new factory
*/
GstElementFactory *
gst_elementfactory_load_thyself (xmlNodePtr parent)
gst_elementfactory_load_thyself (xmlNodePtr parent)
{
GstElementFactory *factory = g_new0(GstElementFactory, 1);
xmlNodePtr children = parent->xmlChildrenNode;
@ -415,7 +417,7 @@ gst_elementfactory_load_thyself (xmlNodePtr parent)
}
if (!strcmp(children->name, "padtemplate")) {
GstPadTemplate *template;
template = gst_padtemplate_load_thyself (children);
gst_elementfactory_add_padtemplate (factory, template);

View file

@ -24,10 +24,6 @@
#include "gst_private.h"
#include "gstpipeline.h"
#include "gstthread.h"
#include "gstutils.h"
#include "gsttype.h"
#include "gstautoplug.h"
GstElementDetails gst_pipeline_details = {

View file

@ -80,6 +80,8 @@ _gst_plugin_initialize (void)
PLUGINS_SRCDIR "/gst/elements");
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/types");
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/autoplug");
#else /* PLUGINS_USE_SRCDIR */
/* add the main (installed) library path */
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths, PLUGINS_DIR);
@ -395,6 +397,8 @@ gst_plugin_new (const gchar *name)
plugin->numelements = 0;
plugin->types = NULL;
plugin->numtypes = 0;
plugin->autopluggers = NULL;
plugin->numautopluggers = 0;
plugin->loaded = TRUE;
return plugin;
@ -529,15 +533,7 @@ gst_plugin_find (const gchar *name)
return NULL;
}
/**
* gst_plugin_find_elementfactory:
* @name: name of elementfactory to find
*
* Find a registered elementfactory by name.
*
* Returns: @GstElementFactory if found, NULL if not
*/
GstElementFactory*
static GstElementFactory*
gst_plugin_find_elementfactory (const gchar *name)
{
GList *plugins, *factories;
@ -609,6 +605,77 @@ gst_plugin_load_elementfactory (const gchar *name)
return factory;
}
static GstAutoplugFactory*
gst_plugin_find_autoplugfactory (const gchar *name)
{
GList *plugins, *factories;
GstAutoplugFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
plugins = _gst_plugins;
while (plugins) {
factories = ((GstPlugin *)(plugins->data))->autopluggers;
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
if (!strcmp(factory->name, name))
return (GstAutoplugFactory*)(factory);
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return NULL;
}
/**
* gst_plugin_load_autoplugfactory:
* @name: name of autoplugfactory to load
*
* Load a registered autoplugfactory by name.
*
* Returns: @GstAutoplugFactory if loaded, NULL if not
*/
GstAutoplugFactory*
gst_plugin_load_autoplugfactory (const gchar *name)
{
GList *plugins, *factories;
GstAutoplugFactory *factory = NULL;
GstPlugin *plugin;
g_return_val_if_fail(name != NULL, NULL);
plugins = _gst_plugins;
while (plugins) {
plugin = (GstPlugin *)plugins->data;
factories = plugin->autopluggers;
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
if (!strcmp(factory->name,name)) {
if (!plugin->loaded) {
gchar *filename = g_strdup (plugin->filename);
gchar *pluginname = g_strdup (plugin->name);
GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded autoplugfactory %s from plugin %s",name,plugin->name);
gst_plugin_remove(plugin);
if (!gst_plugin_load_absolute(filename)) {
GST_DEBUG (0,"gstplugin: error loading autoplug factory %s from plugin %s\n", name, pluginname);
}
g_free (pluginname);
g_free (filename);
}
factory = gst_plugin_find_autoplugfactory(name);
return factory;
}
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return factory;
}
/**
* gst_plugin_load_typefactory:
* @mime: name of typefactory to load
@ -696,6 +763,24 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
gst_type_register (factory);
}
/**
* gst_plugin_add_type:
* @plugin: plugin to add type to
* @factory: the typefactory to add
*
* Add a typefactory to the list of those provided by the plugin.
*/
void
gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory)
{
g_return_if_fail (plugin != NULL);
g_return_if_fail (factory != NULL);
// g_print("adding factory to plugin\n");
plugin->autopluggers = g_list_prepend (plugin->autopluggers, factory);
plugin->numautopluggers++;
}
/**
* gst_plugin_get_list:
*
@ -704,7 +789,7 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
* Returns; a GList of GstPlugin elements
*/
GList*
gst_plugin_get_list(void)
gst_plugin_get_list (void)
{
return _gst_plugins;
}
@ -721,34 +806,45 @@ xmlNodePtr
gst_plugin_save_thyself (xmlNodePtr parent)
{
xmlNodePtr tree, subtree;
GList *plugins = NULL, *elements = NULL, *types = NULL;
GList *plugins = NULL, *elements = NULL, *types = NULL, *autopluggers = NULL;
plugins = gst_plugin_get_list();
plugins = gst_plugin_get_list ();
while (plugins) {
GstPlugin *plugin = (GstPlugin *)plugins->data;
tree = xmlNewChild(parent,NULL,"plugin",NULL);
xmlNewChild(tree,NULL,"name",plugin->name);
xmlNewChild(tree,NULL,"longname",plugin->longname);
xmlNewChild(tree,NULL,"filename",plugin->filename);
tree = xmlNewChild (parent, NULL, "plugin", NULL);
xmlNewChild (tree, NULL, "name", plugin->name);
xmlNewChild (tree, NULL, "longname", plugin->longname);
xmlNewChild (tree, NULL, "filename", plugin->filename);
types = plugin->types;
while (types) {
GstTypeFactory *factory = (GstTypeFactory *)types->data;
subtree = xmlNewChild(tree,NULL,"typefactory",NULL);
subtree = xmlNewChild(tree, NULL, "typefactory", NULL);
gst_typefactory_save_thyself(factory, subtree);
gst_typefactory_save_thyself (factory, subtree);
types = g_list_next(types);
types = g_list_next (types);
}
elements = plugin->elements;
while (elements) {
GstElementFactory *factory = (GstElementFactory *)elements->data;
subtree = xmlNewChild(tree,NULL,"elementfactory",NULL);
subtree = xmlNewChild (tree, NULL, "elementfactory", NULL);
gst_elementfactory_save_thyself(factory, subtree);
gst_elementfactory_save_thyself (factory, subtree);
elements = g_list_next(elements);
elements = g_list_next (elements);
}
plugins = g_list_next(plugins);
autopluggers = plugin->autopluggers;
while (autopluggers) {
GstAutoplugFactory *factory = (GstAutoplugFactory *)autopluggers->data;
subtree = xmlNewChild (tree, NULL, "autoplugfactory", NULL);
gst_autoplugfactory_save_thyself (factory, subtree);
autopluggers = g_list_next (autopluggers);
}
plugins = g_list_next (plugins);
}
return parent;
}
@ -764,43 +860,50 @@ gst_plugin_load_thyself (xmlNodePtr parent)
{
xmlNodePtr kinderen;
gint elementcount = 0;
gint autoplugcount = 0;
gint typecount = 0;
gchar *pluginname;
kinderen = parent->xmlChildrenNode; // Dutch invasion :-)
while (kinderen) {
if (!strcmp(kinderen->name, "plugin")) {
if (!strcmp (kinderen->name, "plugin")) {
xmlNodePtr field = kinderen->xmlChildrenNode;
GstPlugin *plugin = g_new0 (GstPlugin, 1);
plugin->elements = NULL;
plugin->types = NULL;
plugin->loaded = FALSE;
while (field) {
if (!strcmp(field->name, "name")) {
pluginname = xmlNodeGetContent(field);
if (gst_plugin_find(pluginname)) {
g_free(pluginname);
g_free(plugin);
if (!strcmp (field->name, "name")) {
pluginname = xmlNodeGetContent (field);
if (gst_plugin_find (pluginname)) {
g_free (pluginname);
g_free (plugin);
plugin = NULL;
break;
} else {
plugin->name = pluginname;
}
}
else if (!strcmp(field->name, "longname")) {
plugin->longname = xmlNodeGetContent(field);
else if (!strcmp (field->name, "longname")) {
plugin->longname = xmlNodeGetContent (field);
}
else if (!strcmp(field->name, "filename")) {
plugin->filename = xmlNodeGetContent(field);
else if (!strcmp (field->name, "filename")) {
plugin->filename = xmlNodeGetContent (field);
}
else if (!strcmp(field->name, "elementfactory")) {
GstElementFactory *factory = gst_elementfactory_load_thyself(field);
else if (!strcmp (field->name, "elementfactory")) {
GstElementFactory *factory = gst_elementfactory_load_thyself (field);
gst_plugin_add_factory (plugin, factory);
elementcount++;
}
else if (!strcmp(field->name, "typefactory")) {
GstTypeFactory *factory = gst_typefactory_load_thyself(field);
else if (!strcmp (field->name, "autoplugfactory")) {
GstAutoplugFactory *factory = gst_autoplugfactory_load_thyself (field);
gst_plugin_add_autoplugger (plugin, factory);
autoplugcount++;
}
else if (!strcmp (field->name, "typefactory")) {
GstTypeFactory *factory = gst_typefactory_load_thyself (field);
gst_plugin_add_type (plugin, factory);
elementcount++;
typecount++;
@ -810,13 +913,14 @@ gst_plugin_load_thyself (xmlNodePtr parent)
}
if (plugin) {
_gst_plugins = g_list_prepend(_gst_plugins, plugin);
_gst_plugins = g_list_prepend (_gst_plugins, plugin);
}
}
kinderen = kinderen->next;
}
GST_INFO (GST_CAT_PLUGIN_LOADING,"added %d registered factories and %d types",elementcount,typecount);
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d registered factories, %d autopluggers and %d types",
elementcount, autoplugcount, typecount);
}
@ -851,3 +955,19 @@ gst_plugin_get_type_list (GstPlugin *plugin)
return plugin->types;
}
/**
* gst_plugin_get_autoplug_list:
* @plugin: the plugin to get the autoplugfactories from
*
* get a list of all the autoplugfactories that this plugin provides
*
* Returns: a GList of factories
*/
GList*
gst_plugin_get_autoplug_list (GstPlugin *plugin)
{
g_return_val_if_fail (plugin != NULL, NULL);
return plugin->autopluggers;
}

View file

@ -36,6 +36,7 @@
#include <gst/gsttype.h>
#include <gst/gstelement.h>
#include <gst/gstautoplug.h>
typedef struct _GstPlugin GstPlugin;
@ -50,6 +51,8 @@ struct _GstPlugin {
gint numtypes;
GList *elements; /* list of elements provided */
gint numelements;
GList *autopluggers; /* list of autopluggers provided */
gint numautopluggers;
gboolean loaded; /* if the plugin is in memory */
};
@ -71,6 +74,7 @@ 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);
@ -79,14 +83,14 @@ 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_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);
GstAutoplugFactory* gst_plugin_load_autoplugfactory (const gchar *name);
xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent);
void gst_plugin_load_thyself (xmlNodePtr parent);

View file

@ -578,7 +578,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
prop = xmlGetProp (field, "min");
sscanf (prop, "%d", &entry->data.int_range_data.min);
g_free (prop);
prop = xmlGetProp (field, "min");
prop = xmlGetProp (field, "max");
sscanf (prop, "%d", &entry->data.int_range_data.max);
g_free (prop);
}
@ -601,6 +601,10 @@ gst_props_load_thyself_func (xmlNodePtr field)
sscanf (prop, "%08x", &entry->data.fourcc_data);
g_free (prop);
}
else {
g_free (entry);
entry = NULL;
}
return entry;
}
@ -634,7 +638,8 @@ gst_props_load_thyself (xmlNodePtr parent)
while (subfield) {
GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
if (subentry)
entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
subfield = subfield->next;
}

View file

@ -43,10 +43,10 @@ struct _GstTypeFindInfo {
GstPlugin *plugin; /* the plugin with this typefind function */
};
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
void
_gst_type_initialize (void)
void
_gst_type_initialize (void)
{
_gst_types = NULL;
_gst_maxtype = 1; /* type 0 is undefined */
@ -60,8 +60,8 @@ _gst_type_initialize (void)
*
* Returns: the new type id
*/
guint16
gst_type_register (GstTypeFactory *factory)
guint16
gst_type_register (GstTypeFactory *factory)
{
guint16 id;
GstType *type;
@ -70,14 +70,14 @@ gst_type_register (GstTypeFactory *factory)
// GST_INFO (GST_CAT_TYPES,"type register %s", factory->mime);
id = gst_type_find_by_mime (factory->mime);
if (!id) {
type = g_new0 (GstType, 1);
type->id = _gst_maxtype++;
type->mime = factory->mime;
type->exts = factory->exts;
_gst_types = g_list_prepend (_gst_types, type);
type->id = _gst_maxtype++;
type->mime = factory->mime;
type->exts = factory->exts;
_gst_types = g_list_prepend (_gst_types, type);
id = type->id;
@ -96,8 +96,8 @@ gst_type_register (GstTypeFactory *factory)
return id;
}
static
guint16 gst_type_find_by_mime_func (const gchar *mime)
static
guint16 gst_type_find_by_mime_func (const gchar *mime)
{
GList *walk;
GstType *type;
@ -142,8 +142,8 @@ guint16 gst_type_find_by_mime_func (const gchar *mime)
*
* Returns: the type id
*/
guint16
gst_type_find_by_mime (const gchar *mime)
guint16
gst_type_find_by_mime (const gchar *mime)
{
return gst_type_find_by_mime_func (mime);
}
@ -156,8 +156,8 @@ gst_type_find_by_mime (const gchar *mime)
*
* Returns: the type id
*/
guint16
gst_type_find_by_ext (const gchar *ext)
guint16
gst_type_find_by_ext (const gchar *ext)
{
//FIXME
g_warning ("gsttype: find_by_ext not implemented");
@ -173,7 +173,7 @@ gst_type_find_by_ext (const gchar *ext)
* Returns: the type
*/
GstType*
gst_type_find_by_id (guint16 id)
gst_type_find_by_id (guint16 id)
{
GList *walk = _gst_types;
GstType *type;
@ -196,7 +196,7 @@ gst_type_find_by_id (guint16 id)
* Returns: a list of GstTypes
*/
GList*
gst_type_get_list (void)
gst_type_get_list (void)
{
return _gst_types;
}
@ -210,8 +210,8 @@ gst_type_get_list (void)
*
* Returns: the new xmlNodePtr
*/
xmlNodePtr
gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
xmlNodePtr
gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
{
xmlNewChild (parent, NULL, "mime", factory->mime);
if (factory->exts) {
@ -220,11 +220,11 @@ gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
if (factory->typefindfunc) {
xmlNewChild (parent, NULL, "typefind", NULL);
}
return parent;
}
static GstCaps *
static GstCaps *
gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
{
GstType *type = (GstType *)priv;
@ -263,7 +263,7 @@ gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
* Returns: the new typefactory
*/
GstTypeFactory*
gst_typefactory_load_thyself (xmlNodePtr parent)
gst_typefactory_load_thyself (xmlNodePtr parent)
{
GstTypeFactory *factory = g_new0 (GstTypeFactory, 1);

View file

@ -206,14 +206,20 @@ gst_play_audio_handoff (GstElement *element,
}
static void
gst_play_object_introspect (GstElement *element,
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);
@ -229,8 +235,8 @@ gst_play_object_introspect (GstElement *element,
* this will change with glib 1.4
* */
static void
gst_play_object_added (GstElement *pipeline,
GstElement *element,
gst_play_object_added (GstAutoplug* autoplug,
GstObject *object,
GstPlay *play)
{
GstPlayPrivate *priv;
@ -239,23 +245,23 @@ gst_play_object_added (GstElement *pipeline,
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);
gst_play_object_introspect (object, "offset", &priv->offset_element);
if (!priv->bit_rate_element)
gst_play_object_introspect (element, "bit_rate", &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);
}
}
@ -337,6 +343,7 @@ gst_play_set_uri (GstPlay *play,
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);
@ -351,6 +358,7 @@ gst_play_set_uri (GstPlay *play,
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);
@ -363,8 +371,12 @@ gst_play_set_uri (GstPlay *play,
return GST_PLAY_UNKNOWN_MEDIA;
}
new_element = gst_autoplug_caps_list
(gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
autoplug = gst_autoplugfactory_make ("static");
gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play);
new_element = gst_autoplug_caps_list (autoplug,
gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
gst_pad_get_caps_list (gst_element_get_pad (priv->video_queue, "sink")),
gst_pad_get_caps_list (gst_element_get_pad (priv->audio_queue, "sink")),
NULL);

View file

@ -32,7 +32,7 @@
GstElementDetails gst_disksrc_details = {
"hronous Disk Source",
"asynchronous Disk Source",
"Source/File",
"Read from arbitrary point in a file",
VERSION,

View file

@ -2,7 +2,7 @@
* 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
@ -48,27 +48,27 @@ struct _elements_entry {
};
static struct _elements_entry _elements[] = {
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL },
{ "asyncdisksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "identity", gst_identity_get_type, &gst_identity_details, NULL },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL },
{ "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL },
{ "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL },
{ "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init },
{ "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL },
{ "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL },
{ "asyncdisksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init },
{ "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL },
{ "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL },
{ "identity", gst_identity_get_type, &gst_identity_details, NULL },
{ "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL },
{ "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL },
{ "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL },
{ "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL },
{ "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;

View file

@ -1,7 +1,7 @@
SUBDIRS = sched eos
noinst_PROGRAMS = init loadall simplefake states caps queue registry \
paranoia rip mp3encode autoplug props case4 markup load tee
paranoia rip mp3encode autoplug props case4 markup load tee autoplug2
# we have nothing but apps here, we can do this safely
LIBS += $(GST_LIBS)

View file

@ -1,10 +1,17 @@
#include <gst/gst.h>
static void
new_object_added (GstAutoplug *autoplug, GstObject *object)
{
g_print ("added new object \"%s\"\n", gst_object_get_name (object));
}
int
main (int argc, char *argv[])
{
GstElement *element;
GstElement *videosink, *audiosink;
GstAutoplug *autoplugger;
GList *testcaps;
gst_init(&argc,&argv);
@ -22,9 +29,14 @@ main (int argc, char *argv[])
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL)));
autoplugger = gst_autoplugfactory_make ("static");
element = gst_autoplug_caps_list (testcaps, gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")), NULL);
gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL);
element = gst_autoplug_caps_list (autoplugger, testcaps,
gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")),
NULL);
g_assert (element != NULL);
xmlDocDump (stdout, gst_xml_write (element));

52
tests/autoplug2.c Normal file
View file

@ -0,0 +1,52 @@
#include <gst/gst.h>
static GstElement*
autoplug_caps (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_caps_list (caps1, caps2, NULL);
}
int
main (int argc, char *argv[])
{
GstElement *element;
gst_init(&argc,&argv);
element = autoplug_caps ("audio/mp3", "audio/raw");
xmlSaveFile ("autoplug2_1.gst", gst_xml_write (element));
element = autoplug_caps ("video/mpeg", "audio/raw");
xmlSaveFile ("autoplug2_2.gst", gst_xml_write (element));
element = gst_autoplug_caps_list (
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_caps_list (
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));
exit (0);
}

View file

@ -42,7 +42,7 @@ void print_prop(GstPropsEntry *prop,gboolean showname,gchar *pfx) {
g_free(longprefix);
break;
default:
printf("\n");
printf("unknown props %d\n", prop->propstype);
}
}
@ -59,30 +59,9 @@ void print_props(GstProps *properties,gchar *pfx) {
}
}
/*
struct _GstPropsEntry {
GQuark propid;
GstPropsId propstype;
union {
// flat values
gboolean bool_data;
guint32 fourcc_data;
gint int_data;
// structured values
struct {
GList *entries;
} list_data;
struct {
gint min;
gint max;
} int_range_data;
} data;
};
*/
gint print_element_info(GstElementFactory *factory) {
gint
print_element_info (GstElementFactory *factory)
{
GstElement *element;
GstObjectClass *gstobject_class;
GstElementClass *gstelement_class;
@ -322,11 +301,9 @@ void print_element_list() {
}
}
void print_plugin_info(GstPlugin *plugin) {
GList *factories;
GstElementFactory *factory;
void
print_plugin_info (GstPlugin *plugin)
{
printf("Plugin Details:\n");
printf(" Name:\t\t%s\n",plugin->name);
printf(" Long Name:\t%s\n",plugin->longname);
@ -334,6 +311,9 @@ void print_plugin_info(GstPlugin *plugin) {
printf("\n");
if (plugin->numelements) {
GList *factories;
GstElementFactory *factory;
printf("Element Factories:\n");
factories = gst_plugin_get_factory_list(plugin);
@ -344,6 +324,36 @@ void print_plugin_info(GstPlugin *plugin) {
printf(" %s: %s\n",factory->name,factory->details->longname);
}
}
if (plugin->numautopluggers) {
GList *factories;
GstAutoplugFactory *factory;
printf("Autpluggers:\n");
factories = gst_plugin_get_autoplug_list(plugin);
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
factories = g_list_next(factories);
printf(" %s: %s\n", factory->name, factory->longdesc);
}
}
if (plugin->numtypes) {
GList *factories;
GstTypeFactory *factory;
printf("Types:\n");
factories = gst_plugin_get_type_list(plugin);
while (factories) {
factory = (GstTypeFactory*)(factories->data);
factories = g_list_next(factories);
printf(" %s: %s\n", factory->mime, factory->exts);
if (factory->typefindfunc)
printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc));
}
}
printf("\n");
}
@ -357,7 +367,7 @@ int main(int argc,char *argv[]) {
// if no arguments, print out list of elements
if (argc == 1) {
print_element_list();
print_element_list();
// else we try to get a factory
} else {