1 /* GStreamer LADSPA sink category
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
4 * 2003 Andy Wingo <wingo at pobox.com>
5 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com> (fakesink)
6 * Copyright (C) 2013 Juan Manuel Borges Caño <juanmabcmail@gmail.com>
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., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "gstladspasink.h"
29 #include "gstladspa.h"
30 #include "gstladspautils.h"
31 #include <gst/base/gstbasetransform.h>
32
33 #include <string.h>
34
35 GST_DEBUG_CATEGORY_EXTERN (ladspa_debug);
36 #define GST_CAT_DEFAULT ladspa_debug
37
38 #define GST_LADSPA_SINK_CLASS_TAGS "Sink/Audio/LADSPA"
39 #define GST_LADSPA_SINK_DEFAULT_SYNC TRUE
40 #define GST_LADSPA_SINK_DEFAULT_CAN_ACTIVATE_PUSH TRUE
41 #define GST_LADSPA_SINK_DEFAULT_CAN_ACTIVATE_PULL FALSE
42 #define GST_LADSPA_SINK_DEFAULT_NUM_BUFFERS -1
43
44 enum
45 {
46 GST_LADSPA_SINK_PROP_0,
47 GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PUSH,
48 GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PULL,
49 GST_LADSPA_SINK_PROP_NUM_BUFFERS,
50 GST_LADSPA_SINK_PROP_LAST
51 };
52
53 static GstLADSPASinkClass *gst_ladspa_sink_type_parent_class = NULL;
54
55 /*
56 * Boilerplates BaseSink add pad.
57 */
58 void
gst_my_base_sink_class_add_pad_template(GstBaseSinkClass * base_class,GstCaps * sinkcaps)59 gst_my_base_sink_class_add_pad_template (GstBaseSinkClass * base_class,
60 GstCaps * sinkcaps)
61 {
62 GstElementClass *elem_class = GST_ELEMENT_CLASS (base_class);
63 GstPadTemplate *pad_template;
64
65 g_return_if_fail (GST_IS_CAPS (sinkcaps));
66
67 pad_template =
68 gst_pad_template_new (GST_BASE_TRANSFORM_SINK_NAME, GST_PAD_SINK,
69 GST_PAD_ALWAYS, sinkcaps);
70 gst_element_class_add_pad_template (elem_class, pad_template);
71 }
72
73 static gboolean
gst_ladspa_sink_type_set_caps(GstBaseSink * base,GstCaps * caps)74 gst_ladspa_sink_type_set_caps (GstBaseSink * base, GstCaps * caps)
75 {
76 GstLADSPASink *ladspa = GST_LADSPA_SINK (base);
77 GstAudioInfo info;
78
79 if (!gst_audio_info_from_caps (&info, caps)) {
80 GST_ERROR_OBJECT (base, "received invalid caps");
81 return FALSE;
82 }
83
84 GST_DEBUG_OBJECT (ladspa, "negotiated to caps %" GST_PTR_FORMAT, caps);
85
86 ladspa->info = info;
87
88 return gst_ladspa_setup (&ladspa->ladspa, GST_AUDIO_INFO_RATE (&info));
89 }
90
91 static gboolean
gst_ladspa_sink_type_query(GstBaseSink * base,GstQuery * query)92 gst_ladspa_sink_type_query (GstBaseSink * base, GstQuery * query)
93 {
94 gboolean ret;
95
96 switch (GST_QUERY_TYPE (query)) {
97 case GST_QUERY_SEEKING:{
98 GstFormat fmt;
99
100 /* we don't supporting seeking */
101 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
102 gst_query_set_seeking (query, fmt, FALSE, 0, -1);
103 ret = TRUE;
104 break;
105 }
106 default:
107 ret =
108 GST_BASE_SINK_CLASS (gst_ladspa_sink_type_parent_class)->query
109 (base, query);
110 break;
111 }
112
113 return ret;
114 }
115
116 static GstFlowReturn
gst_ladspa_sink_type_preroll(GstBaseSink * base,GstBuffer * buffer)117 gst_ladspa_sink_type_preroll (GstBaseSink * base, GstBuffer * buffer)
118 {
119 GstLADSPASink *ladspa = GST_LADSPA_SINK (base);
120
121 if (ladspa->num_buffers_left == 0) {
122 GST_DEBUG_OBJECT (ladspa, "we are EOS");
123 return GST_FLOW_EOS;
124 }
125
126 return GST_FLOW_OK;
127 }
128
129 static GstFlowReturn
gst_ladspa_sink_type_render(GstBaseSink * base,GstBuffer * buf)130 gst_ladspa_sink_type_render (GstBaseSink * base, GstBuffer * buf)
131 {
132 GstLADSPASink *ladspa = GST_LADSPA_SINK (base);
133 GstMapInfo info;
134
135 if (ladspa->num_buffers_left == 0)
136 goto eos;
137
138 if (ladspa->num_buffers_left != -1)
139 ladspa->num_buffers_left--;
140
141 gst_object_sync_values (GST_OBJECT (ladspa), GST_BUFFER_TIMESTAMP (buf));
142
143 gst_buffer_map (buf, &info, GST_MAP_READ);
144 gst_ladspa_transform (&ladspa->ladspa, NULL,
145 info.size / sizeof (LADSPA_Data) / ladspa->ladspa.klass->count.audio.in,
146 info.data);
147 gst_buffer_unmap (buf, &info);
148
149 if (ladspa->num_buffers_left == 0)
150 goto eos;
151
152 return GST_FLOW_OK;
153
154 /* ERRORS */
155 eos:
156 {
157 GST_DEBUG_OBJECT (ladspa, "we are EOS");
158 return GST_FLOW_EOS;
159 }
160 }
161
162 static GstStateChangeReturn
gst_ladspa_sink_type_change_state(GstElement * element,GstStateChange transition)163 gst_ladspa_sink_type_change_state (GstElement * element,
164 GstStateChange transition)
165 {
166 GstLADSPASink *ladspa = GST_LADSPA_SINK (element);
167 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
168
169 switch (transition) {
170 case GST_STATE_CHANGE_READY_TO_PAUSED:
171 ladspa->num_buffers_left = ladspa->num_buffers;
172 break;
173 default:
174 break;
175 }
176
177 ret =
178 GST_ELEMENT_CLASS (gst_ladspa_sink_type_parent_class)->change_state
179 (element, transition);
180
181 return ret;
182 }
183
184
185 static void
gst_ladspa_sink_type_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)186 gst_ladspa_sink_type_set_property (GObject * object, guint prop_id,
187 const GValue * value, GParamSpec * pspec)
188 {
189 GstLADSPASink *ladspa = GST_LADSPA_SINK (object);
190
191 switch (prop_id) {
192 case GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PUSH:
193 GST_BASE_SINK (ladspa)->can_activate_push = g_value_get_boolean (value);
194 break;
195 case GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PULL:
196 GST_BASE_SINK (ladspa)->can_activate_pull = g_value_get_boolean (value);
197 break;
198 case GST_LADSPA_SINK_PROP_NUM_BUFFERS:
199 ladspa->num_buffers = g_value_get_int (value);
200 break;
201 default:
202 gst_ladspa_object_set_property (&ladspa->ladspa, object, prop_id, value,
203 pspec);
204 break;
205 }
206 }
207
208 static void
gst_ladspa_sink_type_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)209 gst_ladspa_sink_type_get_property (GObject * object, guint prop_id,
210 GValue * value, GParamSpec * pspec)
211 {
212 GstLADSPASink *ladspa = GST_LADSPA_SINK (object);
213
214 switch (prop_id) {
215 case GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PUSH:
216 g_value_set_boolean (value, GST_BASE_SINK (ladspa)->can_activate_push);
217 break;
218 case GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PULL:
219 g_value_set_boolean (value, GST_BASE_SINK (ladspa)->can_activate_pull);
220 break;
221 case GST_LADSPA_SINK_PROP_NUM_BUFFERS:
222 g_value_set_int (value, ladspa->num_buffers);
223 break;
224 default:
225 gst_ladspa_object_get_property (&ladspa->ladspa, object, prop_id, value,
226 pspec);
227 break;
228 }
229 }
230
231 static void
gst_ladspa_sink_type_init(GstLADSPASink * ladspa,LADSPA_Descriptor * desc)232 gst_ladspa_sink_type_init (GstLADSPASink * ladspa, LADSPA_Descriptor * desc)
233 {
234 GstLADSPASinkClass *ladspa_class = GST_LADSPA_SINK_GET_CLASS (ladspa);
235 GstBaseSink *base = GST_BASE_SINK (ladspa);
236
237 gst_ladspa_init (&ladspa->ladspa, &ladspa_class->ladspa);
238
239 ladspa->num_buffers = GST_LADSPA_SINK_DEFAULT_NUM_BUFFERS;
240
241 gst_base_sink_set_sync (base, GST_LADSPA_SINK_DEFAULT_SYNC);
242 }
243
244 static void
gst_ladspa_sink_type_dispose(GObject * object)245 gst_ladspa_sink_type_dispose (GObject * object)
246 {
247 GstLADSPASink *ladspa = GST_LADSPA_SINK (object);
248
249 gst_ladspa_cleanup (&ladspa->ladspa);
250
251 G_OBJECT_CLASS (gst_ladspa_sink_type_parent_class)->dispose (object);
252 }
253
254 static void
gst_ladspa_sink_type_finalize(GObject * object)255 gst_ladspa_sink_type_finalize (GObject * object)
256 {
257 GstLADSPASink *ladspa = GST_LADSPA_SINK (object);
258
259 gst_ladspa_finalize (&ladspa->ladspa);
260
261 G_OBJECT_CLASS (gst_ladspa_sink_type_parent_class)->finalize (object);
262 }
263
264 /*
265 * It is okay for plugins to 'leak' a one-time allocation. This will be freed when
266 * the application exits. When the plugins are scanned for the first time, this is
267 * done from a separate process to not impose the memory overhead on the calling
268 * application (among other reasons). Hence no need for class_finalize.
269 */
270 static void
gst_ladspa_sink_type_base_init(GstLADSPASinkClass * ladspa_class)271 gst_ladspa_sink_type_base_init (GstLADSPASinkClass * ladspa_class)
272 {
273 GstElementClass *elem_class = GST_ELEMENT_CLASS (ladspa_class);
274 GstBaseSinkClass *base_class = GST_BASE_SINK_CLASS (ladspa_class);
275
276 gst_ladspa_class_init (&ladspa_class->ladspa,
277 G_TYPE_FROM_CLASS (ladspa_class));
278
279 gst_ladspa_element_class_set_metadata (&ladspa_class->ladspa, elem_class,
280 GST_LADSPA_SINK_CLASS_TAGS);
281
282 gst_ladspa_sink_type_class_add_pad_template (&ladspa_class->ladspa,
283 base_class);
284 }
285
286
287 static void
gst_ladspa_sink_type_base_finalize(GstLADSPASinkClass * ladspa_class)288 gst_ladspa_sink_type_base_finalize (GstLADSPASinkClass * ladspa_class)
289 {
290 gst_ladspa_class_finalize (&ladspa_class->ladspa);
291 }
292
293 static void
gst_ladspa_sink_type_class_init(GstLADSPASinkClass * ladspa_class,LADSPA_Descriptor * desc)294 gst_ladspa_sink_type_class_init (GstLADSPASinkClass * ladspa_class,
295 LADSPA_Descriptor * desc)
296 {
297 GObjectClass *object_class = G_OBJECT_CLASS (ladspa_class);
298 GstElementClass *elem_class = GST_ELEMENT_CLASS (ladspa_class);
299 GstBaseSinkClass *base_class = GST_BASE_SINK_CLASS (ladspa_class);
300
301 gst_ladspa_sink_type_parent_class = g_type_class_peek_parent (ladspa_class);
302
303 object_class->dispose = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_dispose);
304 object_class->finalize = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_finalize);
305 object_class->set_property =
306 GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_set_property);
307 object_class->get_property =
308 GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_get_property);
309
310 elem_class->change_state =
311 GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_change_state);
312
313 base_class->set_caps = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_set_caps);
314 base_class->preroll = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_preroll);
315 base_class->render = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_render);
316 base_class->query = GST_DEBUG_FUNCPTR (gst_ladspa_sink_type_query);
317
318 g_object_class_install_property (object_class,
319 GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PUSH,
320 g_param_spec_boolean ("can-activate-push", "Can activate push",
321 "Can activate in push mode",
322 GST_LADSPA_SINK_DEFAULT_CAN_ACTIVATE_PUSH,
323 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
324
325 g_object_class_install_property (object_class,
326 GST_LADSPA_SINK_PROP_CAN_ACTIVATE_PULL,
327 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
328 "Can activate in pull mode",
329 GST_LADSPA_SINK_DEFAULT_CAN_ACTIVATE_PULL,
330 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
331
332 g_object_class_install_property (object_class,
333 GST_LADSPA_SINK_PROP_NUM_BUFFERS, g_param_spec_int ("num-buffers",
334 "num-buffers", "Number of buffers to accept going EOS", -1, G_MAXINT,
335 GST_LADSPA_SINK_DEFAULT_NUM_BUFFERS,
336 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
337
338 gst_ladspa_object_class_install_properties (&ladspa_class->ladspa,
339 object_class, GST_LADSPA_SINK_PROP_LAST);
340
341 }
342
343 G_DEFINE_ABSTRACT_TYPE (GstLADSPASink, gst_ladspa_sink, GST_TYPE_BASE_SINK);
344
345 static void
gst_ladspa_sink_init(GstLADSPASink * ladspa)346 gst_ladspa_sink_init (GstLADSPASink * ladspa)
347 {
348 }
349
350 static void
gst_ladspa_sink_class_init(GstLADSPASinkClass * ladspa_class)351 gst_ladspa_sink_class_init (GstLADSPASinkClass * ladspa_class)
352 {
353 }
354
355 /*
356 * Construct the type.
357 */
358 void
ladspa_register_sink_element(GstPlugin * plugin,GstStructure * ladspa_meta)359 ladspa_register_sink_element (GstPlugin * plugin, GstStructure * ladspa_meta)
360 {
361 GTypeInfo info = {
362 sizeof (GstLADSPASinkClass),
363 (GBaseInitFunc) gst_ladspa_sink_type_base_init,
364 (GBaseFinalizeFunc) gst_ladspa_sink_type_base_finalize,
365 (GClassInitFunc) gst_ladspa_sink_type_class_init,
366 NULL,
367 NULL,
368 sizeof (GstLADSPASink),
369 0,
370 (GInstanceInitFunc) gst_ladspa_sink_type_init,
371 NULL
372 };
373 ladspa_register_element (plugin, GST_TYPE_LADSPA_SINK, &info, ladspa_meta);
374 }
375