Added mthodes to request an element to create pads: gst_element_request_pad*

Original commit message from CVS:
Added mthodes to request an element to create pads: gst_element_request_pad*
This can be used to construct a tee and a muxer/mixer/aggregator element.
Moved the tee element to elements/ because it can now be handled with the
new pad request features.
The padfactory also has some changes: a pad can now be of presence REQUEST,
which means that the pad can be requested from this plugin (doh).
This commit is contained in:
Wim Taymans 2001-01-18 23:46:15 +00:00
parent 82769bcae9
commit 90f82b6840
16 changed files with 619 additions and 196 deletions

View file

@ -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 \

View file

@ -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

View file

@ -23,19 +23,20 @@
#include <gst/gst.h>
#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 <gsttypefind.h>
#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 <gsthttpsrc.h>
@ -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

205
gst/elements/gsttee.c Normal file
View file

@ -0,0 +1,205 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wim.taymans@chello.be>
*
* 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 <omega@cse.ogi.edu>\n"
"Wim Taymans <wim.taymans@chello.be>",
"(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; i<tee->numsrcpads-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;
}

View file

@ -24,7 +24,7 @@
#ifndef __GST_TEE_H__
#define __GST_TEE_H__
#include "gstelement.h"
#include <gst/gst.h>
#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
}

View file

@ -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) {

View file

@ -45,7 +45,6 @@
#include <gst/gstutils.h>
#include <gst/gsttrace.h>
#include <gst/gstxml.h>
#include <gst/gsttee.h>
#include <gst/cothreads.h>
#include <gst/gstparse.h>

View file

@ -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

View file

@ -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,

View file

@ -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")) {

View file

@ -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)

View file

@ -1,155 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* 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 <omega@cse.ogi.edu>",
"(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;i<tee->numsrcpads-1;i++)
gst_buffer_ref(buf);
srcpads = tee->srcpads;
while (srcpads) {
gst_pad_push(GST_PAD(srcpads->data),buf);
srcpads = g_slist_next(srcpads);
}
}

View file

@ -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

View file

@ -23,19 +23,20 @@
#include <gst/gst.h>
#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 <gsttypefind.h>
#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 <gsthttpsrc.h>
@ -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

205
plugins/elements/gsttee.c Normal file
View file

@ -0,0 +1,205 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wim.taymans@chello.be>
*
* 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 <omega@cse.ogi.edu>\n"
"Wim Taymans <wim.taymans@chello.be>",
"(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; i<tee->numsrcpads-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;
}

72
plugins/elements/gsttee.h Normal file
View file

@ -0,0 +1,72 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* 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 <gst/gst.h>
#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__ */