f6228c3b96d354d1f10559512449aad6160ab336
[goodguy/history.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 "filexml.h"
25 #include "language.h"
26 #include "pluginaclientlad.h"
27 #include "pluginserver.h"
28 #include "samples.h"
29 #include "vframe.h"
30
31 #include <ctype.h>
32 #include <string.h>
33
34
35
36 PluginAClientConfig::PluginAClientConfig()
37 {
38         reset();
39 }
40
41 PluginAClientConfig::~PluginAClientConfig()
42 {
43         delete_objects();
44 }
45
46 void PluginAClientConfig::reset()
47 {
48         total_ports = 0;
49         port_data = 0;
50         port_type = 0;
51 }
52
53 void PluginAClientConfig::delete_objects()
54 {
55         delete [] port_data;  port_data = 0;
56         delete [] port_type;  port_type = 0;
57         reset();
58 }
59
60
61 int PluginAClientConfig::equivalent(PluginAClientConfig &that)
62 {
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;
66         return 1;
67 }
68
69 // Need PluginServer to do this.
70 void PluginAClientConfig::copy_from(PluginAClientConfig &that)
71 {
72         if( total_ports != that.total_ports ) {
73                 delete_objects();
74                 total_ports = that.total_ports;
75                 port_data = new LADSPA_Data[total_ports];
76                 port_type = new int[total_ports];
77         }
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];
81         }
82 }
83
84 void PluginAClientConfig::interpolate(PluginAClientConfig &prev, PluginAClientConfig &next,
85         int64_t prev_frame, int64_t next_frame, int64_t current_frame)
86 {
87         copy_from(prev);
88 }
89
90 void PluginAClientConfig::initialize(PluginServer *server)
91 {
92         delete_objects();
93
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;
100                 ++total_ports;
101         }
102
103         port_data = new LADSPA_Data[total_ports];
104         port_type = new int[total_ports];
105
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
112                 float value = 0.0;
113
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;
122
123 // Get default of port using crazy hinting system
124                 if( LADSPA_IS_HINT_DEFAULT_0(hint_desc) )
125                         value = 0.0;
126                 else if( LADSPA_IS_HINT_DEFAULT_1(hint_desc) )
127                         value = 1.0;
128                 else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) )
129                         value = 100.0;
130                 else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) )
131                         value = 440.0;
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;
154
155                 port_data[port] = value;
156                 ++port;
157         }
158 }
159
160
161 PluginACLientToggle::PluginACLientToggle(PluginAClientLAD *plugin,
162         int x,
163         int y,
164         LADSPA_Data *output)
165  : BC_CheckBox(x, y, (int)(*output))
166 {
167         this->plugin = plugin;
168         this->output = output;
169 }
170
171 int PluginACLientToggle::handle_event()
172 {
173         *output = get_value();
174         plugin->send_configure_change();
175         return 1;
176 }
177
178
179 PluginACLientILinear::PluginACLientILinear(PluginAClientLAD *plugin,
180         int x,
181         int y,
182         LADSPA_Data *output,
183         int min,
184         int max)
185  : BC_IPot(x, y, (int)(*output), min, max)
186 {
187         this->plugin = plugin;
188         this->output = output;
189 }
190
191 int PluginACLientILinear::handle_event()
192 {
193         *output = get_value();
194         plugin->send_configure_change();
195         return 1;
196 }
197
198
199 PluginACLientFLinear::PluginACLientFLinear(PluginAClientLAD *plugin,
200         int x,
201         int y,
202         LADSPA_Data *output,
203         float min,
204         float max)
205  : BC_FPot(x, y, *output, min, max)
206 {
207         this->plugin = plugin;
208         this->output = output;
209         set_precision(0.01);
210 }
211
212 int PluginACLientFLinear::handle_event()
213 {
214         *output = get_value();
215         plugin->send_configure_change();
216         return 1;
217 }
218
219
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) :
224                 (int)*output)
225 {
226         this->plugin = plugin;
227         this->output = output;
228         this->translate_linear = translate_linear;
229 }
230
231 int PluginACLientFreq::handle_event()
232 {
233         *output = translate_linear ?
234                 (float)get_value() / plugin->PluginAClient::project_sample_rate :
235                 get_value();
236         plugin->send_configure_change();
237         return 1;
238 }
239
240
241
242 PluginAClientWindow::PluginAClientWindow(PluginAClientLAD *plugin)
243  : PluginClientWindow(plugin, 500, plugin->config.total_ports * 30 + 60,
244         500, plugin->config.total_ports * 30 + 60, 0)
245 {
246         this->plugin = plugin;
247 }
248
249 PluginAClientWindow::~PluginAClientWindow()
250 {
251 }
252
253
254 void PluginAClientWindow::create_objects()
255 {
256         PluginServer *server = plugin->server;
257         char string[BCTEXTLEN];
258         int current_port = 0;
259         int x = 10;
260         int y = 10;
261         int x2 = 300;
262         int x3 = 335;
263         int title_vmargin = 5;
264         int max_w = 0;
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;
273         }
274
275         x2 = max_w + 20;
276         x3 = max_w + 55;
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);
288
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],
298                                         min, max));
299                         fpots.append(flinear);
300                         break; }
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 */));
309                         freqs.append(freq);
310                         break; }
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);
318                         break; }
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);
329                         break; }
330                 }
331                 current_port++;
332                 y += 30;
333 //printf("PluginAClientWindow::create_objects 2\n");
334         }
335
336         y += 10;
337         sprintf(string, _("Author: %s"), lad_desc->Maker);
338         add_subwindow(new BC_Title(x, y, string));
339         y += 20;
340         sprintf(string, _("License: %s"), lad_desc->Copyright);
341         add_subwindow(new BC_Title(x, y, string));
342         show_window(1);
343 }
344
345
346
347 PluginAClientLAD::PluginAClientLAD(PluginServer *server)
348  : PluginAClient(server)
349 {
350         in_buffers = 0;
351         total_inbuffers = 0;
352         out_buffers = 0;
353         total_outbuffers = 0;
354         buffer_allocation = 0;
355         lad_instance = 0;
356         snprintf(title, sizeof(title), "L_%s", server->lad_descriptor->Name);
357 }
358
359 PluginAClientLAD::~PluginAClientLAD()
360 {
361         delete_buffers();
362         delete_plugin();
363 }
364
365 NEW_WINDOW_MACRO(PluginAClientLAD, PluginAClientWindow)
366
367 int PluginAClientLAD::is_realtime()
368 {
369         return 1;
370 }
371
372 int PluginAClientLAD::is_multichannel()
373 {
374         if(get_inchannels() > 1 || get_outchannels() > 1) return 1;
375         return 0;
376 }
377
378 int PluginAClientLAD::get_inchannels()
379 {
380         int result = 0;
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;
387                 ++result;
388         }
389         return result;
390 }
391
392 int PluginAClientLAD::get_outchannels()
393 {
394         int result = 0;
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;
401                 ++result;
402         }
403         return result;
404 }
405
406
407 const char* PluginAClientLAD::plugin_title()
408 {
409         return title;
410 }
411
412 int PluginAClientLAD::uses_gui()
413 {
414         return 1;
415 }
416
417 int PluginAClientLAD::is_synthesis()
418 {
419         return 1;
420 }
421
422 LOAD_CONFIGURATION_MACRO(PluginAClientLAD, PluginAClientConfig)
423
424 void PluginAClientLAD::update_gui()
425 {
426 }
427
428 char* PluginAClientLAD::lad_to_string(char *string, const char *input)
429 {
430         strcpy(string, input);
431         int len = strlen(string);
432         for(int j = 0; j < len; j++)
433         {
434                 if(string[j] == ' ' ||
435                         string[j] == '<' ||
436                         string[j] == '>') string[j] = '_';
437         }
438         return string;
439 }
440
441 char* PluginAClientLAD::lad_to_upper(char *string, const char *input)
442 {
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]);
447         return string;
448 }
449
450
451 void PluginAClientLAD::save_data(KeyFrame *keyframe)
452 {
453         FileXML output;
454         char string[BCTEXTLEN];
455         if( !config.port_data ) config.initialize(server);
456
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()));
460
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]);
473                 ++port;
474         }
475
476         output.append_tag();
477         output.terminate_string();
478 }
479
480 void PluginAClientLAD::read_data(KeyFrame *keyframe)
481 {
482         FileXML input;
483         char string[BCTEXTLEN];
484
485         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
486         if( !config.port_data ) config.initialize(server);
487
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]);
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         if(out_buffers)
511                 for(int i = 0; i < total_outbuffers; i++) delete [] out_buffers[i];
512         in_buffers = 0;
513         out_buffers = 0;
514         total_inbuffers = 0;
515         total_outbuffers = 0;
516         buffer_allocation = 0;
517 }
518
519 void PluginAClientLAD::delete_plugin()
520 {
521         if(lad_instance) {
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);
525         }
526         lad_instance = 0;
527 }
528
529 void PluginAClientLAD::init_plugin(int total_in, int total_out, int size)
530 {
531         int need_reconfigure = !lad_instance ? 1 : 0;
532         if( !config.port_data ) {
533                 config.initialize(server);
534                 need_reconfigure = 1;
535         }
536         if(buffer_allocation && buffer_allocation < size) {
537                 delete_buffers();
538                 need_reconfigure = 1;
539         }
540
541         buffer_allocation = MAX(size, buffer_allocation);
542         if(!in_buffers) {
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;
548         }
549
550         if(!out_buffers) {
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;
556         }
557
558         if( load_configuration() )
559                 need_reconfigure = 1;
560
561         const LADSPA_Descriptor *lad_desc = server->lad_descriptor;
562         if( need_reconfigure ) {
563                 need_reconfigure = 0;
564                 delete_plugin();
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;
569
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);
575                                 port++;
576                         }
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);
581                         }
582                 }
583                 if(lad_desc->activate) lad_desc->activate(lad_instance);
584         }
585
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++]);
592         }
593
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++]);
598         }
599 }
600
601 int PluginAClientLAD::process_realtime(int64_t size,
602         Samples *input_ptr,
603         Samples *output_ptr)
604 {
605         int in_channels = get_inchannels();
606         int out_channels = get_outchannels();
607         init_plugin(in_channels, out_channels, size);
608
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];
613         }
614         for(int i = 0; i < out_channels; i++)
615                 bzero(out_buffers[i], sizeof(float) * size);
616
617         server->lad_descriptor->run(lad_instance, size);
618
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];
622         return size;
623 }
624
625 int PluginAClientLAD::process_realtime(int64_t size,
626         Samples **input_ptr, Samples **output_ptr)
627 {
628         int in_channels = get_inchannels();
629         int out_channels = get_outchannels();
630         init_plugin(in_channels, out_channels, size);
631
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];
637         }
638         for(int i = 0; i < out_channels; i++)
639                 bzero(out_buffers[i], sizeof(float) * size);
640
641         server->lad_descriptor->run(lad_instance, size);
642
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];
649         }
650         return size;
651 }
652
653
654