5 * Copyright (C) 2018 GG
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "pluginlv2client.h"
30 #include "pluginlv2config.h"
31 #include "pluginserver.h"
39 PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y)
40 : BC_GenericButton(x, y, _("UI"))
50 int PluginLV2ClientUI::handle_event()
52 if( !gui->plugin->open_lv2_gui(gui) )
57 PluginLV2ClientReset::
58 PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y)
59 : BC_GenericButton(x, y, _("Reset"))
64 PluginLV2ClientReset::
65 ~PluginLV2ClientReset()
69 int PluginLV2ClientReset::handle_event()
71 PluginLV2Client *plugin = gui->plugin;
74 gui->update_selected();
76 plugin->send_configure_change();
81 PluginLV2ClientText(PluginLV2ClientWindow *gui, int x, int y, int w)
82 : BC_TextBox(x, y, w, 1, (char *)"")
88 ~PluginLV2ClientText()
92 int PluginLV2ClientText::handle_event()
98 PluginLV2ClientApply::
99 PluginLV2ClientApply(PluginLV2ClientWindow *gui, int x, int y)
100 : BC_GenericButton(x, y, _("Apply"))
105 PluginLV2ClientApply::
106 ~PluginLV2ClientApply()
110 int PluginLV2ClientApply::handle_event()
112 const char *text = gui->text->get_text();
113 if( text && gui->selected ) {
114 gui->selected->update(atof(text));
115 gui->update_selected();
116 gui->plugin->send_configure_change();
123 PluginLV2Client_OptPanel::
124 PluginLV2Client_OptPanel(PluginLV2ClientWindow *gui, int x, int y, int w, int h)
125 : BC_ListBox(x, y, w, h, LISTBOX_TEXT), opts(items[0]), vals(items[1])
128 update(); // init col/wid/columns
131 PluginLV2Client_OptPanel::
132 ~PluginLV2Client_OptPanel()
136 int PluginLV2Client_OptPanel::selection_changed()
138 PluginLV2Client_Opt *opt = 0;
139 BC_ListBoxItem *item = get_selection(0, 0);
141 PluginLV2Client_OptName *opt_name = (PluginLV2Client_OptName *)item;
148 void PluginLV2Client_OptPanel::update()
152 PluginLV2ClientConfig &conf = gui->plugin->config;
153 for( int i=0; i<conf.size(); ++i ) {
154 PluginLV2Client_Opt *opt = conf[i];
155 opts.append(opt->item_name);
156 vals.append(opt->item_value);
158 const char *cols[] = { "option", "value", };
159 const int col1_w = 150;
160 int wids[] = { col1_w, get_w()-col1_w };
161 BC_ListBox::update(&items[0], &cols[0], &wids[0], sizeof(items)/sizeof(items[0]));
164 PluginLV2ClientWindow::PluginLV2ClientWindow(PluginLV2Client *plugin)
165 : PluginClientWindow(plugin, 500, 300, 500, 300, 1)
167 this->plugin = plugin;
171 PluginLV2ClientWindow::~PluginLV2ClientWindow()
176 void PluginLV2ClientWindow::create_objects()
179 int x = 10, y = 10, x1;
180 add_subwindow(title = new BC_Title(x, y, plugin->title));
182 x1 = get_w() - BC_GenericButton::calculate_w(this, _("UI")) - 8;
183 add_subwindow(ui = new PluginLV2ClientUI(this, x1, y));
187 y += title->get_h() + 10;
188 add_subwindow(varbl = new BC_Title(x, y, ""));
189 add_subwindow(range = new BC_Title(x+160, y, ""));
190 x1 = get_w() - BC_GenericButton::calculate_w(this, _("Reset")) - 8;
191 add_subwindow(reset = new PluginLV2ClientReset(this, x1, y));
192 y += title->get_h() + 10;
193 x1 = get_w() - BC_GenericButton::calculate_w(this, _("Apply")) - 8;
194 add_subwindow(apply = new PluginLV2ClientApply(this, x1, y));
195 add_subwindow(text = new PluginLV2ClientText(this, x, y, x1-x - 8));
196 y += title->get_h() + 10;
197 add_subwindow(pot = new PluginLV2ClientPot(this, x, y));
198 x1 = x + pot->get_w() + 10;
199 add_subwindow(slider = new PluginLV2ClientSlider(this, x1, y+10));
200 y += pot->get_h() + 10;
203 plugin->load_configuration();
204 plugin->config.update();
206 int panel_x = x, panel_y = y;
207 int panel_w = get_w()-10 - panel_x;
208 int panel_h = get_h()-10 - panel_y;
209 panel = new PluginLV2Client_OptPanel(this, panel_x, panel_y, panel_w, panel_h);
210 add_subwindow(panel);
215 int PluginLV2ClientWindow::resize_event(int w, int h)
219 x1 = w - ui->get_w() - 8;
220 ui->reposition_window(x1, ui->get_y());
222 x1 = w - reset->get_w() - 8;
223 reset->reposition_window(x1, reset->get_y());
224 x1 = w - apply->get_w() - 8;
225 apply->reposition_window(x1, apply->get_y());
226 text->reposition_window(text->get_x(), text->get_y(), x1-text->get_x() - 8);
227 x1 = pot->get_x() + pot->get_w() + 10;
228 int w1 = w - slider->get_x() - 20;
229 slider->set_pointer_motion_range(w1);
230 slider->reposition_window(x1, slider->get_y(), w1, slider->get_h());
231 int panel_x = panel->get_x(), panel_y = panel->get_y();
232 panel->reposition_window(panel_x, panel_y, w-10-panel_x, h-10-panel_y);
236 PluginLV2ClientPot::PluginLV2ClientPot(PluginLV2ClientWindow *gui, int x, int y)
237 : BC_FPot(x, y, 0.f, 0.f, 0.f)
242 int PluginLV2ClientPot::handle_event()
244 if( gui->selected ) {
245 gui->selected->update(get_value());
246 gui->update_selected();
247 gui->plugin->send_configure_change();
252 PluginLV2ClientSlider::PluginLV2ClientSlider(PluginLV2ClientWindow *gui, int x, int y)
253 : BC_FSlider(x, y, 0, gui->get_w()-x-20, gui->get_w()-x-20, 0.f, 0.f, 0.f)
258 int PluginLV2ClientSlider::handle_event()
260 if( gui->selected ) {
261 gui->selected->update(get_value());
262 gui->update_selected();
263 gui->plugin->send_configure_change();
268 void PluginLV2ClientWindow::update_selected()
271 if( selected && plugin->parent_gui ) {
273 bfr.idx = selected->idx;
274 bfr.value = selected->get_value();
275 plugin->parent_gui->send_child(LV2_SET, &bfr, sizeof(bfr));
279 int PluginLV2ClientWindow::scalar(float f, char *rp)
282 if( f == FLT_MAX ) cp = "FLT_MAX";
283 else if( f == FLT_MIN ) cp = "FLT_MIN";
284 else if( f == -FLT_MAX ) cp = "-FLT_MAX";
285 else if( f == -FLT_MIN ) cp = "-FLT_MIN";
286 else if( f == 0 ) cp = signbit(f) ? "-0" : "0";
287 else if( isnan(f) ) cp = signbit(f) ? "-NAN" : "NAN";
288 else if( isinf(f) ) cp = signbit(f) ? "-INF" : "INF";
289 else return sprintf(rp, "%g", f);
290 return sprintf(rp, "%s", cp);
293 void PluginLV2ClientWindow::update(PluginLV2Client_Opt *opt)
295 if( selected != opt ) {
296 if( selected ) selected->item_name->set_selected(0);
298 if( selected ) selected->item_name->set_selected(1);
300 char var[BCSTRLEN]; var[0] = 0;
301 char val[BCSTRLEN]; val[0] = 0;
302 char rng[BCTEXTLEN]; rng[0] = 0;
304 sprintf(var,"%s:", opt->conf->names[opt->idx]);
306 cp += sprintf(cp,"( ");
307 float min = opt->conf->mins[opt->idx];
308 cp += scalar(min, cp);
309 cp += sprintf(cp, " .. ");
310 float max = opt->conf->maxs[opt->idx];
311 cp += scalar(max, cp);
312 cp += sprintf(cp, " )");
313 float v = opt->get_value();
314 sprintf(val, "%f", v);
315 slider->update(slider->get_w(), v, min, max);
316 pot->update(v, min, max);
319 slider->update(slider->get_w(), 0.f, 0.f, 0.f);
320 pot->update(0.f, 0.f, 0.f);
329 PluginLV2Client::PluginLV2Client(PluginServer *server)
330 : PluginAClient(server)
351 powerOf2BlockLength = 0;
352 fixedBlockLength = 0;
353 boundedBlockLength = 0;
358 PluginLV2Client::~PluginLV2Client()
361 lilv_world_free(world);
364 void PluginLV2Client::reset_lv2()
366 delete parent_gui; parent_gui = 0;
367 if( instance ) lilv_instance_deactivate(instance);
368 lilv_instance_free(instance); instance = 0;
369 lilv_node_free(powerOf2BlockLength); powerOf2BlockLength = 0;
370 lilv_node_free(fixedBlockLength); fixedBlockLength = 0;
371 lilv_node_free(boundedBlockLength); boundedBlockLength = 0;
372 lilv_node_free(atom_Sequence); atom_Sequence = 0;
373 lilv_node_free(atom_AtomPort); atom_AtomPort = 0;
374 lilv_node_free(lv2_Optional); lv2_Optional = 0;
375 lilv_node_free(lv2_ControlPort); lv2_ControlPort = 0;
376 lilv_node_free(lv2_AudioPort); lv2_AudioPort = 0;
377 lilv_node_free(lv2_CVPort); lv2_CVPort = 0;
378 lilv_node_free(lv2_OutputPort); lv2_OutputPort = 0;
379 lilv_node_free(lv2_InputPort); lv2_InputPort = 0;
380 delete [] (char *)seq_out; seq_out = 0;
381 uri_table.remove_all_objects();
387 config.remove_all_objects();
390 int PluginLV2Client::load_lv2(const char *path)
393 world = lilv_world_new();
395 printf("lv2: lilv_world_new failed");
398 lilv_world_load_all(world);
401 LilvNode *uri = lilv_new_uri(world, path);
403 printf("lv2: lilv_new_uri(%s) failed", path);
407 const LilvPlugins *all_plugins = lilv_world_get_all_plugins(world);
408 lilv = lilv_plugins_get_by_uri(all_plugins, uri);
411 printf("lv2: lilv_plugins_get_by_uriPlugin(%s) failed", path);
415 LilvNode *name = lilv_plugin_get_name(lilv);
416 const char *nm = lilv_node_as_string(name);
417 snprintf(title,sizeof(title),"L2_%s",nm);
418 lilv_node_free(name);
422 int PluginLV2Client::init_lv2()
426 lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort);
427 lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort);
428 lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort);
429 lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
430 lv2_CVPort = lilv_new_uri(world, LV2_CORE__CVPort);
431 lv2_Optional = lilv_new_uri(world, LV2_CORE__connectionOptional);
432 atom_AtomPort = lilv_new_uri(world, LV2_ATOM__AtomPort);
433 atom_Sequence = lilv_new_uri(world, LV2_ATOM__Sequence);
434 powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
435 fixedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
436 boundedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__boundedBlockLength);
437 seq_out = (LV2_Atom_Sequence *) new char[sizeof(LV2_Atom_Sequence) + LV2_SEQ_SIZE];
439 config.init_lv2(lilv);
440 nb_inputs = nb_outputs = 0;
442 for( int i=0; i<config.nb_ports; ++i ) {
443 const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
444 int is_input = lilv_port_is_a(lilv, lp, lv2_InputPort);
445 if( !is_input && !lilv_port_is_a(lilv, lp, lv2_OutputPort) &&
446 !lilv_port_has_property(lilv, lp, lv2_Optional) ) {
447 printf("lv2: not input, not output, and not optional: %s\n", config.names[i]);
450 if( is_input && lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
451 config.append(new PluginLV2Client_Opt(&config, i));
454 if( lilv_port_is_a(lilv, lp, lv2_AudioPort) ||
455 lilv_port_is_a(lilv, lp, lv2_CVPort ) ) {
456 if( is_input ) ++nb_inputs; else ++nb_outputs;
461 map.handle = (void*)&uri_table;
462 map.map = uri_table_map;
463 features.append(new Lv2Feature(LV2_URID_MAP_URI, &map));
464 unmap.handle = (void*)&uri_table;
465 unmap.unmap = uri_table_unmap;
466 features.append(new Lv2Feature(LV2_URID_UNMAP_URI, &unmap));
467 features.append(new Lv2Feature(LV2_BUF_SIZE__powerOf2BlockLength, 0));
468 features.append(new Lv2Feature(LV2_BUF_SIZE__fixedBlockLength, 0));
469 features.append(new Lv2Feature(LV2_BUF_SIZE__boundedBlockLength, 0));
472 instance = lilv_plugin_instantiate(lilv, sample_rate, features);
474 printf("lv2: lilv_plugin_instantiate failed: %s\n", server->title);
477 lilv_instance_activate(instance);
478 // not sure what to do with these
479 max_bufsz = nb_inputs &&
480 (lilv_plugin_has_feature(lilv, powerOf2BlockLength) ||
481 lilv_plugin_has_feature(lilv, fixedBlockLength) ||
482 lilv_plugin_has_feature(lilv, boundedBlockLength)) ? 4096 : 0;
486 LV2_URID PluginLV2Client::uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
488 return ((PluginLV2UriTable *)handle)->map(uri);
491 const char *PluginLV2Client::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
493 return ((PluginLV2UriTable *)handle)->unmap(urid);
496 NEW_WINDOW_MACRO(PluginLV2Client, PluginLV2ClientWindow)
498 int PluginLV2Client::load_configuration()
500 int64_t src_position = get_source_position();
501 KeyFrame *prev_keyframe = get_prev_keyframe(src_position);
502 PluginLV2ClientConfig curr_config;
503 curr_config.copy_from(config);
504 read_data(prev_keyframe);
505 int ret = !config.equivalent(curr_config) ? 1 : 0;
509 void PluginLV2Client::update_gui()
511 PluginClientThread *thread = get_thread();
512 if( !thread ) return;
513 PluginLV2ClientWindow *gui = (PluginLV2ClientWindow*)thread->get_window();
514 gui->lock_window("PluginFClient::update_gui");
515 load_configuration();
516 if( config.update() > 0 ) {
517 gui->update_selected();
520 gui->unlock_window();
523 void PluginLV2Client::update_lv2()
525 if( !parent_gui ) return;
526 parent_gui->send_child(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports);
529 void PluginLV2Client::lv2_update()
531 PluginClientThread *thread = get_thread();
532 if( !thread ) return;
533 PluginLV2ClientWindow *gui = (PluginLV2ClientWindow*)thread->get_window();
534 gui->lock_window("PluginLV2ParentGUI::handle_parent");
535 int ret = config.update();
536 if( ret ) gui->update(0);
537 gui->unlock_window();
538 if( ret ) send_configure_change();
541 void PluginLV2Client::lv2_update(float *vals)
543 int nb_ports = config.nb_ports;
544 float *ctls = config.ctls;
545 for( int i=0; i<nb_ports; ++i ) *ctls++ = *vals++;
549 void PluginLV2Client::lv2_set(int idx, float val)
551 config[idx]->set_value(val);
556 int PluginLV2Client::is_realtime() { return 1; }
557 int PluginLV2Client::is_multichannel() { return nb_inputs > 1 || nb_outputs > 1 ? 1 : 0; }
558 const char* PluginLV2Client::plugin_title() { return title; }
559 int PluginLV2Client::uses_gui() { return 1; }
560 int PluginLV2Client::is_synthesis() { return 1; }
562 char* PluginLV2Client::to_string(char *string, const char *input)
565 for( const char *cp=input; *cp; ++cp )
566 *bp++ = isalnum(*cp) ? *cp : '_';
571 void PluginLV2Client::save_data(KeyFrame *keyframe)
574 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
575 char name[BCTEXTLEN]; to_string(name, plugin_title());
576 output.tag.set_title(name);
577 for( int i=0; i<config.size(); ++i ) {
578 PluginLV2Client_Opt *opt = config[i];
579 output.tag.set_property(opt->get_symbol(), opt->get_value());
582 output.terminate_string();
585 void PluginLV2Client::read_data(KeyFrame *keyframe)
588 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
589 char name[BCTEXTLEN]; to_string(name, plugin_title());
591 while( !input.read_tag() ) {
592 if( !input.tag.title_is(name) ) continue;
593 for( int i=0; i<config.size(); ++i ) {
594 PluginLV2Client_Opt *opt = config[i];
595 float value = input.tag.get_property(opt->get_symbol(), 0.);
596 opt->set_value(value);
601 void PluginLV2Client::connect_ports()
603 int ich = 0, och = 0;
604 for( int i=0; i<config.nb_ports; ++i ) {
605 const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
606 if( lilv_port_is_a(lilv, lp, lv2_AudioPort) ||
607 lilv_port_is_a(lilv, lp, lv2_CVPort) ) {
608 if( lilv_port_is_a(lilv, lp, lv2_InputPort) )
609 lilv_instance_connect_port(instance, i, in_buffers[ich++]);
610 else if( lilv_port_is_a(lilv, lp, lv2_OutputPort))
611 lilv_instance_connect_port(instance, i, out_buffers[och++]);
614 if( lilv_port_is_a(lilv, lp, atom_AtomPort) ) {
615 if( lilv_port_is_a(lilv, lp, lv2_InputPort) )
616 lilv_instance_connect_port(instance, i, &seq_in);
618 lilv_instance_connect_port(instance, i, seq_out);
621 if( lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
622 lilv_instance_connect_port(instance, i, &config.ctls[i]);
627 seq_in[0].atom.size = sizeof(LV2_Atom_Sequence_Body);
628 seq_in[0].atom.type = uri_table.map(LV2_ATOM__Sequence);
629 seq_in[1].atom.size = 0;
630 seq_in[1].atom.type = 0;
631 seq_out->atom.size = LV2_SEQ_SIZE;
632 seq_out->atom.type = uri_table.map(LV2_ATOM__Chunk);
635 void PluginLV2Client::init_plugin(int size)
640 load_configuration();
645 bfrsz = MAX(size, bfrsz);
647 in_buffers = new float*[nb_in_bfrs=nb_inputs];
648 for(int i=0; i<nb_in_bfrs; ++i )
649 in_buffers[i] = new float[bfrsz];
652 out_buffers = new float*[nb_out_bfrs=nb_outputs];
653 for( int i=0; i<nb_out_bfrs; ++i )
654 out_buffers[i] = new float[bfrsz];
658 void PluginLV2Client::delete_buffers()
661 for( int i=0; i<nb_in_bfrs; ++i ) delete [] in_buffers[i];
662 delete [] in_buffers; in_buffers = 0; nb_in_bfrs = 0;
665 for( int i=0; i<nb_out_bfrs; ++i ) delete [] out_buffers[i];
666 delete [] out_buffers; out_buffers = 0; nb_out_bfrs = 0;
671 int PluginLV2Client::open_lv2_gui(PluginLV2ClientWindow *gui)
675 if( !parent_gui->done ) return 0;
678 parent_gui = new PluginLV2ParentGUI(gui);
679 parent_gui->start_child();
680 parent_gui->start_parent();
687 int PluginLV2Client::process_realtime(int64_t size,
688 Samples *input_ptr, Samples *output_ptr)
692 for( int i=0; i<nb_in_bfrs; ++i ) {
693 double *inp = input_ptr->get_data();
694 float *ip = in_buffers[i];
695 for( int j=size; --j>=0; *ip++=*inp++ );
697 for( int i=0; i<nb_out_bfrs; ++i )
698 bzero(out_buffers[i], size*sizeof(float));
701 lilv_instance_run(instance, size);
703 double *outp = output_ptr->get_data();
704 float *op = out_buffers[0];
705 for( int i=size; --i>=0; *outp++=*op++ );
709 int PluginLV2Client::process_realtime(int64_t size,
710 Samples **input_ptr, Samples **output_ptr)
714 for( int i=0; i<nb_in_bfrs; ++i ) {
715 int k = i < PluginClient::total_in_buffers ? i : 0;
716 double *inp = input_ptr[k]->get_data();
717 float *ip = in_buffers[i];
718 for( int j=size; --j>=0; *ip++=*inp++ );
720 for( int i=0; i<nb_out_bfrs; ++i )
721 bzero(out_buffers[i], size*sizeof(float));
724 lilv_instance_run(instance, size);
726 int nbfrs = PluginClient::total_out_buffers;
727 if( nb_out_bfrs < nbfrs ) nbfrs = nb_out_bfrs;
728 for( int i=0; i<nbfrs; ++i ) {
729 double *outp = output_ptr[i]->get_data();
730 float *op = out_buffers[i];
731 for( int j=size; --j>=0; *outp++=*op++ );
736 PluginServer* MWindow::new_lv2_server(MWindow *mwindow, const char *name)
738 return new PluginServer(mwindow, name, PLUGIN_TYPE_LV2);
741 PluginClient *PluginServer::new_lv2_plugin()
743 PluginLV2Client *client = new PluginLV2Client(this);
744 //for some lv2 clients
745 if( client->sample_rate < 64 ) client->sample_rate = 64;
746 if( client->project_sample_rate < 64 ) client->project_sample_rate = 64;
747 if( client->load_lv2(path) ) { delete client; client = 0; }
748 else client->init_lv2();
752 int MWindow::init_lv2_index(MWindow *mwindow, Preferences *preferences, FILE *fp)
754 printf("init lv2 index:\n");
755 LilvWorld *world = lilv_world_new();
756 lilv_world_load_all(world);
757 const LilvPlugins *all_plugins = lilv_world_get_all_plugins(world);
759 LILV_FOREACH(plugins, i, all_plugins) {
760 const LilvPlugin *lilv = lilv_plugins_get(all_plugins, i);
761 const char *uri = lilv_node_as_uri(lilv_plugin_get_uri(lilv));
762 PluginServer server(mwindow, uri, PLUGIN_TYPE_LV2);
763 int result = server.open_plugin(1, preferences, 0, 0);
765 server.write_table(fp, uri, PLUGIN_LV2_ID, 0);
766 server.close_plugin();
770 lilv_world_free(world);
774 ForkChild *PluginLV2ParentGUI::new_fork()
777 return new PluginLV2ChildGUI();
783 PluginLV2ParentGUI::PluginLV2ParentGUI(PluginLV2ClientWindow *gui)
788 PluginLV2ParentGUI::~PluginLV2ParentGUI()
793 void PluginLV2ParentGUI::start_parent()
796 const char *path = gui->plugin->server->path;
797 send_child(LV2_OPEN, path, strlen(path)+1);
798 PluginLV2ClientConfig &conf = gui->plugin->config;
799 send_child(LV2_START, 0, 0);
800 send_child(LV2_LOAD, conf.ctls, conf.nb_ports*sizeof(float));
803 int PluginLV2ParentGUI::handle_parent()
807 switch( parent_token ) {
809 gui->plugin->lv2_update((float *)parent_data);
812 control_t *ctl = (control_t *)parent_data;
813 gui->plugin->lv2_set(ctl->idx, ctl->value);
827 int PluginLV2ChildGUI::handle_child()
834 #include "pluginserver.h"
836 PluginServer* MWindow::new_lv2_server(MWindow *mwindow, const char *name) { return 0; }
837 PluginClient *PluginServer::new_lv2_plugin() { return 0; }
838 int MWindow::init_lv2_index(MWindow *mwindow, Preferences *preferences, FILE *fp) { return 0; }
840 #endif /* HAVE_LV2 */