4 #include "bcwindowbase.h"
11 PluginLV2::PluginLV2()
16 in_buffers = 0; iport = 0;
17 out_buffers = 0; oport = 0;
38 powerOf2BlockLength = 0;
40 boundedBlockLength = 0;
44 PluginLV2::~PluginLV2()
47 if( world ) lilv_world_free(world);
50 void PluginLV2::reset_lv2()
52 if( inst ) lilv_instance_deactivate(inst);
53 lilv_instance_free(inst); inst = 0;
54 lilv_uis_free(lilv_uis); lilv_uis = 0;
56 lilv_node_free(lv2_InputPort); lv2_InputPort = 0;
57 lilv_node_free(lv2_OutputPort); lv2_OutputPort = 0;
58 lilv_node_free(lv2_AudioPort); lv2_AudioPort = 0;
59 lilv_node_free(lv2_ControlPort); lv2_ControlPort = 0;
60 lilv_node_free(lv2_CVPort); lv2_CVPort = 0;
62 lilv_node_free(lv2_Optional); lv2_Optional = 0;
63 lilv_node_free(atom_AtomPort); atom_AtomPort = 0;
64 lilv_node_free(atom_Sequence); atom_Sequence = 0;
65 lilv_node_free(boundedBlockLength); boundedBlockLength = 0;
66 lilv_node_free(fixedBlockLength); fixedBlockLength = 0;
67 lilv_node_free(powerOf2BlockLength); powerOf2BlockLength = 0;
69 delete [] (char *)seq_out; seq_out = 0;
70 uri_table.remove_all_objects();
71 features.remove_all_objects(); ui_features = 0;
76 int PluginLV2::load_lv2(const char *path, char *title)
79 world = lilv_world_new();
81 printf("lv2: lilv_world_new failed\n");
84 lilv_world_load_all(world);
87 LilvNode *uri = lilv_new_uri(world, path);
89 printf("lv2: lilv_new_uri(%s) failed\n", path);
93 const LilvPlugins *all_plugins = lilv_world_get_all_plugins(world);
94 lilv = lilv_plugins_get_by_uri(all_plugins, uri);
97 printf("lv2: lilv_plugins_get_by_uriPlugin(%s) failed\n", path);
102 LilvNode *name = lilv_plugin_get_name(lilv);
103 const char *nm = lilv_node_as_string(name);
104 sprintf(title, "L2_%s", nm);
105 lilv_node_free(name);
110 int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate)
114 lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort);
115 lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
116 lv2_CVPort = lilv_new_uri(world, LV2_CORE__CVPort);
117 lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort);
118 lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort);
119 lv2_Optional = lilv_new_uri(world, LV2_CORE__connectionOptional);
120 atom_AtomPort = lilv_new_uri(world, LV2_ATOM__AtomPort);
121 atom_Sequence = lilv_new_uri(world, LV2_ATOM__Sequence);
122 powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
123 fixedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
124 boundedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__boundedBlockLength);
125 seq_out = (LV2_Atom_Sequence *) new char[sizeof(LV2_Atom_Sequence) + LV2_SEQ_SIZE];
127 conf.init_lv2(lilv, this);
128 nb_inputs = nb_outputs = 0;
130 for( int i=0; i<conf.nb_ports; ++i ) {
131 const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
133 int is_input = lilv_port_is_a(lilv, lp, lv2_InputPort);
134 if( !is_input && !lilv_port_is_a(lilv, lp, lv2_OutputPort) &&
135 !lilv_port_has_property(lilv, lp, lv2_Optional) ) {
136 printf("lv2: not input, not output, and not optional: %s\n", conf.names[i]);
139 if( is_input && lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
140 conf.append(new PluginLV2Client_Opt(&conf, i));
143 if( lilv_port_is_a(lilv, lp, lv2_AudioPort) ||
144 lilv_port_is_a(lilv, lp, lv2_CVPort ) ) {
145 if( is_input ) ++nb_inputs; else ++nb_outputs;
150 map.handle = (void*)&uri_table;
151 map.map = uri_table_map;
152 features.append(new Lv2Feature(LV2_URID_MAP_URI, &map));
153 unmap.handle = (void*)&uri_table;
154 unmap.unmap = uri_table_unmap;
155 features.append(new Lv2Feature(LV2_URID_UNMAP_URI, &unmap));
156 features.append(new Lv2Feature(LV2_BUF_SIZE__powerOf2BlockLength, 0));
157 features.append(new Lv2Feature(LV2_BUF_SIZE__fixedBlockLength, 0));
158 features.append(new Lv2Feature(LV2_BUF_SIZE__boundedBlockLength, 0));
161 if( sample_rate < 64 ) sample_rate = 64;
162 inst = lilv_plugin_instantiate(lilv, sample_rate, features);
164 printf("lv2: lilv_plugin_instantiate failed\n");
168 lilv_instance_activate(inst);
169 // not sure what to do with these
170 max_bufsz = nb_inputs &&
171 (lilv_plugin_has_feature(lilv, powerOf2BlockLength) ||
172 lilv_plugin_has_feature(lilv, fixedBlockLength) ||
173 lilv_plugin_has_feature(lilv, boundedBlockLength)) ? 4096 : 0;
177 LV2_URID PluginLV2::uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
179 return ((PluginLV2UriTable *)handle)->map(uri);
182 const char *PluginLV2::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
184 return ((PluginLV2UriTable *)handle)->unmap(urid);
187 void PluginLV2::connect_ports(PluginLV2ClientConfig &conf, int ports)
189 int ich = 0, och = 0;
190 for( int i=0; i<conf.nb_ports; ++i ) {
191 const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
193 int port = conf.ports[i];
194 if( !(port & ports) ) continue;
195 if( (port & PORTS_CONTROL) ) {
196 lilv_instance_connect_port(inst, i, &conf.ctls[i]);
199 if( (port & PORTS_AUDIO) ) {
200 if( (port & PORTS_INPUT) ) {
201 lilv_instance_connect_port(inst, i, in_buffers[ich]);
204 else if( (port & PORTS_OUTPUT) ) {
205 lilv_instance_connect_port(inst, i, out_buffers[och]);
210 if( (port & PORTS_ATOM) ) {
211 if( (port & PORTS_INPUT) )
212 lilv_instance_connect_port(inst, i, &seq_in);
213 else if( (port & PORTS_OUTPUT) )
214 lilv_instance_connect_port(inst, i, seq_out);
219 seq_in[0].atom.size = sizeof(LV2_Atom_Sequence_Body);
220 seq_in[0].atom.type = uri_table.map(LV2_ATOM__Sequence);
221 seq_in[1].atom.size = 0;
222 seq_in[1].atom.type = 0;
223 seq_out->atom.size = LV2_SEQ_SIZE;
224 seq_out->atom.type = uri_table.map(LV2_ATOM__Chunk);
227 void PluginLV2::del_buffer()
232 delete [] in_buffers; in_buffers = 0;
233 delete [] out_buffers; out_buffers = 0;
236 void PluginLV2::new_buffer(int64_t sz)
239 if( use_shm ) { // currently, always uses shm
240 shmid = shmget(IPC_PRIVATE, sz, IPC_CREAT | 0777);
242 bp = (unsigned char*)shmat(shmid, NULL, 0);
243 if( bp == (void *) -1 ) { perror("shmat"); bp = 0; }
244 shmctl(shmid, IPC_RMID, 0); // delete when last ref gone
247 perror("PluginLV2::allocate_buffer: shmget failed\n");
248 BC_Trace::dump_shm_stats(stdout);
252 shm_bfr = (shm_bfr_t *) bp;
253 if( shm_bfr ) shm_bfr->sz = sz;
256 shm_bfr_t *PluginLV2::shm_buffer(int shmid)
258 if( this->shmid != shmid ) {
259 if( this->shmid >= 0 ) {
260 shmdt(shm_bfr); this->shmid = -1;
264 shm_bfr = (shm_bfr_t *)shmat(shmid, NULL, 0);
265 if( shm_bfr == (void *)-1 ) { perror("shmat"); shm_bfr = 0; }
266 this->shmid = shm_bfr ? shmid : -1;
272 void PluginLV2::init_buffer(int samples)
274 int64_t sz = sizeof(shm_bfr_t) +
275 sizeof(iport[0])*nb_inputs + sizeof(oport[0])*nb_outputs +
276 sizeof(*in_buffers[0]) *samples * nb_inputs +
277 sizeof(*out_buffers[0])*samples * nb_outputs;
280 if( shm_bfr->sz < sz ||
281 shm_bfr->nb_inputs != nb_inputs ||
282 shm_bfr->nb_outputs != nb_outputs )
289 shm_bfr->samples = samples;
291 shm_bfr->nb_inputs = nb_inputs;
292 shm_bfr->nb_outputs = nb_outputs;
300 // int samples, done;
301 // int nb_inputs, nb_outputs;
302 // int iport[nb_inputs],
303 // float in_buffers[samples][nb_inputs];
304 // int oport[nb_outputs];
305 // float out_buffers[samples][nb_outputs];
308 void PluginLV2::map_buffer()
310 uint8_t *bp = (uint8_t *)(shm_bfr + 1);
312 nb_inputs = shm_bfr->nb_inputs;
314 bp += sizeof(iport[0])*nb_inputs;
315 in_buffers = new float*[nb_inputs];
316 int samples = shm_bfr->samples;
317 for(int i=0; i<nb_inputs; ++i ) {
318 in_buffers[i] = (float *)bp;
319 bp += sizeof(*in_buffers[0])*samples;
322 nb_outputs = shm_bfr->nb_outputs;
324 bp += sizeof(oport[0])*nb_outputs;
325 out_buffers = new float*[nb_outputs];
326 for( int i=0; i<nb_outputs; ++i ) {
327 out_buffers[i] = (float *)bp;
328 bp += sizeof(*out_buffers[0])*samples;
334 #include "pluginlv2ui.h"
336 PluginLV2ChildUI::PluginLV2ChildUI()
341 PluginLV2ChildUI::~PluginLV2ChildUI()
345 void PluginLV2ChildUI::run()
347 ArrayList<char *> av;
348 av.set_array_delete();
350 const char *exec_path = File::get_cinlib_path();
351 snprintf(arg, sizeof(arg), "%s/%s", exec_path, "lv2ui");
352 av.append(cstrdup(arg));
353 sprintf(arg, "%d", child_fd);
354 av.append(cstrdup(arg));
355 sprintf(arg, "%d", parent_fd);
356 av.append(cstrdup(arg));
357 sprintf(arg, "%d", ppid);
358 av.append(cstrdup(arg));
360 execv(av[0], &av.values[0]);
361 fprintf(stderr, "execv failed: %s\n %m\n", av.values[0]);
362 av.remove_all_objects();
367 PluginLV2UI::PluginLV2UI()
382 gtk_type = "http://lv2plug.in/ns/extensions/ui#GtkUI";
386 PluginLV2UI::~PluginLV2UI ()