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