+ LADSPA: make the hint guessing logic compatible with logarithmic ports (makes defau...
[calf.git] / src / calf / ladspa_wrap.h
blobfdd3332b17560ff13e5761ccfd0c172e7f714401
1 /* Calf DSP Library
2 * API wrappers for LADSPA/DSSI
4 * Copyright (C) 2007-2008 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_LADSPA_WRAP_H
22 #define __CALF_LADSPA_WRAP_H
24 #if USE_LADSPA
26 #include <ladspa.h>
27 #if USE_DSSI
28 #include <dssi.h>
29 #endif
30 #include "giface.h"
32 namespace calf_plugins {
34 template<class Module>
35 inline int calc_real_param_count()
37 for (int i=0; i < Module::param_count; i++)
39 if ((Module::param_props[i].flags & PF_TYPEMASK) >= PF_STRING)
40 return i;
42 return Module::param_count;
45 /// A template implementing plugin_ctl_iface for a given plugin
46 template<class Module>
47 struct ladspa_instance: public Module, public plugin_ctl_iface
49 bool activate_flag;
50 static int real_param_count()
52 static int _real_param_count = calc_real_param_count<Module>();
53 return _real_param_count;
55 ladspa_instance()
57 for (int i=0; i < Module::in_count; i++)
58 Module::ins[i] = NULL;
59 for (int i=0; i < Module::out_count; i++)
60 Module::outs[i] = NULL;
61 int rpc = real_param_count();
62 for (int i=0; i < rpc; i++)
63 Module::params[i] = NULL;
64 activate_flag = true;
66 virtual parameter_properties *get_param_props(int param_no)
68 return &Module::param_props[param_no];
70 virtual float get_param_value(int param_no)
72 // XXXKF hack
73 if (param_no >= real_param_count())
74 return 0;
75 return *Module::params[param_no];
77 virtual void set_param_value(int param_no, float value)
79 // XXXKF hack
80 if (param_no >= real_param_count())
81 return;
82 *Module::params[param_no] = value;
84 virtual int get_param_count()
86 return real_param_count();
88 virtual int get_param_port_offset()
90 return Module::in_count + Module::out_count;
92 virtual const char *get_gui_xml() {
93 return Module::get_gui_xml();
95 virtual line_graph_iface *get_line_graph_iface()
97 return dynamic_cast<line_graph_iface *>(this);
99 virtual bool activate_preset(int bank, int program) {
100 return false;
102 virtual const char *get_name()
104 return Module::get_name();
106 virtual const char *get_id()
108 return Module::get_id();
110 virtual const char *get_label()
112 return Module::get_label();
114 virtual char *configure(const char *key, const char *value)
116 if (!strcmp(key, "ExecCommand"))
118 if (*value)
120 execute(atoi(value));
122 return NULL;
124 return Module::configure(key, value);
126 virtual int get_input_count() { return Module::in_count; }
127 virtual int get_output_count() { return Module::out_count; }
128 virtual bool get_midi() { return Module::support_midi; }
129 virtual float get_level(unsigned int port) { return 0.f; }
130 virtual void execute(int cmd_no) {
131 Module::execute(cmd_no);
133 virtual void send_configures(send_configure_iface *sci) {
134 Module::send_configures(sci);
138 /// A wrapper class for plugin class object (there is only one ladspa_wrapper for many instances of the same plugin)
139 template<class Module>
140 struct ladspa_wrapper
142 typedef ladspa_instance<Module> instance;
144 /// LADSPA descriptor
145 static LADSPA_Descriptor descriptor;
146 /// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor)
147 static LADSPA_Descriptor descriptor_for_dssi;
148 #if USE_DSSI
149 /// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.)
150 static DSSI_Descriptor dssi_descriptor;
151 static DSSI_Program_Descriptor dssi_default_program;
153 static std::vector<plugin_preset> *presets;
154 static std::vector<DSSI_Program_Descriptor> *preset_descs;
155 #endif
157 ladspa_wrapper()
159 int ins = Module::in_count;
160 int outs = Module::out_count;
161 int params = ladspa_instance<Module>::real_param_count();
162 ladspa_plugin_info &plugin_info = Module::plugin_info;
163 descriptor.UniqueID = plugin_info.unique_id;
164 descriptor.Label = plugin_info.label;
165 descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str());
166 descriptor.Maker = plugin_info.maker;
167 descriptor.Copyright = plugin_info.copyright;
168 descriptor.Properties = Module::rt_capable ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0;
169 descriptor.PortCount = ins + outs + params;
170 descriptor.PortNames = new char *[descriptor.PortCount];
171 descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount];
172 descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount];
173 int i;
174 for (i = 0; i < ins + outs; i++)
176 LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
177 ((int *)descriptor.PortDescriptors)[i] = i < ins ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
178 : i < ins + outs ? LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
179 : LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
180 prh.HintDescriptor = 0;
181 ((const char **)descriptor.PortNames)[i] = Module::port_names[i];
183 for (; i < ins + outs + params; i++)
185 LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
186 parameter_properties &pp = Module::param_props[i - ins - outs];
187 ((int *)descriptor.PortDescriptors)[i] =
188 LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT);
189 prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW;
190 ((const char **)descriptor.PortNames)[i] = pp.name;
191 prh.LowerBound = pp.min;
192 prh.UpperBound = pp.max;
193 switch(pp.flags & PF_TYPEMASK) {
194 case PF_BOOL:
195 prh.HintDescriptor |= LADSPA_HINT_TOGGLED;
196 prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW);
197 break;
198 case PF_INT:
199 case PF_ENUM:
200 prh.HintDescriptor |= LADSPA_HINT_INTEGER;
201 break;
202 default: {
203 int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min));
204 if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG)
205 defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min));
206 if (defpt < 12)
207 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
208 else if (defpt < 37)
209 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
210 else if (defpt < 63)
211 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
212 else if (defpt < 88)
213 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
214 else
215 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
218 if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) {
219 prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK;
220 if (pp.def_value == 1)
221 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1;
222 else if (pp.def_value == 100)
223 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100;
224 else if (pp.def_value == 440)
225 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440;
226 else
227 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0;
229 switch(pp.flags & PF_SCALEMASK) {
230 case PF_SCALE_LOG:
231 prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
232 break;
235 descriptor.ImplementationData = this;
236 descriptor.instantiate = cb_instantiate;
237 descriptor.connect_port = cb_connect;
238 descriptor.activate = cb_activate;
239 descriptor.run = cb_run;
240 descriptor.run_adding = NULL;
241 descriptor.set_run_adding_gain = NULL;
242 descriptor.deactivate = cb_deactivate;
243 descriptor.cleanup = cb_cleanup;
244 #if USE_DSSI
245 memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor));
246 descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str());
247 memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
248 dssi_descriptor.DSSI_API_Version = 1;
249 dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi;
250 dssi_descriptor.configure = cb_configure;
251 dssi_descriptor.get_program = cb_get_program;
252 dssi_descriptor.select_program = cb_select_program;
253 dssi_descriptor.run_synth = cb_run_synth;
255 presets = new std::vector<plugin_preset>;
256 preset_descs = new std::vector<DSSI_Program_Descriptor>;
258 preset_list plist_tmp, plist;
259 plist.load_defaults(true);
260 plist_tmp.load_defaults(false);
261 plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
263 // XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label
264 // if I forget about this, I'll be in a deep trouble
265 dssi_default_program.Bank = 0;
266 dssi_default_program.Program = 0;
267 dssi_default_program.Name = "default";
269 int pos = 1;
270 for (unsigned int i = 0; i < plist.presets.size(); i++)
272 plugin_preset &pp = plist.presets[i];
273 if (strcasecmp(pp.plugin.c_str(), descriptor.Label))
274 continue;
275 DSSI_Program_Descriptor pd;
276 pd.Bank = pos >> 7;
277 pd.Program = pos++;
278 pd.Name = pp.name.c_str();
279 preset_descs->push_back(pd);
280 presets->push_back(pp);
282 // printf("presets = %p:%d name = %s\n", presets, presets->size(), descriptor.Label);
284 #endif
287 ~ladspa_wrapper()
289 delete []descriptor.PortNames;
290 delete []descriptor.PortDescriptors;
291 delete []descriptor.PortRangeHints;
292 #if USE_DSSI
293 presets->clear();
294 preset_descs->clear();
295 delete presets;
296 delete preset_descs;
297 #endif
300 /// LADSPA instantiation function (create a plugin instance)
301 static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)
303 instance *mod = new instance();
304 mod->srate = sample_rate;
305 mod->post_instantiate();
306 return mod;
309 #if USE_DSSI
310 /// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset
311 static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index) {
312 if (index > presets->size())
313 return NULL;
314 if (index)
315 return &(*preset_descs)[index - 1];
316 return &dssi_default_program;
319 /// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset
320 static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program) {
321 instance *mod = (instance *)Instance;
322 unsigned int no = (Bank << 7) + Program - 1;
323 // printf("no = %d presets = %p:%d\n", no, presets, presets->size());
324 if (no == -1U) {
325 int rpc = ladspa_instance<Module>::real_param_count();
326 for (int i =0 ; i < rpc; i++)
327 *mod->params[i] = Module::param_props[i].def_value;
328 return;
330 if (no >= presets->size())
331 return;
332 plugin_preset &p = (*presets)[no];
333 // printf("activating preset %s\n", p.name.c_str());
334 p.activate(mod);
337 #endif
339 /// LADSPA port connection function
340 static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation) {
341 unsigned long ins = Module::in_count;
342 unsigned long outs = Module::out_count;
343 unsigned long params = ladspa_instance<Module>::real_param_count();
344 instance *const mod = (instance *)Instance;
345 if (port < ins)
346 mod->ins[port] = DataLocation;
347 else if (port < ins + outs)
348 mod->outs[port - ins] = DataLocation;
349 else if (port < ins + outs + params) {
350 int i = port - ins - outs;
351 mod->params[i] = DataLocation;
352 *mod->params[i] = Module::param_props[i].def_value;
356 /// LADSPA activate function (note that at this moment the ports are not set)
357 static void cb_activate(LADSPA_Handle Instance) {
358 instance *const mod = (instance *)Instance;
359 mod->activate_flag = true;
362 /// utility function: zero port values if mask is 0
363 static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples)
365 for (int i=0; i<Module::out_count; i++) {
366 if ((mask & (1 << i)) == 0) {
367 dsp::zero(module->outs[i] + offset, nsamples);
372 /// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
373 static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
374 instance *const mod = (instance *)Instance;
375 if (mod->activate_flag)
377 mod->set_sample_rate(mod->srate);
378 mod->activate();
379 mod->activate_flag = false;
381 mod->params_changed();
382 process_slice(mod, 0, SampleCount);
385 /// utility function: call process, and if it returned zeros in output masks, zero out the relevant output port buffers
386 static inline void process_slice(Module *mod, uint32_t offset, uint32_t end)
388 while(offset < end)
390 uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
391 uint32_t out_mask = mod->process(offset, newend - offset, -1, -1);
392 zero_by_mask(mod, out_mask, offset, newend - offset);
393 offset = newend;
397 #if USE_DSSI
398 /// DSSI "run synth" function, same as run() except it allows for event delivery
399 static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount,
400 snd_seq_event_t *Events, unsigned long EventCount) {
401 instance *const mod = (instance *)Instance;
402 if (mod->activate_flag)
404 mod->set_sample_rate(mod->srate);
405 mod->activate();
406 mod->activate_flag = false;
408 mod->params_changed();
410 uint32_t offset = 0;
411 for (uint32_t e = 0; e < EventCount; e++)
413 uint32_t timestamp = Events[e].time.tick;
414 if (timestamp != offset)
415 process_slice(mod, offset, timestamp);
416 process_dssi_event(mod, Events[e]);
417 offset = timestamp;
419 if (offset != SampleCount)
420 process_slice(mod, offset, SampleCount);
423 /// DSSI configure function (named properties)
424 static char *cb_configure(LADSPA_Handle Instance,
425 const char *Key,
426 const char *Value)
428 instance *const mod = (instance *)Instance;
429 return mod->configure(Key, Value);
432 /// Utility function: handle MIDI event (only handles a subset in this version)
433 static void process_dssi_event(Module *module, snd_seq_event_t &event)
435 switch(event.type) {
436 case SND_SEQ_EVENT_NOTEON:
437 module->note_on(event.data.note.note, event.data.note.velocity);
438 break;
439 case SND_SEQ_EVENT_NOTEOFF:
440 module->note_off(event.data.note.note, event.data.note.velocity);
441 break;
442 case SND_SEQ_EVENT_PGMCHANGE:
443 module->program_change(event.data.control.value);
444 break;
445 case SND_SEQ_EVENT_CONTROLLER:
446 module->control_change(event.data.control.param, event.data.control.value);
447 break;
448 case SND_SEQ_EVENT_PITCHBEND:
449 module->pitch_bend(event.data.control.value);
450 break;
453 #endif
455 /// LADSPA deactivate function
456 static void cb_deactivate(LADSPA_Handle Instance) {
457 instance *const mod = (instance *)Instance;
458 mod->deactivate();
461 /// LADSPA cleanup (delete instance) function
462 static void cb_cleanup(LADSPA_Handle Instance) {
463 instance *const mod = (instance *)Instance;
464 delete mod;
467 /// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions
468 static ladspa_wrapper &get() {
469 static ladspa_wrapper instance;
470 return instance;
476 #endif
478 #endif