Make Analyzer UI require instance-access
[calf.git] / src / calf / lv2wrap.h
blob0aecacad35b14f999a0808641c4c7a288ef6d8fc
1 /* Calf DSP Library
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
24 #if USE_LV2
26 #include <string>
27 #include <vector>
28 #include <lv2.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>
36 #include <string.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;
44 bool set_srate;
45 int srate_to_set;
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;
51 int out_count;
52 int real_param_count;
53 lv2_instance(audio_module_iface *_module)
55 module = _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();
61 urid_map = NULL;
62 event_data = NULL;
63 progress_report_feature = NULL;
64 midi_event_type = 0xFFFFFFFF;
66 srate_to_set = 44100;
67 set_srate = true;
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) {
77 return false;
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);
94 if (vars.empty())
95 return;
96 assert(urid_map);
97 uint32_t string_type = urid_map->map(urid_map->handle, LV2_ATOM__String);
98 assert(string_type);
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());
103 size_t len = 0;
104 uint32_t type = 0;
105 uint32_t flags = 0;
106 const void *ptr = (*retrieve)(callback_data, key, &len, &type, &flags);
107 if (ptr)
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());
114 else
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);
128 if (ts > offset)
130 module->process_slice(offset, ts);
131 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)
165 // XXXKF hack
166 if (param_no >= real_param_count)
167 return 0;
168 return (*params)[param_no];
170 virtual void set_param_value(int param_no, float value)
172 // XXXKF hack
173 if (param_no >= real_param_count)
174 return;
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>
188 struct lv2_wrapper
190 typedef lv2_instance instance;
191 static LV2_Descriptor descriptor;
192 static LV2_Calf_Descriptor calf_descriptor;
193 static LV2_State_Interface state_iface;
194 std::string uri;
196 lv2_wrapper()
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();
220 if (port < ins)
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;
251 while(*features)
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);
263 features++;
265 mod->post_instantiate();
266 return mod;
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);
279 mod->activate();
280 inst->set_srate = false;
282 mod->params_changed();
283 uint32_t offset = 0;
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)
293 inst->ins[1] = NULL;
295 static void cb_cleanup(LV2_Handle Instance)
297 instance *const mod = (instance *)Instance;
298 delete mod;
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))
306 return &state_iface;
307 return NULL;
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;
317 void *callback_data;
318 instance *inst;
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()),
326 value,
327 strlen(value) + 1,
328 string_data_type,
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);
334 store_state s;
335 s.store = store;
336 s.callback_data = handle;
337 s.inst = inst;
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;
348 if (inst->set_srate)
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;
357 return *instance;
363 #endif
364 #endif