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   gfloat 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     lower *= 44100;
384     upper *= 44100;
385   }
386 
387   if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
388     lower = CLAMP (lower, G_MININT, G_MAXINT);
389     upper = CLAMP (upper, G_MININT, G_MAXINT);
390   }
391 
392   /* default to lower bound */
393   def = lower;
394 
395 #ifdef LADSPA_IS_HINT_HAS_DEFAULT
396   if (LADSPA_IS_HINT_HAS_DEFAULT (hintdesc)) {
397     if (LADSPA_IS_HINT_DEFAULT_0 (hintdesc))
398       def = 0.0;
399     else if (LADSPA_IS_HINT_DEFAULT_1 (hintdesc))
400       def = 1.0;
401     else if (LADSPA_IS_HINT_DEFAULT_100 (hintdesc))
402       def = 100.0;
403     else if (LADSPA_IS_HINT_DEFAULT_440 (hintdesc))
404       def = 440.0;
405     if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hintdesc))
406       def = lower;
407     else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hintdesc))
408       def = upper;
409     else if (LADSPA_IS_HINT_LOGARITHMIC (hintdesc)) {
410       if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
411         def = exp (0.75 * log (lower) + 0.25 * log (upper));
412       else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
413         def = exp (0.5 * log (lower) + 0.5 * log (upper));
414       else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
415         def = exp (0.25 * log (lower) + 0.75 * log (upper));
416     } else {
417       if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
418         def = 0.75 * lower + 0.25 * upper;
419       else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
420         def = 0.5 * lower + 0.5 * upper;
421       else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
422         def = 0.25 * lower + 0.75 * upper;
423     }
424   }
425 #endif /* LADSPA_IS_HINT_HAS_DEFAULT */
426 
427   if (lower > upper) {
428     gfloat tmp;
429 
430     /* silently swap */
431     tmp = lower;
432     lower = upper;
433     upper = tmp;
434   }
435 
436   def = CLAMP (def, lower, upper);
437 
438   if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
439     ret =
440         g_param_spec_int (name, name, desc->PortNames[portnum], lower, upper,
441         def, perms);
442   } else {
443     ret =
444         g_param_spec_float (name, name, desc->PortNames[portnum], lower, upper,
445         def, perms);
446   }
447 
448   g_free (name);
449 
450   return ret;
451 }
452 
453 void
gst_ladspa_object_set_property(GstLADSPA * ladspa,GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)454 gst_ladspa_object_set_property (GstLADSPA * ladspa, GObject * object,
455     guint prop_id, const GValue * value, GParamSpec * pspec)
456 {
457   /* remember, properties have an offset */
458   prop_id -= ladspa->klass->properties;
459 
460   /* only input ports */
461   g_return_if_fail (prop_id < ladspa->klass->count.control.in);
462 
463   /* now see what type it is */
464   switch (pspec->value_type) {
465     case G_TYPE_BOOLEAN:
466       ladspa->ports.control.in[prop_id] =
467           g_value_get_boolean (value) ? 1.f : 0.f;
468       break;
469     case G_TYPE_INT:
470       ladspa->ports.control.in[prop_id] = g_value_get_int (value);
471       break;
472     case G_TYPE_FLOAT:
473       ladspa->ports.control.in[prop_id] = g_value_get_float (value);
474       break;
475     default:
476       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
477   }
478 }
479 
480 void
gst_ladspa_object_get_property(GstLADSPA * ladspa,GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)481 gst_ladspa_object_get_property (GstLADSPA * ladspa, GObject * object,
482     guint prop_id, GValue * value, GParamSpec * pspec)
483 {
484   LADSPA_Data *controls;
485 
486   /* remember, properties have an offset */
487   prop_id -= ladspa->klass->properties;
488 
489   if (prop_id < ladspa->klass->count.control.in) {
490     controls = ladspa->ports.control.in;
491   } else if (prop_id <
492       ladspa->klass->count.control.in + ladspa->klass->count.control.out) {
493     controls = ladspa->ports.control.out;
494     prop_id -= ladspa->klass->count.control.in;
495   } else {
496     g_return_if_reached ();
497   }
498 
499   /* now see what type it is */
500   switch (pspec->value_type) {
501     case G_TYPE_BOOLEAN:
502       g_value_set_boolean (value, controls[prop_id] > 0.5);
503       break;
504     case G_TYPE_INT:
505       g_value_set_int (value, CLAMP (controls[prop_id], G_MININT, G_MAXINT));
506       break;
507     case G_TYPE_FLOAT:
508       g_value_set_float (value, controls[prop_id]);
509       break;
510     default:
511       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
512   }
513 }
514 
515 void
gst_ladspa_object_class_install_properties(GstLADSPAClass * ladspa_class,GObjectClass * object_class,guint offset)516 gst_ladspa_object_class_install_properties (GstLADSPAClass * ladspa_class,
517     GObjectClass * object_class, guint offset)
518 {
519   GParamSpec *p;
520   gint i;
521 
522   ladspa_class->properties = offset;
523 
524   /* register properties */
525   for (i = 0; i < ladspa_class->count.control.in; i++, offset++) {
526     p = gst_ladspa_object_class_get_param_spec (ladspa_class, object_class,
527         ladspa_class->map.control.in[i]);
528     g_object_class_install_property (object_class, offset, p);
529   }
530   for (i = 0; i < ladspa_class->count.control.out; i++, offset++) {
531     p = gst_ladspa_object_class_get_param_spec (ladspa_class, object_class,
532         ladspa_class->map.control.out[i]);
533     g_object_class_install_property (object_class, offset, p);
534   }
535 }
536 
537 void
gst_ladspa_element_class_set_metadata(GstLADSPAClass * ladspa_class,GstElementClass * elem_class,const gchar * ladspa_class_tags)538 gst_ladspa_element_class_set_metadata (GstLADSPAClass * ladspa_class,
539     GstElementClass * elem_class, const gchar * ladspa_class_tags)
540 {
541   const LADSPA_Descriptor *desc = ladspa_class->descriptor;
542   gchar *longname, *author, *extra_ladspa_class_tags = NULL, *tmp;
543 #ifdef HAVE_LRDF
544   gchar *uri;
545 #endif
546 
547   longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
548   if (!longname)
549     longname = g_strdup ("no LADSPA description available");
550 
551   /* FIXME: no plugin author field different from element author field */
552   tmp = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
553   if (!tmp)
554     tmp = g_strdup ("no LADSPA author available");
555   author =
556       g_strjoin (", ", tmp,
557       "Juan Manuel Borges Caño <juanmabcmail@gmail.com>",
558       "Andy Wingo <wingo at pobox.com>",
559       "Steve Baker <stevebaker_org@yahoo.co.uk>",
560       "Erik Walthinsen <omega@cse.ogi.edu>",
561       "Stefan Sauer <ensonic@users.sf.net>",
562       "Wim Taymans <wim@fluendo.com>", NULL);
563   g_free (tmp);
564 
565 #ifdef HAVE_LRDF
566   /* libldrf support, we want to get extra klass information here */
567   uri = g_strdup_printf (LADSPA_BASE "%ld", desc->UniqueID);
568   if (uri) {
569     lrdf_statement query = { 0, };
570     lrdf_uris *uris;
571     gchar *str, *base_type = NULL;
572 
573     GST_DEBUG ("LADSPA uri (id=%lu) : %s", desc->UniqueID, uri);
574 
575     /* we can take this directly from 'desc', keep this example for future
576        attributes.
577 
578        if ((str = lrdf_get_setting_metadata (uri, "title"))) {
579        GST_DEBUG ("LADSPA title : %s", str);
580        }
581        if ((str = lrdf_get_setting_metadata (uri, "creator"))) {
582        GST_DEBUG ("LADSPA creator : %s", str);
583        }
584      */
585 
586     /* get the rdf:type for this plugin */
587     query.subject = uri;
588     query.predicate = (char *) RDF_BASE "type";
589     query.object = (char *) "?";
590     query.next = NULL;
591     uris = lrdf_match_multi (&query);
592     if (uris) {
593       if (uris->count == 1) {
594         base_type = g_strdup (uris->items[0]);
595         GST_DEBUG ("LADSPA base_type :  %s", base_type);
596       }
597       lrdf_free_uris (uris);
598     }
599 
600     /* query taxonomy */
601     if (base_type) {
602       uris = lrdf_get_all_superclasses (base_type);
603       if (uris) {
604         guint32 j;
605 
606         for (j = 0; j < uris->count; j++) {
607           if ((str = lrdf_get_label (uris->items[j]))) {
608             GST_DEBUG ("LADSPA parent_type_label : %s", str);
609             if (extra_ladspa_class_tags) {
610               gchar *old_tags = extra_ladspa_class_tags;
611               extra_ladspa_class_tags =
612                   g_strconcat (extra_ladspa_class_tags, "/", str, NULL);
613               g_free (old_tags);
614             } else {
615               extra_ladspa_class_tags = g_strconcat ("/", str, NULL);
616             }
617           }
618         }
619         lrdf_free_uris (uris);
620       }
621       g_free (base_type);
622     }
623 
624     /* we can use this for the presets
625 
626        uris = lrdf_get_setting_uris (desc->UniqueID);
627        if (uris) {
628        guint32 j;
629 
630        for (j = 0; j < uris->count; j++) {
631        GST_INFO ("setting_uri : %s", uris->items[j]);
632        if ((str = lrdf_get_label (uris->items[j]))) {
633        GST_INFO ("setting_label : %s", str);
634        }
635        }
636        lrdf_free_uris (uris);
637        }
638 
639      */
640   }
641   g_free (uri);
642 
643   if (extra_ladspa_class_tags) {
644     char *s = g_strconcat (ladspa_class_tags, extra_ladspa_class_tags, NULL);
645     g_free (extra_ladspa_class_tags);
646     extra_ladspa_class_tags = s;
647   }
648 #endif
649 
650   GST_INFO ("tags : %s", ladspa_class_tags);
651   gst_element_class_set_metadata (elem_class, longname,
652       extra_ladspa_class_tags ? extra_ladspa_class_tags : ladspa_class_tags,
653       longname, author);
654 
655   g_free (extra_ladspa_class_tags);
656   g_free (author);
657   g_free (longname);
658 }
659 
660 void
gst_ladspa_filter_type_class_add_pad_templates(GstLADSPAClass * ladspa_class,GstAudioFilterClass * audio_class)661 gst_ladspa_filter_type_class_add_pad_templates (GstLADSPAClass *
662     ladspa_class, GstAudioFilterClass * audio_class)
663 {
664   GstCaps *srccaps, *sinkcaps;
665 
666   srccaps = gst_caps_new_simple ("audio/x-raw",
667       "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
668       "channels", G_TYPE_INT, ladspa_class->count.audio.out,
669       "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
670       "layout", G_TYPE_STRING, "interleaved", NULL);
671 
672   sinkcaps = gst_caps_new_simple ("audio/x-raw",
673       "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
674       "channels", G_TYPE_INT, ladspa_class->count.audio.in,
675       "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
676       "layout", G_TYPE_STRING, "interleaved", NULL);
677 
678   gst_my_audio_filter_class_add_pad_templates (audio_class, srccaps, sinkcaps);
679 
680   gst_caps_unref (sinkcaps);
681   gst_caps_unref (srccaps);
682 }
683 
684 void
gst_ladspa_source_type_class_add_pad_template(GstLADSPAClass * ladspa_class,GstBaseSrcClass * base_class)685 gst_ladspa_source_type_class_add_pad_template (GstLADSPAClass *
686     ladspa_class, GstBaseSrcClass * base_class)
687 {
688   GstCaps *srccaps;
689 
690   srccaps = gst_caps_new_simple ("audio/x-raw",
691       "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
692       "channels", G_TYPE_INT, ladspa_class->count.audio.out,
693       "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
694       "layout", G_TYPE_STRING, "interleaved", NULL);
695 
696   gst_my_base_source_class_add_pad_template (base_class, srccaps);
697 
698   gst_caps_unref (srccaps);
699 }
700 
701 void
gst_ladspa_sink_type_class_add_pad_template(GstLADSPAClass * ladspa_class,GstBaseSinkClass * base_class)702 gst_ladspa_sink_type_class_add_pad_template (GstLADSPAClass * ladspa_class,
703     GstBaseSinkClass * base_class)
704 {
705   GstCaps *sinkcaps;
706 
707   sinkcaps = gst_caps_new_simple ("audio/x-raw",
708       "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
709       "channels", G_TYPE_INT, ladspa_class->count.audio.in,
710       "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
711       "layout", G_TYPE_STRING, "interleaved", NULL);
712 
713   gst_my_base_sink_class_add_pad_template (base_class, sinkcaps);
714 
715   gst_caps_unref (sinkcaps);
716 }
717 
718 void
gst_ladspa_init(GstLADSPA * ladspa,GstLADSPAClass * ladspa_class)719 gst_ladspa_init (GstLADSPA * ladspa, GstLADSPAClass * ladspa_class)
720 {
721   GST_DEBUG ("LADSPA initializing component");
722 
723   ladspa->klass = ladspa_class;
724 
725   ladspa->handle = NULL;
726   ladspa->activated = FALSE;
727   ladspa->rate = 0;
728 
729   ladspa->ports.audio.in = g_new0 (LADSPA_Data *, ladspa_class->count.audio.in);
730   ladspa->ports.audio.out =
731       g_new0 (LADSPA_Data *, ladspa_class->count.audio.out);
732 
733   ladspa->ports.control.in =
734       g_new0 (LADSPA_Data, ladspa_class->count.control.in);
735   ladspa->ports.control.out =
736       g_new0 (LADSPA_Data, ladspa_class->count.control.out);
737 }
738 
739 void
gst_ladspa_finalize(GstLADSPA * ladspa)740 gst_ladspa_finalize (GstLADSPA * ladspa)
741 {
742   GST_DEBUG ("LADSPA finalizing component");
743 
744   g_free (ladspa->ports.control.out);
745   ladspa->ports.control.out = NULL;
746   g_free (ladspa->ports.control.in);
747   ladspa->ports.control.in = NULL;
748 
749   g_free (ladspa->ports.audio.out);
750   ladspa->ports.audio.out = NULL;
751   g_free (ladspa->ports.audio.in);
752   ladspa->ports.audio.in = NULL;
753 }
754 
755 void
gst_ladspa_class_init(GstLADSPAClass * ladspa_class,GType type)756 gst_ladspa_class_init (GstLADSPAClass * ladspa_class, GType type)
757 {
758   guint mapper, ix;
759   guint audio_in = 0, audio_out = 0, control_in = 0, control_out = 0;
760   const GValue *value =
761       gst_structure_get_value (ladspa_meta_all, g_type_name (type));
762   GstStructure *ladspa_meta = g_value_get_boxed (value);
763   const gchar *file_name;
764   LADSPA_Descriptor_Function descriptor_function;
765 
766   GST_DEBUG ("LADSPA initializing class");
767 
768   file_name = gst_structure_get_string (ladspa_meta, "plugin-filename");
769   ladspa_class->plugin =
770       g_module_open (file_name, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
771   g_module_symbol (ladspa_class->plugin, "ladspa_descriptor",
772       (gpointer *) & descriptor_function);
773   gst_structure_get_uint (ladspa_meta, "element-ix", &ix);
774 
775   ladspa_class->descriptor = descriptor_function (ix);
776   gst_structure_get_uint (ladspa_meta, "audio-in",
777       &ladspa_class->count.audio.in);
778   gst_structure_get_uint (ladspa_meta, "audio-out",
779       &ladspa_class->count.audio.out);
780   gst_structure_get_uint (ladspa_meta, "control-in",
781       &ladspa_class->count.control.in);
782   gst_structure_get_uint (ladspa_meta, "control-out",
783       &ladspa_class->count.control.out);
784   ladspa_class->properties = 1;
785 
786   ladspa_class->map.audio.in =
787       g_new0 (unsigned long, ladspa_class->count.audio.in);
788   ladspa_class->map.audio.out =
789       g_new0 (unsigned long, ladspa_class->count.audio.out);
790 
791   ladspa_class->map.control.in =
792       g_new0 (unsigned long, ladspa_class->count.control.in);
793   ladspa_class->map.control.out =
794       g_new0 (unsigned long, ladspa_class->count.control.out);
795 
796   for (mapper = 0; mapper < ladspa_class->descriptor->PortCount; mapper++) {
797     LADSPA_PortDescriptor p = ladspa_class->descriptor->PortDescriptors[mapper];
798 
799     if (LADSPA_IS_PORT_AUDIO (p)) {
800       if (LADSPA_IS_PORT_INPUT (p))
801         ladspa_class->map.audio.in[audio_in++] = mapper;
802       else
803         ladspa_class->map.audio.out[audio_out++] = mapper;
804     } else if (LADSPA_IS_PORT_CONTROL (p)) {
805       if (LADSPA_IS_PORT_INPUT (p))
806         ladspa_class->map.control.in[control_in++] = mapper;
807       else
808         ladspa_class->map.control.out[control_out++] = mapper;
809     }
810   }
811 
812   g_assert (control_out == ladspa_class->count.control.out);
813   g_assert (control_in == ladspa_class->count.control.in);
814 
815   g_assert (audio_out == ladspa_class->count.audio.out);
816   g_assert (audio_in == ladspa_class->count.audio.in);
817 }
818 
819 void
gst_ladspa_class_finalize(GstLADSPAClass * ladspa_class)820 gst_ladspa_class_finalize (GstLADSPAClass * ladspa_class)
821 {
822   GST_DEBUG ("LADSPA finalizing class");
823 
824   g_free (ladspa_class->map.control.out);
825   ladspa_class->map.control.out = NULL;
826   g_free (ladspa_class->map.control.in);
827   ladspa_class->map.control.in = NULL;
828 
829   g_free (ladspa_class->map.audio.out);
830   ladspa_class->map.audio.out = NULL;
831   g_free (ladspa_class->map.audio.in);
832   ladspa_class->map.audio.in = NULL;
833 
834   g_module_close (ladspa_class->plugin);
835   ladspa_class->plugin = NULL;
836 }
837 
838 /*
839  * Create the type & register the element.
840  */
841 void
ladspa_register_element(GstPlugin * plugin,GType parent_type,const GTypeInfo * info,GstStructure * ladspa_meta)842 ladspa_register_element (GstPlugin * plugin, GType parent_type,
843     const GTypeInfo * info, GstStructure * ladspa_meta)
844 {
845   const gchar *type_name =
846       gst_structure_get_string (ladspa_meta, "element-type-name");
847 
848   gst_element_register (plugin, type_name, GST_RANK_NONE,
849       g_type_register_static (parent_type, type_name, info, 0));
850 }
851