+2005-04-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+
+ * gst/autoplug/.cvsignore:
+ * gst/autoplug/Makefile.am:
+ * gst/autoplug/gstsearchfuncs.c:
+ * gst/autoplug/gstsearchfuncs.h:
+ * gst/autoplug/gstspider.c:
+ * gst/autoplug/gstspider.h:
+ * gst/autoplug/gstspideridentity.c:
+ * gst/autoplug/gstspideridentity.h:
+ * gst/autoplug/spidertest.c:
+ Die, spider, die.
+
2005-04-25 Wim Taymans <wim@fluendo.com>
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active),
+++ /dev/null
-autoplugtest
-spidertest
-*.bb
-*.bbg
-*.da
-*.def
+++ /dev/null
-
-plugin_LTLIBRARIES = libgstspider.la
-
-libgstspider_la_SOURCES = \
- gstspider.c gstspideridentity.c \
- gstsearchfuncs.c
-libgstspider_la_CFLAGS = $(GST_OBJ_CFLAGS)
-libgstspider_la_LIBADD = $(GST_OBJ_LIBS)
-libgstspider_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-noinst_HEADERS = gstspider.h gstspideridentity.h gstsearchfuncs.h
-
-noinst_PROGRAMS = spidertest
-
-spidertest_SOURCES = spidertest.c
-spidertest_CFLAGS = $(GST_OBJ_CFLAGS)
-spidertest_LDADD = $(GST_OBJ_LIBS)
-
+++ /dev/null
-/* GStreamer
- * Copyright (C) 1999-2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000-2002 Wim Taymans <wtay@chello.be>
- *
- * gstsearchfuncs.c: functions needed when doing searches while
- * autoplugging
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gstsearchfuncs.h"
-
-/* FIXME: "evil hack" alarm, we need a better way to get a category in here */
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_AUTOPLUG_ATTEMPT);
-#define GST_CAT_DEFAULT GST_CAT_AUTOPLUG_ATTEMPT
-
-/* function that really misses in GLib
- * though the GLib version should take a function as argument...
- */
-static void
-g_list_free_list_and_elements (GList * list)
-{
- GList *walk = list;
-
- while (walk) {
- g_free (walk->data);
- walk = g_list_next (walk);
- }
- g_list_free (list);
-}
-
-/**
- * gst_autoplug_caps_intersect:
- * @src: a source #GstCaps
- * @sink: the sink #GstCaps
- *
- * Checks if the given caps have a non-null intersection.
- *
- * Returns: TRUE, if both caps intersect.
- */
-gboolean
-gst_autoplug_caps_intersect (const GstCaps * src, const GstCaps * sink)
-{
- GstCaps *caps;
-
- /* get an intersection */
- caps = gst_caps_intersect (src, sink);
-
- /* if the caps can't link, there is no intersection */
- if (gst_caps_is_empty (caps)) {
- gst_caps_unref (caps);
- return FALSE;
- }
-
- /* hurrah, we can link, now remove the intersection */
- gst_caps_unref (caps);
- return TRUE;
-}
-
-/**
- * gst_autoplug_can_connect_src:
- * @fac: factory to connect to
- * @src: caps to check
- *
- * Checks if a factory's sink can connect to the given caps
- *
- * Returns: #GstPadTemplate that can connect to the given caps
- */
-GstPadTemplate *
-gst_autoplug_can_connect_src (GstElementFactory * fac, const GstCaps * src)
-{
- GList *templs;
-
- templs = fac->padtemplates;
-
- while (templs) {
- if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK) &&
- gst_autoplug_caps_intersect (src,
- GST_PAD_TEMPLATE_CAPS (templs->data))) {
- return GST_PAD_TEMPLATE (templs->data);
- }
- templs = g_list_next (templs);
- }
-
- return NULL;
-}
-
-/**
- * gst_autoplug_can_connect_sink:
- * @fac: factory to connect to
- * @sink: caps to check
- *
- * Checks if a factory's src can connect to the given caps
- *
- * Returns: #GstPadTemplate that can connect to the given caps
- */
-GstPadTemplate *
-gst_autoplug_can_connect_sink (GstElementFactory * fac, const GstCaps * sink)
-{
- GList *templs;
-
- templs = fac->padtemplates;
-
- while (templs) {
- GstCaps *caps = GST_PAD_TEMPLATE_CAPS (templs->data);
-
- if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SRC) &&
- gst_autoplug_caps_intersect (caps, sink)) {
- return GST_PAD_TEMPLATE (templs->data);
- }
- templs = g_list_next (templs);
- }
-
- return NULL;
-}
-
-GstPadTemplate *
-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_autoplug_caps_intersect (gst_pad_template_get_caps (srctemp),
- gst_pad_template_get_caps (desttemp))) {
- GST_DEBUG ("factory \"%s\" can connect with factory \"%s\"",
- GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
- return desttemp;
- }
- }
-
- desttemps = g_list_next (desttemps);
- }
- srctemps = g_list_next (srctemps);
- }
- GST_DEBUG ("factory \"%s\" cannot connect with factory \"%s\"",
- GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
- return NULL;
-}
-
-/* returns TRUE if the factory has padtemplates with the specified direction */
-gboolean
-gst_autoplug_factory_has_direction (GstElementFactory * fac,
- GstPadDirection dir)
-{
- GList *templs = fac->padtemplates;
-
- while (templs) {
- if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
- return TRUE;
- }
- templs = g_list_next (templs);
- }
-
- return FALSE;
-}
-
-/* Decisions are based on the padtemplates.
- * These functions return a new list so be sure to free it.
- */
-GList *
-gst_autoplug_factories_sinks (GList * factories)
-{
- GList *ret = NULL;
-
- while (factories) {
- if (gst_autoplug_factory_has_sink (factories->data))
- ret = g_list_prepend (ret, factories->data);
- factories = g_list_next (factories);
- }
- return ret;
-}
-
-GList *
-gst_autoplug_factories_srcs (GList * factories)
-{
- GList *ret = NULL;
-
- while (factories) {
- if (gst_autoplug_factory_has_src (factories->data))
- ret = g_list_prepend (ret, factories->data);
- factories = g_list_next (factories);
- }
- return ret;
-}
-
-GList *
-gst_autoplug_factories_filters (GList * factories)
-{
- GList *ret = NULL;
-
- while (factories) {
- /* if you want it faster do src/sink check at once, don't call two functions */
- if (gst_autoplug_factory_has_src (factories->data)
- && gst_autoplug_factory_has_sink (factories->data))
- ret = g_list_prepend (ret, factories->data);
- factories = g_list_next (factories);
- }
- return ret;
-}
-
-
-static gint
-gst_autoplug_rank_compare (const GstElementFactory * a,
- const GstElementFactory * b)
-{
- if (GST_PLUGIN_FEATURE (a)->rank > GST_PLUGIN_FEATURE (b)->rank)
- return -1;
- return (GST_PLUGIN_FEATURE (a)->rank < GST_PLUGIN_FEATURE (b)->rank) ? 1 : 0;
-}
-
-/* returns all factories which have sinks with non-NULL caps and srcs with
- * any caps. also only returns factories with a non-zero rank, and sorts by
- * rank descending.
- */
-GList *
-gst_autoplug_factories_filters_with_sink_caps (GList * factories)
-{
- GList *ret = NULL;
- GstElementFactory *factory;
- GList *templs;
-
- while (factories) {
- factory = (GstElementFactory *) factories->data;
- templs = factory->padtemplates;
-
- if (GST_PLUGIN_FEATURE (factory)->rank > 0) {
- gboolean have_src = FALSE;
- gboolean have_sink = FALSE;
-
- while (templs) {
- if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SRC) {
- have_src = TRUE;
- }
- if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK)
- && (GST_PAD_TEMPLATE_CAPS (templs->data) != NULL)) {
- have_sink = TRUE;
- }
- if (have_src && have_sink) {
- ret = g_list_prepend (ret, factory);
- break;
- }
- templs = g_list_next (templs);
- }
- }
- factories = g_list_next (factories);
- }
- return g_list_sort (ret, (GCompareFunc) gst_autoplug_rank_compare);
-}
-
-
-
-/* returns all factories which have a maximum of maxtemplates GstPadTemplates in direction dir
- */
-GList *
-gst_autoplug_factories_at_most_templates (GList * factories,
- GstPadDirection dir, guint maxtemplates)
-{
- GList *ret = NULL;
-
- while (factories) {
- guint count = 0;
- GList *templs = ((GstElementFactory *) factories->data)->padtemplates;
-
- while (templs) {
- if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
- count++;
- }
- if (count > maxtemplates)
- break;
- templs = g_list_next (templs);
- }
- if (count <= maxtemplates)
- ret = g_list_prepend (ret, factories->data);
-
- factories = g_list_next (factories);
- }
- return ret;
-}
-
-/*********************************************************************
- *
- * SHORTEST PATH ALGORITHM
- */
-/**
- * gst_autoplug_sp:
- * @src_caps: a #GstCaps to plug from.
- * @sink_caps: the #GstCaps to plug to.
- * @factories: a #GList containing all allowed #GstElementFactory entries.
- *
- * Finds the shortest path of elements that together make up a possible
- * connection between the source and sink caps.
- *
- * Returns: a #GList of #GstElementFactory items which have to be connected
- * to get the shortest path.
- */
-GList *
-gst_autoplug_sp (const GstCaps * srccaps, const GstCaps * sinkcaps,
- GList * factories)
-{
- GList *factory_nodes = NULL;
- guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */
- GstAutoplugNode *bestnode = NULL; /* best (unconnected) endpoint currently */
-
- g_return_val_if_fail (srccaps != NULL, NULL);
- g_return_val_if_fail (sinkcaps != NULL, NULL);
-
- GST_INFO ("attempting to autoplug via shortest path from %"
- GST_PTR_FORMAT " to %" GST_PTR_FORMAT, srccaps, sinkcaps);
-
- /* wrap all factories as GstAutoplugNode
- * initialize the cost */
- while (factories) {
- GstAutoplugNode *node = g_new0 (GstAutoplugNode, 1);
-
- node->prev = NULL;
- node->fac = (GstElementFactory *) factories->data;
- GST_DEBUG ("trying with %s", node->fac->details.longname);
- node->templ = gst_autoplug_can_connect_src (node->fac, srccaps);
- node->cost = (node->templ ? gst_autoplug_get_cost (node->fac)
- : GST_AUTOPLUG_MAX_COST);
- node->endpoint = gst_autoplug_can_connect_sink (node->fac, sinkcaps);
- if (node->templ && node->endpoint)
- GST_DEBUG ("%s makes connection possible", node->fac->details.longname);
- else
- GST_DEBUG ("direct connection with %s not possible",
- node->fac->details.longname);
- if ((node->endpoint != NULL) &&
- ((bestnode == NULL) || (node->cost < bestnode->cost))) {
- bestnode = node;
- }
- factory_nodes = g_list_prepend (factory_nodes, node);
- /* make curcost the minimum cost of any plugin */
- curcost = node->cost < curcost ? node->cost : curcost;
- factories = g_list_next (factories);
- }
-
- /* check if we even have possible endpoints */
- if (bestnode == NULL) {
- GST_DEBUG ("no factory found that could connect to sink caps");
- g_list_free_list_and_elements (factory_nodes);
- return NULL;
- }
-
- /* iterate until we found the best path */
- while (curcost < GST_AUTOPLUG_MAX_COST) {
- GList *nodes = factory_nodes;
- guint nextcost = GST_AUTOPLUG_MAX_COST; /* next cost to check */
-
- GST_DEBUG ("iterating at current cost %d, bestnode %s at %d", curcost,
- GST_OBJECT_NAME (bestnode->fac), bestnode->cost);
- /* check if we already have a valid best connection to the sink */
- if (bestnode->cost <= curcost) {
- GList *ret;
-
- GST_DEBUG ("found a way to connect via %s",
- GST_OBJECT_NAME ((GstObject *) bestnode->fac));
- /* enter all factories into the return list */
- ret = g_list_prepend (NULL, bestnode->fac);
- bestnode = bestnode->prev;
- while (bestnode != NULL) {
- ret = g_list_prepend (ret, bestnode->fac);
- bestnode = bestnode->prev;
- }
- g_list_free_list_and_elements (factory_nodes);
- return ret;
- }
-
- /* iterate over all factories we have
- * if they have the current cost, calculate if this
- * factory supplies shorter paths to other elements
- */
- while (nodes) {
- if (((GstAutoplugNode *) nodes->data)->cost == curcost) {
- /* now check all elements if we got a shorter path */
- GList *sinknodes = factory_nodes;
- GstAutoplugNode *srcnode = (GstAutoplugNode *) nodes->data;
-
- while (sinknodes) {
- GstAutoplugNode *sinknode = (GstAutoplugNode *) sinknodes->data;
- GstPadTemplate *templ;
-
- if ((sinknode->cost >
- srcnode->cost + gst_autoplug_get_cost (sinknode->fac))
- && (templ = gst_autoplug_can_match (srcnode->fac, sinknode->fac))) {
- /* we got a shorter path
- * now enter that path to that node */
- sinknode->prev = srcnode;
- sinknode->templ = templ;
- sinknode->cost =
- srcnode->cost + gst_autoplug_get_cost (sinknode->fac);
- /* make sure to set which cost to view next */
- nextcost = (nextcost > sinknode->cost) ? sinknode->cost : nextcost;
- /* did we get a new best node? */
- if (sinknode->endpoint && (sinknode->cost < bestnode->cost)) {
- bestnode = sinknode;
- }
- }
- sinknodes = g_list_next (sinknodes);
- }
- /* FIXME: for speed remove the item we just iterated with from the factory_nodes
- * but don't free it yet and don't forget to free it.
- */
- }
- nodes = g_list_next (nodes);
- }
- curcost = nextcost;
- }
-
- GST_DEBUG ("found no path from source caps to sink caps");
- g_list_free_list_and_elements (factory_nodes);
- return NULL;
-}
+++ /dev/null
-/* GStreamer
- * Copyright (C) 1999-2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000-2002 Wim Taymans <wtay@chello.be>
- *
- * gstsearchfuncs.h: Header for gstsearchfuncs.c
- *
- * 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_SEARCHFUNCS_H__
-#define __GST_SEARCHFUNCS_H__
-
-#include <gst/gst.h>
-
-/* placeholder for maximum cost when plugging */
-#define GST_AUTOPLUG_MAX_COST 999999
-
-/* struct for a node, in the search tree */
-typedef struct _GstAutoplugNode GstAutoplugNode;
-
-struct _GstAutoplugNode {
- GstAutoplugNode *prev; /* previous node */
- GstElementFactory *fac; /* factory of element to connect to */
- GstPadTemplate *templ; /* template which can connect */
- guint cost; /* total cost to get here */
- GstPadTemplate *endpoint; /* pad template that can connect to sink caps */
-};
-
-/* helper functions */
-gboolean gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink);
-GstPadTemplate * gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src);
-GstPadTemplate * gst_autoplug_can_connect_sink (GstElementFactory *fac, const GstCaps *sink);
-GstPadTemplate * gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest);
-gboolean gst_autoplug_factory_has_direction (GstElementFactory *fac, GstPadDirection dir);
-#define gst_autoplug_factory_has_sink(fac) gst_autoplug_factory_has_direction((fac), GST_PAD_SINK)
-#define gst_autoplug_factory_has_src(fac) gst_autoplug_factory_has_direction((fac), GST_PAD_SRC)
-
-/* cost functions */
-#define gst_autoplug_get_cost(fac) 1
-
-/* factory selections */
-GList * gst_autoplug_factories_sinks (GList *factories);
-GList * gst_autoplug_factories_srcs (GList *factories);
-GList * gst_autoplug_factories_filters (GList *factories);
-GList * gst_autoplug_factories_filters_with_sink_caps(GList *factories);
-GList * gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates);
-
-/* shortest path algorithm */
-GList * gst_autoplug_sp (const GstCaps *src_caps, const GstCaps *sink_caps, GList *factories);
-
-#endif /* __GST_SEARCHFUNCS_H__ */
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2002 Wim Taymans <wtay@chello.be>
- *
- * gstspider.c: element to automatically link sinks and sources
- *
- * 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.
- */
-
-/*
- * TODO:
- * - handle automatic removal of unneeded elements
- * - make the spider handle and send events (esp. new media)
- * - decide if we plug pads or elements, currently it's a mess
- * - allow unlinking
- * - implement proper saving/loading from xml
- * - implement a way to allow merging/splitting (aka tee)
- * - find ways to define which elements to use when plugging
- * - remove pads
- * - improve typefinding
- * - react to errors inside the pipeline
- * - implement more properties, change the current
- * - emit signals (most important: "NOT PLUGGABLE")
- * - implement something for reporting the state of the spider
- * to allow easier debugging.
- * (could be useful for bins in general)
- * - fix bugs
- * ...
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "../gst-i18n-lib.h"
-#include "gstspider.h"
-#include "gstspideridentity.h"
-#include "gstsearchfuncs.h"
-
-static GstElementDetails gst_spider_details = GST_ELEMENT_DETAILS ("Spider",
- "Generic",
- "Automatically link sinks and sources",
- "Benjamin Otte <in7y118@public.uni-hamburg.de>");
-
-GST_DEBUG_CATEGORY (gst_spider_debug);
-#define GST_CAT_DEFAULT gst_spider_debug
-
-/* signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_FACTORIES,
- /* FILL ME TOO */
-};
-
-/* generic templates */
-static GstStaticPadTemplate spider_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-static GstStaticPadTemplate spider_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src_%d",
- GST_PAD_SRC,
- GST_PAD_REQUEST,
- GST_STATIC_CAPS_ANY);
-
-/* standard GObject stuff */
-static void gst_spider_class_init (GstSpiderClass * klass);
-static void gst_spider_init (GstSpider * spider);
-static void gst_spider_dispose (GObject * object);
-
-/* element class functions */
-static GstPad *gst_spider_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
-static void gst_spider_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_spider_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-/* link functions */
-static GstSpiderConnection *gst_spider_link_new (GstSpiderIdentity * src);
-static void gst_spider_link_destroy (GstSpiderConnection * conn);
-static void gst_spider_link_reset (GstSpiderConnection * conn, GstElement * to);
-static void gst_spider_link_add (GstSpiderConnection * conn,
- GstElement * element);
-static GstSpiderConnection *gst_spider_link_find (GstSpiderIdentity * src);
-static GstSpiderConnection *gst_spider_link_get (GstSpiderIdentity * src);
-
-/* autoplugging functions */
-static GstElement *gst_spider_find_element_to_plug (GstElement * src,
- GstElementFactory * fac, GstPadDirection dir);
-static GstPadLinkReturn gst_spider_plug (GstSpiderConnection * conn);
-static GstPadLinkReturn gst_spider_plug_from_srcpad (GstSpiderConnection * conn,
- GstPad * srcpad);
-/*static GstPadLinkReturn gst_spider_plug_peers (GstSpider *spider, GstPad *srcpad, GstPad *sinkpad); */
-static GstPadLinkReturn gst_spider_create_and_plug (GstSpiderConnection * conn,
- GList * plugpath);
-
-/* random functions */
-static gchar *gst_spider_unused_elementname (GstBin * bin,
- const gchar * startwith);
-
-/* debugging stuff
-static void print_spider_contents (GstSpider *spider);
-static void print_spider_link (GstSpiderConnection *conn); */
-
-/* === variables === */
-static GstElementClass *parent_class = NULL;
-
-/* no signals yet
-static guint gst_spider_signals[LAST_SIGNAL] = { 0 };*/
-
-/* GObject and GStreamer init functions */
-GType
-gst_spider_get_type (void)
-{
- static GType spider_type = 0;
-
- if (!spider_type) {
- static const GTypeInfo spider_info = {
- sizeof (GstSpiderClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_spider_class_init,
- NULL,
- NULL,
- sizeof (GstSpider),
- 0,
- (GInstanceInitFunc) gst_spider_init,
- };
-
- spider_type =
- g_type_register_static (GST_TYPE_BIN, "GstSpider", &spider_info, 0);
- }
- return spider_type;
-}
-
-static void
-gst_spider_class_init (GstSpiderClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_ref (GST_TYPE_BIN);
-
- /* properties */
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FACTORIES,
- g_param_spec_pointer ("factories", "allowed factories",
- "allowed factories for autoplugging", G_PARAM_READWRITE));
-
- gobject_class->set_property = gst_spider_set_property;
- gobject_class->get_property = gst_spider_get_property;
- gobject_class->dispose = gst_spider_dispose;
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&spider_sink_factory));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&spider_src_factory));
- gst_element_class_set_details (gstelement_class, &gst_spider_details);
-
- gstelement_class->request_new_pad =
- GST_DEBUG_FUNCPTR (gst_spider_request_new_pad);
-}
-static void
-gst_spider_init (GstSpider * spider)
-{
- /* use only elements which have sources and sinks and where the sinks have caps */
- /* FIXME: How do we handle factories that are added after the spider was constructed? */
- GList *list = gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY);
-
- spider->factories = gst_autoplug_factories_filters_with_sink_caps (list);
- g_list_free (list);
-
- spider->links = NULL;
-
- spider->sink_ident = gst_spider_identity_new_sink ("sink_ident");
- gst_bin_add (GST_BIN (spider), GST_ELEMENT (spider->sink_ident));
- gst_element_add_ghost_pad (GST_ELEMENT (spider), spider->sink_ident->sink,
- "sink");
-
-}
-
-static void
-gst_spider_dispose (GObject * object)
-{
- GstSpider *spider;
- GList *list;
-
- spider = GST_SPIDER (object);
- g_list_free (spider->factories);
- spider->factories = NULL;
-
- for (list = spider->links; list; list = list->next) {
- GstSpiderConnection *conn = list->data;
-
- g_list_free (conn->path);
- g_free (conn);
- }
- g_list_free (spider->links);
- spider->links = NULL;
-
- ((GObjectClass *) parent_class)->dispose (object);
-}
-static GstPad *
-gst_spider_request_new_pad (GstElement * element, GstPadTemplate * templ,
- const gchar * name)
-{
- GstPad *returnpad;
- gchar *padname;
- GstSpiderIdentity *identity;
- GstSpider *spider;
-
- g_return_val_if_fail (templ != NULL, NULL);
- g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
- g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC,
- NULL);
-
- spider = GST_SPIDER (element);
-
- /* create an identity object, so we have a pad */
- padname = gst_spider_unused_elementname ((GstBin *) spider, "src_");
- identity = gst_spider_identity_new_src (padname);
- returnpad = identity->src;
-
- /* FIXME: use the requested name for the pad */
-
- gst_object_replace ((GstObject **) & returnpad->padtemplate,
- (GstObject *) templ);
-
- gst_bin_add (GST_BIN (element), GST_ELEMENT (identity));
-
- returnpad = gst_element_add_ghost_pad (element, returnpad, padname);
- g_free (padname);
- gst_spider_link_new (identity);
- GST_DEBUG ("successfully created requested pad %s:%s",
- GST_DEBUG_PAD_NAME (returnpad));
-
- return returnpad;
-}
-
-static void
-gst_spider_set_property (GObject * object, guint prop_id, const GValue * value,
- GParamSpec * pspec)
-{
- GstSpider *spider;
- GList *list;
-
- /* it's not null if we got it, but it might not be ours */
- g_return_if_fail (GST_IS_SPIDER (object));
-
- spider = GST_SPIDER (object);
-
- switch (prop_id) {
- case ARG_FACTORIES:
- list = (GList *) g_value_get_pointer (value);
- for (; list; list = list->next) {
- g_return_if_fail (list->data != NULL);
- g_return_if_fail (GST_IS_ELEMENT_FACTORY (list->data));
- }
- g_list_free (spider->factories);
- spider->factories = (GList *) g_value_get_pointer (value);
- break;
- default:
- break;
- }
-}
-static void
-gst_spider_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstSpider *spider;
-
- /* it's not null if we got it, but it might not be ours */
- spider = GST_SPIDER (object);
-
- switch (prop_id) {
- case ARG_FACTORIES:
- g_value_set_pointer (value, spider->factories);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* get a name for an element that isn't used yet */
-static gchar *
-gst_spider_unused_elementname (GstBin * bin, const gchar * startwith)
-{
- gchar *name = g_strdup_printf ("%s%d", startwith, 0);
- guint i;
-
- for (i = 0; gst_bin_get_by_name (bin, name) != NULL;) {
- g_free (name);
- name = g_strdup_printf ("%s%d", startwith, ++i);
- }
-
- return name;
-}
-static void
-gst_spider_link_sometimes (GstElement * src, GstPad * pad,
- GstSpiderConnection * conn)
-{
- gulong signal_id = conn->signal_id;
-
- GST_INFO ("plugging from new sometimes pad %s:%s", GST_DEBUG_PAD_NAME (pad));
- /* try to autoplug the elements */
- if (gst_spider_plug_from_srcpad (conn, pad) != GST_PAD_LINK_REFUSED) {
- GST_DEBUG ("%s:%s was autoplugged to %s:%s, removing callback",
- GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (conn->src->sink));
- g_signal_handler_disconnect (src, signal_id);
- signal_id = 0;
- }
-}
-
-/* create a new link from those two elements */
-static GstSpiderConnection *
-gst_spider_link_new (GstSpiderIdentity * src)
-{
- GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (src));
-
- GstSpiderConnection *conn = g_new0 (GstSpiderConnection, 1);
-
- conn->src = src;
- conn->path = NULL;
- conn->current = (GstElement *) spider->sink_ident;
- spider->links = g_list_prepend (spider->links, conn);
-
- return conn;
-}
-static void
-gst_spider_link_destroy (GstSpiderConnection * conn)
-{
- GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
-
- /* reset link to unplugged */
- gst_spider_link_reset (conn, (GstElement *) spider->sink_ident);
- g_free (conn);
-}
-static void
-gst_spider_link_reset (GstSpiderConnection * conn, GstElement * to)
-{
- GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
-
- GST_DEBUG ("resetting link from %s to %s, currently at %s to %s",
- GST_ELEMENT_NAME (spider->sink_ident), GST_ELEMENT_NAME (conn->src),
- GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (to));
- while ((conn->path != NULL) && ((GstElement *) conn->path->data != to)) {
- gst_object_unref ((GstObject *) conn->path->data);
- conn->path = g_list_delete_link (conn->path, conn->path);
- }
- if (conn->path == NULL) {
- conn->current = (GstElement *) spider->sink_ident;
- } else {
- conn->current = to;
- }
-}
-
-/* add an element to the link */
-static void
-gst_spider_link_add (GstSpiderConnection * conn, GstElement * element)
-{
- conn->path = g_list_prepend (conn->path, element);
- conn->current = element;
-}
-
-/* find the link from those two elements */
-static GstSpiderConnection *
-gst_spider_link_find (GstSpiderIdentity * src)
-{
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (src);
- GList *list;
-
- for (list = spider->links; list; list = list->next) {
- GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
-
- if (conn->src == src) {
- return conn;
- }
- }
- return NULL;
-}
-
-/* get a new link from those two elements
- * search first; if none is found, create a new one */
-static GstSpiderConnection *
-gst_spider_link_get (GstSpiderIdentity * src)
-{
- GstSpiderConnection *ret;
-
- if ((ret = gst_spider_link_find (src)) != NULL) {
- return ret;
- }
- return gst_spider_link_new (src);
-}
-
-void
-gst_spider_identity_plug (GstSpiderIdentity * ident)
-{
- GstSpider *spider;
- const GList *padlist;
- GstPadDirection dir;
- GstSpiderConnection *conn;
-
- /* checks */
- g_return_if_fail (ident != NULL);
- g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
- spider = GST_SPIDER (GST_ELEMENT_PARENT (ident));
- g_assert (spider != NULL);
- g_assert (GST_IS_SPIDER (spider));
-
- /* return if we're already plugged */
- if (ident->plugged)
- return;
-
- /* check if there is at least one element factory that can handle the
- identity's src caps */
- {
- GstCaps *src_caps = gst_pad_get_caps (ident->src);
-
- if (!gst_caps_is_empty (src_caps) && !gst_caps_is_any (src_caps)) {
- GList *factories;
- GstPadTemplate *padtemp;
- gboolean found = FALSE;
-
- factories = spider->factories;
- while (factories) {
- if ((padtemp =
- gst_autoplug_can_connect_src (factories->data, src_caps))) {
- GST_DEBUG ("can connect src to %s pad template: %" GST_PTR_FORMAT,
- GST_PLUGIN_FEATURE_NAME (factories->data),
- gst_pad_template_get_caps (padtemp));
- found = TRUE;
- }
- factories = factories->next;
- }
- if (!found) {
- const char *mime;
-
- mime = gst_structure_get_name (gst_caps_get_structure (src_caps, 0));
-
- GST_ELEMENT_ERROR (spider, STREAM, CODEC_NOT_FOUND,
- (_("There is no element present to handle the stream's mime type %s."), mime), (NULL));
- gst_caps_unref (src_caps);
- return;
- }
- }
- gst_caps_unref (src_caps);
- }
-
- /* get the direction of our ident */
- if (GST_PAD_PEER (ident->sink)) {
- if (GST_PAD_PEER (ident->src)) {
- /* Hey, the ident is linked on both sides */
- g_warning ("Trying to autoplug a linked element. Aborting...");
- return;
- } else {
- dir = GST_PAD_SINK;
- }
- } else {
- if (GST_PAD_PEER (ident->src)) {
- dir = GST_PAD_SRC;
- } else {
- /* the ident isn't linked on either side */
- g_warning ("Trying to autoplug an unlinked element. Aborting...");
- return;
- }
- }
-
- /* now iterate all possible pads and link when needed */
- padlist = GST_ELEMENT (spider)->pads;
- for (; padlist; padlist = padlist->next) {
- GstPad *otherpad;
- GstSpiderIdentity *peer;
-
- g_assert (GST_IS_PAD (padlist->data));
- otherpad = (GstPad *) GST_GPAD_REALPAD (padlist->data);
- peer = (GstSpiderIdentity *) GST_PAD_PARENT (otherpad);
- /* we only want to link to the other side */
- if (dir != GST_PAD_DIRECTION (otherpad)) {
- /* we only link to plugged in elements */
- if (peer->plugged == TRUE) {
- /* plug in the right direction */
- if (dir == GST_PAD_SINK) {
- conn = gst_spider_link_get (peer);
- } else {
- conn = gst_spider_link_get (ident);
- }
- if ((GstElement *) spider->sink_ident == conn->current) {
- gst_spider_plug (conn);
- }
- }
- }
- }
-
- ident->plugged = TRUE;
-}
-
-void
-gst_spider_identity_unplug (GstSpiderIdentity * ident)
-{
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (ident);
- GList *list;
-
- for (list = spider->links; list; list = list->next) {
- GstSpiderConnection *conn = list->data;
-
- if (conn->src == ident) {
- g_list_delete_link (spider->links, list);
- gst_spider_link_destroy (conn);
- }
- }
- ident->plugged = FALSE;
-}
-
-/* links src to sink using the elementfactories in plugpath
- * plugpath will be removed afterwards */
-static GstPadLinkReturn
-gst_spider_create_and_plug (GstSpiderConnection * conn, GList * plugpath)
-{
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
- GList *endelements = NULL, *templist = NULL;
- GstElement *element;
-
- /* exit if plugging is already done */
- if ((GstElement *) conn->src == conn->current)
- return GST_PAD_LINK_DONE;
-
- /* try to shorten the list at the end and not duplicate link code */
- if (plugpath != NULL) {
- templist = g_list_last (plugpath);
- element = (GstElement *) conn->src;
- while ((plugpath != NULL)
- && (element =
- gst_spider_find_element_to_plug (element,
- (GstElementFactory *) plugpath->data, GST_PAD_SINK))) {
- GList *cur = templist;
-
- endelements = g_list_prepend (endelements, element);
- templist = g_list_previous (templist);
- g_list_delete_link (cur, cur);
- }
- }
-
- /* do the linking */
- while (conn->current != (GstElement *) (endelements ==
- NULL ? conn->src : endelements->data)) {
- /* get sink element to plug, src is conn->current */
- if (plugpath == NULL) {
- element =
- (GstElement *) (endelements == NULL ? conn->src : endelements->data);
- } else {
- element =
- gst_element_factory_create ((GstElementFactory *) plugpath->data,
- NULL);
- GST_DEBUG
- ("Adding element %s of type %s and syncing state with autoplugger",
- GST_ELEMENT_NAME (element), GST_PLUGIN_FEATURE_NAME (plugpath->data));
- gst_bin_add (GST_BIN (spider), element);
- }
- /* insert and link new element */
- if (gst_element_link (conn->current, element)) {
- gst_element_sync_state_with_parent (element);
- } else {
- /* check if the src has SOMETIMES templates. If so, link a callback */
- GList *templs = gst_element_get_pad_template_list (conn->current);
-
- /* remove element that couldn't be linked, if it wasn't the endpoint */
- if (element != (GstElement *) conn->src)
- gst_bin_remove (GST_BIN (spider), element);
-
- for (; templs; templs = templs->next) {
- GstPadTemplate *templ = (GstPadTemplate *) templs->data;
-
- if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC)
- && (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES)) {
- GST_DEBUG ("adding callback to link element %s to %s",
- GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
- conn->signal_id =
- g_signal_connect (G_OBJECT (conn->current), "new_pad",
- G_CALLBACK (gst_spider_link_sometimes), conn);
- g_list_free (plugpath);
- return GST_PAD_LINK_DELAYED;
- }
- }
- GST_DEBUG ("no chance to link element %s to %s",
- GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
- g_list_free (plugpath);
- return GST_PAD_LINK_REFUSED;
- }
- GST_DEBUG ("coupling %s and %s",
- GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (conn->current));
- gst_spider_link_add (conn, element);
- if (plugpath != NULL)
- plugpath = g_list_delete_link (plugpath, plugpath);
- }
-
- /* ref all elements at the end */
- while (endelements) {
- gst_spider_link_add (conn, endelements->data);
- endelements = g_list_delete_link (endelements, endelements);
- }
-
- return GST_PAD_LINK_DONE;
-}
-
-/* checks, if src is already linked to an element from factory fac on direction dir */
-static GstElement *
-gst_spider_find_element_to_plug (GstElement * src, GstElementFactory * fac,
- GstPadDirection dir)
-{
- GList *padlist = GST_ELEMENT_PADS (src);
-
- for (; padlist; padlist = padlist->next) {
- GstPad *pad = (GstPad *) GST_PAD_REALIZE (padlist->data);
-
- /* is the pad on the right side and is it linked? */
- if ((GST_PAD_DIRECTION (pad) == dir)
- && (pad = (GstPad *) (GST_RPAD_PEER (pad)))) {
- /* is the element the pad is linked to of the right type? */
- GstElement *element = GST_PAD_PARENT (pad);
-
- if (G_TYPE_FROM_INSTANCE (element) ==
- gst_element_factory_get_element_type (fac)) {
- return element;
- }
- }
- }
-
- return NULL;
-}
-
-/* try to establish the link */
-static GstPadLinkReturn
-gst_spider_plug (GstSpiderConnection * conn)
-{
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
-
- if ((GstElement *) conn->src == conn->current)
- return GST_PAD_LINK_DONE;
- if ((GstElement *) spider->sink_ident == conn->current)
- return gst_spider_plug_from_srcpad (conn, spider->sink_ident->src);
- g_warning
- ("FIXME: autoplugging only possible from GstSpiderIdentity conn->sink yet (yep, that's technical)\n");
- return GST_PAD_LINK_REFUSED;
-}
-
-/* try to establish the link using this pad */
-static GstPadLinkReturn
-gst_spider_plug_from_srcpad (GstSpiderConnection * conn, GstPad * srcpad)
-{
- GstElement *element;
- GList *plugpath;
- gboolean result = TRUE;
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
- GstElement *startelement = conn->current;
- GstCaps *caps1;
- GstCaps *caps2;
-
- g_assert ((GstElement *) GST_OBJECT_PARENT (srcpad) == conn->current);
- GST_DEBUG ("trying to plug from %s:%s to %s",
- GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (conn->src));
-
- /* see if they match already */
- if (gst_pad_link (srcpad, conn->src->sink)) {
- GST_DEBUG ("%s:%s and %s:%s can link directly",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (conn->src->sink));
- gst_pad_unlink (srcpad, conn->src->sink);
- gst_spider_create_and_plug (conn, NULL);
- return GST_PAD_LINK_OK;
- }
-
- /* find a path from src to sink */
- caps1 = gst_pad_get_caps (srcpad);
- caps2 = gst_pad_get_caps (conn->src->sink);
- plugpath = gst_autoplug_sp (caps1, caps2, spider->factories);
- gst_caps_unref (caps1);
- gst_caps_unref (caps2);
-
- /* prints out the path that was found for plugging */
- /* g_print ("found path from %s to %s:\n", GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
- templist = plugpath;
- while (templist)
- {
- g_print("%s\n", GST_OBJECT_NAME (templist->data));
- templist = g_list_next (templist);
- } */
-
- /* if there is no way to plug: return */
- if (plugpath == NULL) {
- GST_DEBUG ("no chance to plug from %s to %s",
- GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
- return GST_PAD_LINK_REFUSED;
- }
- GST_DEBUG ("found a link that needs %d elements", g_list_length (plugpath));
-
- /* now remove non-needed elements from the beginning of the path
- * alter src to point to the new element where we need to start
- * plugging and alter the plugpath to represent the elements, that must be plugged
- */
- element = conn->current;
- while ((plugpath != NULL)
- && (element =
- gst_spider_find_element_to_plug (element,
- (GstElementFactory *) plugpath->data, GST_PAD_SRC))) {
- gst_spider_link_add (conn, element);
- plugpath = g_list_delete_link (plugpath, plugpath);
- }
-
- GST_DEBUG ("%d elements must be inserted to establish the link",
- g_list_length (plugpath));
- /* create the elements and plug them */
- result = gst_spider_create_and_plug (conn, plugpath);
-
- /* reset the "current" element */
- if (result == GST_PAD_LINK_REFUSED) {
- gst_spider_link_reset (conn, startelement);
- }
-
- return result;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_spider_debug, "spider", 0,
- "spider autoplugging element");
-
- if (!gst_element_register (plugin, "spider", GST_RANK_NONE, GST_TYPE_SPIDER))
- return FALSE;
- if (!gst_element_register (plugin, "spideridentity", GST_RANK_NONE,
- GST_TYPE_SPIDER_IDENTITY))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "gstspider",
- "a 1:n autoplugger",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2002 Wim Taymans <wtay@chello.be>
- *
- * gstspider.h: Header for GstSpider object
- *
- * 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_SPIDER_H__
-#define __GST_SPIDER_H__
-
-#include <gst/gst.h>
-#include "gstspideridentity.h"
-
-G_BEGIN_DECLS
-
-GST_DEBUG_CATEGORY_EXTERN(gst_spider_debug);
-
-/*
- * Theory of operation:
- * When connecting a sink to a source, GstSpiderConnections are used to keep track
- * of the current status of the link. sink -> src is the path we intend to
- * plug. current is how far we've come. If current equals
- * - NULL, there is no possible path,
- * - src, the link is established.
- * - sink, it wasn't tried to establish a link.
- * - something else, we have come that far while plugging.
- * signal_id is used to remember the signal_id when we are waiting for a "new_pad"
- * callback during link.
- * When a path is established, the elements in the path (excluding sink and src)
- * are refcounted once for every path.
- * A GstSpider keeps a list of all GstSpiderConnections in it.
- */
-typedef struct {
- GstSpiderIdentity *src;
- /* dunno if the path should stay here or if its too much load.
- * it's at least easier then always searching it */
- GList *path;
- GstElement *current;
- gulong signal_id;
-} GstSpiderConnection;
-
-#define GST_TYPE_SPIDER \
- (gst_spider_get_type())
-#define GST_SPIDER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPIDER,GstSpider))
-#define GST_SPIDER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPIDER,GstSpiderClass))
-#define GST_IS_SPIDER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPIDER))
-#define GST_IS_SPIDER_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPIDER))
-
-typedef struct _GstSpider GstSpider;
-typedef struct _GstSpiderClass GstSpiderClass;
-
-struct _GstSpider {
- GstBin parent;
-
- GstSpiderIdentity *sink_ident;
- GList * factories; /* factories to use for plugging */
-
- GList * links; /* GStSpiderConnection list of all links */
-};
-
-struct _GstSpiderClass {
- GstBinClass parent_class;
-};
-
-/* default initialization stuff */
-GType gst_spider_get_type (void);
-
-/* private link functions to be called by GstSpiderIdentity */
-void gst_spider_identity_plug (GstSpiderIdentity *ident);
-void gst_spider_identity_unplug (GstSpiderIdentity *ident);
-
-G_END_DECLS
-
-#endif /* __GST_SPIDER_H__ */
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2002 Wim Taymans <wtay@chello.be>
- *
- * gstspideridentity.c: identity element for the spider autoplugger
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gstspideridentity.h"
-#include "gstspider.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_spider_identity_debug);
-#define GST_CAT_DEFAULT gst_spider_identity_debug
-
-static GstElementDetails gst_spider_identity_details =
-GST_ELEMENT_DETAILS ("SpiderIdentity",
- "Generic",
- "Link between spider and outside elements",
- "Benjamin Otte <in7y118@public.uni-hamburg.de>");
-
-
-/* generic templates
- * delete me when meging with spider.c
- */
-static GstStaticPadTemplate spider_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate spider_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-/* SpiderIdentity signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0
- /* FILL ME */
-};
-
-/* GObject stuff */
-static void gst_spider_identity_class_init (GstSpiderIdentityClass * klass);
-static void gst_spider_identity_init (GstSpiderIdentity * spider_identity);
-
-/* functions set in pads, elements and stuff */
-static void gst_spider_identity_chain (GstPad * pad, GstBuffer * buf);
-static GstElementStateReturn gst_spider_identity_change_state (GstElement *
- element);
-static GstPadLinkReturn gst_spider_identity_link (GstPad * pad,
- const GstCaps * caps);
-static GstCaps *gst_spider_identity_getcaps (GstPad * pad);
-
-/* loop functions */
-static void gst_spider_identity_dumb_loop (GstSpiderIdentity * ident);
-static void gst_spider_identity_src_loop (GstSpiderIdentity * ident);
-static void gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *
- ident);
-
-static gboolean gst_spider_identity_handle_src_event (GstPad * pad,
- GstEvent * event);
-
-/* other functions */
-static void gst_spider_identity_start_type_finding (GstSpiderIdentity * ident);
-
-static GstElementClass *parent_class = NULL;
-
-/* no signals
-static guint gst_spider_identity_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_spider_identity_get_type (void)
-{
- static GType spider_identity_type = 0;
-
- if (!spider_identity_type) {
- static const GTypeInfo spider_identity_info = {
- sizeof (GstSpiderIdentityClass), NULL,
- NULL,
- (GClassInitFunc) gst_spider_identity_class_init,
- NULL,
- NULL,
- sizeof (GstSpiderIdentity),
- 0,
- (GInstanceInitFunc) gst_spider_identity_init,
- };
-
- spider_identity_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstSpiderIdentity",
- &spider_identity_info, 0);
- GST_DEBUG_CATEGORY_INIT (gst_spider_identity_debug, "spideridentity", 0,
- "spider autoplugging proxy element");
- }
- return spider_identity_type;
-}
-
-static void
-gst_spider_identity_class_init (GstSpiderIdentityClass * klass)
-{
- GstElementClass *gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
- /* add our two pad templates */
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&spider_src_factory));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&spider_sink_factory));
- gst_element_class_set_details (gstelement_class,
- &gst_spider_identity_details);
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_spider_identity_change_state);
- gstelement_class->request_new_pad =
- GST_DEBUG_FUNCPTR (gst_spider_identity_request_new_pad);
-}
-
-static void
-gst_spider_identity_init (GstSpiderIdentity * ident)
-{
- /* sink */
- ident->sink =
- gst_pad_new_from_template (gst_static_pad_template_get
- (&spider_sink_factory), "sink");
- gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
- gst_pad_set_link_function (ident->sink,
- GST_DEBUG_FUNCPTR (gst_spider_identity_link));
- gst_pad_set_getcaps_function (ident->sink,
- GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
- /* src */
- ident->src =
- gst_pad_new_from_template (gst_static_pad_template_get
- (&spider_src_factory), "src");
- gst_element_add_pad (GST_ELEMENT (ident), ident->src);
- gst_pad_set_link_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_link));
- gst_pad_set_getcaps_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
- gst_pad_set_event_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
-
- /* variables */
- ident->plugged = FALSE;
-}
-
-static void
-gst_spider_identity_chain (GstPad * pad, GstBuffer * buf)
-{
- GstSpiderIdentity *ident;
-
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
-
- if (buf == NULL)
- return;
-
- ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
-
- if (GST_IS_EVENT (buf)) {
- GST_DEBUG_OBJECT (ident, "spider identity received event %p", buf);
- /* start hack for current event stuff here */
- /* check for unlinked elements and send them the EOS event, too */
- if (GST_EVENT_TYPE (GST_EVENT (buf)) == GST_EVENT_EOS) {
- GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (ident);
- GList *list = spider->links;
-
- while (list) {
- GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
-
- list = g_list_next (list);
- if (conn->current != (GstElement *) conn->src) {
- GstEvent *event;
-
- event = gst_event_new (GST_EVENT_EOS);
- GST_DEBUG_OBJECT (ident,
- "sending EOS event %p to unconnected element %s from %s",
- event, GST_ELEMENT_NAME (conn->src), GST_ELEMENT_NAME (ident));
- gst_pad_push (conn->src->src, GST_DATA (event));
- gst_element_set_eos (GST_ELEMENT (conn->src));
- }
- }
- }
- /* end hack for current event stuff here */
- GST_DEBUG_OBJECT (ident,
- "calling default handler for event %p on pad %s:%s",
- buf, GST_DEBUG_PAD_NAME (pad));
-
- gst_pad_event_default (pad, GST_EVENT (buf));
- return;
- }
-
- if ((ident->src != NULL) && (GST_PAD_PEER (ident->src) != NULL)) {
- GST_LOG_OBJECT (ident, "pushing buffer %p "
- "(refcount %d, size %u, offset %" G_GINT64_FORMAT ") ",
- buf, GST_BUFFER_REFCOUNT_VALUE (buf),
- GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf));
- gst_pad_push (ident->src, GST_DATA (buf));
- } else if (GST_IS_BUFFER (buf)) {
- gst_buffer_unref (buf);
- }
-}
-
-GstSpiderIdentity *
-gst_spider_identity_new_src (gchar * name)
-{
- GstSpiderIdentity *ret =
- (GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
- /* set the right functions */
- gst_element_set_loop_function (GST_ELEMENT (ret), (GstElementLoopFunction)
- GST_DEBUG_FUNCPTR (gst_spider_identity_src_loop));
-
- return ret;
-}
-
-GstSpiderIdentity *
-gst_spider_identity_new_sink (gchar * name)
-{
- GstSpiderIdentity *ret =
- (GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
-
- /* set the right functions */
- gst_element_set_loop_function (GST_ELEMENT (ret), (GstElementLoopFunction)
- GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
-
- return ret;
-}
-
-/* shamelessly stolen from gstqueue.c to get proxy links */
-static GstPadLinkReturn
-gst_spider_identity_link (GstPad * pad, const GstCaps * caps)
-{
- GstSpiderIdentity *spider_identity =
- GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
- GstPad *otherpad;
-
- if (pad == spider_identity->src) {
- otherpad = spider_identity->sink;
- if (GST_PAD_PEER (otherpad) == NULL)
- return GST_PAD_LINK_DELAYED;
- } else {
- otherpad = spider_identity->src;
- }
-
- g_return_val_if_fail (otherpad != NULL, GST_PAD_LINK_REFUSED);
-
- return gst_pad_try_set_caps (otherpad, caps);
-}
-
-static GstCaps *
-gst_spider_identity_getcaps (GstPad * pad)
-{
- GstSpiderIdentity *ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
- GstPad *otherpad;
-
- if (pad == ident->src)
- otherpad = ident->sink;
- else
- otherpad = ident->src;
-
- if (otherpad != NULL) {
- if (GST_PAD_PEER (otherpad)) {
- GstCaps *ret = gst_pad_get_allowed_caps (otherpad);
-
- if (ident->caps) {
- GstCaps *ret2 = gst_caps_intersect (ident->caps, ret);
-
- gst_caps_unref (ret);
- ret = ret2;
- }
- return ret;
- }
- }
- if (ident->caps)
- return gst_caps_copy (ident->caps);
-
- return gst_caps_new_any ();
-}
-
-GstPad *
-gst_spider_identity_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name)
-{
- GstSpiderIdentity *ident;
-
- /*checks */
- g_return_val_if_fail (templ != NULL, NULL);
- g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
- ident = GST_SPIDER_IDENTITY (element);
- g_return_val_if_fail (ident != NULL, NULL);
- g_return_val_if_fail (GST_IS_SPIDER_IDENTITY (ident), NULL);
-
- switch (GST_PAD_TEMPLATE_DIRECTION (templ)) {
- case GST_PAD_SINK:
- if (ident->sink != NULL)
- break;
- /* sink */
- GST_DEBUG ("element %s requests new sink pad", GST_ELEMENT_NAME (ident));
- ident->sink =
- gst_pad_new_from_template (gst_static_pad_template_get
- (&spider_sink_factory), "sink");
- gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
- gst_pad_set_link_function (ident->sink,
- GST_DEBUG_FUNCPTR (gst_spider_identity_link));
- gst_pad_set_getcaps_function (ident->sink,
- GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
- return ident->sink;
- case GST_PAD_SRC:
- /* src */
- if (ident->src != NULL)
- break;
- GST_DEBUG ("element %s requests new src pad", GST_ELEMENT_NAME (ident));
- ident->src =
- gst_pad_new_from_template (gst_static_pad_template_get
- (&spider_src_factory), "src");
- gst_element_add_pad (GST_ELEMENT (ident), ident->src);
- gst_pad_set_link_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_link));
- gst_pad_set_getcaps_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
- gst_pad_set_event_function (ident->src,
- GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
- return ident->src;
- default:
- break;
- }
-
- GST_DEBUG ("element %s requested a new pad but none could be created",
- GST_ELEMENT_NAME (ident));
- return NULL;
-}
-
-/* this function has to
- * - start the autoplugger
- * - start type finding
- * ...
- */
-static GstElementStateReturn
-gst_spider_identity_change_state (GstElement * element)
-{
- GstSpiderIdentity *ident;
- GstSpider *spider;
- GstElementStateReturn ret = GST_STATE_SUCCESS;
-
- /* element check */
- ident = GST_SPIDER_IDENTITY (element);
- g_return_val_if_fail (ident != NULL, GST_STATE_FAILURE);
- g_return_val_if_fail (GST_IS_SPIDER_IDENTITY (ident), GST_STATE_FAILURE);
-
- switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_PAUSED_TO_READY:
- gst_caps_replace (&ident->caps, NULL);
- break;
- case GST_STATE_PAUSED_TO_PLAYING:
- /* autoplugger check */
- spider = GST_SPIDER (GST_ELEMENT_PARENT (ident));
- g_return_val_if_fail (spider != NULL, GST_STATE_FAILURE);
- g_return_val_if_fail (GST_IS_SPIDER (spider), GST_STATE_FAILURE);
-
- /* start typefinding or plugging */
- if ((GST_RPAD_PEER (ident->sink) != NULL)
- && (GST_RPAD_PEER (ident->src) == NULL)) {
- GstCaps *caps =
- gst_pad_get_caps ((GstPad *) GST_PAD_PEER (ident->sink));
- if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) {
- gst_spider_identity_start_type_finding (ident);
- gst_caps_unref (caps);
- break;
- } else {
- gst_spider_identity_plug (ident);
- }
- gst_caps_unref (caps);
- }
- /* autoplug on src */
- if ((GST_RPAD_PEER (ident->src) != NULL)
- && (GST_RPAD_PEER (ident->sink) == NULL)) {
- gst_spider_identity_plug (ident);
- }
- default:
- break;
- }
-
- if ((ret != GST_STATE_FAILURE)
- && (GST_ELEMENT_CLASS (parent_class)->change_state))
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
-
- return ret;
-}
-
-static void
-gst_spider_identity_start_type_finding (GstSpiderIdentity * ident)
-{
-/* GstElement* typefind;
- gchar *name;*/
- gboolean restart = FALSE;
-
- GST_DEBUG ("element %s starts typefinding", GST_ELEMENT_NAME (ident));
- if (GST_STATE (GST_ELEMENT_PARENT (ident)) == GST_STATE_PLAYING) {
- gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)),
- GST_STATE_PAUSED);
- restart = TRUE;
- }
-
- gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction)
- GST_DEBUG_FUNCPTR (gst_spider_identity_sink_loop_type_finding));
-
- if (restart) {
- gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)),
- GST_STATE_PLAYING);
- }
-}
-
-/* since we can't set the loop function to NULL if there's a cothread for us,
- * we have to use a dumb one
- */
-static void
-gst_spider_identity_dumb_loop (GstSpiderIdentity * ident)
-{
- GstBuffer *buf;
-
- g_return_if_fail (ident != NULL);
- g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
- g_assert (ident->sink != NULL);
-
- buf = GST_BUFFER (gst_pad_pull (ident->sink));
-
- gst_spider_identity_chain (ident->sink, buf);
-}
-
-/* do nothing until we're linked - then disable yourself
- */
-static void
-gst_spider_identity_src_loop (GstSpiderIdentity * ident)
-{
- /* checks - disable for speed */
- g_return_if_fail (ident != NULL);
- g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
-
- /* we don't want a loop function if we're plugged */
- if (ident->sink && GST_PAD_PEER (ident->sink)) {
- gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction)
- GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
- gst_spider_identity_dumb_loop (ident);
- return;
- }
- gst_element_interrupt (GST_ELEMENT (ident));
-}
-
-/* This loop function is only needed when typefinding.
- */
-typedef struct
-{
- GstBuffer *buffer;
- guint best_probability;
- GstCaps *caps;
-}
-SpiderTypeFind;
-static guint8 *
-spider_find_peek (gpointer data, gint64 offset, guint size)
-{
- SpiderTypeFind *find = (SpiderTypeFind *) data;
- gint64 buffer_offset = GST_BUFFER_OFFSET_IS_VALID (find->buffer) ?
- GST_BUFFER_OFFSET (find->buffer) : 0;
-
- if (offset >= buffer_offset
- && offset + size <= buffer_offset + GST_BUFFER_SIZE (find->buffer)) {
- GST_LOG ("peek %" G_GINT64_FORMAT ", %u successful", offset, size);
- return GST_BUFFER_DATA (find->buffer) + offset - buffer_offset;
- } else {
- GST_LOG ("peek %" G_GINT64_FORMAT ", %u failed", offset, size);
- return NULL;
- }
-}
-static void
-spider_find_suggest (gpointer data, guint probability, const GstCaps * caps)
-{
- SpiderTypeFind *find = (SpiderTypeFind *) data;
-
- GST_INFO ("suggest %u, %" GST_PTR_FORMAT, probability, caps);
- if (probability > find->best_probability) {
- gst_caps_replace (&find->caps, gst_caps_copy (caps));
- find->best_probability = probability;
- }
-}
-static void
-gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity * ident)
-{
- GstData *data;
- GstTypeFind gst_find;
- SpiderTypeFind find;
- GList *walk, *type_list = NULL;
-
- g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
-
- data = gst_pad_pull (ident->sink);
- if (!GST_IS_BUFFER (data)) {
- gst_spider_identity_chain (ident->sink, GST_BUFFER (data));
- return;
- }
-
- find.buffer = GST_BUFFER (data);
- /* maybe there are already valid caps now? */
- find.caps = gst_pad_get_allowed_caps (ident->sink);
- if (!gst_caps_is_empty (find.caps) && !gst_caps_is_any (find.caps)) {
- goto plug;
- } else {
- gst_caps_unref (find.caps);
- find.caps = NULL;
- }
-
- /* now do the actual typefinding with the supplied buffer */
- walk = type_list = gst_type_find_factory_get_list ();
-
- find.best_probability = 0;
- find.caps = NULL;
- gst_find.data = &find;
- gst_find.get_length = NULL;
- gst_find.peek = spider_find_peek;
- gst_find.suggest = spider_find_suggest;
- while (walk) {
- GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
-
- GST_DEBUG ("trying typefind function %s",
- GST_PLUGIN_FEATURE_NAME (factory));
- gst_type_find_factory_call_function (factory, &gst_find);
- if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
- goto plug;
- walk = g_list_next (walk);
- }
- if (find.best_probability > 0)
- goto plug;
- GST_ELEMENT_ERROR (ident, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
- find.buffer = GST_BUFFER (gst_event_new (GST_EVENT_EOS));
-
-end:
- /* remove loop function */
- gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction)
- GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
-
- /* push the buffer */
- gst_spider_identity_chain (ident->sink, find.buffer);
-
- return;
-
-plug:
- GST_INFO ("typefind function found caps");
- ident->caps = find.caps;
- if (GST_PAD_IS_LINKED (ident->src)) {
- GstPadLinkReturn ret;
-
- ret = gst_pad_try_set_caps (ident->src, find.caps);
- if (GST_PAD_LINK_FAILED (ret)) {
- g_critical ("could not set caps on spideridentity src pad\n");
- }
- }
- GST_LOG_OBJECT (ident, "spider starting caps: %" GST_PTR_FORMAT, find.caps);
- if (type_list)
- g_list_free (type_list);
-
- gst_spider_identity_plug (ident);
-
- goto end;
-}
-
-static gboolean
-gst_spider_identity_handle_src_event (GstPad * pad, GstEvent * event)
-{
- gboolean res = TRUE;
- GstSpiderIdentity *ident;
-
- GST_DEBUG ("spider_identity src_event");
-
- ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH:
- case GST_EVENT_SEEK:
- default:
- res = gst_pad_event_default (pad, event);
- break;
- }
-
- return res;
-}
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
- * 2002 Wim Taymans <wtay@chello.be>
- *
- * gstspideridentity.h:
- *
- * 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_SPIDER_IDENTITY_H__
-#define __GST_SPIDER_IDENTITY_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_SPIDER_IDENTITY \
- (gst_spider_identity_get_type())
-#define GST_SPIDER_IDENTITY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPIDER_IDENTITY,GstSpiderIdentity))
-#define GST_SPIDER_IDENTITY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPIDER_IDENTITY,GstSpiderIdentityClass))
-#define GST_IS_SPIDER_IDENTITY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPIDER_IDENTITY))
-#define GST_IS_SPIDER_IDENTITY_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPIDER_IDENTITY))
-
-typedef struct _GstSpiderIdentity GstSpiderIdentity;
-typedef struct _GstSpiderIdentityClass GstSpiderIdentityClass;
-
-struct _GstSpiderIdentity {
- GstElement element;
-
- /* sink and source */
- GstPad *sink;
- GstPad *src;
-
- /* plugged into autoplugger yet? */
- gboolean plugged;
-
- /* Caps from typefinding */
- GstCaps *caps;
-};
-
-struct _GstSpiderIdentityClass {
- GstElementClass parent_class;
-
-};
-
-GType gst_spider_identity_get_type (void);
-
-GstSpiderIdentity* gst_spider_identity_new_sink (gchar *name);
-GstSpiderIdentity* gst_spider_identity_new_src (gchar *name);
-GstPad* gst_spider_identity_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name);
-
-G_END_DECLS
-
-#endif /* __GST_SPIDER_IDENTITY_H__ */
+++ /dev/null
-#include <stdlib.h>
-#include <gst/gst.h>
-
-/* returns all factories which have a maximum of maxtemplates GstPadTemplates in direction dir
- */
-GList *
-gst_factories_at_most_templates (GList * factories, GstPadDirection dir,
- guint maxtemplates)
-{
- GList *ret = NULL;
-
- while (factories) {
- guint count = 0;
- GList *templs = ((GstElementFactory *) factories->data)->padtemplates;
-
- while (templs) {
- if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
- count++;
- }
- if (count > maxtemplates)
- break;
- templs = g_list_next (templs);
- }
- if (count <= maxtemplates)
- ret = g_list_prepend (ret, factories->data);
-
- factories = g_list_next (factories);
- }
- return ret;
-}
-
-static void
-property_change_callback (GObject * object, GstObject * orig,
- GParamSpec * pspec)
-{
- GValue value = { 0, }; /* the important thing is that value.type = 0 */
- gchar *str = 0;
-
- if (pspec->flags & G_PARAM_READABLE) {
- g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- g_object_get_property (G_OBJECT (orig), pspec->name, &value);
- if (G_IS_PARAM_SPEC_STRING (pspec))
- str = g_value_dup_string (&value);
- else if (G_IS_PARAM_SPEC_ENUM (pspec))
- str = g_strdup_printf ("%d", g_value_get_enum (&value));
- else if (G_IS_PARAM_SPEC_INT64 (pspec))
- str = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (&value));
- else
- str = g_strdup_value_contents (&value);
-
- g_print ("%s: %s = %s\n", GST_OBJECT_NAME (orig), pspec->name, str);
- g_free (str);
- g_value_unset (&value);
- } else {
- g_warning ("Parameter not readable. What's up with that?");
- }
-}
-
-static void
-error_callback (GObject * object, GstObject * orig, gchar * error)
-{
- g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
-}
-
-/*
- * Test program for the autoplugger.
- * Uses new API extensions (2002-01-28), too.
- *
- * USAGE: spidertest <mediafile>
- * If mediafile can be recognized, xvideo and oss audio output are tried.
- */
-int
-main (int argc, char *argv[])
-{
- GstElement *bin, *filesrc, *decoder, *osssink, *videosink;
- GList *facs;
-
- if (argc < 2) {
- g_print ("usage: %s <file>\n", argv[0]);
- exit (-1);
- }
-
- gst_init (&argc, &argv);
-
- /* create a new bin to hold the elements */
- bin = gst_pipeline_new ("pipeline");
- g_signal_connect (bin, "deep_notify", G_CALLBACK (property_change_callback),
- NULL);
- g_signal_connect (bin, "error", G_CALLBACK (error_callback), NULL);
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
-
- /* now it's time to get the decoder */
- decoder = gst_element_factory_make ("spider", "spider");
- if (!decoder) {
- g_print ("could not find plugin \"spider\"\n");
- exit (-2);
- }
-
- /* only use decoding plugins */
- g_object_get (decoder, "factories", &facs, NULL);
- facs = gst_factories_at_most_templates (facs, GST_PAD_SINK, 1);
- g_object_set (decoder, "factories", facs, NULL);
-
- /* create video and audio sink */
- osssink = gst_element_factory_make ("osssink", "audio");
- videosink = gst_element_factory_make ("xvideosink", "video");
-
- if ((!osssink) || (!videosink)) {
- g_print ("could not create output plugins\n");
- exit (-3);
- }
-
- /* add objects to the main pipeline */
- gst_bin_add (GST_BIN (bin), filesrc);
- gst_bin_add (GST_BIN (bin), decoder);
- gst_bin_add (GST_BIN (bin), osssink);
- gst_bin_add (GST_BIN (bin), videosink);
-
- /* link objects */
- if (!(gst_element_link (filesrc, decoder) &&
- gst_element_link (decoder, osssink) &&
- gst_element_link (decoder, videosink))) {
- g_print ("the pipeline could not be linked\n");
- exit (-4);
- }
-
-/* gst_bin_use_clock (GST_BIN (bin), gst_system_clock_obtain ());*/
-
- /* start playing */
- gst_element_set_state (bin, GST_STATE_PLAYING);
-
- while (gst_bin_iterate (GST_BIN (bin)));
-
- exit (0);
-}