4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "pluginaclientlad.h"
27 #include "pluginserver.h"
36 PluginAClientConfig::PluginAClientConfig()
41 PluginAClientConfig::~PluginAClientConfig()
46 void PluginAClientConfig::reset()
53 void PluginAClientConfig::delete_objects()
55 delete [] port_data; port_data = 0;
56 delete [] port_type; port_type = 0;
61 int PluginAClientConfig::equivalent(PluginAClientConfig &that)
63 if(that.total_ports != total_ports) return 0;
64 for(int i = 0; i < total_ports; i++)
65 if(!EQUIV(port_data[i], that.port_data[i])) return 0;
69 // Need PluginServer to do this.
70 void PluginAClientConfig::copy_from(PluginAClientConfig &that)
72 if(total_ports != that.total_ports)
75 total_ports = that.total_ports;
76 port_data = new LADSPA_Data[total_ports];
77 port_type = new int[total_ports];
80 for(int i = 0; i < total_ports; i++)
82 port_type[i] = that.port_type[i];
83 port_data[i] = that.port_data[i];
84 //printf("PluginAClientConfig::copy_from 1 %f %f\n", port_data[i], that.port_data[i]);
89 void PluginAClientConfig::interpolate(PluginAClientConfig &prev,
90 PluginAClientConfig &next,
93 int64_t current_frame)
98 void PluginAClientConfig::initialize(PluginServer *server)
102 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
103 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
104 const LADSPA_PortRangeHint *lad_hint = lad_desc->PortRangeHints;
105 int port_count = lad_desc->PortCount;
106 for(int i = 0; i < port_count; i++) {
107 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
108 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
112 port_data = new LADSPA_Data[total_ports];
113 port_type = new int[total_ports];
115 for(int port = 0, i = 0; i < port_count; i++) {
116 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
117 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
118 // Convert LAD default to default value
120 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
122 // Store type of port for GUI use
123 port_type[port] = PORT_NORMAL;
124 if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) /* &&
125 LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc) &&
126 LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc) */ ) // LAD frequency table
127 port_type[port] = PORT_FREQ_INDEX;
128 else if(LADSPA_IS_HINT_TOGGLED(hint_desc))
129 port_type[port] = PORT_TOGGLE;
130 else if(LADSPA_IS_HINT_INTEGER(hint_desc))
131 port_type[port] = PORT_INTEGER;
133 // Get default of port using crazy hinting system
134 if( LADSPA_IS_HINT_DEFAULT_0(hint_desc) )
136 else if( LADSPA_IS_HINT_DEFAULT_1(hint_desc) )
138 else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) )
140 else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) )
141 value = port_type[port] == PORT_FREQ_INDEX ?
142 440.0 / 44100 : 440.0;
143 else if( LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_desc) )
144 value = lad_hint->UpperBound;
145 else if( LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_desc) )
146 value = lad_hint->LowerBound;
147 else if( LADSPA_IS_HINT_DEFAULT_LOW(hint_desc) )
148 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
149 exp(log(lad_hint->LowerBound) * 0.25 +
150 log(lad_hint->UpperBound) * 0.75) :
151 lad_hint->LowerBound * 0.25 +
152 lad_hint->UpperBound * 0.75;
153 else if( LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_desc) )
154 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
155 exp(log(lad_hint->LowerBound) * 0.5 +
156 log(lad_hint->UpperBound) * 0.5) :
157 lad_hint->LowerBound * 0.5 +
158 lad_hint->UpperBound * 0.5;
159 else if( LADSPA_IS_HINT_DEFAULT_HIGH(hint_desc) )
160 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
161 exp(log(lad_hint->LowerBound) * 0.75 +
162 log(lad_hint->UpperBound) * 0.25) :
163 lad_hint->LowerBound * 0.75 +
164 lad_hint->UpperBound * 0.25;
166 port_data[port] = value;
172 PluginACLientToggle::PluginACLientToggle(PluginAClientLAD *plugin,
176 : BC_CheckBox(x, y, (int)(*output))
178 this->plugin = plugin;
179 this->output = output;
182 int PluginACLientToggle::handle_event()
184 *output = get_value();
185 plugin->send_configure_change();
190 PluginACLientILinear::PluginACLientILinear(PluginAClientLAD *plugin,
196 : BC_IPot(x, y, (int)(*output), min, max)
198 this->plugin = plugin;
199 this->output = output;
202 int PluginACLientILinear::handle_event()
204 *output = get_value();
205 plugin->send_configure_change();
210 PluginACLientFLinear::PluginACLientFLinear(PluginAClientLAD *plugin,
216 : BC_FPot(x, y, *output, min, max)
218 this->plugin = plugin;
219 this->output = output;
223 int PluginACLientFLinear::handle_event()
225 *output = get_value();
226 plugin->send_configure_change();
231 PluginACLientFreq::PluginACLientFreq(PluginAClientLAD *plugin,
232 int x, int y, LADSPA_Data *output, int translate_linear)
233 : BC_QPot(x, y, translate_linear ?
234 (int)(*output * plugin->PluginAClient::project_sample_rate) :
237 this->plugin = plugin;
238 this->output = output;
239 this->translate_linear = translate_linear;
242 int PluginACLientFreq::handle_event()
244 *output = translate_linear ?
245 (float)get_value() / plugin->PluginAClient::project_sample_rate :
247 plugin->send_configure_change();
253 PluginAClientWindow::PluginAClientWindow(PluginAClientLAD *plugin)
254 : PluginClientWindow(plugin, 500, plugin->config.total_ports * 30 + 60,
255 500, plugin->config.total_ports * 30 + 60, 0)
257 this->plugin = plugin;
260 PluginAClientWindow::~PluginAClientWindow()
265 void PluginAClientWindow::create_objects()
267 PluginServer *server = plugin->server;
268 char string[BCTEXTLEN];
269 int current_port = 0;
274 int title_vmargin = 5;
276 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
277 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
278 int port_count = lad_desc->PortCount;
279 for(int i = 0; i < port_count; i++) {
280 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
281 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
282 int w = get_text_width(MEDIUMFONT, (char*)lad_desc->PortNames[i]);
283 if(w > max_w) max_w = w;
288 for(int i = 0; i < port_count; i++) {
289 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
290 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
291 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
292 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
293 int use_min = LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc);
294 int use_max = LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc);
295 sprintf(string, "%s:", lad_desc->PortNames[i]);
296 // printf("PluginAClientWindow::create_objects 1 %s type=%d lower: %d %f upper: %d %f\n",
297 // string, plugin->config.port_type[current_port],
298 // use_min, lad_hint->LowerBound, use_max, lad_hint->UpperBound);
300 switch(plugin->config.port_type[current_port]) {
301 case PluginAClientConfig::PORT_NORMAL: {
302 PluginACLientFLinear *flinear;
303 float min = use_min ? lad_hint->LowerBound : 0;
304 float max = use_max ? lad_hint->UpperBound : 100;
305 add_subwindow(new BC_Title(x, y + title_vmargin, string));
306 add_subwindow(flinear = new PluginACLientFLinear(
307 plugin, (current_port % 2) ? x2 : x3, y,
308 &plugin->config.port_data[current_port],
310 fpots.append(flinear);
312 case PluginAClientConfig::PORT_FREQ_INDEX: {
313 PluginACLientFreq *freq;
314 add_subwindow(new BC_Title(x, y + title_vmargin, string));
315 add_subwindow(freq = new PluginACLientFreq(plugin,
316 (current_port % 2) ? x2 : x3, y,
317 &plugin->config.port_data[current_port], 0
318 /* (plugin->config.port_type[current_port] ==
319 PluginAClientConfig::PORT_FREQ_INDEX */));
322 case PluginAClientConfig::PORT_TOGGLE: {
323 PluginACLientToggle *toggle;
324 add_subwindow(new BC_Title(x, y + title_vmargin, string));
325 add_subwindow(toggle = new PluginACLientToggle(plugin,
326 (current_port % 2) ? x2 : x3, y,
327 &plugin->config.port_data[current_port]));
328 toggles.append(toggle);
330 case PluginAClientConfig::PORT_INTEGER: {
331 PluginACLientILinear *ilinear;
332 float min = use_min ? lad_hint->LowerBound : 0;
333 float max = use_max ? lad_hint->UpperBound : 100;
334 add_subwindow(new BC_Title(x, y + title_vmargin, string));
335 add_subwindow(ilinear = new PluginACLientILinear( plugin,
336 (current_port % 2) ? x2 : x3, y,
337 &plugin->config.port_data[current_port],
338 (int)min, (int)max));
339 ipots.append(ilinear);
344 //printf("PluginAClientWindow::create_objects 2\n");
348 sprintf(string, _("Author: %s"), lad_desc->Maker);
349 add_subwindow(new BC_Title(x, y, string));
351 sprintf(string, _("License: %s"), lad_desc->Copyright);
352 add_subwindow(new BC_Title(x, y, string));
358 PluginAClientLAD::PluginAClientLAD(PluginServer *server)
359 : PluginAClient(server)
364 total_outbuffers = 0;
365 buffer_allocation = 0;
369 PluginAClientLAD::~PluginAClientLAD()
375 NEW_WINDOW_MACRO(PluginAClientLAD, PluginAClientWindow)
377 int PluginAClientLAD::is_realtime()
382 int PluginAClientLAD::is_multichannel()
384 if(get_inchannels() > 1 || get_outchannels() > 1) return 1;
388 int PluginAClientLAD::get_inchannels()
391 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
392 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
393 int port_count = lad_desc->PortCount;
394 for( int i = 0; i < port_count; ++i ) {
395 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
396 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
402 int PluginAClientLAD::get_outchannels()
405 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
406 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
407 int port_count = lad_desc->PortCount;
408 for( int i = 0; i < port_count; ++i ) {
409 if( !LADSPA_IS_PORT_OUTPUT(port_desc[i]) ) continue;
410 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
417 const char* PluginAClientLAD::plugin_title()
419 return (char*)server->lad_descriptor->Name;
422 int PluginAClientLAD::uses_gui()
427 int PluginAClientLAD::is_synthesis()
432 LOAD_CONFIGURATION_MACRO(PluginAClientLAD, PluginAClientConfig)
434 void PluginAClientLAD::update_gui()
438 char* PluginAClientLAD::lad_to_string(char *string, const char *input)
440 strcpy(string, input);
441 int len = strlen(string);
442 for(int j = 0; j < len; j++)
444 if(string[j] == ' ' ||
446 string[j] == '>') string[j] = '_';
451 char* PluginAClientLAD::lad_to_upper(char *string, const char *input)
453 lad_to_string(string, input);
454 int len = strlen(string);
455 for(int j = 0; j < len; j++)
456 string[j] = toupper(string[j]);
461 void PluginAClientLAD::save_data(KeyFrame *keyframe)
464 char string[BCTEXTLEN];
465 if( !config.port_data ) config.initialize(server);
467 // cause data to be stored directly in text
468 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
469 output.tag.set_title(lad_to_upper(string, plugin_title()));
471 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
472 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
473 //printf("PluginAClientLAD::save_data %d\n", lad_desc->PortCount);
474 int port_count = lad_desc->PortCount;
475 for(int port = 0, i = 0; i < port_count; i++) {
476 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
477 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
478 // Convert LAD port name to default title
479 PluginAClientLAD::lad_to_upper(string,
480 (char*)lad_desc->PortNames[i]);
481 output.tag.set_property(string, config.port_data[port]);
482 //printf("PluginAClientLAD::save_data %d %f\n", port, config.port_data[port]);
487 output.terminate_string();
490 void PluginAClientLAD::read_data(KeyFrame *keyframe)
493 char string[BCTEXTLEN];
495 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
496 config.initialize(server);
498 while(! input.read_tag() ) {
499 //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title());
500 if(! input.tag.title_is(lad_to_upper(string, plugin_title())) ) continue;
501 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
502 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
503 int port_count = lad_desc->PortCount;
504 for(int port = 0, i = 0; i < port_count; i++) {
505 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
506 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
507 PluginAClientLAD::lad_to_upper(string, (char*)lad_desc->PortNames[i]);
508 config.port_data[port] =
509 input.tag.get_property(string, config.port_data[port]);
510 //printf("PluginAClientLAD::read_data %d %f\n", port, config.port_data[port]);
516 void PluginAClientLAD::delete_buffers()
519 for(int i = 0; i < total_inbuffers; i++) delete [] in_buffers[i];
521 for(int i = 0; i < total_outbuffers; i++) delete [] out_buffers[i];
525 total_outbuffers = 0;
526 buffer_allocation = 0;
529 void PluginAClientLAD::delete_plugin()
532 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
533 if( lad_desc->deactivate ) lad_desc->deactivate(lad_instance);
534 lad_desc->cleanup(lad_instance);
539 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
541 int need_reconfigure = !lad_instance ? 1 : 0;
542 if(buffer_allocation && buffer_allocation < size) {
544 need_reconfigure = 1;
547 buffer_allocation = MAX(size, buffer_allocation);
549 total_inbuffers = total_in;
550 in_buffers = new LADSPA_Data*[total_inbuffers];
551 for(int i = 0; i < total_inbuffers; i++)
552 in_buffers[i] = new LADSPA_Data[buffer_allocation];
553 need_reconfigure = 1;
557 total_outbuffers = total_out;
558 out_buffers = new LADSPA_Data*[total_outbuffers];
559 for(int i = 0; i < total_outbuffers; i++)
560 out_buffers[i] = new LADSPA_Data[buffer_allocation];
561 need_reconfigure = 1;
564 if( load_configuration() )
565 need_reconfigure = 1;
567 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
568 if( need_reconfigure ) {
569 need_reconfigure = 0;
571 lad_instance = lad_desc->instantiate(
572 lad_desc,PluginAClient::project_sample_rate);
573 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
574 int port_count = lad_desc->PortCount;
576 for(int port = 0, i = 0; i < port_count; i++) {
577 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
578 LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
579 lad_desc->connect_port(lad_instance, i,
580 config.port_data + port);
583 else if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
584 LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
585 lad_desc->connect_port(lad_instance, i,
586 &dummy_control_output);
589 if(lad_desc->activate) lad_desc->activate(lad_instance);
592 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
593 int port_count = lad_desc->PortCount;
594 for(int port = 0, i = 0; i < port_count; i++) {
595 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
596 LADSPA_IS_PORT_AUDIO(port_desc[i]) )
597 lad_desc->connect_port(lad_instance, i, in_buffers[port++]);
600 for(int port = 0, i = 0; i < port_count; i++) {
601 if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
602 LADSPA_IS_PORT_AUDIO(port_desc[i]) )
603 lad_desc->connect_port(lad_instance, i, out_buffers[port++]);
607 int PluginAClientLAD::process_realtime(int64_t size,
611 int in_channels = get_inchannels();
612 int out_channels = get_outchannels();
613 init_plugin(in_channels, out_channels, size);
615 double *input_samples = input_ptr->get_data();
616 for(int i = 0; i < in_channels; i++) {
617 LADSPA_Data *in_buffer = in_buffers[i];
618 for(int j = 0; j < size; j++) in_buffer[j] = input_samples[j];
620 for(int i = 0; i < out_channels; i++)
621 bzero(out_buffers[i], sizeof(float) * size);
623 server->lad_descriptor->run(lad_instance, size);
625 double *output_samples = output_ptr->get_data();
626 LADSPA_Data *out_buffer = out_buffers[0];
627 for(int i = 0; i < size; i++) output_samples[i] = out_buffer[i];
631 int PluginAClientLAD::process_realtime(int64_t size,
632 Samples **input_ptr, Samples **output_ptr)
634 int in_channels = get_inchannels();
635 int out_channels = get_outchannels();
636 init_plugin(in_channels, out_channels, size);
638 for(int i = 0; i < in_channels; i++) {
639 float *in_buffer = in_buffers[i];
640 int k = i < PluginClient::total_in_buffers ? i : 0;
641 double *in_ptr = input_ptr[k]->get_data();
642 for(int j = 0; j < size; j++) in_buffer[j] = in_ptr[j];
644 for(int i = 0; i < out_channels; i++)
645 bzero(out_buffers[i], sizeof(float) * size);
647 server->lad_descriptor->run(lad_instance, size);
649 int nbfrs = PluginClient::total_out_buffers;
650 if( out_channels < nbfrs ) nbfrs = out_channels;
651 for(int i = 0; i < nbfrs; i++) {
652 LADSPA_Data *out_buffer = out_buffers[i];
653 double *out_ptr = output_ptr[i]->get_data();
654 for(int j = 0; j < size; j++) out_ptr[j] = out_buffer[j];