diff --git a/gst/Makefile.am b/gst/Makefile.am index 94aadcec7a..607ab9e805 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -33,7 +33,6 @@ libgst_la_SOURCES = \ gstplugin.c \ gstprops.c \ gstscheduler.c \ - gsttee.c \ gstthread.c \ gsttrace.c \ gsttype.c \ @@ -88,7 +87,6 @@ libgstinclude_HEADERS = \ gstplugin.h \ gstprops.h \ gstscheduler.h \ - gsttee.h \ gstthread.h \ gsttrace.h \ gsttype.h \ diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am index 2078a21cda..3a140270c3 100644 --- a/gst/elements/Makefile.am +++ b/gst/elements/Makefile.am @@ -22,6 +22,7 @@ libgstelements_la_SOURCES = \ gstfdsink.c \ gstpipefilter.c \ gstqueue.c \ + gsttee.c \ gsttypefind.c \ gstsinesrc.c \ $(GSTHTTPSRC) @@ -39,6 +40,7 @@ noinst_HEADERS = \ gstfdsink.h \ gstpipefilter.h \ gstqueue.h \ + gsttee.h \ gsttypefind.h \ gstsinesrc.h diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c index 15091a005e..da7c0f6f6f 100644 --- a/gst/elements/gstelements.c +++ b/gst/elements/gstelements.c @@ -23,19 +23,20 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "gstasyncdisksrc.h" +#include "gstaudiosink.h" +#include "gstaudiosrc.h" +#include "gstdisksrc.h" +#include "gstidentity.h" +#include "gstfakesink.h" +#include "gstfakesrc.h" +#include "gstfdsink.h" +#include "gstfdsrc.h" +#include "gstpipefilter.h" +#include "gstqueue.h" +#include "gstsinesrc.h" +#include "gsttee.h" +#include "gsttypefind.h" #if HAVE_LIBGHTTP #include @@ -62,6 +63,7 @@ static struct _elements_entry _elements[] = { { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, { "queue", gst_queue_get_type, &gst_queue_details, NULL }, { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL }, + { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, { "typefind", gst_typefind_get_type, &gst_typefind_details, NULL }, #if HAVE_LIBGHTTP diff --git a/gst/elements/gsttee.c b/gst/elements/gsttee.c new file mode 100644 index 0000000000..ffb0ed032f --- /dev/null +++ b/gst/elements/gsttee.c @@ -0,0 +1,205 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gsttee.c: Tee element, one in N out + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gsttee.h" + + +GstElementDetails gst_tee_details = { + "Tee pipe fitting", + "Tee", + "1-to-N pipe fitting", + VERSION, + "Erik Walthinsen \n" + "Wim Taymans ", + "(C) 1999, 2000", +}; + +/* Tee signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_NUM_PADS, + /* FILL ME */ +}; + +static GstPadFactory tee_src_factory = { + "src%d", + GST_PAD_FACTORY_SRC, + GST_PAD_FACTORY_REQUEST, + NULL, /* no caps */ + NULL, +}; + + +static void gst_tee_class_init (GstTeeClass *klass); +static void gst_tee_init (GstTee *tee); + +static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp); + +static void gst_tee_get_arg (GtkObject *object, GtkArg *arg, guint id); + +static void gst_tee_chain (GstPad *pad, GstBuffer *buf); + +static GstElementClass *parent_class = NULL; +//static guint gst_tee_signals[LAST_SIGNAL] = { 0 }; +static GstPadTemplate *gst_tee_src_template; + +GtkType +gst_tee_get_type(void) { + static GtkType tee_type = 0; + + if (!tee_type) { + static const GtkTypeInfo tee_info = { + "GstTee", + sizeof(GstTee), + sizeof(GstTeeClass), + (GtkClassInitFunc)gst_tee_class_init, + (GtkObjectInitFunc)gst_tee_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + tee_type = gtk_type_unique (GST_TYPE_ELEMENT, &tee_info); + } + return tee_type; +} + +static void +gst_tee_class_init (GstTeeClass *klass) +{ + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); + + gtk_object_add_arg_type ("GstTee::num_pads", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_NUM_PADS); + + gtkobject_class->get_arg = gst_tee_get_arg; + + gstelement_class->request_new_pad = gst_tee_request_new_pad; +} + +static void +gst_tee_init (GstTee *tee) +{ + tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); + gst_pad_set_chain_function (tee->sinkpad, gst_tee_chain); + + tee->numsrcpads = 0; + tee->srcpads = NULL; +} + +static GstPad* +gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ) +{ + gchar *name; + GstPad *srcpad; + GstTee *tee; + + g_return_val_if_fail (GST_IS_TEE (element), NULL); + + if (templ->direction != GST_PAD_SRC) { + g_warning ("gsttee: request new pad that is not a SRC pad\n"); + return NULL; + } + + tee = GST_TEE (element); + + name = g_strdup_printf ("src%d",tee->numsrcpads); + + srcpad = gst_pad_new_from_template (templ, name); + gst_element_add_pad (GST_ELEMENT (tee), srcpad); + + tee->srcpads = g_slist_prepend (tee->srcpads, srcpad); + tee->numsrcpads++; + + return srcpad; +} + +static void +gst_tee_get_arg (GtkObject *object, GtkArg *arg, guint id) +{ + GstTee *tee; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_TEE (object)); + + tee = GST_TEE (object); + + switch(id) { + case ARG_NUM_PADS: + GTK_VALUE_INT (*arg) = tee->numsrcpads; + break; + default: + break; + } +} + +/** + * gst_tee_chain: + * @pad: the pad to follow + * @buf: the buffer to pass + * + * Chain a buffer on a pad. + */ +static void +gst_tee_chain (GstPad *pad, GstBuffer *buf) +{ + GstTee *tee; + GSList *srcpads; + int i; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + tee = GST_TEE (pad->parent); + gst_trace_add_entry (NULL, 0, buf, "tee buffer"); + + for (i=0; inumsrcpads-1; i++) + gst_buffer_ref (buf); + + srcpads = tee->srcpads; + while (srcpads) { + gst_pad_push (GST_PAD (srcpads->data), buf); + srcpads = g_slist_next (srcpads); + } +} + +gboolean +gst_tee_factory_init (GstElementFactory *factory) +{ + gst_tee_src_template = gst_padtemplate_new (&tee_src_factory); + gst_elementfactory_add_padtemplate (factory, gst_tee_src_template); + + return TRUE; +} + diff --git a/gst/gsttee.h b/gst/elements/gsttee.h similarity index 91% rename from gst/gsttee.h rename to gst/elements/gsttee.h index 3d9a90a7cd..f7f3979d22 100644 --- a/gst/gsttee.h +++ b/gst/elements/gsttee.h @@ -24,7 +24,7 @@ #ifndef __GST_TEE_H__ #define __GST_TEE_H__ -#include "gstelement.h" +#include #ifdef __cplusplus @@ -62,10 +62,7 @@ struct _GstTeeClass { GtkType gst_tee_get_type (void); -GstElement* gst_tee_new (gchar *name); - -gchar* gst_tee_new_pad (GstTee *tee); -void gst_tee_chain (GstPad *pad, GstBuffer *buf); +gboolean gst_tee_factory_init (GstElementFactory *factory); #ifdef __cplusplus } diff --git a/gst/gst.c b/gst/gst.c index 633fba5b94..1b98c5dbe9 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -31,7 +31,6 @@ #include "gstbin.h" #include "gstpipeline.h" #include "gstthread.h" -#include "gsttee.h" @@ -77,7 +76,6 @@ gst_init (int *argc, char **argv[]) gst_elementfactory_new ("bin", gst_bin_get_type (), &gst_bin_details); gst_elementfactory_new ("pipeline", gst_pipeline_get_type (), &gst_pipeline_details); gst_elementfactory_new ("thread", gst_thread_get_type (), &gst_thread_details); - gst_elementfactory_new ("tee", gst_tee_get_type (), &gst_tee_details); _gst_trace_on = 0; if (_gst_trace_on) { diff --git a/gst/gst.h b/gst/gst.h index a47b2e240d..a2d98c6a7c 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/gst/gstelement.c b/gst/gstelement.c index 31c4cb2192..5f24ac9c83 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -303,6 +303,75 @@ gst_element_get_padtemplate_list (GstElement *element) return oclass->elementfactory->padtemplates; } +/** + * gst_element_get_padtemplate_by_name: + * @element: element to get padtemplate of + * @name: the name of the padtemplate to get. + * + * Retrieve a padtemplate from this element with the + * given name. + * + * Returns: the padtemplate with the given name + */ +GstPadTemplate* +gst_element_get_padtemplate_by_name (GstElement *element, const guchar *name) +{ + GList *padlist; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (name != NULL, NULL); + + padlist = gst_element_get_padtemplate_list (element); + + while (padlist) { + GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data; + + if (!strcmp (padtempl->name_template, name)) + return padtempl; + + padlist = g_list_next (padlist); + } + + return NULL; +} + +GstPad* +gst_element_request_pad (GstElement *element, GstPadTemplate *temp) +{ + GstPad *newpad = NULL; + GstElementClass *oclass; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (temp != NULL, NULL); + + /* call the state change function so it can set the state */ + oclass = GST_ELEMENT_CLASS (GTK_OBJECT (element)->klass); + if (oclass->request_new_pad) + newpad = (oclass->request_new_pad)(element, temp); + + return newpad; +} + +GstPad* +gst_element_request_pad_by_name (GstElement *element, const gchar *name) +{ + GstPadTemplate *templ; + GstPad *pad; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (name != NULL, NULL); + + templ = gst_element_get_padtemplate_by_name (element, name); + g_return_val_if_fail (templ != NULL, NULL); + + pad = gst_element_request_pad (element, templ); + + return pad; +} + /** * gst_element_connect: * @src: element containing source pad diff --git a/gst/gstelement.h b/gst/gstelement.h index 28e739e848..7f463a39b8 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -158,7 +158,9 @@ struct _GstElementClass { void (*eos) (GstElement *element); /* change the element state */ - GstElementStateReturn (*change_state) (GstElement *element); + GstElementStateReturn (*change_state) (GstElement *element); + /* request a new pad */ + GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *temp); /* create or read XML representation of self */ xmlNodePtr (*save_thyself) (GstElement *element, xmlNodePtr parent); @@ -201,9 +203,13 @@ void gst_element_add_pad (GstElement *element, GstPad *pad); GstPad* gst_element_get_pad (GstElement *element, const gchar *name); GList* gst_element_get_pad_list (GstElement *element); GList* gst_element_get_padtemplate_list (GstElement *element); +GstPadTemplate* gst_element_get_padtemplate_by_name (GstElement *element, const guchar *name); void gst_element_add_ghost_pad (GstElement *element, GstPad *pad); void gst_element_remove_ghost_pad (GstElement *element, GstPad *pad); +GstPad* gst_element_request_pad (GstElement *element, GstPadTemplate *temp); +GstPad* gst_element_request_pad_by_name (GstElement *element, const gchar *name); + void gst_element_connect (GstElement *src, const gchar *srcpadname, GstElement *dest, const gchar *destpadname); void gst_element_disconnect (GstElement *src, const gchar *srcpadname, @@ -234,12 +240,12 @@ GstElementFactory* gst_elementfactory_new (const gchar *name,GtkType type, GstElementDetails *details); void gst_elementfactory_destroy (GstElementFactory *elementfactory); -void gst_elementfactory_add_padtemplate (GstElementFactory *elementfactory, - GstPadTemplate *temp); - GstElementFactory* gst_elementfactory_find (const gchar *name); GList* gst_elementfactory_get_list (void); +void gst_elementfactory_add_padtemplate (GstElementFactory *elementfactory, + GstPadTemplate *temp); + gboolean gst_elementfactory_can_src_caps (GstElementFactory *factory, GstCaps *caps); gboolean gst_elementfactory_can_sink_caps (GstElementFactory *factory, diff --git a/gst/gstpad.c b/gst/gstpad.c index b2ce44fb9b..727988e628 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -977,10 +977,26 @@ gst_padtemplate_save_thyself (GstPadTemplate *pad, xmlNodePtr parent) { xmlNodePtr subtree; GList *caps; + guchar *presence; xmlNewChild(parent,NULL,"nametemplate", pad->name_template); xmlNewChild(parent,NULL,"direction", (pad->direction == GST_PAD_SINK? "sink":"src")); - xmlNewChild(parent,NULL,"presence", (pad->presence == GST_PAD_ALWAYS? "always":"sometimes")); + + switch (pad->presence) { + case GST_PAD_ALWAYS: + presence = "always"; + break; + case GST_PAD_SOMETIMES: + presence = "sometimes"; + break; + case GST_PAD_REQUEST: + presence = "request"; + break; + default: + presence = "unknown"; + break; + } + xmlNewChild(parent,NULL,"presence", presence); caps = pad->caps; while (caps) { @@ -1034,6 +1050,9 @@ gst_padtemplate_load_thyself (xmlNodePtr parent) else if (!strcmp(value, "sometimes")) { factory->presence = GST_PAD_SOMETIMES; } + else if (!strcmp(value, "request")) { + factory->presence = GST_PAD_REQUEST; + } g_free (value); } else if (!strcmp(field->name, "caps")) { diff --git a/gst/gstpad.h b/gst/gstpad.h index d3e0008f38..795eed1029 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -137,6 +137,7 @@ struct _GstPadClass { typedef enum { GST_PAD_ALWAYS, GST_PAD_SOMETIMES, + GST_PAD_REQUEST, } GstPadPresence; struct _GstPadTemplate { @@ -162,6 +163,7 @@ typedef GstPadFactoryEntry GstPadFactory[]; #define GST_PAD_FACTORY_ALWAYS GINT_TO_POINTER(GST_PAD_ALWAYS) #define GST_PAD_FACTORY_SOMETIMES GINT_TO_POINTER(GST_PAD_SOMETIMES) +#define GST_PAD_FACTORY_REQUEST GINT_TO_POINTER(GST_PAD_REQUEST) #define GST_PAD_FACTORY_SRC GINT_TO_POINTER(GST_PAD_SRC) #define GST_PAD_FACTORY_SINK GINT_TO_POINTER(GST_PAD_SINK) diff --git a/gst/gsttee.c b/gst/gsttee.c deleted file mode 100644 index be5ed0213f..0000000000 --- a/gst/gsttee.c +++ /dev/null @@ -1,155 +0,0 @@ -/* GStreamer - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000 Wim Taymans - * - * gsttee.c: Tee element, one in N out - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gst_private.h" - -#include "gsttee.h" - - -GstElementDetails gst_tee_details = { - "Tee pipe fitting", - "Tee", - "1-to-N pipe fitting", - VERSION, - "Erik Walthinsen ", - "(C) 1999", -}; - -/* Tee signals and args */ -enum { - /* FILL ME */ - LAST_SIGNAL -}; - -enum { - ARG_0, - /* FILL ME */ -}; - - -static void gst_tee_class_init(GstTeeClass *klass); -static void gst_tee_init(GstTee *tee); - -//static xmlNodePtr gst_tee_save_thyself(GstElement *element,xmlNodePtr parent); - -static GstElementClass *parent_class = NULL; -//static guint gst_tee_signals[LAST_SIGNAL] = { 0 }; - -GtkType -gst_tee_get_type(void) { - static GtkType tee_type = 0; - - if (!tee_type) { - static const GtkTypeInfo tee_info = { - "GstTee", - sizeof(GstTee), - sizeof(GstTeeClass), - (GtkClassInitFunc)gst_tee_class_init, - (GtkObjectInitFunc)gst_tee_init, - (GtkArgSetFunc)NULL, - (GtkArgGetFunc)NULL, - (GtkClassInitFunc)NULL, - }; - tee_type = gtk_type_unique(GST_TYPE_ELEMENT,&tee_info); - } - return tee_type; -} - -static void -gst_tee_class_init(GstTeeClass *klass) { - GstElementClass *gstelement_class; - - gstelement_class = (GstElementClass*)klass; - - parent_class = gtk_type_class(GST_TYPE_ELEMENT); -} - -static void gst_tee_init(GstTee *tee) { - tee->sinkpad = gst_pad_new("sink",GST_PAD_SINK); - gst_element_add_pad(GST_ELEMENT(tee),tee->sinkpad); - gst_pad_set_chain_function(tee->sinkpad,gst_tee_chain); - - tee->numsrcpads = 0; - tee->srcpads = NULL; -} - -/** - * gst_tee_new: - * @name: the name of the new tee - * - * Create a new tee element. - * - * Returns: the new tee element - */ -GstElement *gst_tee_new(gchar *name) { - return gst_elementfactory_make ("tee", name); -} - -/** - * gst_tee_new_pad: - * @tee: the tee to create the new pad on - * - * Create a new pad on a given tee. - * - * Returns: the name of the new pad - */ -gchar *gst_tee_new_pad(GstTee *tee) { - gchar *name; - GstPad *srcpad; - - g_return_val_if_fail(tee != NULL, NULL); - g_return_val_if_fail(GST_IS_TEE(tee), NULL); - - name = g_strdup_printf("src%d",tee->numsrcpads); - srcpad = gst_pad_new(name,GST_PAD_SRC); - gst_element_add_pad(GST_ELEMENT(tee),srcpad); - tee->srcpads = g_slist_prepend(tee->srcpads,srcpad); - tee->numsrcpads++; - return name; -} - -/** - * gst_tee_chain: - * @pad: the pad to follow - * @buf: the buffer to pass - * - * Chain a buffer on a pad. - */ -void gst_tee_chain(GstPad *pad,GstBuffer *buf) { - GstTee *tee; - GSList *srcpads; - int i; - - g_return_if_fail(pad != NULL); - g_return_if_fail(GST_IS_PAD(pad)); - g_return_if_fail(buf != NULL); - - tee = GST_TEE(pad->parent); - gst_trace_add_entry(NULL,0,buf,"tee buffer"); - for (i=0;inumsrcpads-1;i++) - gst_buffer_ref(buf); - srcpads = tee->srcpads; - while (srcpads) { - gst_pad_push(GST_PAD(srcpads->data),buf); - srcpads = g_slist_next(srcpads); - } -} diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am index 2078a21cda..3a140270c3 100644 --- a/plugins/elements/Makefile.am +++ b/plugins/elements/Makefile.am @@ -22,6 +22,7 @@ libgstelements_la_SOURCES = \ gstfdsink.c \ gstpipefilter.c \ gstqueue.c \ + gsttee.c \ gsttypefind.c \ gstsinesrc.c \ $(GSTHTTPSRC) @@ -39,6 +40,7 @@ noinst_HEADERS = \ gstfdsink.h \ gstpipefilter.h \ gstqueue.h \ + gsttee.h \ gsttypefind.h \ gstsinesrc.h diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index 15091a005e..da7c0f6f6f 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -23,19 +23,20 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "gstasyncdisksrc.h" +#include "gstaudiosink.h" +#include "gstaudiosrc.h" +#include "gstdisksrc.h" +#include "gstidentity.h" +#include "gstfakesink.h" +#include "gstfakesrc.h" +#include "gstfdsink.h" +#include "gstfdsrc.h" +#include "gstpipefilter.h" +#include "gstqueue.h" +#include "gstsinesrc.h" +#include "gsttee.h" +#include "gsttypefind.h" #if HAVE_LIBGHTTP #include @@ -62,6 +63,7 @@ static struct _elements_entry _elements[] = { { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, { "queue", gst_queue_get_type, &gst_queue_details, NULL }, { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL }, + { "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init }, { "typefind", gst_typefind_get_type, &gst_typefind_details, NULL }, #if HAVE_LIBGHTTP diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c new file mode 100644 index 0000000000..ffb0ed032f --- /dev/null +++ b/plugins/elements/gsttee.c @@ -0,0 +1,205 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gsttee.c: Tee element, one in N out + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gsttee.h" + + +GstElementDetails gst_tee_details = { + "Tee pipe fitting", + "Tee", + "1-to-N pipe fitting", + VERSION, + "Erik Walthinsen \n" + "Wim Taymans ", + "(C) 1999, 2000", +}; + +/* Tee signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_NUM_PADS, + /* FILL ME */ +}; + +static GstPadFactory tee_src_factory = { + "src%d", + GST_PAD_FACTORY_SRC, + GST_PAD_FACTORY_REQUEST, + NULL, /* no caps */ + NULL, +}; + + +static void gst_tee_class_init (GstTeeClass *klass); +static void gst_tee_init (GstTee *tee); + +static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp); + +static void gst_tee_get_arg (GtkObject *object, GtkArg *arg, guint id); + +static void gst_tee_chain (GstPad *pad, GstBuffer *buf); + +static GstElementClass *parent_class = NULL; +//static guint gst_tee_signals[LAST_SIGNAL] = { 0 }; +static GstPadTemplate *gst_tee_src_template; + +GtkType +gst_tee_get_type(void) { + static GtkType tee_type = 0; + + if (!tee_type) { + static const GtkTypeInfo tee_info = { + "GstTee", + sizeof(GstTee), + sizeof(GstTeeClass), + (GtkClassInitFunc)gst_tee_class_init, + (GtkObjectInitFunc)gst_tee_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + tee_type = gtk_type_unique (GST_TYPE_ELEMENT, &tee_info); + } + return tee_type; +} + +static void +gst_tee_class_init (GstTeeClass *klass) +{ + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); + + gtk_object_add_arg_type ("GstTee::num_pads", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_NUM_PADS); + + gtkobject_class->get_arg = gst_tee_get_arg; + + gstelement_class->request_new_pad = gst_tee_request_new_pad; +} + +static void +gst_tee_init (GstTee *tee) +{ + tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); + gst_pad_set_chain_function (tee->sinkpad, gst_tee_chain); + + tee->numsrcpads = 0; + tee->srcpads = NULL; +} + +static GstPad* +gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ) +{ + gchar *name; + GstPad *srcpad; + GstTee *tee; + + g_return_val_if_fail (GST_IS_TEE (element), NULL); + + if (templ->direction != GST_PAD_SRC) { + g_warning ("gsttee: request new pad that is not a SRC pad\n"); + return NULL; + } + + tee = GST_TEE (element); + + name = g_strdup_printf ("src%d",tee->numsrcpads); + + srcpad = gst_pad_new_from_template (templ, name); + gst_element_add_pad (GST_ELEMENT (tee), srcpad); + + tee->srcpads = g_slist_prepend (tee->srcpads, srcpad); + tee->numsrcpads++; + + return srcpad; +} + +static void +gst_tee_get_arg (GtkObject *object, GtkArg *arg, guint id) +{ + GstTee *tee; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_TEE (object)); + + tee = GST_TEE (object); + + switch(id) { + case ARG_NUM_PADS: + GTK_VALUE_INT (*arg) = tee->numsrcpads; + break; + default: + break; + } +} + +/** + * gst_tee_chain: + * @pad: the pad to follow + * @buf: the buffer to pass + * + * Chain a buffer on a pad. + */ +static void +gst_tee_chain (GstPad *pad, GstBuffer *buf) +{ + GstTee *tee; + GSList *srcpads; + int i; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + tee = GST_TEE (pad->parent); + gst_trace_add_entry (NULL, 0, buf, "tee buffer"); + + for (i=0; inumsrcpads-1; i++) + gst_buffer_ref (buf); + + srcpads = tee->srcpads; + while (srcpads) { + gst_pad_push (GST_PAD (srcpads->data), buf); + srcpads = g_slist_next (srcpads); + } +} + +gboolean +gst_tee_factory_init (GstElementFactory *factory) +{ + gst_tee_src_template = gst_padtemplate_new (&tee_src_factory); + gst_elementfactory_add_padtemplate (factory, gst_tee_src_template); + + return TRUE; +} + diff --git a/plugins/elements/gsttee.h b/plugins/elements/gsttee.h new file mode 100644 index 0000000000..f7f3979d22 --- /dev/null +++ b/plugins/elements/gsttee.h @@ -0,0 +1,72 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gsttee.h: Header for GstTee element + * + * 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_TEE_H__ +#define __GST_TEE_H__ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern GstElementDetails gst_tee_details; + +#define GST_TYPE_TEE \ + (gst_tee_get_type()) +#define GST_TEE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_TEE,GstTee)) +#define GST_TEE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_TEE,GstTeeClass)) +#define GST_IS_TEE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_TEE)) +#define GST_IS_TEE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_TEE)) + +typedef struct _GstTee GstTee; +typedef struct _GstTeeClass GstTeeClass; + +struct _GstTee { + GstElement element; + + GstPad *sinkpad; + + gint numsrcpads; + GSList *srcpads; +}; + +struct _GstTeeClass { + GstElementClass parent_class; +}; + +GtkType gst_tee_get_type (void); + +gboolean gst_tee_factory_init (GstElementFactory *factory); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_TEE_H__ */