MatN prevents continuous reload of plugins for AppImage + Andrew libaom compile mod
[goodguy/cinelerra.git] / cinelerra-5.1 / 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, int y, LADSPA_Data *output, int min, int max)
183  : BC_IPot(x, y, (int)(*output), min, max)
184 {
185         this->plugin = plugin;
186         this->output = output;
187 }
188
189 int PluginACLientILinear::handle_event()
190 {
191         *output = get_value();
192         plugin->send_configure_change();
193         return 1;
194 }
195
196
197 PluginACLientFLinear::PluginACLientFLinear(PluginAClientLAD *plugin,
198         int x, int y, LADSPA_Data *output, float min, float max)
199  : BC_FPot(x, y, *output, min, max)
200 {
201         this->plugin = plugin;
202         this->output = output;
203         set_precision(0.01);
204 }
205
206 int PluginACLientFLinear::handle_event()
207 {
208         *output = get_value();
209         plugin->send_configure_change();
210         return 1;
211 }
212
213
214 PluginACLientFreq::PluginACLientFreq(PluginAClientLAD *plugin,
215         int x, int y, LADSPA_Data *output, int translate_linear)
216  : BC_QPot(x, y, translate_linear ?
217                 (int)(*output * plugin->PluginAClient::project_sample_rate) :
218                 (int)*output)
219 {
220         this->plugin = plugin;
221         this->output = output;
222         this->translate_linear = translate_linear;
223 }
224
225 int PluginACLientFreq::handle_event()
226 {
227         *output = translate_linear ?
228                 (float)get_value() / plugin->PluginAClient::project_sample_rate :
229                 get_value();
230         plugin->send_configure_change();
231         return 1;
232 }
233
234
235
236 PluginAClientWindow::PluginAClientWindow(PluginAClientLAD *plugin)
237  : PluginClientWindow(plugin, xS(500), plugin->config.total_ports * yS(30) + yS(60),
238         xS(500), plugin->config.total_ports * yS(30) + yS(60), 0)
239 {
240         this->plugin = plugin;
241 }
242
243 PluginAClientWindow::~PluginAClientWindow()
244 {
245 }
246
247
248 void PluginAClientWindow::create_objects()
249 {
250         PluginServer *server = plugin->server;
251         char string[BCTEXTLEN];
252         int current_port = 0;
253         int x = xS(10), y = yS(10);
254         int x2 = xS(300), x3 = xS(335);
255         int title_vmargin = 5;
256         int max_w = 0;
257         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
258         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
259         int port_count = lad_desc->PortCount;
260         for(int i = 0; i < port_count; i++) {
261                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
262                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
263                 int w = get_text_width(MEDIUMFONT, (char*)lad_desc->PortNames[i]);
264                 if(w > max_w) max_w = w;
265         }
266
267         x2 = max_w + xS(20);
268         x3 = max_w + xS(55);
269         for(int i = 0; i < port_count; i++) {
270                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
271                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
272                 const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i];
273                 LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor;
274                 int use_min = LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc);
275                 int use_max = LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc);
276                 sprintf(string, "%s:", lad_desc->PortNames[i]);
277 // printf("PluginAClientWindow::create_objects 1 %s type=%d lower: %d %f upper: %d %f\n",
278 // string, plugin->config.port_type[current_port],
279 // use_min, lad_hint->LowerBound,  use_max, lad_hint->UpperBound);
280
281                 switch(plugin->config.port_type[current_port]) {
282                 case PluginAClientConfig::PORT_NORMAL: {
283                         PluginACLientFLinear *flinear;
284                         float min = use_min ? lad_hint->LowerBound : 0;
285                         float max = use_max ? lad_hint->UpperBound : 100;
286                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
287                         add_subwindow(flinear = new PluginACLientFLinear(
288                                         plugin, (current_port % 2) ? x2 : x3, y,
289                                         &plugin->config.port_data[current_port],
290                                         min, max));
291                         fpots.append(flinear);
292                         break; }
293                 case PluginAClientConfig::PORT_FREQ_INDEX: {
294                         PluginACLientFreq *freq;
295                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
296                         add_subwindow(freq = new PluginACLientFreq(plugin,
297                                         (current_port % 2) ? x2 : x3, y,
298                                                 &plugin->config.port_data[current_port], 0
299                                         /*      (plugin->config.port_type[current_port] ==
300                                                         PluginAClientConfig::PORT_FREQ_INDEX */));
301                         freqs.append(freq);
302                         break; }
303                 case PluginAClientConfig::PORT_TOGGLE: {
304                         PluginACLientToggle *toggle;
305                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
306                         add_subwindow(toggle = new PluginACLientToggle(plugin,
307                                         (current_port % 2) ? x2 : x3, y,
308                                                 &plugin->config.port_data[current_port]));
309                         toggles.append(toggle);
310                         break; }
311                 case PluginAClientConfig::PORT_INTEGER: {
312                         PluginACLientILinear *ilinear;
313                         float min = use_min ? lad_hint->LowerBound : 0;
314                         float max = use_max ? lad_hint->UpperBound : 100;
315                         add_subwindow(new BC_Title(x, y + title_vmargin, string));
316                         add_subwindow(ilinear = new PluginACLientILinear( plugin,
317                                         (current_port % 2) ? x2 : x3, y,
318                                                 &plugin->config.port_data[current_port],
319                                                 (int)min, (int)max));
320                         ipots.append(ilinear);
321                         break; }
322                 }
323                 current_port++;
324                 y += yS(30);
325 //printf("PluginAClientWindow::create_objects 2\n");
326         }
327
328         y += yS(10);
329         sprintf(string, _("Author: %s"), lad_desc->Maker);
330         add_subwindow(new BC_Title(x, y, string));
331         y += yS(20);
332         sprintf(string, _("License: %s"), lad_desc->Copyright);
333         add_subwindow(new BC_Title(x, y, string));
334         show_window(1);
335 }
336
337
338
339 PluginAClientLAD::PluginAClientLAD(PluginServer *server)
340  : PluginAClient(server)
341 {
342         in_buffers = 0;
343         total_inbuffers = 0;
344         out_buffers = 0;
345         total_outbuffers = 0;
346         buffer_allocation = 0;
347         lad_instance = 0;
348         snprintf(title, sizeof(title), "L_%s", server->lad_descriptor->Name);
349 }
350
351 PluginAClientLAD::~PluginAClientLAD()
352 {
353         delete_buffers();
354         delete_plugin();
355 }
356
357 NEW_WINDOW_MACRO(PluginAClientLAD, PluginAClientWindow)
358
359 int PluginAClientLAD::is_realtime()
360 {
361         return 1;
362 }
363
364 int PluginAClientLAD::is_multichannel()
365 {
366         if(get_inchannels() > 1 || get_outchannels() > 1) return 1;
367         return 0;
368 }
369
370 int PluginAClientLAD::get_inchannels()
371 {
372         int result = 0;
373         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
374         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
375         int port_count = lad_desc->PortCount;
376         for( int i = 0; i < port_count; ++i ) {
377                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
378                 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
379                 ++result;
380         }
381         return result;
382 }
383
384 int PluginAClientLAD::get_outchannels()
385 {
386         int result = 0;
387         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
388         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
389         int port_count = lad_desc->PortCount;
390         for( int i = 0; i < port_count; ++i ) {
391                 if( !LADSPA_IS_PORT_OUTPUT(port_desc[i]) ) continue;
392                 if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue;
393                 ++result;
394         }
395         return result;
396 }
397
398
399 const char* PluginAClientLAD::plugin_title()
400 {
401         return title;
402 }
403
404 int PluginAClientLAD::uses_gui()
405 {
406         return 1;
407 }
408
409 int PluginAClientLAD::is_synthesis()
410 {
411         return 1;
412 }
413
414 LOAD_CONFIGURATION_MACRO(PluginAClientLAD, PluginAClientConfig)
415
416 void PluginAClientLAD::update_gui()
417 {
418 }
419
420 char* PluginAClientLAD::lad_to_string(char *string, const char *input)
421 {
422         strcpy(string, input);
423         int len = strlen(string);
424         for(int j = 0; j < len; j++)
425         {
426                 if(string[j] == ' ' ||
427                         string[j] == '<' ||
428                         string[j] == '>') string[j] = '_';
429         }
430         return string;
431 }
432
433 char* PluginAClientLAD::lad_to_upper(char *string, const char *input)
434 {
435         lad_to_string(string, input);
436         int len = strlen(string);
437         for(int j = 0; j < len; j++)
438                 string[j] = toupper(string[j]);
439         return string;
440 }
441
442
443 void PluginAClientLAD::save_data(KeyFrame *keyframe)
444 {
445         if( !config.port_data ) config.initialize(server);
446         FileXML output;
447 // cause data to be stored directly in text
448         output.set_shared_output(keyframe->xbuf);
449         char string[BCTEXTLEN];
450         output.tag.set_title(lad_to_upper(string, plugin_title()));
451
452         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
453         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
454 //printf("PluginAClientLAD::save_data %d\n", lad_desc->PortCount);
455         int port_count = lad_desc->PortCount;
456         for(int port = 0, i = 0; i < port_count; i++) {
457                 if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
458                 if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
459 // Convert LAD port name to default title
460                 PluginAClientLAD::lad_to_upper(string,
461                         (char*)lad_desc->PortNames[i]);
462                 output.tag.set_property(string, config.port_data[port]);
463 //printf("PluginAClientLAD::save_data %d %f\n", port, config.port_data[port]);
464                 ++port;
465         }
466
467         output.append_tag();
468         output.terminate_string();
469 }
470
471 void PluginAClientLAD::read_data(KeyFrame *keyframe)
472 {
473         if( !config.port_data ) config.initialize(server);
474         FileXML input;
475         input.set_shared_input(keyframe->xbuf);
476
477         while(! input.read_tag() ) {
478 //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title());
479                 char string[BCTEXTLEN];
480                 if(! input.tag.title_is(lad_to_upper(string, plugin_title())) ) continue;
481                 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
482                 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
483                 int port_count = lad_desc->PortCount;
484                 for(int port = 0, i = 0; i < port_count; i++) {
485                         if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue;
486                         if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue;
487                         PluginAClientLAD::lad_to_upper(string, (char*)lad_desc->PortNames[i]);
488                         config.port_data[port] =
489                                 input.tag.get_property(string, config.port_data[port]);
490 //printf("PluginAClientLAD::read_data %d %f\n", port, config.port_data[port]);
491                         port++;
492                 }
493         }
494 }
495
496 void PluginAClientLAD::delete_buffers()
497 {
498         if( in_buffers ) {
499                 for( int i=0; i<total_inbuffers; ++i ) delete [] in_buffers[i];
500                 delete [] in_buffers;  in_buffers = 0;
501         }
502         if( out_buffers ) {
503                 for( int i=0; i<total_outbuffers; ++i ) delete [] out_buffers[i];
504                 delete [] out_buffers;  out_buffers = 0;
505         }
506         total_inbuffers = 0;
507         total_outbuffers = 0;
508         buffer_allocation = 0;
509 }
510
511 void PluginAClientLAD::delete_plugin()
512 {
513         if(lad_instance) {
514                 const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
515                 if( lad_desc->deactivate ) lad_desc->deactivate(lad_instance);
516                 lad_desc->cleanup(lad_instance);
517         }
518         lad_instance = 0;
519 }
520
521 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
522 {
523         int need_reconfigure = !lad_instance ? 1 : 0;
524         if( !config.port_data ) {
525                 config.initialize(server);
526                 need_reconfigure = 1;
527         }
528         if(buffer_allocation && buffer_allocation < size) {
529                 delete_buffers();
530                 need_reconfigure = 1;
531         }
532
533         buffer_allocation = MAX(size, buffer_allocation);
534         if(!in_buffers) {
535                 total_inbuffers = total_in;
536                 in_buffers = new LADSPA_Data*[total_inbuffers];
537                 for(int i = 0; i < total_inbuffers; i++)
538                         in_buffers[i] = new LADSPA_Data[buffer_allocation];
539                 need_reconfigure = 1;
540         }
541
542         if(!out_buffers) {
543                 total_outbuffers = total_out;
544                 out_buffers = new LADSPA_Data*[total_outbuffers];
545                 for(int i = 0; i < total_outbuffers; i++)
546                         out_buffers[i] = new LADSPA_Data[buffer_allocation];
547                 need_reconfigure = 1;
548         }
549
550         if( load_configuration() )
551                 need_reconfigure = 1;
552
553         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
554         if( need_reconfigure ) {
555                 need_reconfigure = 0;
556                 delete_plugin();
557                 lad_instance = lad_desc->instantiate(
558                                 lad_desc,PluginAClient::project_sample_rate);
559                 const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
560                 int port_count = lad_desc->PortCount;
561
562                 for(int port = 0, i = 0; i < port_count; i++) {
563                         if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
564                             LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
565                                 lad_desc->connect_port(lad_instance, i,
566                                         config.port_data + port);
567                                 port++;
568                         }
569                         else if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
570                                  LADSPA_IS_PORT_CONTROL(port_desc[i]) ) {
571                                 lad_desc->connect_port(lad_instance, i,
572                                         &dummy_control_output);
573                         }
574                 }
575                 if(lad_desc->activate) lad_desc->activate(lad_instance);
576         }
577
578         const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors;
579         int port_count = lad_desc->PortCount;
580         for(int port = 0, i = 0; i < port_count; i++) {
581                 if( LADSPA_IS_PORT_INPUT(port_desc[i]) &&
582                     LADSPA_IS_PORT_AUDIO(port_desc[i]) )
583                         lad_desc->connect_port(lad_instance, i, in_buffers[port++]);
584         }
585
586         for(int port = 0, i = 0; i < port_count; i++) {
587                 if( LADSPA_IS_PORT_OUTPUT(port_desc[i]) &&
588                     LADSPA_IS_PORT_AUDIO(port_desc[i]) )
589                         lad_desc->connect_port(lad_instance, i, out_buffers[port++]);
590         }
591 }
592
593 int PluginAClientLAD::process_realtime(int64_t size,
594         Samples *input_ptr,
595         Samples *output_ptr)
596 {
597         int in_channels = get_inchannels();
598         int out_channels = get_outchannels();
599         init_plugin(in_channels, out_channels, size);
600
601         double *input_samples = input_ptr->get_data();
602         for(int i = 0; i < in_channels; i++) {
603                 LADSPA_Data *in_buffer = in_buffers[i];
604                 for(int j = 0; j < size; j++) in_buffer[j] = input_samples[j];
605         }
606         for(int i = 0; i < out_channels; i++)
607                 bzero(out_buffers[i], sizeof(float) * size);
608
609         server->lad_descriptor->run(lad_instance, size);
610
611         double *output_samples = output_ptr->get_data();
612         LADSPA_Data *out_buffer = out_buffers[0];
613         for(int i = 0; i < size; i++) output_samples[i] = out_buffer[i];
614         return size;
615 }
616
617 int PluginAClientLAD::process_realtime(int64_t size,
618         Samples **input_ptr, Samples **output_ptr)
619 {
620         int in_channels = get_inchannels();
621         int out_channels = get_outchannels();
622         init_plugin(in_channels, out_channels, size);
623
624         for(int i = 0; i < in_channels; i++) {
625                 float *in_buffer = in_buffers[i];
626                 int k = i < PluginClient::total_in_buffers ? i : 0;
627                 double *in_ptr = input_ptr[k]->get_data();
628                 for(int j = 0; j < size; j++) in_buffer[j] = in_ptr[j];
629         }
630         for(int i = 0; i < out_channels; i++)
631                 bzero(out_buffers[i], sizeof(float) * size);
632
633         server->lad_descriptor->run(lad_instance, size);
634
635         int nbfrs = PluginClient::total_out_buffers;
636         if( out_channels < nbfrs ) nbfrs = out_channels;
637         for(int i = 0; i < nbfrs; i++) {
638                 LADSPA_Data *out_buffer = out_buffers[i];
639                 double *out_ptr = output_ptr[i]->get_data();
640                 for(int j = 0; j < size; j++) out_ptr[j] = out_buffer[j];
641         }
642         return size;
643 }