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 ) {
74 total_ports = that.total_ports;
75 port_data = new LADSPA_Data[total_ports];
76 port_type = new int[total_ports];
78 for( int i=0; i<total_ports; ++i ) {
79 port_type[i] = that.port_type[i];
80 port_data[i] = that.port_data[i];
84 void PluginAClientConfig::interpolate(PluginAClientConfig &prev, PluginAClientConfig &next,
85 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
90 void PluginAClientConfig::initialize(PluginServer *server)
94 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
95 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
96 int port_count = lad_desc->PortCount;
97 for(int i = 0; i < port_count; i++) {
98 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
99 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
103 port_data = new LADSPA_Data[total_ports];
104 port_type = new int[total_ports];
106 for(int port = 0, 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;
109 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
110 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
111 // Convert LAD default to default value
114 // Store type of port for GUI use
115 port_type[port] = PORT_NORMAL;
116 if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) )
117 port_type[port] = PORT_FREQ_INDEX;
118 else if(LADSPA_IS_HINT_TOGGLED(hint_desc))
119 port_type[port] = PORT_TOGGLE;
120 else if(LADSPA_IS_HINT_INTEGER(hint_desc))
121 port_type[port] = PORT_INTEGER;
123 // Get default of port using crazy hinting system
124 if( LADSPA_IS_HINT_DEFAULT_0(hint_desc) )
126 else if( LADSPA_IS_HINT_DEFAULT_1(hint_desc) )
128 else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) )
130 else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) )
132 else if( LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_desc) )
133 value = lad_hint->UpperBound;
134 else if( LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_desc) )
135 value = lad_hint->LowerBound;
136 else if( LADSPA_IS_HINT_DEFAULT_LOW(hint_desc) )
137 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
138 exp(log(lad_hint->LowerBound) * 0.25 +
139 log(lad_hint->UpperBound) * 0.75) :
140 lad_hint->LowerBound * 0.25 +
141 lad_hint->UpperBound * 0.75;
142 else if( LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_desc) )
143 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
144 exp(log(lad_hint->LowerBound) * 0.5 +
145 log(lad_hint->UpperBound) * 0.5) :
146 lad_hint->LowerBound * 0.5 +
147 lad_hint->UpperBound * 0.5;
148 else if( LADSPA_IS_HINT_DEFAULT_HIGH(hint_desc) )
149 value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
150 exp(log(lad_hint->LowerBound) * 0.75 +
151 log(lad_hint->UpperBound) * 0.25) :
152 lad_hint->LowerBound * 0.75 +
153 lad_hint->UpperBound * 0.25;
155 port_data[port] = value;
161 PluginACLientToggle::PluginACLientToggle(PluginAClientLAD *plugin,
165 : BC_CheckBox(x, y, (int)(*output))
167 this->plugin = plugin;
168 this->output = output;
171 int PluginACLientToggle::handle_event()
173 *output = get_value();
174 plugin->send_configure_change();
179 PluginACLientILinear::PluginACLientILinear(PluginAClientLAD *plugin,
185 : BC_IPot(x, y, (int)(*output), min, max)
187 this->plugin = plugin;
188 this->output = output;
191 int PluginACLientILinear::handle_event()
193 *output = get_value();
194 plugin->send_configure_change();
199 PluginACLientFLinear::PluginACLientFLinear(PluginAClientLAD *plugin,
205 : BC_FPot(x, y, *output, min, max)
207 this->plugin = plugin;
208 this->output = output;
212 int PluginACLientFLinear::handle_event()
214 *output = get_value();
215 plugin->send_configure_change();
220 PluginACLientFreq::PluginACLientFreq(PluginAClientLAD *plugin,
221 int x, int y, LADSPA_Data *output, int translate_linear)
222 : BC_QPot(x, y, translate_linear ?
223 (int)(*output * plugin->PluginAClient::project_sample_rate) :
226 this->plugin = plugin;
227 this->output = output;
228 this->translate_linear = translate_linear;
231 int PluginACLientFreq::handle_event()
233 *output = translate_linear ?
234 (float)get_value() / plugin->PluginAClient::project_sample_rate :
236 plugin->send_configure_change();
242 PluginAClientWindow::PluginAClientWindow(PluginAClientLAD *plugin)
243 : PluginClientWindow(plugin, 500, plugin->config.total_ports * 30 + 60,
244 500, plugin->config.total_ports * 30 + 60, 0)
246 this->plugin = plugin;
249 PluginAClientWindow::~PluginAClientWindow()
254 void PluginAClientWindow::create_objects()
256 PluginServer *server = plugin->server;
257 char string[BCTEXTLEN];
258 int current_port = 0;
263 int title_vmargin = 5;
265 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
266 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
267 int port_count = lad_desc->PortCount;
268 for(int i = 0; i < port_count; i++) {
269 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
270 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
271 int w = get_text_width(MEDIUMFONT, (char*)lad_desc->PortNames[i]);
272 if(w > max_w) max_w = w;
277 for(int i = 0; i < port_count; i++) {
278 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
279 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
280 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
281 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
282 int use_min = LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc);
283 int use_max = LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc);
284 sprintf(string, "%s:", lad_desc->PortNames[i]);
285 // printf("PluginAClientWindow::create_objects 1 %s type=%d lower: %d %f upper: %d %f\n",
286 // string, plugin->config.port_type[current_port],
287 // use_min, lad_hint->LowerBound, use_max, lad_hint->UpperBound);
289 switch(plugin->config.port_type[current_port]) {
290 case PluginAClientConfig::PORT_NORMAL: {
291 PluginACLientFLinear *flinear;
292 float min = use_min ? lad_hint->LowerBound : 0;
293 float max = use_max ? lad_hint->UpperBound : 100;
294 add_subwindow(new BC_Title(x, y + title_vmargin, string));
295 add_subwindow(flinear = new PluginACLientFLinear(
296 plugin, (current_port % 2) ? x2 : x3, y,
297 &plugin->config.port_data[current_port],
299 fpots.append(flinear);
301 case PluginAClientConfig::PORT_FREQ_INDEX: {
302 PluginACLientFreq *freq;
303 add_subwindow(new BC_Title(x, y + title_vmargin, string));
304 add_subwindow(freq = new PluginACLientFreq(plugin,
305 (current_port % 2) ? x2 : x3, y,
306 &plugin->config.port_data[current_port], 0
307 /* (plugin->config.port_type[current_port] ==
308 PluginAClientConfig::PORT_FREQ_INDEX */));
311 case PluginAClientConfig::PORT_TOGGLE: {
312 PluginACLientToggle *toggle;
313 add_subwindow(new BC_Title(x, y + title_vmargin, string));
314 add_subwindow(toggle = new PluginACLientToggle(plugin,
315 (current_port % 2) ? x2 : x3, y,
316 &plugin->config.port_data[current_port]));
317 toggles.append(toggle);
319 case PluginAClientConfig::PORT_INTEGER: {
320 PluginACLientILinear *ilinear;
321 float min = use_min ? lad_hint->LowerBound : 0;
322 float max = use_max ? lad_hint->UpperBound : 100;
323 add_subwindow(new BC_Title(x, y + title_vmargin, string));
324 add_subwindow(ilinear = new PluginACLientILinear( plugin,
325 (current_port % 2) ? x2 : x3, y,
326 &plugin->config.port_data[current_port],
327 (int)min, (int)max));
328 ipots.append(ilinear);
333 //printf("PluginAClientWindow::create_objects 2\n");
337 sprintf(string, _("Author: %s"), lad_desc->Maker);
338 add_subwindow(new BC_Title(x, y, string));
340 sprintf(string, _("License: %s"), lad_desc->Copyright);
341 add_subwindow(new BC_Title(x, y, string));
347 PluginAClientLAD::PluginAClientLAD(PluginServer *server)
348 : PluginAClient(server)
353 total_outbuffers = 0;
354 buffer_allocation = 0;
356 snprintf(title, sizeof(title), "L_%s", server->lad_descriptor->Name);
359 PluginAClientLAD::~PluginAClientLAD()
365 NEW_WINDOW_MACRO(PluginAClientLAD, PluginAClientWindow)
367 int PluginAClientLAD::is_realtime()
372 int PluginAClientLAD::is_multichannel()
374 if(get_inchannels() > 1 || get_outchannels() > 1) return 1;
378 int PluginAClientLAD::get_inchannels()
381 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
382 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
383 int port_count = lad_desc->PortCount;
384 for( int i = 0; i < port_count; ++i ) {
385 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
386 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
392 int PluginAClientLAD::get_outchannels()
395 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
396 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
397 int port_count = lad_desc->PortCount;
398 for( int i = 0; i < port_count; ++i ) {
399 if( !LADSPA_IS_PORT_OUTPUT(port_desc[i]) ) continue;
400 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
407 const char* PluginAClientLAD::plugin_title()
412 int PluginAClientLAD::uses_gui()
417 int PluginAClientLAD::is_synthesis()
422 LOAD_CONFIGURATION_MACRO(PluginAClientLAD, PluginAClientConfig)
424 void PluginAClientLAD::update_gui()
428 char* PluginAClientLAD::lad_to_string(char *string, const char *input)
430 strcpy(string, input);
431 int len = strlen(string);
432 for(int j = 0; j < len; j++)
434 if(string[j] == ' ' ||
436 string[j] == '>') string[j] = '_';
441 char* PluginAClientLAD::lad_to_upper(char *string, const char *input)
443 lad_to_string(string, input);
444 int len = strlen(string);
445 for(int j = 0; j < len; j++)
446 string[j] = toupper(string[j]);
451 void PluginAClientLAD::save_data(KeyFrame *keyframe)
454 char string[BCTEXTLEN];
455 if( !config.port_data ) config.initialize(server);
457 // cause data to be stored directly in text
458 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
459 output.tag.set_title(lad_to_upper(string, plugin_title()));
461 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
462 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
463 //printf("PluginAClientLAD::save_data %d\n", lad_desc->PortCount);
464 int port_count = lad_desc->PortCount;
465 for(int port = 0, i = 0; i < port_count; i++) {
466 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
467 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
468 // Convert LAD port name to default title
469 PluginAClientLAD::lad_to_upper(string,
470 (char*)lad_desc->PortNames[i]);
471 output.tag.set_property(string, config.port_data[port]);
472 //printf("PluginAClientLAD::save_data %d %f\n", port, config.port_data[port]);
477 output.terminate_string();
480 void PluginAClientLAD::read_data(KeyFrame *keyframe)
483 char string[BCTEXTLEN];
485 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
486 if( !config.port_data ) config.initialize(server);
488 while(! input.read_tag() ) {
489 //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title());
490 if(! input.tag.title_is(lad_to_upper(string, plugin_title())) ) continue;
491 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
492 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
493 int port_count = lad_desc->PortCount;
494 for(int port = 0, i = 0; i < port_count; i++) {
495 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
496 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
497 PluginAClientLAD::lad_to_upper(string, (char*)lad_desc->PortNames[i]);
498 config.port_data[port] =
499 input.tag.get_property(string, config.port_data[port]);
500 //printf("PluginAClientLAD::read_data %d %f\n", port, config.port_data[port]);
506 void PluginAClientLAD::delete_buffers()
509 for(int i = 0; i < total_inbuffers; i++) delete [] in_buffers[i];
511 for(int i = 0; i < total_outbuffers; i++) delete [] out_buffers[i];
515 total_outbuffers = 0;
516 buffer_allocation = 0;
519 void PluginAClientLAD::delete_plugin()
522 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
523 if( lad_desc->deactivate ) lad_desc->deactivate(lad_instance);
524 lad_desc->cleanup(lad_instance);
529 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
531 int need_reconfigure = !lad_instance ? 1 : 0;
532 if( !config.port_data ) {
533 config.initialize(server);
534 need_reconfigure = 1;
536 if(buffer_allocation && buffer_allocation < size) {
538 need_reconfigure = 1;
541 buffer_allocation = MAX(size, buffer_allocation);
543 total_inbuffers = total_in;
544 in_buffers = new LADSPA_Data*[total_inbuffers];
545 for(int i = 0; i < total_inbuffers; i++)
546 in_buffers[i] = new LADSPA_Data[buffer_allocation];
547 need_reconfigure = 1;
551 total_outbuffers = total_out;
552 out_buffers = new LADSPA_Data*[total_outbuffers];
553 for(int i = 0; i < total_outbuffers; i++)
554 out_buffers[i] = new LADSPA_Data[buffer_allocation];
555 need_reconfigure = 1;
558 if( load_configuration() )
559 need_reconfigure = 1;
561 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
562 if( need_reconfigure ) {
563 need_reconfigure = 0;
565 lad_instance = lad_desc->instantiate(
566 lad_desc,PluginAClient::project_sample_rate);
567 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
568 int port_count = lad_desc->PortCount;
570 for(int port = 0, i = 0; i < port_count; i++) {
571 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
572 LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
573 lad_desc->connect_port(lad_instance, i,
574 config.port_data + port);
577 else if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
578 LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
579 lad_desc->connect_port(lad_instance, i,
580 &dummy_control_output);
583 if(lad_desc->activate) lad_desc->activate(lad_instance);
586 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
587 int port_count = lad_desc->PortCount;
588 for(int port = 0, i = 0; i < port_count; i++) {
589 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
590 LADSPA_IS_PORT_AUDIO(port_desc[i]) )
591 lad_desc->connect_port(lad_instance, i, in_buffers[port++]);
594 for(int port = 0, i = 0; i < port_count; i++) {
595 if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
596 LADSPA_IS_PORT_AUDIO(port_desc[i]) )
597 lad_desc->connect_port(lad_instance, i, out_buffers[port++]);
601 int PluginAClientLAD::process_realtime(int64_t size,
605 int in_channels = get_inchannels();
606 int out_channels = get_outchannels();
607 init_plugin(in_channels, out_channels, size);
609 double *input_samples = input_ptr->get_data();
610 for(int i = 0; i < in_channels; i++) {
611 LADSPA_Data *in_buffer = in_buffers[i];
612 for(int j = 0; j < size; j++) in_buffer[j] = input_samples[j];
614 for(int i = 0; i < out_channels; i++)
615 bzero(out_buffers[i], sizeof(float) * size);
617 server->lad_descriptor->run(lad_instance, size);
619 double *output_samples = output_ptr->get_data();
620 LADSPA_Data *out_buffer = out_buffers[0];
621 for(int i = 0; i < size; i++) output_samples[i] = out_buffer[i];
625 int PluginAClientLAD::process_realtime(int64_t size,
626 Samples **input_ptr, Samples **output_ptr)
628 int in_channels = get_inchannels();
629 int out_channels = get_outchannels();
630 init_plugin(in_channels, out_channels, size);
632 for(int i = 0; i < in_channels; i++) {
633 float *in_buffer = in_buffers[i];
634 int k = i < PluginClient::total_in_buffers ? i : 0;
635 double *in_ptr = input_ptr[k]->get_data();
636 for(int j = 0; j < size; j++) in_buffer[j] = in_ptr[j];
638 for(int i = 0; i < out_channels; i++)
639 bzero(out_buffers[i], sizeof(float) * size);
641 server->lad_descriptor->run(lad_instance, size);
643 int nbfrs = PluginClient::total_out_buffers;
644 if( out_channels < nbfrs ) nbfrs = out_channels;
645 for(int i = 0; i < nbfrs; i++) {
646 LADSPA_Data *out_buffer = out_buffers[i];
647 double *out_ptr = output_ptr[i]->get_data();
648 for(int j = 0; j < size; j++) out_ptr[j] = out_buffer[j];