+ Filter: move implementation of get_changed_offsets to .cpp file
[calf.git] / src / calf / ladspa_wrap.h
blob250b556f8fa043f5c0ee26727c4ffa5446e86425
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 #if USE_DSSI
51 dssi_feedback_sender *feedback_sender;
52 #endif
54 static int real_param_count()
56 static int _real_param_count = calc_real_param_count<Module>();
57 return _real_param_count;
59 ladspa_instance()
61 for (int i=0; i < Module::in_count; i++)
62 Module::ins[i] = NULL;
63 for (int i=0; i < Module::out_count; i++)
64 Module::outs[i] = NULL;
65 int rpc = real_param_count();
66 for (int i=0; i < rpc; i++)
67 Module::params[i] = NULL;
68 activate_flag = true;
69 #if USE_DSSI
70 feedback_sender = NULL;
71 #endif
73 virtual parameter_properties *get_param_props(int param_no)
75 return &Module::param_props[param_no];
77 virtual float get_param_value(int param_no)
79 // XXXKF hack
80 if (param_no >= real_param_count())
81 return 0;
82 return *Module::params[param_no];
84 virtual void set_param_value(int param_no, float value)
86 // XXXKF hack
87 if (param_no >= real_param_count())
88 return;
89 *Module::params[param_no] = value;
91 virtual int get_param_count()
93 return real_param_count();
95 virtual int get_param_port_offset()
97 return Module::in_count + Module::out_count;
99 virtual const char *get_gui_xml() {
100 return Module::get_gui_xml();
102 virtual line_graph_iface *get_line_graph_iface()
104 return dynamic_cast<line_graph_iface *>(this);
106 virtual bool activate_preset(int bank, int program) {
107 return false;
109 virtual const char *get_name()
111 return Module::get_name();
113 virtual const char *get_id()
115 return Module::get_id();
117 virtual const char *get_label()
119 return Module::get_label();
121 virtual char *configure(const char *key, const char *value)
123 #if USE_DSSI
124 if (!strcmp(key, "OSC:FEEDBACK_URI"))
126 line_graph_iface *lgi = dynamic_cast<line_graph_iface *>(this);
127 if (!lgi)
128 return NULL;
129 if (*value)
131 if (feedback_sender) {
132 delete feedback_sender;
133 feedback_sender = NULL;
135 feedback_sender = new dssi_feedback_sender(value, lgi, get_param_props(0), get_param_count());
137 else
139 if (feedback_sender) {
140 delete feedback_sender;
141 feedback_sender = NULL;
144 return NULL;
146 else
147 if (!strcmp(key, "OSC:UPDATE"))
149 if (feedback_sender)
150 feedback_sender->update();
151 return NULL;
153 else
154 #endif
155 if (!strcmp(key, "ExecCommand"))
157 if (*value)
159 execute(atoi(value));
161 return NULL;
163 return Module::configure(key, value);
165 virtual int get_input_count() { return Module::in_count; }
166 virtual int get_output_count() { return Module::out_count; }
167 virtual bool get_midi() { return Module::support_midi; }
168 virtual float get_level(unsigned int port) { return 0.f; }
169 virtual void execute(int cmd_no) {
170 Module::execute(cmd_no);
172 virtual void send_configures(send_configure_iface *sci) {
173 Module::send_configures(sci);
177 /// A wrapper class for plugin class object (there is only one ladspa_wrapper for many instances of the same plugin)
178 template<class Module>
179 struct ladspa_wrapper
181 typedef ladspa_instance<Module> instance;
183 /// LADSPA descriptor
184 static LADSPA_Descriptor descriptor;
185 /// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor)
186 static LADSPA_Descriptor descriptor_for_dssi;
187 #if USE_DSSI
188 /// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.)
189 static DSSI_Descriptor dssi_descriptor;
190 static DSSI_Program_Descriptor dssi_default_program;
192 static std::vector<plugin_preset> *presets;
193 static std::vector<DSSI_Program_Descriptor> *preset_descs;
194 #endif
196 ladspa_wrapper()
198 int ins = Module::in_count;
199 int outs = Module::out_count;
200 int params = ladspa_instance<Module>::real_param_count();
201 ladspa_plugin_info &plugin_info = Module::plugin_info;
202 descriptor.UniqueID = plugin_info.unique_id;
203 descriptor.Label = plugin_info.label;
204 descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str());
205 descriptor.Maker = plugin_info.maker;
206 descriptor.Copyright = plugin_info.copyright;
207 descriptor.Properties = Module::rt_capable ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0;
208 descriptor.PortCount = ins + outs + params;
209 descriptor.PortNames = new char *[descriptor.PortCount];
210 descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount];
211 descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount];
212 int i;
213 for (i = 0; i < ins + outs; i++)
215 LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
216 ((int *)descriptor.PortDescriptors)[i] = i < ins ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
217 : i < ins + outs ? LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
218 : LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
219 prh.HintDescriptor = 0;
220 ((const char **)descriptor.PortNames)[i] = Module::port_names[i];
222 for (; i < ins + outs + params; i++)
224 LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
225 parameter_properties &pp = Module::param_props[i - ins - outs];
226 ((int *)descriptor.PortDescriptors)[i] =
227 LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT);
228 prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW;
229 ((const char **)descriptor.PortNames)[i] = pp.name;
230 prh.LowerBound = pp.min;
231 prh.UpperBound = pp.max;
232 switch(pp.flags & PF_TYPEMASK) {
233 case PF_BOOL:
234 prh.HintDescriptor |= LADSPA_HINT_TOGGLED;
235 prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW);
236 break;
237 case PF_INT:
238 case PF_ENUM:
239 prh.HintDescriptor |= LADSPA_HINT_INTEGER;
240 break;
241 default: {
242 int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min));
243 if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG)
244 defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min));
245 if (defpt < 12)
246 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
247 else if (defpt < 37)
248 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
249 else if (defpt < 63)
250 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
251 else if (defpt < 88)
252 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
253 else
254 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
257 if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) {
258 prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK;
259 if (pp.def_value == 1)
260 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1;
261 else if (pp.def_value == 100)
262 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100;
263 else if (pp.def_value == 440)
264 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440;
265 else
266 prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0;
268 switch(pp.flags & PF_SCALEMASK) {
269 case PF_SCALE_LOG:
270 prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
271 break;
274 descriptor.ImplementationData = this;
275 descriptor.instantiate = cb_instantiate;
276 descriptor.connect_port = cb_connect;
277 descriptor.activate = cb_activate;
278 descriptor.run = cb_run;
279 descriptor.run_adding = NULL;
280 descriptor.set_run_adding_gain = NULL;
281 descriptor.deactivate = cb_deactivate;
282 descriptor.cleanup = cb_cleanup;
283 #if USE_DSSI
284 memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor));
285 descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str());
286 memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
287 dssi_descriptor.DSSI_API_Version = 1;
288 dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi;
289 dssi_descriptor.configure = cb_configure;
290 dssi_descriptor.get_program = cb_get_program;
291 dssi_descriptor.select_program = cb_select_program;
292 if (Module::support_midi)
293 dssi_descriptor.run_synth = cb_run_synth;
295 presets = new std::vector<plugin_preset>;
296 preset_descs = new std::vector<DSSI_Program_Descriptor>;
298 preset_list plist_tmp, plist;
299 plist.load_defaults(true);
300 plist_tmp.load_defaults(false);
301 plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
303 // XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label
304 // if I forget about this, I'll be in a deep trouble
305 dssi_default_program.Bank = 0;
306 dssi_default_program.Program = 0;
307 dssi_default_program.Name = "default";
309 int pos = 1;
310 for (unsigned int i = 0; i < plist.presets.size(); i++)
312 plugin_preset &pp = plist.presets[i];
313 if (strcasecmp(pp.plugin.c_str(), descriptor.Label))
314 continue;
315 DSSI_Program_Descriptor pd;
316 pd.Bank = pos >> 7;
317 pd.Program = pos++;
318 pd.Name = pp.name.c_str();
319 preset_descs->push_back(pd);
320 presets->push_back(pp);
322 // printf("presets = %p:%d name = %s\n", presets, presets->size(), descriptor.Label);
324 #endif
327 ~ladspa_wrapper()
329 delete []descriptor.PortNames;
330 delete []descriptor.PortDescriptors;
331 delete []descriptor.PortRangeHints;
332 #if USE_DSSI
333 presets->clear();
334 preset_descs->clear();
335 delete presets;
336 delete preset_descs;
337 #endif
340 /// LADSPA instantiation function (create a plugin instance)
341 static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)
343 instance *mod = new instance();
344 mod->srate = sample_rate;
345 mod->post_instantiate();
346 return mod;
349 #if USE_DSSI
350 /// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset
351 static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index) {
352 if (index > presets->size())
353 return NULL;
354 if (index)
355 return &(*preset_descs)[index - 1];
356 return &dssi_default_program;
359 /// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset
360 static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program) {
361 instance *mod = (instance *)Instance;
362 unsigned int no = (Bank << 7) + Program - 1;
363 // printf("no = %d presets = %p:%d\n", no, presets, presets->size());
364 if (no == -1U) {
365 int rpc = ladspa_instance<Module>::real_param_count();
366 for (int i =0 ; i < rpc; i++)
367 *mod->params[i] = Module::param_props[i].def_value;
368 return;
370 if (no >= presets->size())
371 return;
372 plugin_preset &p = (*presets)[no];
373 // printf("activating preset %s\n", p.name.c_str());
374 p.activate(mod);
377 #endif
379 /// LADSPA port connection function
380 static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation) {
381 unsigned long ins = Module::in_count;
382 unsigned long outs = Module::out_count;
383 unsigned long params = ladspa_instance<Module>::real_param_count();
384 instance *const mod = (instance *)Instance;
385 if (port < ins)
386 mod->ins[port] = DataLocation;
387 else if (port < ins + outs)
388 mod->outs[port - ins] = DataLocation;
389 else if (port < ins + outs + params) {
390 int i = port - ins - outs;
391 mod->params[i] = DataLocation;
392 *mod->params[i] = Module::param_props[i].def_value;
396 /// LADSPA activate function (note that at this moment the ports are not set)
397 static void cb_activate(LADSPA_Handle Instance) {
398 instance *const mod = (instance *)Instance;
399 mod->activate_flag = true;
402 /// utility function: zero port values if mask is 0
403 static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples)
405 for (int i=0; i<Module::out_count; i++) {
406 if ((mask & (1 << i)) == 0) {
407 dsp::zero(module->outs[i] + offset, nsamples);
412 /// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
413 static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
414 instance *const mod = (instance *)Instance;
415 if (mod->activate_flag)
417 mod->set_sample_rate(mod->srate);
418 mod->activate();
419 mod->activate_flag = false;
421 mod->params_changed();
422 process_slice(mod, 0, SampleCount);
425 /// utility function: call process, and if it returned zeros in output masks, zero out the relevant output port buffers
426 static inline void process_slice(Module *mod, uint32_t offset, uint32_t end)
428 while(offset < end)
430 uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
431 uint32_t out_mask = mod->process(offset, newend - offset, -1, -1);
432 zero_by_mask(mod, out_mask, offset, newend - offset);
433 offset = newend;
437 #if USE_DSSI
438 /// DSSI "run synth" function, same as run() except it allows for event delivery
439 static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount,
440 snd_seq_event_t *Events, unsigned long EventCount) {
441 instance *const mod = (instance *)Instance;
442 if (mod->activate_flag)
444 mod->set_sample_rate(mod->srate);
445 mod->activate();
446 mod->activate_flag = false;
448 mod->params_changed();
450 uint32_t offset = 0;
451 for (uint32_t e = 0; e < EventCount; e++)
453 uint32_t timestamp = Events[e].time.tick;
454 if (timestamp != offset)
455 process_slice(mod, offset, timestamp);
456 process_dssi_event(mod, Events[e]);
457 offset = timestamp;
459 if (offset != SampleCount)
460 process_slice(mod, offset, SampleCount);
463 /// DSSI configure function (named properties)
464 static char *cb_configure(LADSPA_Handle Instance,
465 const char *Key,
466 const char *Value)
468 instance *const mod = (instance *)Instance;
469 return mod->configure(Key, Value);
472 /// Utility function: handle MIDI event (only handles a subset in this version)
473 static void process_dssi_event(Module *module, snd_seq_event_t &event)
475 switch(event.type) {
476 case SND_SEQ_EVENT_NOTEON:
477 module->note_on(event.data.note.note, event.data.note.velocity);
478 break;
479 case SND_SEQ_EVENT_NOTEOFF:
480 module->note_off(event.data.note.note, event.data.note.velocity);
481 break;
482 case SND_SEQ_EVENT_PGMCHANGE:
483 module->program_change(event.data.control.value);
484 break;
485 case SND_SEQ_EVENT_CONTROLLER:
486 module->control_change(event.data.control.param, event.data.control.value);
487 break;
488 case SND_SEQ_EVENT_PITCHBEND:
489 module->pitch_bend(event.data.control.value);
490 break;
493 #endif
495 /// LADSPA deactivate function
496 static void cb_deactivate(LADSPA_Handle Instance) {
497 instance *const mod = (instance *)Instance;
498 mod->deactivate();
501 /// LADSPA cleanup (delete instance) function
502 static void cb_cleanup(LADSPA_Handle Instance) {
503 instance *const mod = (instance *)Instance;
504 delete mod;
507 /// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions
508 static ladspa_wrapper &get() {
509 static ladspa_wrapper instance;
510 return instance;
516 #endif
518 #endif