Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / cinelerra / pluginaclientlad.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "clip.h"
23 #include "bchash.h"
24 #include "filesystem.h"
25 #include "filexml.h"
26 #include "language.h"
27 #include "mwindow.h"
28 #include "pluginaclientlad.h"
29 #include "pluginserver.h"
30 #include "samples.h"
31 #include "vframe.h"
32
33 #include <ctype.h>
34 #include <string.h>
35
36
37
38 PluginAClientConfig::PluginAClientConfig()
39 {
40         reset();
41 }
42
43 PluginAClientConfig::~PluginAClientConfig()
44 {
45         delete_objects();
46 }
47
48 void PluginAClientConfig::reset()
49 {
50         total_ports = 0;
51         port_data = 0;
52         port_type = 0;
53 }
54
55 void PluginAClientConfig::delete_objects()
56 {
57         delete [] port_data;  port_data = 0;
58         delete [] port_type;  port_type = 0;
59         reset();
60 }
61
62
63 int PluginAClientConfig::equivalent(PluginAClientConfig &that)
64 {
65         if(that.total_ports != total_ports) return 0;
66         for(int i = 0; i < total_ports; i++)
67                 if(!EQUIV(port_data[i], that.port_data[i])) return 0;
68         return 1;
69 }
70
71 // Need PluginServer to do this.
72 void PluginAClientConfig::copy_from(PluginAClientConfig &that)
73 {
74         if( total_ports != that.total_ports ) {
75                 delete_objects();
76                 total_ports = that.total_ports;
77                 port_data = new LADSPA_Data[total_ports];
78                 port_type = new int[total_ports];
79         }
80         for( int i=0; i<total_ports; ++i ) {
81                 port_type[i] = that.port_type[i];
82                 port_data[i] = that.port_data[i];
83         }
84 }
85
86 void PluginAClientConfig::interpolate(PluginAClientConfig &prev, PluginAClientConfig &next,
87         int64_t prev_frame, int64_t next_frame, int64_t current_frame)
88 {
89         copy_from(prev);
90 }
91
92 void PluginAClientConfig::initialize(PluginServer *server)
93 {
94         delete_objects();
95
96         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
97         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
98         int port_count = lad_desc->PortCount;
99         for(int i = 0; i < port_count; i++) {
100                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
101                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
102                 ++total_ports;
103         }
104
105         port_data = new LADSPA_Data[total_ports];
106         port_type = new int[total_ports];
107
108         for(int port = 0, i = 0; i < port_count; i++) {
109                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
110                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
111                 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
112                 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
113 // Convert LAD default to default value
114                 float value = 0.0;
115
116 // Store type of port for GUI use
117                 port_type[port] = PORT_NORMAL;
118                 if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) )
119                         port_type[port] = PORT_FREQ_INDEX;
120                 else if(LADSPA_IS_HINT_TOGGLED(hint_desc))
121                         port_type[port] = PORT_TOGGLE;
122                 else if(LADSPA_IS_HINT_INTEGER(hint_desc))
123                         port_type[port] = PORT_INTEGER;
124
125 // Get default of port using crazy hinting system
126                 if( LADSPA_IS_HINT_DEFAULT_0(hint_desc) )
127                         value = 0.0;
128                 else if( LADSPA_IS_HINT_DEFAULT_1(hint_desc) )
129                         value = 1.0;
130                 else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) )
131                         value = 100.0;
132                 else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) )
133                         value = 440.0;
134                 else if( LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_desc) )
135                         value = lad_hint->UpperBound;
136                 else if( LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_desc) )
137                         value = lad_hint->LowerBound;
138                 else if( LADSPA_IS_HINT_DEFAULT_LOW(hint_desc) )
139                         value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
140                                 exp(log(lad_hint->LowerBound) * 0.25 +
141                                         log(lad_hint->UpperBound) * 0.75) :
142                                 lad_hint->LowerBound * 0.25 +
143                                         lad_hint->UpperBound * 0.75;
144                 else if( LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_desc) )
145                         value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
146                                 exp(log(lad_hint->LowerBound) * 0.5 +
147                                         log(lad_hint->UpperBound) * 0.5) :
148                                 lad_hint->LowerBound * 0.5 +
149                                         lad_hint->UpperBound * 0.5;
150                 else if( LADSPA_IS_HINT_DEFAULT_HIGH(hint_desc) )
151                         value = LADSPA_IS_HINT_LOGARITHMIC(hint_desc) ?
152                                 exp(log(lad_hint->LowerBound) * 0.75 +
153                                         log(lad_hint->UpperBound) * 0.25) :
154                                 lad_hint->LowerBound * 0.75 +
155                                         lad_hint->UpperBound * 0.25;
156
157                 port_data[port] = value;
158                 ++port;
159         }
160 }
161
162
163 PluginACLientToggle::PluginACLientToggle(PluginAClientLAD *plugin,
164         int x,
165         int y,
166         LADSPA_Data *output)
167  : BC_CheckBox(x, y, (int)(*output))
168 {
169         this->plugin = plugin;
170         this->output = output;
171 }
172
173 int PluginACLientToggle::handle_event()
174 {
175         *output = get_value();
176         plugin->send_configure_change();
177         return 1;
178 }
179
180
181 PluginACLientILinear::PluginACLientILinear(PluginAClientLAD *plugin,
182         int x,
183         int y,
184         LADSPA_Data *output,
185         int min,
186         int max)
187  : BC_IPot(x, y, (int)(*output), min, max)
188 {
189         this->plugin = plugin;
190         this->output = output;
191 }
192
193 int PluginACLientILinear::handle_event()
194 {
195         *output = get_value();
196         plugin->send_configure_change();
197         return 1;
198 }
199
200
201 PluginACLientFLinear::PluginACLientFLinear(PluginAClientLAD *plugin,
202         int x,
203         int y,
204         LADSPA_Data *output,
205         float min,
206         float max)
207  : BC_FPot(x, y, *output, min, max)
208 {
209         this->plugin = plugin;
210         this->output = output;
211         set_precision(0.01);
212 }
213
214 int PluginACLientFLinear::handle_event()
215 {
216         *output = get_value();
217         plugin->send_configure_change();
218         return 1;
219 }
220
221
222 PluginACLientFreq::PluginACLientFreq(PluginAClientLAD *plugin,
223         int x, int y, LADSPA_Data *output, int translate_linear)
224  : BC_QPot(x, y, translate_linear ?
225                 (int)(*output * plugin->PluginAClient::project_sample_rate) :
226                 (int)*output)
227 {
228         this->plugin = plugin;
229         this->output = output;
230         this->translate_linear = translate_linear;
231 }
232
233 int PluginACLientFreq::handle_event()
234 {
235         *output = translate_linear ?
236                 (float)get_value() / plugin->PluginAClient::project_sample_rate :
237                 get_value();
238         plugin->send_configure_change();
239         return 1;
240 }
241
242
243
244 PluginAClientWindow::PluginAClientWindow(PluginAClientLAD *plugin)
245  : PluginClientWindow(plugin, 500, plugin->config.total_ports * 30 + 60,
246         500, plugin->config.total_ports * 30 + 60, 0)
247 {
248         this->plugin = plugin;
249 }
250
251 PluginAClientWindow::~PluginAClientWindow()
252 {
253 }
254
255
256 void PluginAClientWindow::create_objects()
257 {
258         PluginServer *server = plugin->server;
259         char string[BCTEXTLEN];
260         int current_port = 0;
261         int x = 10;
262         int y = 10;
263         int x2 = 300;
264         int x3 = 335;
265         int title_vmargin = 5;
266         int max_w = 0;
267         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
268         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
269         int port_count = lad_desc->PortCount;
270         for(int i = 0; i < port_count; i++) {
271                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
272                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
273                 int w = get_text_width(MEDIUMFONT, (char*)lad_desc->PortNames[i]);
274                 if(w > max_w) max_w = w;
275         }
276
277         x2 = max_w + 20;
278         x3 = max_w + 55;
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                 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
283                 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
284                 int use_min = LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc);
285                 int use_max = LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc);
286                 sprintf(string, "%s:", lad_desc->PortNames[i]);
287 // printf("PluginAClientWindow::create_objects 1 %s type=%d lower: %d %f upper: %d %f\n",
288 // string, plugin->config.port_type[current_port],
289 // use_min, lad_hint->LowerBound,  use_max, lad_hint->UpperBound);
290
291                 switch(plugin->config.port_type[current_port]) {
292                 case PluginAClientConfig::PORT_NORMAL: {
293                         PluginACLientFLinear *flinear;
294                         float min = use_min ? lad_hint->LowerBound : 0;
295                         float max = use_max ? lad_hint->UpperBound : 100;
296                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
297                         add_subwindow(flinear = new PluginACLientFLinear(
298                                         plugin, (current_port % 2) ? x2 : x3, y,
299                                         &plugin->config.port_data[current_port],
300                                         min, max));
301                         fpots.append(flinear);
302                         break; }
303                 case PluginAClientConfig::PORT_FREQ_INDEX: {
304                         PluginACLientFreq *freq;
305                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
306                         add_subwindow(freq = new PluginACLientFreq(plugin,
307                                         (current_port % 2) ? x2 : x3, y,
308                                                 &plugin->config.port_data[current_port], 0
309                                         /*      (plugin->config.port_type[current_port] ==
310                                                         PluginAClientConfig::PORT_FREQ_INDEX */));
311                         freqs.append(freq);
312                         break; }
313                 case PluginAClientConfig::PORT_TOGGLE: {
314                         PluginACLientToggle *toggle;
315                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
316                         add_subwindow(toggle = new PluginACLientToggle(plugin,
317                                         (current_port % 2) ? x2 : x3, y,
318                                                 &plugin->config.port_data[current_port]));
319                         toggles.append(toggle);
320                         break; }
321                 case PluginAClientConfig::PORT_INTEGER: {
322                         PluginACLientILinear *ilinear;
323                         float min = use_min ? lad_hint->LowerBound : 0;
324                         float max = use_max ? lad_hint->UpperBound : 100;
325                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
326                         add_subwindow(ilinear = new PluginACLientILinear( plugin,
327                                         (current_port % 2) ? x2 : x3, y,
328                                                 &plugin->config.port_data[current_port],
329                                                 (int)min, (int)max));
330                         ipots.append(ilinear);
331                         break; }
332                 }
333                 current_port++;
334                 y += 30;
335 //printf("PluginAClientWindow::create_objects 2\n");
336         }
337
338         y += 10;
339         sprintf(string, _("Author: %s"), lad_desc->Maker);
340         add_subwindow(new BC_Title(x, y, string));
341         y += 20;
342         sprintf(string, _("License: %s"), lad_desc->Copyright);
343         add_subwindow(new BC_Title(x, y, string));
344         show_window(1);
345 }
346
347
348
349 PluginAClientLAD::PluginAClientLAD(PluginServer *server)
350  : PluginAClient(server)
351 {
352         in_buffers = 0;
353         total_inbuffers = 0;
354         out_buffers = 0;
355         total_outbuffers = 0;
356         buffer_allocation = 0;
357         lad_instance = 0;
358         snprintf(title, sizeof(title), "L_%s", server->lad_descriptor->Name);
359 }
360
361 PluginAClientLAD::~PluginAClientLAD()
362 {
363         delete_buffers();
364         delete_plugin();
365 }
366
367 NEW_WINDOW_MACRO(PluginAClientLAD, PluginAClientWindow)
368
369 int PluginAClientLAD::is_realtime()
370 {
371         return 1;
372 }
373
374 int PluginAClientLAD::is_multichannel()
375 {
376         if(get_inchannels() > 1 || get_outchannels() > 1) return 1;
377         return 0;
378 }
379
380 int PluginAClientLAD::get_inchannels()
381 {
382         int result = 0;
383         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
384         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
385         int port_count = lad_desc->PortCount;
386         for( int i = 0; i < port_count; ++i ) {
387                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
388                 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
389                 ++result;
390         }
391         return result;
392 }
393
394 int PluginAClientLAD::get_outchannels()
395 {
396         int result = 0;
397         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
398         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
399         int port_count = lad_desc->PortCount;
400         for( int i = 0; i < port_count; ++i ) {
401                 if( !LADSPA_IS_PORT_OUTPUT(port_desc[i]) ) continue;
402                 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
403                 ++result;
404         }
405         return result;
406 }
407
408
409 const char* PluginAClientLAD::plugin_title()
410 {
411         return title;
412 }
413
414 int PluginAClientLAD::uses_gui()
415 {
416         return 1;
417 }
418
419 int PluginAClientLAD::is_synthesis()
420 {
421         return 1;
422 }
423
424 LOAD_CONFIGURATION_MACRO(PluginAClientLAD, PluginAClientConfig)
425
426 void PluginAClientLAD::update_gui()
427 {
428 }
429
430 char* PluginAClientLAD::lad_to_string(char *string, const char *input)
431 {
432         strcpy(string, input);
433         int len = strlen(string);
434         for(int j = 0; j < len; j++)
435         {
436                 if(string[j] == ' ' ||
437                         string[j] == '<' ||
438                         string[j] == '>') string[j] = '_';
439         }
440         return string;
441 }
442
443 char* PluginAClientLAD::lad_to_upper(char *string, const char *input)
444 {
445         lad_to_string(string, input);
446         int len = strlen(string);
447         for(int j = 0; j < len; j++)
448                 string[j] = toupper(string[j]);
449         return string;
450 }
451
452
453 void PluginAClientLAD::save_data(KeyFrame *keyframe)
454 {
455         if( !config.port_data ) config.initialize(server);
456         FileXML output;
457 // cause data to be stored directly in text
458         output.set_shared_output(keyframe->xbuf);
459         char string[BCTEXTLEN];
460         output.tag.set_title(lad_to_upper(string, plugin_title()));
461
462         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
463         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
464 //printf("PluginAClientLAD::save_data %d\n", lad_desc->PortCount);
465         int port_count = lad_desc->PortCount;
466         for(int port = 0, i = 0; i < port_count; i++) {
467                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
468                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
469 // Convert LAD port name to default title
470                 PluginAClientLAD::lad_to_upper(string,
471                         (char*)lad_desc->PortNames[i]);
472                 output.tag.set_property(string, config.port_data[port]);
473 //printf("PluginAClientLAD::save_data %d %f\n", port, config.port_data[port]);
474                 ++port;
475         }
476
477         output.append_tag();
478         output.terminate_string();
479 }
480
481 void PluginAClientLAD::read_data(KeyFrame *keyframe)
482 {
483         if( !config.port_data ) config.initialize(server);
484         FileXML input;
485         input.set_shared_input(keyframe->xbuf);
486
487         while(! input.read_tag() ) {
488 //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title());
489                 char string[BCTEXTLEN];
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]);
501                         port++;
502                 }
503         }
504 }
505
506 void PluginAClientLAD::delete_buffers()
507 {
508         if( in_buffers ) {
509                 for( int i=0; i<total_inbuffers; ++i ) delete [] in_buffers[i];
510                 delete [] in_buffers;  in_buffers = 0;
511         }
512         if( out_buffers ) {
513                 for( int i=0; i<total_outbuffers; ++i ) delete [] out_buffers[i];
514                 delete [] out_buffers;  out_buffers = 0;
515         }
516         total_inbuffers = 0;
517         total_outbuffers = 0;
518         buffer_allocation = 0;
519 }
520
521 void PluginAClientLAD::delete_plugin()
522 {
523         if(lad_instance) {
524                 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
525                 if( lad_desc->deactivate ) lad_desc->deactivate(lad_instance);
526                 lad_desc->cleanup(lad_instance);
527         }
528         lad_instance = 0;
529 }
530
531 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
532 {
533         int need_reconfigure = !lad_instance ? 1 : 0;
534         if( !config.port_data ) {
535                 config.initialize(server);
536                 need_reconfigure = 1;
537         }
538         if(buffer_allocation && buffer_allocation < size) {
539                 delete_buffers();
540                 need_reconfigure = 1;
541         }
542
543         buffer_allocation = MAX(size, buffer_allocation);
544         if(!in_buffers) {
545                 total_inbuffers = total_in;
546                 in_buffers = new LADSPA_Data*[total_inbuffers];
547                 for(int i = 0; i < total_inbuffers; i++)
548                         in_buffers[i] = new LADSPA_Data[buffer_allocation];
549                 need_reconfigure = 1;
550         }
551
552         if(!out_buffers) {
553                 total_outbuffers = total_out;
554                 out_buffers = new LADSPA_Data*[total_outbuffers];
555                 for(int i = 0; i < total_outbuffers; i++)
556                         out_buffers[i] = new LADSPA_Data[buffer_allocation];
557                 need_reconfigure = 1;
558         }
559
560         if( load_configuration() )
561                 need_reconfigure = 1;
562
563         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
564         if( need_reconfigure ) {
565                 need_reconfigure = 0;
566                 delete_plugin();
567                 lad_instance = lad_desc->instantiate(
568                                 lad_desc,PluginAClient::project_sample_rate);
569                 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
570                 int port_count = lad_desc->PortCount;
571
572                 for(int port = 0, i = 0; i < port_count; i++) {
573                         if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
574                             LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
575                                 lad_desc->connect_port(lad_instance, i,
576                                         config.port_data + port);
577                                 port++;
578                         }
579                         else if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
580                                  LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
581                                 lad_desc->connect_port(lad_instance, i,
582                                         &dummy_control_output);
583                         }
584                 }
585                 if(lad_desc->activate) lad_desc->activate(lad_instance);
586         }
587
588         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
589         int port_count = lad_desc->PortCount;
590         for(int port = 0, i = 0; i < port_count; i++) {
591                 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
592                     LADSPA_IS_PORT_AUDIO(port_desc[i]) )
593                         lad_desc->connect_port(lad_instance, i, in_buffers[port++]);
594         }
595
596         for(int port = 0, i = 0; i < port_count; i++) {
597                 if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
598                     LADSPA_IS_PORT_AUDIO(port_desc[i]) )
599                         lad_desc->connect_port(lad_instance, i, out_buffers[port++]);
600         }
601 }
602
603 int PluginAClientLAD::process_realtime(int64_t size,
604         Samples *input_ptr,
605         Samples *output_ptr)
606 {
607         int in_channels = get_inchannels();
608         int out_channels = get_outchannels();
609         init_plugin(in_channels, out_channels, size);
610
611         double *input_samples = input_ptr->get_data();
612         for(int i = 0; i < in_channels; i++) {
613                 LADSPA_Data *in_buffer = in_buffers[i];
614                 for(int j = 0; j < size; j++) in_buffer[j] = input_samples[j];
615         }
616         for(int i = 0; i < out_channels; i++)
617                 bzero(out_buffers[i], sizeof(float) * size);
618
619         server->lad_descriptor->run(lad_instance, size);
620
621         double *output_samples = output_ptr->get_data();
622         LADSPA_Data *out_buffer = out_buffers[0];
623         for(int i = 0; i < size; i++) output_samples[i] = out_buffer[i];
624         return size;
625 }
626
627 int PluginAClientLAD::process_realtime(int64_t size,
628         Samples **input_ptr, Samples **output_ptr)
629 {
630         int in_channels = get_inchannels();
631         int out_channels = get_outchannels();
632         init_plugin(in_channels, out_channels, size);
633
634         for(int i = 0; i < in_channels; i++) {
635                 float *in_buffer = in_buffers[i];
636                 int k = i < PluginClient::total_in_buffers ? i : 0;
637                 double *in_ptr = input_ptr[k]->get_data();
638                 for(int j = 0; j < size; j++) in_buffer[j] = in_ptr[j];
639         }
640         for(int i = 0; i < out_channels; i++)
641                 bzero(out_buffers[i], sizeof(float) * size);
642
643         server->lad_descriptor->run(lad_instance, size);
644
645         int nbfrs = PluginClient::total_out_buffers;
646         if( out_channels < nbfrs ) nbfrs = out_channels;
647         for(int i = 0; i < nbfrs; i++) {
648                 LADSPA_Data *out_buffer = out_buffers[i];
649                 double *out_ptr = output_ptr[i]->get_data();
650                 for(int j = 0; j < size; j++) out_ptr[j] = out_buffer[j];
651         }
652         return size;
653 }
654
655 int MWindow::init_ladspa_index(MWindow *mwindow, Preferences *preferences,
656         FILE *fp, const char *plugin_dir)
657 {
658         char plugin_path[BCTEXTLEN], *path = FileSystem::basepath(plugin_dir);
659         strcpy(plugin_path, path);  delete [] path;
660         printf("init ladspa index: %s\n", plugin_dir);
661         fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
662         fprintf(fp, "%s\n", plugin_dir);
663         init_plugin_index(mwindow, preferences, fp, plugin_path);
664         return 0;
665 }
666