1 /* GStreamer LADSPA utils
2 * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
4 * 2003 Andy Wingo <wingo at pobox.com>
5 * 2013 Juan Manuel Borges Caño <juanmabcmail@gmail.com>
6 * 2013 Stefan Sauer <ensonic@users.sf.net>
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 /*
25 * This module is smartly shared between the source, transform and
26 * sink elements. Handling any specific LADSPA <-> gstreamer interaction.
27 *
28 * FIXME:
29 * Assigning channel orders could be tricky since LADSPA seems to not
30 * specify order of channels in a really nice computer parseable way,
31 * stereo is probably wrong, more than stereo is crazy. LADSPA has
32 * no channel order. All that could be done is to parse the port names
33 * for "(Left)/(Right)", "-L/-R" or ":l/:r" - these are the 3 patterns
34 * seen most of the time. By now, it just let's them pass in / pass out.
35 * Some nice effort might be done to set channel-masks and/or channel
36 * positions correctly, if this is needed and expected, users will tell.
37 *
38 * This affects mainly interleaving, right now, it just interleaves all
39 * input and output ports. This is the right thing in 90% of the cases,
40 * but will e.g. create a 4 channel out for a plugin that has 2 stereo
41 * 'pairs'.
42 *
43 * Also, gstreamer supports not-interleaved audio, where you just memcpy
44 * each channel after each other: c1...c1c2....c2 and so on. This is not
45 * taken into account, but could be added to the _transform and caps easily
46 * if users demands it.
47 */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gstladspa.h"
54 #include "gstladspautils.h"
55 #include "gstladspafilter.h"
56 #include "gstladspasource.h"
57 #include "gstladspasink.h"
58
59 #include <math.h>
60
61 #ifdef HAVE_LRDF
62 #include <lrdf.h>
63 #endif
64
65 GST_DEBUG_CATEGORY_EXTERN (ladspa_debug);
66 #define GST_CAT_DEFAULT ladspa_debug
67
68 /*
69 * Interleaved buffer: (c1c2c1c2...)
70 * De-interleaved buffer: (c1c1...c2c2...)
71 */
72 static inline void
gst_ladspa_ladspa_deinterleave_data(GstLADSPA * ladspa,LADSPA_Data * outdata,guint samples,guint8 * indata)73 gst_ladspa_ladspa_deinterleave_data (GstLADSPA * ladspa, LADSPA_Data * outdata,
74 guint samples, guint8 * indata)
75 {
76 guint i, j;
77 const guint audio_in = ladspa->klass->count.audio.in;
78
79 for (i = 0; i < audio_in; i++)
80 for (j = 0; j < samples; j++)
81 outdata[i * samples + j] = ((LADSPA_Data *) indata)[j * audio_in + i];
82 }
83
84 /*
85 * Interleaved buffer: (c1c2c1c2...)
86 * De-interleaved buffer: (c1c1...c2c2...)
87 */
88 static inline void
gst_ladspa_interleave_ladspa_data(GstLADSPA * ladspa,guint8 * outdata,guint samples,LADSPA_Data * indata)89 gst_ladspa_interleave_ladspa_data (GstLADSPA * ladspa, guint8 * outdata,
90 guint samples, LADSPA_Data * indata)
91 {
92 guint i, j;
93 const guint audio_out = ladspa->klass->count.audio.out;
94
95 for (i = 0; i < audio_out; i++)
96 for (j = 0; j < samples; j++)
97 ((LADSPA_Data *) outdata)[j * audio_out + i] = indata[i * samples + j];
98 }
99
100 /*
101 * Connect the audio in ports.
102 */
103 static inline void
gst_ladspa_connect_audio_in(GstLADSPA * ladspa,guint samples,LADSPA_Data * data)104 gst_ladspa_connect_audio_in (GstLADSPA * ladspa, guint samples,
105 LADSPA_Data * data)
106 {
107 guint i;
108
109 for (i = 0; i < ladspa->klass->count.audio.in; i++) {
110 ladspa->ports.audio.in[i] = data + (i * samples);
111 ladspa->klass->descriptor->connect_port (ladspa->handle,
112 ladspa->klass->map.audio.in[i], ladspa->ports.audio.in[i]);
113 }
114 }
115
116 /*
117 * Connect the audio out ports.
118 */
119 static inline void
gst_ladspa_connect_audio_out(GstLADSPA * ladspa,guint samples,LADSPA_Data * data)120 gst_ladspa_connect_audio_out (GstLADSPA * ladspa, guint samples,
121 LADSPA_Data * data)
122 {
123 guint i;
124
125 for (i = 0; i < ladspa->klass->count.audio.out; i++) {
126 ladspa->ports.audio.out[i] = data + (i * samples);
127 ladspa->klass->descriptor->connect_port (ladspa->handle,
128 ladspa->klass->map.audio.out[i], ladspa->ports.audio.out[i]);
129 }
130 }
131
132 /*
133 * Process a block of audio with the ladspa plugin.
134 */
135 static inline void
gst_ladspa_run(GstLADSPA * ladspa,guint nframes)136 gst_ladspa_run (GstLADSPA * ladspa, guint nframes)
137 {
138 ladspa->klass->descriptor->run (ladspa->handle, nframes);
139 }
140
141 /*
142 * The data entry/exit point.
143 */
144 gboolean
gst_ladspa_transform(GstLADSPA * ladspa,guint8 * outdata,guint samples,guint8 * indata)145 gst_ladspa_transform (GstLADSPA * ladspa, guint8 * outdata, guint samples,
146 guint8 * indata)
147 {
148 LADSPA_Data *in, *out;
149
150 in = g_new0 (LADSPA_Data, samples * ladspa->klass->count.audio.in);
151 out = g_new0 (LADSPA_Data, samples * ladspa->klass->count.audio.out);
152
153 gst_ladspa_ladspa_deinterleave_data (ladspa, in, samples, indata);
154
155 gst_ladspa_connect_audio_in (ladspa, samples, in);
156 gst_ladspa_connect_audio_out (ladspa, samples, out);
157
158 gst_ladspa_run (ladspa, samples);
159
160 gst_ladspa_interleave_ladspa_data (ladspa, outdata, samples, out);
161
162 g_free (out);
163 g_free (in);
164
165 return TRUE;
166 }
167
168 static gboolean
gst_ladspa_activate(GstLADSPA * ladspa)169 gst_ladspa_activate (GstLADSPA * ladspa)
170 {
171 g_return_val_if_fail (ladspa->handle != NULL, FALSE);
172 g_return_val_if_fail (ladspa->activated == FALSE, FALSE);
173
174 GST_DEBUG ("activating LADSPA plugin");
175
176 if (ladspa->klass->descriptor->activate)
177 ladspa->klass->descriptor->activate (ladspa->handle);
178
179 ladspa->activated = TRUE;
180
181 return TRUE;
182 }
183
184 static gboolean
gst_ladspa_deactivate(GstLADSPA * ladspa)185 gst_ladspa_deactivate (GstLADSPA * ladspa)
186 {
187 g_return_val_if_fail (ladspa->handle != NULL, FALSE);
188 g_return_val_if_fail (ladspa->activated == TRUE, FALSE);
189
190 GST_DEBUG ("LADSPA deactivating plugin");
191
192 if (ladspa->klass->descriptor->deactivate)
193 ladspa->klass->descriptor->deactivate (ladspa->handle);
194
195 ladspa->activated = FALSE;
196
197 return TRUE;
198 }
199
200 static gboolean
gst_ladspa_open(GstLADSPA * ladspa,unsigned long rate)201 gst_ladspa_open (GstLADSPA * ladspa, unsigned long rate)
202 {
203 guint i;
204
205 GST_DEBUG ("LADSPA instantiating plugin at %lu Hz", rate);
206
207 if (!(ladspa->handle =
208 ladspa->klass->descriptor->instantiate (ladspa->klass->descriptor,
209 rate))) {
210 GST_WARNING ("could not instantiate LADSPA plugin");
211 return FALSE;
212 }
213
214 ladspa->rate = rate;
215
216 /* connect the control ports */
217 for (i = 0; i < ladspa->klass->count.control.in; i++)
218 ladspa->klass->descriptor->connect_port (ladspa->handle,
219 ladspa->klass->map.control.in[i], &(ladspa->ports.control.in[i]));
220 for (i = 0; i < ladspa->klass->count.control.out; i++)
221 ladspa->klass->descriptor->connect_port (ladspa->handle,
222 ladspa->klass->map.control.out[i], &(ladspa->ports.control.out[i]));
223
224 return TRUE;
225 }
226
227 static void
gst_ladspa_close(GstLADSPA * ladspa)228 gst_ladspa_close (GstLADSPA * ladspa)
229 {
230 g_return_if_fail (ladspa->handle != NULL);
231 g_return_if_fail (ladspa->activated == FALSE);
232
233 GST_DEBUG ("LADSPA deinstantiating plugin");
234
235 if (ladspa->klass->descriptor->cleanup)
236 ladspa->klass->descriptor->cleanup (ladspa->handle);
237
238 ladspa->rate = 0;
239 ladspa->handle = NULL;
240 }
241
242 /*
243 * Safe open.
244 */
245 gboolean
gst_ladspa_setup(GstLADSPA * ladspa,unsigned long rate)246 gst_ladspa_setup (GstLADSPA * ladspa, unsigned long rate)
247 {
248 gboolean ret = TRUE;
249
250 GST_DEBUG ("LADSPA setting up plugin");
251
252 if (ladspa->handle && ladspa->rate != rate) {
253 if (ladspa->activated)
254 gst_ladspa_deactivate (ladspa);
255
256 gst_ladspa_close (ladspa);
257 }
258
259 if (!ladspa->handle) {
260 gst_ladspa_open (ladspa, rate);
261 if (!(ret = gst_ladspa_activate (ladspa)))
262 gst_ladspa_close (ladspa);
263 }
264
265 return ret;
266 }
267
268 /*
269 * Safe close.
270 */
271 gboolean
gst_ladspa_cleanup(GstLADSPA * ladspa)272 gst_ladspa_cleanup (GstLADSPA * ladspa)
273 {
274 gboolean ret = TRUE;
275
276 GST_DEBUG ("LADSPA cleaning up plugin");
277
278 if (ladspa->handle) {
279 if (ladspa->activated)
280 ret = gst_ladspa_deactivate (ladspa);
281 gst_ladspa_close (ladspa);
282 }
283
284 return ret;
285 }
286
287 static gchar *
gst_ladspa_object_class_get_param_name(GstLADSPAClass * ladspa_class,GObjectClass * object_class,unsigned long portnum)288 gst_ladspa_object_class_get_param_name (GstLADSPAClass * ladspa_class,
289 GObjectClass * object_class, unsigned long portnum)
290 {
291 const LADSPA_Descriptor *desc = ladspa_class->descriptor;
292 gchar *name, **namev, **v, *tmp;
293 guint i;
294
295 /* beauty in the mess */
296 name = g_strdup ("");
297 namev = g_strsplit_set (desc->PortNames[portnum], "[]()", 0);
298 for (i = 0, v = namev; *v; i++, v++) {
299 if (!(i % 2)) {
300 tmp = name;
301 name = g_strconcat (name, *v, NULL);
302 g_free (tmp);
303 }
304 }
305 g_strfreev (namev);
306 g_strstrip (name);
307 tmp = name;
308 name = g_ascii_strdown (name, -1);
309 g_free (tmp);
310
311 /* this is the same thing that param_spec_* will do */
312 g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
313
314 /* satisfy glib2 (argname[0] must be [A-Za-z]) */
315 if (!((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A'
316 && name[0] <= 'Z'))) {
317 tmp = name;
318 name = g_strconcat ("param-", name, NULL);
319 g_free (tmp);
320 }
321
322 /* check for duplicate property names */
323 if (g_object_class_find_property (G_OBJECT_CLASS (object_class), name)) {
324 gint n = 1;
325 gchar *nprop = g_strdup_printf ("%s-%d", name, n++);
326
327 while (g_object_class_find_property (G_OBJECT_CLASS (object_class), nprop)) {
328 g_free (nprop);
329 nprop = g_strdup_printf ("%s-%d", name, n++);
330 }
331 g_free (name);
332 name = nprop;
333 }
334
335 GST_DEBUG ("LADSPA built property name '%s' from port name '%s'", name,
336 desc->PortNames[portnum]);
337
338 return name;
339 }
340
341 static GParamSpec *
gst_ladspa_object_class_get_param_spec(GstLADSPAClass * ladspa_class,GObjectClass * object_class,unsigned long portnum)342 gst_ladspa_object_class_get_param_spec (GstLADSPAClass * ladspa_class,
343 GObjectClass * object_class, unsigned long portnum)
344 {
345 const LADSPA_Descriptor *desc = ladspa_class->descriptor;
346 GParamSpec *ret;
347 gchar *name;
348 gint hintdesc, perms;
349 gdouble lower, upper, def;
350
351 name =
352 gst_ladspa_object_class_get_param_name (ladspa_class, object_class,
353 portnum);
354 perms = G_PARAM_READABLE;
355 if (LADSPA_IS_PORT_INPUT (desc->PortDescriptors[portnum]))
356 perms |= G_PARAM_WRITABLE | G_PARAM_CONSTRUCT;
357 if (LADSPA_IS_PORT_CONTROL (desc->PortDescriptors[portnum]))
358 perms |= GST_PARAM_CONTROLLABLE;
359
360 /* short name for hint descriptor */
361 hintdesc = desc->PortRangeHints[portnum].HintDescriptor;
362
363 if (LADSPA_IS_HINT_TOGGLED (hintdesc)) {
364 ret =
365 g_param_spec_boolean (name, name, desc->PortNames[portnum], FALSE,
366 perms);
367 g_free (name);
368 return ret;
369 }
370
371 if (LADSPA_IS_HINT_BOUNDED_BELOW (hintdesc))
372 lower = desc->PortRangeHints[portnum].LowerBound;
373 else
374 lower = -G_MAXFLOAT;
375
376 if (LADSPA_IS_HINT_BOUNDED_ABOVE (hintdesc))
377 upper = desc->PortRangeHints[portnum].UpperBound;
378 else
379 upper = G_MAXFLOAT;
380
381 if (LADSPA_IS_HINT_SAMPLE_RATE (hintdesc)) {
382 /* FIXME:! (*= ladspa->rate?, *= GST_AUDIO_DEF_RATE?) */
383 if (LADSPA_IS_HINT_BOUNDED_BELOW (hintdesc))
384 lower *= 44100;
385 if (LADSPA_IS_HINT_BOUNDED_ABOVE (hintdesc))
386 upper *= 44100;
387 }
388
389 if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
390 lower = CLAMP (lower, G_MININT, G_MAXINT);
391 upper = CLAMP (upper, G_MININT, G_MAXINT);
392 }
393
394 /* default to lower bound */
395 def = lower;
396
397 #ifdef LADSPA_IS_HINT_HAS_DEFAULT
398 if (LADSPA_IS_HINT_HAS_DEFAULT (hintdesc)) {
399 if (LADSPA_IS_HINT_DEFAULT_0 (hintdesc))
400 def = 0.0;
401 else if (LADSPA_IS_HINT_DEFAULT_1 (hintdesc))
402 def = 1.0;
403 else if (LADSPA_IS_HINT_DEFAULT_100 (hintdesc))
404 def = 100.0;
405 else if (LADSPA_IS_HINT_DEFAULT_440 (hintdesc))
406 def = 440.0;
407 if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hintdesc))
408 def = lower;
409 else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hintdesc))
410 def = upper;
411 else if (LADSPA_IS_HINT_LOGARITHMIC (hintdesc)) {
412 if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
413 def = exp (0.75 * log (lower) + 0.25 * log (upper));
414 else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
415 def = exp (0.5 * log (lower) + 0.5 * log (upper));
416 else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
417 def = exp (0.25 * log (lower) + 0.75 * log (upper));
418 } else {
419 if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
420 def = 0.75 * lower + 0.25 * upper;
421 else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
422 def = 0.5 * lower + 0.5 * upper;
423 else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
424 def = 0.25 * lower + 0.75 * upper;
425 }
426 }
427 #endif /* LADSPA_IS_HINT_HAS_DEFAULT */
428
429 if (lower > upper) {
430 gfloat tmp;
431
432 /* silently swap */
433 tmp = lower;
434 lower = upper;
435 upper = tmp;
436 }
437
438 def = CLAMP (def, lower, upper);
439
440 if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
441 ret =
442 g_param_spec_int (name, name, desc->PortNames[portnum], lower, upper,
443 def, perms);
444 } else {
445 ret =
446 g_param_spec_float (name, name, desc->PortNames[portnum], lower, upper,
447 def, perms);
448 }
449
450 g_free (name);
451
452 return ret;
453 }
454
455 void
gst_ladspa_object_set_property(GstLADSPA * ladspa,GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)456 gst_ladspa_object_set_property (GstLADSPA * ladspa, GObject * object,
457 guint prop_id, const GValue * value, GParamSpec * pspec)
458 {
459 /* remember, properties have an offset */
460 prop_id -= ladspa->klass->properties;
461
462 /* only input ports */
463 g_return_if_fail (prop_id < ladspa->klass->count.control.in);
464
465 /* now see what type it is */
466 switch (pspec->value_type) {
467 case G_TYPE_BOOLEAN:
468 ladspa->ports.control.in[prop_id] =
469 g_value_get_boolean (value) ? 1.f : 0.f;
470 break;
471 case G_TYPE_INT:
472 ladspa->ports.control.in[prop_id] = g_value_get_int (value);
473 break;
474 case G_TYPE_FLOAT:
475 ladspa->ports.control.in[prop_id] = g_value_get_float (value);
476 break;
477 default:
478 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
479 }
480 }
481
482 void
gst_ladspa_object_get_property(GstLADSPA * ladspa,GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)483 gst_ladspa_object_get_property (GstLADSPA * ladspa, GObject * object,
484 guint prop_id, GValue * value, GParamSpec * pspec)
485 {
486 LADSPA_Data *controls;
487
488 /* remember, properties have an offset */
489 prop_id -= ladspa->klass->properties;
490
491 if (prop_id < ladspa->klass->count.control.in) {
492 controls = ladspa->ports.control.in;
493 } else if (prop_id <
494 ladspa->klass->count.control.in + ladspa->klass->count.control.out) {
495 controls = ladspa->ports.control.out;
496 prop_id -= ladspa->klass->count.control.in;
497 } else {
498 g_return_if_reached ();
499 }
500
501 /* now see what type it is */
502 switch (pspec->value_type) {
503 case G_TYPE_BOOLEAN:
504 g_value_set_boolean (value, controls[prop_id] > 0.5);
505 break;
506 case G_TYPE_INT:{
507 gint64 ival = CLAMP ((gint64) controls[prop_id], G_MININT, G_MAXINT);
508 g_value_set_int (value, ival);
509 break;
510 }
511 case G_TYPE_FLOAT:
512 g_value_set_float (value, controls[prop_id]);
513 break;
514 default:
515 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
516 }
517 }
518
519 void
gst_ladspa_object_class_install_properties(GstLADSPAClass * ladspa_class,GObjectClass * object_class,guint offset)520 gst_ladspa_object_class_install_properties (GstLADSPAClass * ladspa_class,
521 GObjectClass * object_class, guint offset)
522 {
523 GParamSpec *p;
524 gint i;
525
526 ladspa_class->properties = offset;
527
528 /* register properties */
529 for (i = 0; i < ladspa_class->count.control.in; i++, offset++) {
530 p = gst_ladspa_object_class_get_param_spec (ladspa_class, object_class,
531 ladspa_class->map.control.in[i]);
532 g_object_class_install_property (object_class, offset, p);
533 }
534 for (i = 0; i < ladspa_class->count.control.out; i++, offset++) {
535 p = gst_ladspa_object_class_get_param_spec (ladspa_class, object_class,
536 ladspa_class->map.control.out[i]);
537 g_object_class_install_property (object_class, offset, p);
538 }
539 }
540
541 void
gst_ladspa_element_class_set_metadata(GstLADSPAClass * ladspa_class,GstElementClass * elem_class,const gchar * ladspa_class_tags)542 gst_ladspa_element_class_set_metadata (GstLADSPAClass * ladspa_class,
543 GstElementClass * elem_class, const gchar * ladspa_class_tags)
544 {
545 const LADSPA_Descriptor *desc = ladspa_class->descriptor;
546 gchar *longname, *author, *extra_ladspa_class_tags = NULL, *tmp;
547 #ifdef HAVE_LRDF
548 gchar *uri;
549 #endif
550
551 longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
552 if (!longname)
553 longname = g_strdup ("no LADSPA description available");
554
555 /* FIXME: no plugin author field different from element author field */
556 tmp = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
557 if (!tmp)
558 tmp = g_strdup ("no LADSPA author available");
559 author =
560 g_strjoin (", ", tmp,
561 "Juan Manuel Borges Caño <juanmabcmail@gmail.com>",
562 "Andy Wingo <wingo at pobox.com>",
563 "Steve Baker <stevebaker_org@yahoo.co.uk>",
564 "Erik Walthinsen <omega@cse.ogi.edu>",
565 "Stefan Sauer <ensonic@users.sf.net>",
566 "Wim Taymans <wim@fluendo.com>", NULL);
567 g_free (tmp);
568
569 #ifdef HAVE_LRDF
570 /* libldrf support, we want to get extra klass information here */
571 uri = g_strdup_printf (LADSPA_BASE "%ld", desc->UniqueID);
572 if (uri) {
573 lrdf_statement query = { 0, };
574 lrdf_uris *uris;
575 gchar *str, *base_type = NULL;
576
577 GST_DEBUG ("LADSPA uri (id=%lu) : %s", desc->UniqueID, uri);
578
579 /* we can take this directly from 'desc', keep this example for future
580 attributes.
581
582 if ((str = lrdf_get_setting_metadata (uri, "title"))) {
583 GST_DEBUG ("LADSPA title : %s", str);
584 }
585 if ((str = lrdf_get_setting_metadata (uri, "creator"))) {
586 GST_DEBUG ("LADSPA creator : %s", str);
587 }
588 */
589
590 /* get the rdf:type for this plugin */
591 query.subject = uri;
592 query.predicate = (char *) RDF_BASE "type";
593 query.object = (char *) "?";
594 query.next = NULL;
595 uris = lrdf_match_multi (&query);
596 if (uris) {
597 if (uris->count == 1) {
598 base_type = g_strdup (uris->items[0]);
599 GST_DEBUG ("LADSPA base_type : %s", base_type);
600 }
601 lrdf_free_uris (uris);
602 }
603
604 /* query taxonomy */
605 if (base_type) {
606 uris = lrdf_get_all_superclasses (base_type);
607 if (uris) {
608 guint32 j;
609
610 for (j = 0; j < uris->count; j++) {
611 if ((str = lrdf_get_label (uris->items[j]))) {
612 GST_DEBUG ("LADSPA parent_type_label : %s", str);
613 if (extra_ladspa_class_tags) {
614 gchar *old_tags = extra_ladspa_class_tags;
615 extra_ladspa_class_tags =
616 g_strconcat (extra_ladspa_class_tags, "/", str, NULL);
617 g_free (old_tags);
618 } else {
619 extra_ladspa_class_tags = g_strconcat ("/", str, NULL);
620 }
621 }
622 }
623 lrdf_free_uris (uris);
624 }
625 g_free (base_type);
626 }
627
628 /* we can use this for the presets
629
630 uris = lrdf_get_setting_uris (desc->UniqueID);
631 if (uris) {
632 guint32 j;
633
634 for (j = 0; j < uris->count; j++) {
635 GST_INFO ("setting_uri : %s", uris->items[j]);
636 if ((str = lrdf_get_label (uris->items[j]))) {
637 GST_INFO ("setting_label : %s", str);
638 }
639 }
640 lrdf_free_uris (uris);
641 }
642
643 */
644 }
645 g_free (uri);
646
647 if (extra_ladspa_class_tags) {
648 char *s = g_strconcat (ladspa_class_tags, extra_ladspa_class_tags, NULL);
649 g_free (extra_ladspa_class_tags);
650 extra_ladspa_class_tags = s;
651 }
652 #endif
653
654 GST_INFO ("tags : %s", ladspa_class_tags);
655 gst_element_class_set_metadata (elem_class, longname,
656 extra_ladspa_class_tags ? extra_ladspa_class_tags : ladspa_class_tags,
657 longname, author);
658
659 g_free (extra_ladspa_class_tags);
660 g_free (author);
661 g_free (longname);
662 }
663
664 void
gst_ladspa_filter_type_class_add_pad_templates(GstLADSPAClass * ladspa_class,GstAudioFilterClass * audio_class)665 gst_ladspa_filter_type_class_add_pad_templates (GstLADSPAClass *
666 ladspa_class, GstAudioFilterClass * audio_class)
667 {
668 GstCaps *srccaps, *sinkcaps;
669
670 srccaps = gst_caps_new_simple ("audio/x-raw",
671 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
672 "channels", G_TYPE_INT, ladspa_class->count.audio.out,
673 "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
674 "layout", G_TYPE_STRING, "interleaved", NULL);
675
676 sinkcaps = gst_caps_new_simple ("audio/x-raw",
677 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
678 "channels", G_TYPE_INT, ladspa_class->count.audio.in,
679 "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
680 "layout", G_TYPE_STRING, "interleaved", NULL);
681
682 gst_my_audio_filter_class_add_pad_templates (audio_class, srccaps, sinkcaps);
683
684 gst_caps_unref (sinkcaps);
685 gst_caps_unref (srccaps);
686 }
687
688 void
gst_ladspa_source_type_class_add_pad_template(GstLADSPAClass * ladspa_class,GstBaseSrcClass * base_class)689 gst_ladspa_source_type_class_add_pad_template (GstLADSPAClass *
690 ladspa_class, GstBaseSrcClass * base_class)
691 {
692 GstCaps *srccaps;
693
694 srccaps = gst_caps_new_simple ("audio/x-raw",
695 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
696 "channels", G_TYPE_INT, ladspa_class->count.audio.out,
697 "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
698 "layout", G_TYPE_STRING, "interleaved", NULL);
699
700 gst_my_base_source_class_add_pad_template (base_class, srccaps);
701
702 gst_caps_unref (srccaps);
703 }
704
705 void
gst_ladspa_sink_type_class_add_pad_template(GstLADSPAClass * ladspa_class,GstBaseSinkClass * base_class)706 gst_ladspa_sink_type_class_add_pad_template (GstLADSPAClass * ladspa_class,
707 GstBaseSinkClass * base_class)
708 {
709 GstCaps *sinkcaps;
710
711 sinkcaps = gst_caps_new_simple ("audio/x-raw",
712 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
713 "channels", G_TYPE_INT, ladspa_class->count.audio.in,
714 "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
715 "layout", G_TYPE_STRING, "interleaved", NULL);
716
717 gst_my_base_sink_class_add_pad_template (base_class, sinkcaps);
718
719 gst_caps_unref (sinkcaps);
720 }
721
722 void
gst_ladspa_init(GstLADSPA * ladspa,GstLADSPAClass * ladspa_class)723 gst_ladspa_init (GstLADSPA * ladspa, GstLADSPAClass * ladspa_class)
724 {
725 GST_DEBUG ("LADSPA initializing component");
726
727 ladspa->klass = ladspa_class;
728
729 ladspa->handle = NULL;
730 ladspa->activated = FALSE;
731 ladspa->rate = 0;
732
733 ladspa->ports.audio.in = g_new0 (LADSPA_Data *, ladspa_class->count.audio.in);
734 ladspa->ports.audio.out =
735 g_new0 (LADSPA_Data *, ladspa_class->count.audio.out);
736
737 ladspa->ports.control.in =
738 g_new0 (LADSPA_Data, ladspa_class->count.control.in);
739 ladspa->ports.control.out =
740 g_new0 (LADSPA_Data, ladspa_class->count.control.out);
741 }
742
743 void
gst_ladspa_finalize(GstLADSPA * ladspa)744 gst_ladspa_finalize (GstLADSPA * ladspa)
745 {
746 GST_DEBUG ("LADSPA finalizing component");
747
748 g_free (ladspa->ports.control.out);
749 ladspa->ports.control.out = NULL;
750 g_free (ladspa->ports.control.in);
751 ladspa->ports.control.in = NULL;
752
753 g_free (ladspa->ports.audio.out);
754 ladspa->ports.audio.out = NULL;
755 g_free (ladspa->ports.audio.in);
756 ladspa->ports.audio.in = NULL;
757 }
758
759 void
gst_ladspa_class_init(GstLADSPAClass * ladspa_class,GType type)760 gst_ladspa_class_init (GstLADSPAClass * ladspa_class, GType type)
761 {
762 guint mapper, ix;
763 guint audio_in = 0, audio_out = 0, control_in = 0, control_out = 0;
764 const GValue *value =
765 gst_structure_get_value (ladspa_meta_all, g_type_name (type));
766 GstStructure *ladspa_meta = g_value_get_boxed (value);
767 const gchar *file_name;
768 LADSPA_Descriptor_Function descriptor_function;
769
770 GST_DEBUG ("LADSPA initializing class");
771
772 file_name = gst_structure_get_string (ladspa_meta, "plugin-filename");
773 ladspa_class->plugin =
774 g_module_open (file_name, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
775 g_module_symbol (ladspa_class->plugin, "ladspa_descriptor",
776 (gpointer *) & descriptor_function);
777 gst_structure_get_uint (ladspa_meta, "element-ix", &ix);
778
779 ladspa_class->descriptor = descriptor_function (ix);
780 gst_structure_get_uint (ladspa_meta, "audio-in",
781 &ladspa_class->count.audio.in);
782 gst_structure_get_uint (ladspa_meta, "audio-out",
783 &ladspa_class->count.audio.out);
784 gst_structure_get_uint (ladspa_meta, "control-in",
785 &ladspa_class->count.control.in);
786 gst_structure_get_uint (ladspa_meta, "control-out",
787 &ladspa_class->count.control.out);
788 ladspa_class->properties = 1;
789
790 ladspa_class->map.audio.in =
791 g_new0 (unsigned long, ladspa_class->count.audio.in);
792 ladspa_class->map.audio.out =
793 g_new0 (unsigned long, ladspa_class->count.audio.out);
794
795 ladspa_class->map.control.in =
796 g_new0 (unsigned long, ladspa_class->count.control.in);
797 ladspa_class->map.control.out =
798 g_new0 (unsigned long, ladspa_class->count.control.out);
799
800 for (mapper = 0; mapper < ladspa_class->descriptor->PortCount; mapper++) {
801 LADSPA_PortDescriptor p = ladspa_class->descriptor->PortDescriptors[mapper];
802
803 if (LADSPA_IS_PORT_AUDIO (p)) {
804 if (LADSPA_IS_PORT_INPUT (p))
805 ladspa_class->map.audio.in[audio_in++] = mapper;
806 else
807 ladspa_class->map.audio.out[audio_out++] = mapper;
808 } else if (LADSPA_IS_PORT_CONTROL (p)) {
809 if (LADSPA_IS_PORT_INPUT (p))
810 ladspa_class->map.control.in[control_in++] = mapper;
811 else
812 ladspa_class->map.control.out[control_out++] = mapper;
813 }
814 }
815
816 g_assert (control_out == ladspa_class->count.control.out);
817 g_assert (control_in == ladspa_class->count.control.in);
818
819 g_assert (audio_out == ladspa_class->count.audio.out);
820 g_assert (audio_in == ladspa_class->count.audio.in);
821 }
822
823 void
gst_ladspa_class_finalize(GstLADSPAClass * ladspa_class)824 gst_ladspa_class_finalize (GstLADSPAClass * ladspa_class)
825 {
826 GST_DEBUG ("LADSPA finalizing class");
827
828 g_free (ladspa_class->map.control.out);
829 ladspa_class->map.control.out = NULL;
830 g_free (ladspa_class->map.control.in);
831 ladspa_class->map.control.in = NULL;
832
833 g_free (ladspa_class->map.audio.out);
834 ladspa_class->map.audio.out = NULL;
835 g_free (ladspa_class->map.audio.in);
836 ladspa_class->map.audio.in = NULL;
837
838 g_module_close (ladspa_class->plugin);
839 ladspa_class->plugin = NULL;
840 }
841
842 /*
843 * Create the type & register the element.
844 */
845 void
ladspa_register_element(GstPlugin * plugin,GType parent_type,const GTypeInfo * info,GstStructure * ladspa_meta)846 ladspa_register_element (GstPlugin * plugin, GType parent_type,
847 const GTypeInfo * info, GstStructure * ladspa_meta)
848 {
849 const gchar *type_name =
850 gst_structure_get_string (ladspa_meta, "element-type-name");
851
852 gst_element_register (plugin, type_name, GST_RANK_NONE,
853 g_type_register_static (parent_type, type_name, info, 0));
854 }
855