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