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