This is a megapatch with the following changes:
[platform/upstream/gstreamer.git] / gst / elements / gsttee.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *
5  * gsttee.c: Tee element, one in N out
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "gsttee.h"
24
25
26 GstElementDetails gst_tee_details = {
27   "Tee pipe fitting",
28   "Tee",
29   "1-to-N pipe fitting",
30   VERSION,
31   "Erik Walthinsen <omega@cse.ogi.edu>\n"
32   "Wim Taymans <wim.taymans@chello.be>",
33   "(C) 1999, 2000",
34 };
35
36 /* Tee signals and args */
37 enum {
38   /* FILL ME */
39   LAST_SIGNAL
40 };
41
42 enum {
43   ARG_0,
44   ARG_NUM_PADS,
45   /* FILL ME */
46 };
47
48 static GstPadFactory tee_src_factory = {
49   "src%d",
50   GST_PAD_FACTORY_SRC,
51   GST_PAD_FACTORY_REQUEST,
52   NULL,                 /* no caps */
53   NULL,
54 };
55
56
57 static void     gst_tee_class_init      (GstTeeClass *klass);
58 static void     gst_tee_init            (GstTee *tee);
59
60 static GstPad*  gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp);
61
62 static void     gst_tee_get_arg         (GtkObject *object, GtkArg *arg, guint id);
63
64 static void     gst_tee_chain           (GstPad *pad, GstBuffer *buf);
65
66 static GstElementClass *parent_class = NULL;
67 //static guint gst_tee_signals[LAST_SIGNAL] = { 0 };
68 static GstPadTemplate *gst_tee_src_template;
69
70 GtkType
71 gst_tee_get_type(void) {
72   static GtkType tee_type = 0;
73
74   if (!tee_type) {
75     static const GtkTypeInfo tee_info = {
76       "GstTee",
77       sizeof(GstTee),
78       sizeof(GstTeeClass),
79       (GtkClassInitFunc)gst_tee_class_init,
80       (GtkObjectInitFunc)gst_tee_init,
81       (GtkArgSetFunc)NULL,
82       (GtkArgGetFunc)NULL,
83       (GtkClassInitFunc)NULL,
84     };
85     tee_type = gtk_type_unique (GST_TYPE_ELEMENT, &tee_info);
86   }
87   return tee_type;
88 }
89
90 static void
91 gst_tee_class_init (GstTeeClass *klass) 
92 {
93   GtkObjectClass *gtkobject_class;
94   GstElementClass *gstelement_class;
95
96   gtkobject_class = (GtkObjectClass*)klass;
97   gstelement_class = (GstElementClass*)klass;
98
99   parent_class = gtk_type_class(GST_TYPE_ELEMENT);
100
101   gtk_object_add_arg_type ("GstTee::num_pads", GTK_TYPE_INT,
102                             GTK_ARG_READABLE, ARG_NUM_PADS);
103
104   gtkobject_class->get_arg = gst_tee_get_arg;
105
106   gstelement_class->request_new_pad = gst_tee_request_new_pad;
107 }
108
109 static void 
110 gst_tee_init (GstTee *tee) 
111 {
112   tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
113   gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
114   gst_pad_set_chain_function (tee->sinkpad, gst_tee_chain);
115
116   tee->numsrcpads = 0;
117   tee->srcpads = NULL;
118 }
119
120 static GstPad*
121 gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ) 
122 {
123   gchar *name;
124   GstPad *srcpad;
125   GstTee *tee;
126
127   g_return_val_if_fail (GST_IS_TEE (element), NULL);
128
129   if (templ->direction != GST_PAD_SRC) {
130     g_warning ("gsttee: request new pad that is not a SRC pad\n");
131     return NULL;
132   }
133
134   tee = GST_TEE (element);
135
136   name = g_strdup_printf ("src%d",tee->numsrcpads);
137   
138   srcpad = gst_pad_new_from_template (templ, name);
139   gst_element_add_pad (GST_ELEMENT (tee), srcpad);
140   
141   tee->srcpads = g_slist_prepend (tee->srcpads, srcpad);
142   tee->numsrcpads++;
143   
144   return srcpad;
145 }
146
147 static void
148 gst_tee_get_arg (GtkObject *object, GtkArg *arg, guint id)
149 {
150   GstTee *tee;
151
152   /* it's not null if we got it, but it might not be ours */
153   g_return_if_fail (GST_IS_TEE (object));
154
155   tee = GST_TEE (object);
156
157   switch(id) {
158     case ARG_NUM_PADS:
159       GTK_VALUE_INT (*arg) = tee->numsrcpads;
160       break;
161     default:
162       break;
163   }
164 }
165
166 /**
167  * gst_tee_chain:
168  * @pad: the pad to follow
169  * @buf: the buffer to pass
170  *
171  * Chain a buffer on a pad.
172  */
173 static void 
174 gst_tee_chain (GstPad *pad, GstBuffer *buf) 
175 {
176   GstTee *tee;
177   GSList *srcpads;
178   int i;
179
180   g_return_if_fail (pad != NULL);
181   g_return_if_fail (GST_IS_PAD (pad));
182   g_return_if_fail (buf != NULL);
183
184   tee = GST_TEE (gst_pad_get_parent (pad));
185   gst_trace_add_entry (NULL, 0, buf, "tee buffer");
186
187   for (i=0; i<tee->numsrcpads-1; i++)
188     gst_buffer_ref (buf);
189   
190   srcpads = tee->srcpads;
191   while (srcpads) {
192     gst_pad_push (GST_PAD (srcpads->data), buf);
193     srcpads = g_slist_next (srcpads);
194   }
195 }
196
197 gboolean
198 gst_tee_factory_init (GstElementFactory *factory)
199 {
200   gst_tee_src_template = gst_padtemplate_new (&tee_src_factory);
201   gst_elementfactory_add_padtemplate (factory, gst_tee_src_template);
202
203   return TRUE;
204 }
205