valve: gst_element_class_set_details => gst_element_class_set_details_simple
[platform/upstream/gstreamer.git] / plugins / elements / gstvalve.c
1 /*
2  * Farsight Voice+Video library
3  *
4  *  Copyright 2007 Collabora Ltd, 
5  *  Copyright 2007 Nokia Corporation
6  *   @author: Olivier Crete <olivier.crete@collabora.co.uk>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 /**
25  * SECTION:element-valve
26  *
27  * The valve is a simple element that drops buffers when the #GstValve::drop
28  * property is set to %TRUE and lets then through otherwise.
29  *
30  * Any downstream error received while the #GstValve::drop property is %FALSE
31  * is ignored. So downstream element can be set to  %GST_STATE_NULL and removed,
32  * without using pad blocking.
33  *
34  * Last reviewed on 2008-02-10 (0.10.11)
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "gstvalve.h"
42
43 #include <string.h>
44
45 GST_DEBUG_CATEGORY (valve_debug);
46 #define GST_CAT_DEFAULT (valve_debug)
47
48 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
49     GST_PAD_SINK,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS_ANY);
52
53 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
54     GST_PAD_SRC,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS_ANY);
57
58 /* Valve signals and args */
59 enum
60 {
61   /* FILL ME */
62   LAST_SIGNAL
63 };
64
65 enum
66 {
67   ARG_0,
68   ARG_DROP,
69 };
70
71
72
73
74 static void gst_valve_set_property (GObject * object,
75     guint prop_id, const GValue * value, GParamSpec * pspec);
76 static void gst_valve_get_property (GObject * object,
77     guint prop_id, GValue * value, GParamSpec * pspec);
78
79 static gboolean gst_valve_event (GstPad * pad, GstEvent * event);
80 static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
81     guint size, GstCaps * caps, GstBuffer ** buf);
82 static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer);
83 static GstCaps *gst_valve_getcaps (GstPad * pad);
84
85 static void
86 _do_init (GType type)
87 {
88   GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
89 }
90
91 GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement,
92     GST_TYPE_ELEMENT, _do_init);
93
94 static void
95 gst_valve_base_init (gpointer klass)
96 {
97   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
98
99   gst_element_class_add_pad_template (element_class,
100       gst_static_pad_template_get (&srctemplate));
101   gst_element_class_add_pad_template (element_class,
102       gst_static_pad_template_get (&sinktemplate));
103
104   gst_element_class_set_details_simple (element_class, "Valve element",
105       "Filter",
106       "This element drops all packets when drop is TRUE",
107       "Olivier Crete <olivier.crete@collabora.co.uk>");
108 }
109
110 static void
111 gst_valve_class_init (GstValveClass * klass)
112 {
113   GObjectClass *gobject_class;
114
115   gobject_class = (GObjectClass *) klass;
116
117   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_valve_set_property);
118   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_valve_get_property);
119
120   g_object_class_install_property (gobject_class, ARG_DROP,
121       g_param_spec_boolean ("drop",
122           "Drops all buffers if TRUE",
123           "If this property if TRUE, the element will drop all buffers, if its FALSE, it will let them through",
124           FALSE, G_PARAM_READWRITE));
125
126   parent_class = g_type_class_peek_parent (klass);
127 }
128
129 static void
130 gst_valve_init (GstValve * valve, GstValveClass * klass)
131 {
132   valve->drop = FALSE;
133   valve->discont = FALSE;
134
135   valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
136   gst_pad_set_getcaps_function (valve->srcpad,
137       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
138   gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
139
140   valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
141   gst_pad_set_chain_function (valve->sinkpad,
142       GST_DEBUG_FUNCPTR (gst_valve_chain));
143   gst_pad_set_event_function (valve->sinkpad,
144       GST_DEBUG_FUNCPTR (gst_valve_event));
145   gst_pad_set_bufferalloc_function (valve->sinkpad,
146       GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc));
147   gst_pad_set_getcaps_function (valve->sinkpad,
148       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
149   gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
150 }
151
152
153 static void
154 gst_valve_set_property (GObject * object,
155     guint prop_id, const GValue * value, GParamSpec * pspec)
156 {
157   GstValve *valve = GST_VALVE (object);
158
159   switch (prop_id) {
160     default:
161       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
162       break;
163     case ARG_DROP:
164       GST_OBJECT_LOCK (object);
165       valve->drop = g_value_get_boolean (value);
166       GST_OBJECT_UNLOCK (object);
167       break;
168   }
169 }
170
171 static void
172 gst_valve_get_property (GObject * object,
173     guint prop_id, GValue * value, GParamSpec * pspec)
174 {
175   GstValve *valve = GST_VALVE (object);
176
177   switch (prop_id) {
178     default:
179       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
180       break;
181     case ARG_DROP:
182       GST_OBJECT_LOCK (object);
183       g_value_set_boolean (value, valve->drop);
184       GST_OBJECT_UNLOCK (object);
185       break;
186   }
187 }
188
189 static GstFlowReturn
190 gst_valve_chain (GstPad * pad, GstBuffer * buffer)
191 {
192   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
193   GstFlowReturn ret = GST_FLOW_OK;
194   gboolean drop;
195
196   GST_OBJECT_LOCK (GST_OBJECT (valve));
197   drop = valve->drop;
198
199   if (!drop && valve->discont) {
200     buffer = gst_buffer_make_metadata_writable (buffer);
201     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
202     valve->discont = FALSE;
203   }
204   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
205
206   if (drop)
207     gst_buffer_unref (buffer);
208   else
209     ret = gst_pad_push (valve->srcpad, buffer);
210
211
212   GST_OBJECT_LOCK (GST_OBJECT (valve));
213   if (valve->drop)
214     ret = GST_FLOW_OK;
215   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
216
217   gst_object_unref (valve);
218
219   return ret;
220 }
221
222
223 static gboolean
224 gst_valve_event (GstPad * pad, GstEvent * event)
225 {
226   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
227   gboolean ret = TRUE;
228   gboolean drop;
229
230   GST_OBJECT_LOCK (GST_OBJECT (valve));
231   drop = valve->drop;
232   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
233
234   if (drop)
235     gst_event_unref (event);
236   else
237     ret = gst_pad_push_event (valve->srcpad, event);
238
239   GST_OBJECT_LOCK (GST_OBJECT (valve));
240   if (valve->drop)
241     ret = TRUE;
242   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
243
244   gst_object_unref (valve);
245   return ret;
246 }
247
248 static GstFlowReturn
249 gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
250     GstCaps * caps, GstBuffer ** buf)
251 {
252   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
253   GstFlowReturn ret = GST_FLOW_OK;
254   gboolean drop;
255
256   GST_OBJECT_LOCK (GST_OBJECT (valve));
257   drop = valve->drop;
258   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
259
260   if (drop)
261     *buf = NULL;
262   else
263     ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf);
264
265   GST_OBJECT_LOCK (GST_OBJECT (valve));
266   if (valve->drop)
267     ret = GST_FLOW_OK;
268   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
269
270   gst_object_unref (valve);
271
272   return ret;
273 }
274
275 static GstCaps *
276 gst_valve_getcaps (GstPad * pad)
277 {
278   GstValve *valve = GST_VALVE (gst_pad_get_parent (pad));
279   GstCaps *caps;
280
281   if (pad == valve->sinkpad)
282     caps = gst_pad_peer_get_caps (valve->srcpad);
283   else
284     caps = gst_pad_peer_get_caps (valve->sinkpad);
285
286   if (caps == NULL)
287     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
288
289   gst_object_unref (valve);
290
291   return caps;
292 }
293
294
295 static gboolean
296 plugin_init (GstPlugin * plugin)
297 {
298   return gst_element_register (plugin, "valve",
299       GST_RANK_MARGINAL, GST_TYPE_VALVE);
300 }
301
302 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
303     GST_VERSION_MINOR,
304     "valve",
305     "Valve",
306     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)