2 * LV2 wrapper templates
4 * Copyright (C) 2001-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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
21 #ifndef CALF_LV2WRAP_H
22 #define CALF_LV2WRAP_H
29 #include <calf/giface.h>
30 #include <calf/lv2_atom.h>
31 #include <calf/lv2_atom_util.h>
32 #include <calf/lv2_midi.h>
33 #include <calf/lv2_state.h>
34 #include <calf/lv2_progress.h>
35 #include <calf/lv2_urid.h>
38 namespace calf_plugins
{
40 struct lv2_instance
: public plugin_ctl_iface
, public progress_report_iface
42 const plugin_metadata_iface
*metadata
;
43 audio_module_iface
*module
;
46 LV2_Atom_Sequence
*event_data
;
47 LV2_URID_Map
*urid_map
;
48 uint32_t midi_event_type
;
49 LV2_Progress
*progress_report_feature
;
50 float **ins
, **outs
, **params
;
53 lv2_instance(audio_module_iface
*_module
)
56 module
->get_port_arrays(ins
, outs
, params
);
57 metadata
= module
->get_metadata_iface();
58 out_count
= metadata
->get_output_count();
59 real_param_count
= metadata
->get_param_count();
63 progress_report_feature
= NULL
;
64 midi_event_type
= 0xFFFFFFFF;
69 /// This, and not Module::post_instantiate, is actually called by lv2_wrapper class
70 void post_instantiate()
72 if (progress_report_feature
)
73 module
->set_progress_report_iface(this);
74 module
->post_instantiate(srate_to_set
);
76 virtual bool activate_preset(int bank
, int program
) {
79 virtual float get_level(unsigned int port
) { return 0.f
; }
80 virtual void execute(int cmd_no
) {
81 module
->execute(cmd_no
);
83 virtual void report_progress(float percentage
, const std::string
&message
) {
84 if (progress_report_feature
)
85 (*progress_report_feature
->progress
)(progress_report_feature
->context
, percentage
, !message
.empty() ? message
.c_str() : NULL
);
87 void send_configures(send_configure_iface
*sci
) {
88 module
->send_configures(sci
);
90 void impl_restore(LV2_State_Retrieve_Function retrieve
, void *callback_data
)
92 std::vector
<std::string
> vars
;
93 module
->get_metadata_iface()->get_configure_vars(vars
);
97 uint32_t string_type
= urid_map
->map(urid_map
->handle
, LV2_ATOM__String
);
99 for (size_t i
= 0; i
< vars
.size(); ++i
)
101 std::string pred
= std::string("urn:calf:") + vars
[i
];
102 const uint32_t key
= urid_map
->map(urid_map
->handle
, pred
.c_str());
106 const void *ptr
= (*retrieve
)(callback_data
, key
, &len
, &type
, &flags
);
109 if (type
!= string_type
)
110 fprintf(stderr
, "Warning: type is %d, expected %d\n", (int)type
, (int)string_type
);
111 printf("Calling configure on %s\n", vars
[i
].c_str());
112 configure(vars
[i
].c_str(), std::string((const char *)ptr
, len
).c_str());
115 configure(vars
[i
].c_str(), NULL
);
118 char *configure(const char *key
, const char *value
) {
119 // disambiguation - the plugin_ctl_iface version is just a stub, so don't use it
120 return module
->configure(key
, value
);
123 void process_events(uint32_t &offset
) {
124 LV2_ATOM_SEQUENCE_FOREACH(event_data
, ev
) {
125 const uint8_t* const data
= (const uint8_t*)(ev
+ 1);
126 uint32_t ts
= ev
->time
.frames
;
127 // printf("Event: timestamp %d type %d vs %d\n", ts, ev->body.type, midi_event_type);
130 module
->process_slice(offset
, ts
);
133 if (ev
->body
.type
== midi_event_type
)
135 // printf("Midi message %x %x %x %d\n", data[0], data[1], data[2], ev->body.size);
136 int channel
= data
[0] & 0x0f;
137 switch (lv2_midi_message_type(data
))
139 case LV2_MIDI_MSG_INVALID
: break;
140 case LV2_MIDI_MSG_NOTE_OFF
: module
->note_off(channel
, data
[1], data
[2]); break;
141 case LV2_MIDI_MSG_NOTE_ON
: module
->note_on(channel
, data
[1], data
[2]); break;
142 case LV2_MIDI_MSG_CONTROLLER
: module
->control_change(channel
, data
[1], data
[2]); break;
143 case LV2_MIDI_MSG_PGM_CHANGE
: module
->program_change(channel
, data
[1]); break;
144 case LV2_MIDI_MSG_CHANNEL_PRESSURE
: module
->channel_pressure(channel
, data
[1]); break;
145 case LV2_MIDI_MSG_BENDER
: module
->pitch_bend(channel
, data
[1] + 128 * data
[2] - 8192); break;
146 case LV2_MIDI_MSG_NOTE_PRESSURE
: break;
147 case LV2_MIDI_MSG_SYSTEM_EXCLUSIVE
: break;
148 case LV2_MIDI_MSG_MTC_QUARTER
: break;
149 case LV2_MIDI_MSG_SONG_POS
: break;
150 case LV2_MIDI_MSG_SONG_SELECT
: break;
151 case LV2_MIDI_MSG_TUNE_REQUEST
: break;
152 case LV2_MIDI_MSG_CLOCK
: break;
153 case LV2_MIDI_MSG_START
: break;
154 case LV2_MIDI_MSG_CONTINUE
: break;
155 case LV2_MIDI_MSG_STOP
: break;
156 case LV2_MIDI_MSG_ACTIVE_SENSE
: break;
157 case LV2_MIDI_MSG_RESET
: break;
163 virtual float get_param_value(int param_no
)
166 if (param_no
>= real_param_count
)
168 return (*params
)[param_no
];
170 virtual void set_param_value(int param_no
, float value
)
173 if (param_no
>= real_param_count
)
175 *params
[param_no
] = value
;
177 virtual const plugin_metadata_iface
*get_metadata_iface() const { return metadata
; }
178 virtual const line_graph_iface
*get_line_graph_iface() const { return module
->get_line_graph_iface(); }
179 virtual const phase_graph_iface
*get_phase_graph_iface() const { return module
->get_phase_graph_iface(); }
180 virtual int send_status_updates(send_updates_iface
*sui
, int last_serial
) { return module
->send_status_updates(sui
, last_serial
); }
183 struct LV2_Calf_Descriptor
{
184 plugin_ctl_iface
*(*get_pci
)(LV2_Handle Instance
);
187 template<class Module
>
190 typedef lv2_instance instance
;
191 static LV2_Descriptor descriptor
;
192 static LV2_Calf_Descriptor calf_descriptor
;
193 static LV2_State_Interface state_iface
;
198 ladspa_plugin_info
&info
= Module::plugin_info
;
199 uri
= "http://calf.sourceforge.net/plugins/" + std::string(info
.label
);
200 descriptor
.URI
= uri
.c_str();
201 descriptor
.instantiate
= cb_instantiate
;
202 descriptor
.connect_port
= cb_connect
;
203 descriptor
.activate
= cb_activate
;
204 descriptor
.run
= cb_run
;
205 descriptor
.deactivate
= cb_deactivate
;
206 descriptor
.cleanup
= cb_cleanup
;
207 descriptor
.extension_data
= cb_ext_data
;
208 state_iface
.save
= cb_state_save
;
209 state_iface
.restore
= cb_state_restore
;
210 calf_descriptor
.get_pci
= cb_get_pci
;
213 static void cb_connect(LV2_Handle Instance
, uint32_t port
, void *DataLocation
)
215 instance
*const mod
= (instance
*)Instance
;
216 const plugin_metadata_iface
*md
= mod
->metadata
;
217 unsigned long ins
= md
->get_input_count();
218 unsigned long outs
= md
->get_output_count();
219 unsigned long params
= md
->get_param_count();
221 mod
->ins
[port
] = (float *)DataLocation
;
222 else if (port
< ins
+ outs
)
223 mod
->outs
[port
- ins
] = (float *)DataLocation
;
224 else if (port
< ins
+ outs
+ params
) {
225 int i
= port
- ins
- outs
;
226 mod
->params
[i
] = (float *)DataLocation
;
228 else if (md
->get_midi() && port
== ins
+ outs
+ params
) {
229 mod
->event_data
= (LV2_Atom_Sequence
*)DataLocation
;
233 static void cb_activate(LV2_Handle Instance
)
235 instance
*const mod
= (instance
*)Instance
;
236 mod
->set_srate
= true;
239 static void cb_deactivate(LV2_Handle Instance
)
241 instance
*const mod
= (instance
*)Instance
;
242 mod
->module
->deactivate();
245 static LV2_Handle
cb_instantiate(const LV2_Descriptor
* Descriptor
, double sample_rate
, const char *bundle_path
, const LV2_Feature
*const *features
)
247 instance
*mod
= new instance(new Module
);
248 // XXXKF some people use fractional sample rates; we respect them ;-)
249 mod
->srate_to_set
= (uint32_t)sample_rate
;
250 mod
->set_srate
= true;
253 if (!strcmp((*features
)->URI
, LV2_URID_MAP_URI
))
255 mod
->urid_map
= (LV2_URID_Map
*)((*features
)->data
);
256 mod
->midi_event_type
= mod
->urid_map
->map(
257 mod
->urid_map
->handle
, LV2_MIDI__MidiEvent
);
259 else if (!strcmp((*features
)->URI
, LV2_PROGRESS_URI
))
261 mod
->progress_report_feature
= (LV2_Progress
*)((*features
)->data
);
265 mod
->post_instantiate();
268 static plugin_ctl_iface
*cb_get_pci(LV2_Handle Instance
)
270 return static_cast<plugin_ctl_iface
*>(Instance
);
273 static void cb_run(LV2_Handle Instance
, uint32_t SampleCount
)
275 instance
*const inst
= (instance
*)Instance
;
276 audio_module_iface
*mod
= inst
->module
;
277 if (inst
->set_srate
) {
278 mod
->set_sample_rate(inst
->srate_to_set
);
280 inst
->set_srate
= false;
282 mod
->params_changed();
284 if (inst
->event_data
)
286 inst
->process_events(offset
);
288 bool simulate_stereo_input
= (Module::in_count
> 1) && Module::simulate_stereo_input
&& !inst
->ins
[1];
289 if (simulate_stereo_input
)
290 inst
->ins
[1] = inst
->ins
[0];
291 inst
->module
->process_slice(offset
, SampleCount
);
292 if (simulate_stereo_input
)
295 static void cb_cleanup(LV2_Handle Instance
)
297 instance
*const mod
= (instance
*)Instance
;
301 static const void *cb_ext_data(const char *URI
)
303 if (!strcmp(URI
, "http://foltman.com/ns/calf-plugin-instance"))
304 return &calf_descriptor
;
305 if (!strcmp(URI
, LV2_STATE__interface
))
309 static LV2_State_Status
cb_state_save(
310 LV2_Handle Instance
, LV2_State_Store_Function store
, LV2_State_Handle handle
,
311 uint32_t flags
, const LV2_Feature
*const * features
)
313 instance
*const inst
= (instance
*)Instance
;
314 struct store_state
: public send_configure_iface
316 LV2_State_Store_Function store
;
319 uint32_t string_data_type
;
321 virtual void send_configure(const char *key
, const char *value
)
323 std::string pred
= std::string("urn:calf:") + key
;
324 (*store
)(callback_data
,
325 inst
->urid_map
->map(inst
->urid_map
->handle
, pred
.c_str()),
329 LV2_STATE_IS_POD
|LV2_STATE_IS_PORTABLE
);
332 // A host that supports State MUST support URID-Map as well.
333 assert(inst
->urid_map
);
336 s
.callback_data
= handle
;
338 s
.string_data_type
= inst
->urid_map
->map(inst
->urid_map
->handle
, LV2_ATOM__String
);
340 inst
->send_configures(&s
);
341 return LV2_STATE_SUCCESS
;
343 static LV2_State_Status
cb_state_restore(
344 LV2_Handle Instance
, LV2_State_Retrieve_Function retrieve
, LV2_State_Handle callback_data
,
345 uint32_t flags
, const LV2_Feature
*const * features
)
347 instance
*const inst
= (instance
*)Instance
;
349 inst
->module
->set_sample_rate(inst
->srate_to_set
);
351 inst
->impl_restore(retrieve
, callback_data
);
352 return LV2_STATE_SUCCESS
;
355 static lv2_wrapper
&get() {
356 static lv2_wrapper
*instance
= new lv2_wrapper
;