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