1 /*
2  * JACK Rack
3  *
4  * Original:
5  * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
6  *
7  * Modification for MLT:
8  * Copyright (C) 2004-2014 Meltytech, LLC
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 
25 #include <math.h>
26 #include <float.h>
27 #include <string.h>
28 
29 #include "plugin_desc.h"
30 #include "plugin.h"
31 
32 #define set_string_property(property, value) \
33   \
34   if (property) \
35     g_free (property); \
36   \
37   if (value) \
38     (property) = g_strdup (value); \
39   else \
40     (property) = NULL;
41 
42 
43 void
44 plugin_desc_set_ports (plugin_desc_t * pd,
45                        unsigned long port_count,
46  	               const LADSPA_PortDescriptor * port_descriptors,
47                        const LADSPA_PortRangeHint * port_range_hints,
48                        const char * const * port_names);
49 
50 
51 
52 static void
plugin_desc_init(plugin_desc_t * pd)53 plugin_desc_init (plugin_desc_t * pd)
54 {
55   pd->object_file      = NULL;
56   pd->id               = 0;
57   pd->name             = NULL;
58   pd->maker            = NULL;
59   pd->properties       = 0;
60   pd->channels         = 0;
61   pd->port_count       = 0;
62   pd->port_descriptors = NULL;
63   pd->port_range_hints = NULL;
64   pd->audio_input_port_indicies = NULL;
65   pd->audio_output_port_indicies = NULL;
66   pd->audio_aux_port_indicies = NULL;
67   pd->control_port_count = 0;
68   pd->control_port_indicies = NULL;
69   pd->status_port_count = 0;
70   pd->status_port_indicies = NULL;
71   pd->aux_channels = 0;
72   pd->aux_are_input = TRUE;
73   pd->has_input = TRUE;
74 }
75 
76 static void
plugin_desc_free_ports(plugin_desc_t * pd)77 plugin_desc_free_ports (plugin_desc_t * pd)
78 {
79   if (pd->port_count)
80     {
81       g_free (pd->port_descriptors);
82       g_free (pd->port_range_hints);
83       g_free (pd->audio_input_port_indicies);
84       g_free (pd->audio_output_port_indicies);
85       g_free (pd->port_names);
86       g_free (pd->control_port_indicies);
87       g_free (pd->status_port_indicies);
88       g_free (pd->audio_aux_port_indicies);
89       pd->port_descriptors = NULL;
90       pd->port_range_hints = NULL;
91       pd->audio_input_port_indicies = NULL;
92       pd->audio_output_port_indicies = NULL;
93       pd->port_names = NULL;
94       pd->control_port_indicies = NULL;
95       pd->status_port_indicies = NULL;
96       pd->audio_aux_port_indicies = NULL;
97 
98       pd->port_count = 0;
99     }
100 }
101 
102 static void
plugin_desc_free(plugin_desc_t * pd)103 plugin_desc_free (plugin_desc_t * pd)
104 {
105   plugin_desc_set_object_file (pd, NULL);
106   plugin_desc_set_name        (pd, NULL);
107   plugin_desc_set_maker       (pd, NULL);
108   plugin_desc_free_ports      (pd);
109 }
110 
111 plugin_desc_t *
plugin_desc_new()112 plugin_desc_new ()
113 {
114   plugin_desc_t * pd;
115   pd = g_malloc (sizeof (plugin_desc_t));
116   plugin_desc_init (pd);
117   return pd;
118 }
119 
120 plugin_desc_t *
plugin_desc_new_with_descriptor(const char * object_file,unsigned long index,const LADSPA_Descriptor * descriptor)121 plugin_desc_new_with_descriptor (const char * object_file,
122                                  unsigned long index,
123                                  const LADSPA_Descriptor * descriptor)
124 {
125   plugin_desc_t * pd;
126   pd = plugin_desc_new ();
127 
128   plugin_desc_set_object_file (pd, object_file);
129   plugin_desc_set_index       (pd, index);
130   plugin_desc_set_id          (pd, descriptor->UniqueID);
131   plugin_desc_set_name        (pd, descriptor->Name);
132   plugin_desc_set_maker       (pd, descriptor->Maker);
133   plugin_desc_set_properties  (pd, descriptor->Properties);
134   plugin_desc_set_ports       (pd,
135                                descriptor->PortCount,
136                                descriptor->PortDescriptors,
137                                descriptor->PortRangeHints,
138                                descriptor->PortNames);
139 
140   pd->rt = LADSPA_IS_HARD_RT_CAPABLE(pd->properties) ? TRUE : FALSE;
141 
142   return pd;
143 }
144 
145 void
plugin_desc_destroy(plugin_desc_t * pd)146 plugin_desc_destroy (plugin_desc_t * pd)
147 {
148   plugin_desc_free (pd);
149   g_free (pd);
150 }
151 
152 void
plugin_desc_set_object_file(plugin_desc_t * pd,const char * object_file)153 plugin_desc_set_object_file (plugin_desc_t * pd, const char * object_file)
154 {
155   set_string_property (pd->object_file, object_file);
156 }
157 
158 void
plugin_desc_set_index(plugin_desc_t * pd,unsigned long index)159 plugin_desc_set_index          (plugin_desc_t * pd, unsigned long index)
160 {
161   pd->index = index;
162 }
163 
164 
165 void
plugin_desc_set_id(plugin_desc_t * pd,unsigned long id)166 plugin_desc_set_id          (plugin_desc_t * pd, unsigned long id)
167 {
168   pd->id = id;
169 }
170 
171 void
plugin_desc_set_name(plugin_desc_t * pd,const char * name)172 plugin_desc_set_name        (plugin_desc_t * pd, const char * name)
173 {
174   set_string_property (pd->name, name);
175 }
176 
177 void
plugin_desc_set_maker(plugin_desc_t * pd,const char * maker)178 plugin_desc_set_maker       (plugin_desc_t * pd, const char * maker)
179 {
180   set_string_property (pd->maker, maker);
181 }
182 
183 void
plugin_desc_set_properties(plugin_desc_t * pd,LADSPA_Properties properties)184 plugin_desc_set_properties  (plugin_desc_t * pd, LADSPA_Properties properties)
185 {
186   pd->properties = properties;
187 }
188 
189 static void
plugin_desc_add_audio_port_index(unsigned long ** indices,unsigned long * current_port_count,unsigned long index)190 plugin_desc_add_audio_port_index (unsigned long ** indices,
191                                   unsigned long * current_port_count,
192                                   unsigned long index)
193 {
194   (*current_port_count)++;
195 
196   if (*current_port_count == 0)
197     *indices = g_malloc (sizeof (unsigned long) * *current_port_count);
198   else
199     *indices = g_realloc (*indices, sizeof (unsigned long) * *current_port_count);
200 
201   (*indices)[*current_port_count - 1] = index;
202 }
203 
204 static void
plugin_desc_set_port_counts(plugin_desc_t * pd)205 plugin_desc_set_port_counts (plugin_desc_t * pd)
206 {
207   unsigned long i;
208   unsigned long icount = 0;
209   unsigned long ocount = 0;
210 
211   for (i = 0; i < pd->port_count; i++)
212     {
213       if (LADSPA_IS_PORT_AUDIO (pd->port_descriptors[i]))
214         {
215           if (LADSPA_IS_PORT_INPUT (pd->port_descriptors[i]))
216             plugin_desc_add_audio_port_index (&pd->audio_input_port_indicies, &icount, i);
217           else
218             plugin_desc_add_audio_port_index (&pd->audio_output_port_indicies, &ocount, i);
219         }
220       else
221         {
222           if (LADSPA_IS_PORT_OUTPUT (pd->port_descriptors[i]))
223             {
224               pd->status_port_count++;
225               if (pd->status_port_count == 0)
226                 pd->status_port_indicies = g_malloc (sizeof (unsigned long) * pd->status_port_count);
227               else
228                 pd->status_port_indicies = g_realloc (pd->status_port_indicies,
229                                                        sizeof (unsigned long) * pd->status_port_count);
230               pd->status_port_indicies[pd->status_port_count - 1] = i;
231             }
232           else
233             {
234               pd->control_port_count++;
235               if (pd->control_port_count == 0)
236                 pd->control_port_indicies = g_malloc (sizeof (unsigned long) * pd->control_port_count);
237               else
238                 pd->control_port_indicies = g_realloc (pd->control_port_indicies,
239                                                        sizeof (unsigned long) * pd->control_port_count);
240               pd->control_port_indicies[pd->control_port_count - 1] = i;
241             }
242         }
243     }
244 
245   if (icount == ocount)
246     pd->channels = icount;
247   else if( icount == 0 )
248     {
249       pd->channels = ocount;
250       pd->has_input = FALSE;
251     }
252   else
253     { /* deal with auxiliary ports */
254       unsigned long ** port_indicies;
255       unsigned long port_count;
256       unsigned long i, j;
257 
258       if (icount > ocount)
259         {
260           pd->channels = ocount;
261           pd->aux_channels = icount - ocount;
262           pd->aux_are_input = TRUE;
263           port_indicies = &pd->audio_input_port_indicies;
264           port_count = icount;
265         }
266       else
267         {
268           pd->channels = icount;
269           pd->aux_channels = ocount - icount;
270           pd->aux_are_input = FALSE;
271           port_indicies = &pd->audio_output_port_indicies;
272           port_count = ocount;
273         }
274 
275       /* allocate indices */
276       pd->audio_aux_port_indicies = g_malloc (sizeof (unsigned long) * pd->aux_channels);
277 
278       /* copy indices */
279       for (i = pd->channels, j = 0; i < port_count; i++, j++)
280         pd->audio_aux_port_indicies[j] = (*port_indicies)[i];
281 
282       /* shrink the main indices to only have channels indices */
283       *port_indicies = g_realloc (*port_indicies, sizeof (unsigned long) * pd->channels);
284     }
285 }
286 
287 void
plugin_desc_set_ports(plugin_desc_t * pd,unsigned long port_count,const LADSPA_PortDescriptor * port_descriptors,const LADSPA_PortRangeHint * port_range_hints,const char * const * port_names)288 plugin_desc_set_ports (plugin_desc_t * pd,
289                        unsigned long port_count,
290                        const LADSPA_PortDescriptor * port_descriptors,
291                        const LADSPA_PortRangeHint * port_range_hints,
292                        const char * const * port_names)
293 {
294   unsigned long i;
295 
296   plugin_desc_free_ports (pd);
297 
298   if (!port_count)
299     return;
300 
301   pd->port_count = port_count;
302   pd->port_descriptors = g_malloc (sizeof (LADSPA_PortDescriptor) * port_count);
303   pd->port_range_hints = g_malloc (sizeof (LADSPA_PortRangeHint) * port_count);
304   pd->port_names       = g_malloc (sizeof (char *) * port_count);
305 
306   memcpy (pd->port_descriptors, port_descriptors, sizeof (LADSPA_PortDescriptor) * port_count);
307   memcpy (pd->port_range_hints, port_range_hints, sizeof (LADSPA_PortRangeHint) * port_count);
308 
309   for (i = 0; i < port_count; i++)
310     pd->port_names[i] = g_strdup (port_names[i]);
311 
312   plugin_desc_set_port_counts (pd);
313 }
314 
315 
316 LADSPA_Data
plugin_desc_get_default_control_value(plugin_desc_t * pd,unsigned long port_index,guint32 sample_rate)317 plugin_desc_get_default_control_value (plugin_desc_t * pd, unsigned long port_index, guint32 sample_rate)
318 {
319   LADSPA_Data upper, lower;
320   LADSPA_PortRangeHintDescriptor hint_descriptor;
321 
322   hint_descriptor = pd->port_range_hints[port_index].HintDescriptor;
323 
324   /* set upper and lower, possibly adjusted to the sample rate */
325   if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
326     upper = pd->port_range_hints[port_index].UpperBound * (LADSPA_Data) sample_rate;
327     lower = pd->port_range_hints[port_index].LowerBound * (LADSPA_Data) sample_rate;
328   } else {
329     upper = pd->port_range_hints[port_index].UpperBound;
330     lower = pd->port_range_hints[port_index].LowerBound;
331   }
332 
333   if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor))
334     {
335       if (lower < FLT_EPSILON)
336         lower = FLT_EPSILON;
337     }
338 
339 
340   if (LADSPA_IS_HINT_HAS_DEFAULT(hint_descriptor)) {
341 
342            if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_descriptor)) {
343 
344       return lower;
345 
346     } else if (LADSPA_IS_HINT_DEFAULT_LOW(hint_descriptor)) {
347 
348       if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
349         return exp(log(lower) * 0.75 + log(upper) * 0.25);
350       } else {
351         return lower * 0.75 + upper * 0.25;
352       }
353 
354     } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_descriptor)) {
355 
356       if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
357         return exp(log(lower) * 0.5 + log(upper) * 0.5);
358       } else {
359         return lower * 0.5 + upper * 0.5;
360       }
361 
362     } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint_descriptor)) {
363 
364       if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
365         return exp(log(lower) * 0.25 + log(upper) * 0.75);
366       } else {
367         return lower * 0.25 + upper * 0.75;
368       }
369 
370     } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_descriptor)) {
371 
372       return upper;
373 
374     } else if (LADSPA_IS_HINT_DEFAULT_0(hint_descriptor)) {
375 
376       return 0.0;
377 
378     } else if (LADSPA_IS_HINT_DEFAULT_1(hint_descriptor)) {
379 
380       if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
381         return (LADSPA_Data) sample_rate;
382       } else {
383         return 1.0;
384       }
385 
386     } else if (LADSPA_IS_HINT_DEFAULT_100(hint_descriptor)) {
387 
388       if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
389         return 100.0 * (LADSPA_Data) sample_rate;
390       } else {
391         return 100.0;
392       }
393 
394     } else if (LADSPA_IS_HINT_DEFAULT_440(hint_descriptor)) {
395 
396       if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
397         return 440.0 * (LADSPA_Data) sample_rate;
398       } else {
399         return 440.0;
400       }
401 
402     }
403 
404   } else { /* try and find a reasonable default */
405 
406            if (LADSPA_IS_HINT_BOUNDED_BELOW(hint_descriptor)) {
407       return lower;
408     } else if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint_descriptor)) {
409       return upper;
410     }
411   }
412 
413   return 0.0;
414 }
415 
416 LADSPA_Data
plugin_desc_change_control_value(plugin_desc_t * pd,unsigned long control_index,LADSPA_Data value,guint32 old_sample_rate,guint32 new_sample_rate)417 plugin_desc_change_control_value (plugin_desc_t * pd,
418                                   unsigned long control_index,
419                                   LADSPA_Data value,
420                                   guint32 old_sample_rate,
421                                   guint32 new_sample_rate)
422 {
423 
424   if (LADSPA_IS_HINT_SAMPLE_RATE (pd->port_range_hints[control_index].HintDescriptor))
425     {
426       LADSPA_Data old_sr, new_sr;
427 
428       old_sr = (LADSPA_Data) old_sample_rate;
429       new_sr = (LADSPA_Data) new_sample_rate;
430 
431       value /= old_sr;
432       value *= new_sr;
433     }
434 
435   return value;
436 }
437 
438 gint
plugin_desc_get_copies(plugin_desc_t * pd,unsigned long rack_channels)439 plugin_desc_get_copies (plugin_desc_t * pd, unsigned long rack_channels)
440 {
441   gint copies = 1;
442 
443   if (pd->channels > rack_channels)
444     return 0;
445 
446   while (pd->channels * copies < rack_channels)
447     copies++;
448 
449   if (pd->channels * copies > rack_channels)
450     return 0;
451 
452   return copies;
453 }
454 
455 /* EOF */
456