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
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
)
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
50 static int real_param_count()
52 static int _real_param_count
= calc_real_param_count
<Module
>();
53 return _real_param_count
;
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
;
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
)
73 if (param_no
>= real_param_count())
75 return *Module::params
[param_no
];
77 virtual void set_param_value(int param_no
, float value
)
80 if (param_no
>= real_param_count())
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
) {
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"))
120 execute(atoi(value
));
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
;
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
;
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
];
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
) {
195 prh
.HintDescriptor
|= LADSPA_HINT_TOGGLED
;
196 prh
.HintDescriptor
&= ~(LADSPA_HINT_BOUNDED_ABOVE
| LADSPA_HINT_BOUNDED_BELOW
);
200 prh
.HintDescriptor
|= LADSPA_HINT_INTEGER
;
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
));
207 prh
.HintDescriptor
|= LADSPA_HINT_DEFAULT_MINIMUM
;
209 prh
.HintDescriptor
|= LADSPA_HINT_DEFAULT_LOW
;
211 prh
.HintDescriptor
|= LADSPA_HINT_DEFAULT_MIDDLE
;
213 prh
.HintDescriptor
|= LADSPA_HINT_DEFAULT_HIGH
;
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
;
227 prh
.HintDescriptor
|= LADSPA_HINT_DEFAULT_0
;
229 switch(pp
.flags
& PF_SCALEMASK
) {
231 prh
.HintDescriptor
|= LADSPA_HINT_LOGARITHMIC
;
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
;
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";
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
))
275 DSSI_Program_Descriptor pd
;
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);
289 delete []descriptor
.PortNames
;
290 delete []descriptor
.PortDescriptors
;
291 delete []descriptor
.PortRangeHints
;
294 preset_descs
->clear();
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();
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())
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());
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
;
330 if (no
>= presets
->size())
332 plugin_preset
&p
= (*presets
)[no
];
333 // printf("activating preset %s\n", p.name.c_str());
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
;
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
);
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
)
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
);
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
);
406 mod
->activate_flag
= false;
408 mod
->params_changed();
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
]);
419 if (offset
!= SampleCount
)
420 process_slice(mod
, offset
, SampleCount
);
423 /// DSSI configure function (named properties)
424 static char *cb_configure(LADSPA_Handle Instance
,
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
)
436 case SND_SEQ_EVENT_NOTEON
:
437 module
->note_on(event
.data
.note
.note
, event
.data
.note
.velocity
);
439 case SND_SEQ_EVENT_NOTEOFF
:
440 module
->note_off(event
.data
.note
.note
, event
.data
.note
.velocity
);
442 case SND_SEQ_EVENT_PGMCHANGE
:
443 module
->program_change(event
.data
.control
.value
);
445 case SND_SEQ_EVENT_CONTROLLER
:
446 module
->control_change(event
.data
.control
.param
, event
.data
.control
.value
);
448 case SND_SEQ_EVENT_PITCHBEND
:
449 module
->pitch_bend(event
.data
.control
.value
);
455 /// LADSPA deactivate function
456 static void cb_deactivate(LADSPA_Handle Instance
) {
457 instance
*const mod
= (instance
*)Instance
;
461 /// LADSPA cleanup (delete instance) function
462 static void cb_cleanup(LADSPA_Handle Instance
) {
463 instance
*const mod
= (instance
*)Instance
;
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
;