cd69dfe7b4a6f899f351402446b7606114d7d086
[goodguy/history.git] / cinelerra-5.1 / cinelerra / pluginserver.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009 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 "amodule.h"
23 #include "atrack.h"
24 #include "attachmentpoint.h"
25 #include "autoconf.h"
26 #include "bcsignals.h"
27 #include "cplayback.h"
28 #include "cstrdup.h"
29 #include "cwindow.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "file.h"
33 #include "floatautos.h"
34 #include "keyframes.h"
35 #include "localsession.h"
36 #include "mainerror.h"
37 #include "mainprogress.h"
38 #include "menueffects.h"
39 #include "mwindow.h"
40 #include "mwindowgui.h"
41 #include "playbackengine.h"
42 #include "plugin.h"
43 #include "pluginaclient.h"
44 #include "pluginaclientlad.h"
45 #include "pluginfclient.h"
46 #include "pluginclient.h"
47 #include "plugincommands.h"
48 #include "pluginserver.h"
49 #include "pluginvclient.h"
50 #include "preferences.h"
51 #include "samples.h"
52 #include "sema.h"
53 #include "mainsession.h"
54 #include "theme.h"
55 #include "trackcanvas.h"
56 #include "transportque.h"
57 #include "vdevicex11.h"
58 #include "vframe.h"
59 #include "videodevice.h"
60 #include "virtualanode.h"
61 #include "virtualvnode.h"
62 #include "vmodule.h"
63 #include "vtrack.h"
64
65
66 #include<stdio.h>
67 #include<unistd.h>
68 #include<fcntl.h>
69 #include <sys/types.h>
70 #include <sys/wait.h>
71 #include<sys/stat.h>
72 #include <sys/mman.h>
73
74
75 void PluginServer::init()
76 {
77         reset_parameters();
78         this->plugin_type = PLUGIN_TYPE_UNKNOWN;
79         plugin_obj = new PluginObj();
80         modules = new ArrayList<Module*>;
81         nodes = new ArrayList<VirtualNode*>;
82 }
83
84 PluginServer::PluginServer()
85 {
86         init();
87 }
88
89 PluginServer::PluginServer(MWindow *mwindow, char *path, int type)
90 {
91         char fpath[BCTEXTLEN];
92         init();
93         this->plugin_type = type;
94         this->mwindow = mwindow;
95         if( type == PLUGIN_TYPE_FFMPEG ) {
96                 ff_name = cstrdup(path);
97                 sprintf(fpath, "ff_%s", path);
98                 path = fpath;
99         }
100         set_path(path);
101 }
102
103 PluginServer::PluginServer(PluginServer &that)
104 {
105         reset_parameters();
106         plugin_type = that.plugin_type;
107         plugin_obj = that.plugin_obj;
108         plugin_obj->add_user();
109         title = !that.title ? 0 : cstrdup(that.title);
110         path = !that.path ? 0 : cstrdup(that.path);
111         ff_name = !that.ff_name ? 0 : cstrdup(that.ff_name);
112         modules = new ArrayList<Module*>;
113         nodes = new ArrayList<VirtualNode*>;
114
115         attachment = that.attachment;
116         realtime = that.realtime;
117         multichannel = that.multichannel;
118         preferences = that.preferences;
119         synthesis = that.synthesis;
120         audio = that.audio;
121         video = that.video;
122         theme = that.theme;
123         fileio = that.fileio;
124         uses_gui = that.uses_gui;
125         mwindow = that.mwindow;
126         keyframe = that.keyframe;
127         new_plugin = that.new_plugin;
128
129         lad_descriptor = that.lad_descriptor;
130         lad_descriptor_function = that.lad_descriptor_function;
131         lad_index = that.lad_index;
132 }
133
134 PluginServer::~PluginServer()
135 {
136         close_plugin();
137         delete [] path;
138         delete [] ff_name;
139         delete [] title;
140         delete modules;
141         delete nodes;
142         delete picon;
143         plugin_obj->remove_user();
144 }
145
146 // Done only once at creation
147 int PluginServer::reset_parameters()
148 {
149         mwindow = 0;
150         keyframe = 0;
151         prompt = 0;
152         cleanup_plugin();
153         autos = 0;
154         edl = 0;
155         preferences = 0;
156         title = 0;
157         path = 0;
158         ff_name = 0;
159         audio = video = theme = 0;
160         fileio = 0;
161         uses_gui = 0;
162         realtime = multichannel = fileio = 0;
163         synthesis = 0;
164         start_auto = end_auto = 0;
165         transition = 0;
166         new_plugin = 0;
167         client = 0;
168         use_opengl = 0;
169         vdevice = 0;
170         modules = 0;
171         nodes = 0;
172         picon = 0;
173
174         lad_index = -1;
175         lad_descriptor_function = 0;
176         lad_descriptor = 0;
177         return 0;
178 }
179
180 // Done every time the plugin is opened or closed
181 int PluginServer::cleanup_plugin()
182 {
183         in_buffer_size = out_buffer_size = 0;
184         total_in_buffers = total_out_buffers = 0;
185         error_flag = 0;
186         written_samples = 0;
187         shared_buffers = 0;
188         new_buffers = 0;
189         written_samples = written_frames = 0;
190         gui_on = 0;
191         plugin = 0;
192         plugin_open = 0;
193         return 0;
194 }
195
196 void PluginServer::set_mwindow(MWindow *mwindow)
197 {
198         this->mwindow = mwindow;
199 }
200
201 void PluginServer::set_attachmentpoint(AttachmentPoint *attachmentpoint)
202 {
203         this->attachmentpoint = attachmentpoint;
204 }
205
206 void PluginServer::set_keyframe(KeyFrame *keyframe)
207 {
208         this->keyframe = keyframe;
209 }
210
211 void PluginServer::set_prompt(MenuEffectPrompt *prompt)
212 {
213         this->prompt = prompt;
214 }
215
216 void PluginServer::set_lad_index(int i)
217 {
218         this->lad_index = i;
219 }
220
221 int PluginServer::get_lad_index()
222 {
223         return this->lad_index;
224 }
225
226 int PluginServer::is_ladspa()
227 {
228         return plugin_type == PLUGIN_TYPE_LADSPA ? 1 : 0;
229 }
230
231 int PluginServer::is_ffmpeg()
232 {
233         return plugin_type == PLUGIN_TYPE_FFMPEG ? 1 : 0;
234 }
235
236 void PluginServer::set_path(const char *path)
237 {
238         delete [] this->path;
239         this->path = cstrdup(path);
240 }
241
242 char* PluginServer::get_path()
243 {
244         return this->path;
245 }
246
247 int PluginServer::get_synthesis()
248 {
249         return synthesis;
250 }
251
252
253 void PluginServer::set_title(const char *string)
254 {
255         if(title) delete [] title;
256         title = cstrdup(string);
257 }
258
259 void PluginServer::generate_display_title(char *string)
260 {
261         char ltitle[BCTEXTLEN];
262         if(BC_Resources::locale_utf8)
263                 strcpy(ltitle, _(title));
264         else
265                 BC_Resources::encode(BC_Resources::encoding, 0,
266                                 _(title),strlen(title)+1, ltitle,BCTEXTLEN);
267         if(plugin && plugin->track)
268                 sprintf(string, "%s: %s", plugin->track->title, ltitle);
269         else
270                 strcpy(string, ltitle);
271 }
272
273 void *PluginObj::load(const char *plugin_dir, const char *path)
274 {
275         char dlpath[BCTEXTLEN], *dp = dlpath;
276         const char *cp = path;
277         if( *cp != '/' ) {
278                 const char *bp = plugin_dir;
279                 while( *bp ) *dp++ = *bp++;
280                 *dp++ = '/';
281         }
282         while( *cp ) *dp++ = *cp++;
283         *dp = 0;
284         return dlobj = load(dlpath);
285 }
286
287 int PluginServer::load_obj()
288 {
289         void *obj = plugin_obj->obj();
290         if( !obj ) obj =plugin_obj->load(preferences->plugin_dir, path);
291         return obj ? 1 : 0;
292 }
293
294 const char *PluginServer::load_error()
295 {
296         return plugin_obj->load_error();
297 }
298
299 void *PluginServer::get_sym(const char *sym)
300 {
301         if( !plugin_obj->obj() ) return 0;
302         return plugin_obj->load_sym(sym);
303 }
304
305 // Open plugin for signal processing
306 int PluginServer::open_plugin(int master,
307         Preferences *preferences,
308         EDL *edl,
309         Plugin *plugin)
310 {
311         if(plugin_open) return 0;
312
313         this->preferences = preferences;
314         this->plugin = plugin;
315         this->edl = edl;
316         if( plugin_type != PLUGIN_TYPE_FFMPEG && plugin_type != PLUGIN_TYPE_EXECUTABLE && !load_obj() ) {
317 // If the load failed, can't use error to detect executable
318 //  because locale and language selection change the load_error()
319 //      if( !strstr(string, "executable") ) { set_title(path); plugin_type = PLUGIN_TYPE_EXECUTABLE; }
320                 eprintf("PluginServer::open_plugin: load_obj %s = %s\n", path, load_error());
321                 return PLUGINSERVER_NOT_RECOGNIZED;
322         }
323         if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_BUILTIN ) {
324                 new_plugin =
325                         (PluginClient* (*)(PluginServer*)) get_sym("new_plugin");
326                 if( new_plugin )
327                         plugin_type = PLUGIN_TYPE_BUILTIN;
328         }
329         if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_LADSPA ) {
330                 lad_descriptor_function =
331                         (LADSPA_Descriptor_Function) get_sym("ladspa_descriptor");
332                 if( lad_descriptor_function ) {
333                         if( lad_index < 0 ) return PLUGINSERVER_IS_LAD;
334                         lad_descriptor = lad_descriptor_function(lad_index);
335                         if( !lad_descriptor )
336                                 return PLUGINSERVER_NOT_RECOGNIZED;
337                         plugin_type = PLUGIN_TYPE_LADSPA;
338                 }
339         }
340         if( plugin_type == PLUGIN_TYPE_UNKNOWN ) {
341                 fprintf(stderr, "PluginServer::open_plugin "
342                         " %d: plugin undefined in %s\n", __LINE__, path);
343                 return PLUGINSERVER_NOT_RECOGNIZED;
344         }
345         switch( plugin_type ) {
346         case PLUGIN_TYPE_EXECUTABLE:
347                 return PLUGINSERVER_OK;
348         case PLUGIN_TYPE_BUILTIN:
349                 client = new_plugin(this);
350                 break;
351         case PLUGIN_TYPE_LADSPA:
352                 client = new PluginAClientLAD(this);
353                 break;
354         case PLUGIN_TYPE_FFMPEG:
355                 client = new_ffmpeg_plugin();
356                 break;
357         default:
358                 client = 0;
359                 break;
360         }
361         if( !client )
362                 return PLUGINSERVER_NOT_RECOGNIZED;
363
364 // Run initialization functions
365         realtime = client->is_realtime();
366 // Don't load defaults when probing the directory.
367         if(!master) {
368                 if(realtime)
369                         client->load_defaults_xml();
370                 else
371                         client->load_defaults();
372         }
373         audio = client->is_audio();
374         video = client->is_video();
375         theme = client->is_theme();
376         fileio = client->is_fileio();
377         uses_gui = client->uses_gui();
378         multichannel = client->is_multichannel();
379         synthesis = client->is_synthesis();
380         transition = client->is_transition();
381         set_title(client->plugin_title());
382
383 //printf("PluginServer::open_plugin 2\n");
384         plugin_open = 1;
385         return PLUGINSERVER_OK;
386 }
387
388 int PluginServer::close_plugin()
389 {
390         if(!plugin_open) return 0;
391
392         if(client)
393         {
394 // Defaults are saved in the thread.
395 //              if(client->defaults) client->save_defaults();
396                 delete client;
397         }
398
399 // shared object is persistent since plugin deletion would unlink its own object
400         plugin_open = 0;
401         cleanup_plugin();
402         return 0;
403 }
404
405 void PluginServer::client_side_close()
406 {
407 // Last command executed in client thread
408         if(plugin)
409                 mwindow->hide_plugin(plugin, 1);
410         else
411         if(prompt)
412         {
413                 prompt->lock_window();
414                 prompt->set_done(1);
415                 prompt->unlock_window();
416         }
417 }
418
419 void PluginServer::render_stop()
420 {
421         if(client)
422                 client->render_stop();
423 }
424
425 void PluginServer::write_table(FILE *fp, const char *path, int idx, int64_t mtime)
426 {
427         if(!fp) return;
428         fprintf(fp, "%d \"%s\" \"%s\" %jd %d %d %d %d %d %d %d %d %d %d %d\n",
429                 plugin_type, path, title, mtime, idx, audio, video, theme, realtime,
430                 fileio, uses_gui, multichannel, synthesis, transition, lad_index);
431 }
432
433 int PluginServer::scan_table(char *text, int &type, char *path, char *title, int64_t &mtime)
434 {
435         int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" %jd", &type, path, title, &mtime);
436         return n < 4 ? 1 : 0;
437 }
438
439 int PluginServer::read_table(char *text)
440 {
441         char path[BCTEXTLEN], title[BCTEXTLEN];
442         int64_t mtime;
443         int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" %jd %d %d %d %d %d %d %d %d %d %d %d",
444                 &plugin_type, path, title, &mtime, &dir_idx, &audio, &video, &theme, &realtime,
445                 &fileio, &uses_gui, &multichannel, &synthesis, &transition, &lad_index);
446         if( n != 15 ) return 1;
447         set_title(title);
448         return 0;
449 }
450
451 int PluginServer::init_realtime(int realtime_sched,
452                 int total_in_buffers,
453                 int buffer_size)
454 {
455
456         if(!plugin_open) return 0;
457
458 // set for realtime priority
459 // initialize plugin
460 // Call start_realtime
461         this->total_in_buffers = this->total_out_buffers = total_in_buffers;
462         client->plugin_init_realtime(realtime_sched,
463                 total_in_buffers,
464                 buffer_size);
465
466         return 0;
467 }
468
469
470 // Replaced by pull method but still needed for transitions
471 void PluginServer::process_transition(VFrame *input,
472                 VFrame *output,
473                 int64_t current_position,
474                 int64_t total_len)
475 {
476         if(!plugin_open) return;
477         PluginVClient *vclient = (PluginVClient*)client;
478
479         vclient->source_position = current_position;
480         vclient->source_start = 0;
481         vclient->total_len = total_len;
482
483         vclient->input = new VFrame*[1];
484         vclient->output = new VFrame*[1];
485
486         vclient->input[0] = input;
487         vclient->output[0] = output;
488
489         vclient->process_realtime(input, output);
490         vclient->age_temp();
491         delete [] vclient->input;
492         delete [] vclient->output;
493         use_opengl = 0;
494 }
495
496 void PluginServer::process_transition(Samples *input,
497                 Samples *output,
498                 int64_t current_position,
499                 int64_t fragment_size,
500                 int64_t total_len)
501 {
502         if(!plugin_open) return;
503         PluginAClient *aclient = (PluginAClient*)client;
504
505         aclient->source_position = current_position;
506         aclient->total_len = total_len;
507         aclient->source_start = 0;
508         aclient->process_realtime(fragment_size,
509                 input,
510                 output);
511 }
512
513
514 void PluginServer::process_buffer(VFrame **frame,
515         int64_t current_position,
516         double frame_rate,
517         int64_t total_len,
518         int direction)
519 {
520         if(!plugin_open) return;
521         PluginVClient *vclient = (PluginVClient*)client;
522
523         vclient->source_position = current_position;
524         vclient->total_len = total_len;
525         vclient->frame_rate = frame_rate;
526         vclient->input = new VFrame*[total_in_buffers];
527         vclient->output = new VFrame*[total_in_buffers];
528         for(int i = 0; i < total_in_buffers; i++)
529         {
530                 vclient->input[i] = frame[i];
531                 vclient->output[i] = frame[i];
532         }
533
534         if(plugin)
535         {
536                 vclient->source_start = (int64_t)plugin->startproject *
537                         frame_rate /
538                         vclient->project_frame_rate;
539         }
540         vclient->direction = direction;
541
542
543 //PRINT_TRACE
544 //printf("plugin=%p source_start=%ld\n", plugin, vclient->source_start);
545
546         vclient->begin_process_buffer();
547         if(multichannel)
548         {
549                 vclient->process_buffer(frame, current_position, frame_rate);
550         }
551         else
552         {
553                 vclient->process_buffer(frame[0], current_position, frame_rate);
554         }
555         vclient->end_process_buffer();
556
557         for(int i = 0; i < total_in_buffers; i++)
558                 frame[i]->push_prev_effect(title);
559
560         delete [] vclient->input;
561         delete [] vclient->output;
562
563     vclient->age_temp();
564         use_opengl = 0;
565 }
566
567 void PluginServer::process_buffer(Samples **buffer,
568         int64_t current_position,
569         int64_t fragment_size,
570         int64_t sample_rate,
571         int64_t total_len,
572         int direction)
573 {
574         if(!plugin_open) return;
575         PluginAClient *aclient = (PluginAClient*)client;
576
577         aclient->source_position = current_position;
578         aclient->total_len = total_len;
579         aclient->sample_rate = sample_rate;
580
581         if(plugin)
582                 aclient->source_start = plugin->startproject *
583                         sample_rate /
584                         aclient->project_sample_rate;
585
586         aclient->direction = direction;
587         aclient->begin_process_buffer();
588         if(multichannel)
589         {
590                 aclient->process_buffer(fragment_size,
591                         buffer,
592                         current_position,
593                         sample_rate);
594         }
595         else
596         {
597                 aclient->process_buffer(fragment_size,
598                         buffer[0],
599                         current_position,
600                         sample_rate);
601         }
602         aclient->end_process_buffer();
603 }
604
605
606 void PluginServer::send_render_gui(void *data)
607 {
608 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
609         if(attachmentpoint) attachmentpoint->render_gui(data, this);
610 }
611
612 void PluginServer::send_render_gui(void *data, int size)
613 {
614 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
615         if(attachmentpoint) attachmentpoint->render_gui(data, size, this);
616 }
617
618 void PluginServer::render_gui(void *data)
619 {
620         if(client) client->plugin_render_gui(data);
621 }
622
623 void PluginServer::render_gui(void *data, int size)
624 {
625         if(client) client->plugin_render_gui(data, size);
626 }
627
628 MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
629 {
630         mwindow->gui->lock_window();
631         MainProgressBar *result = mwindow->mainprogress->start_progress(string, length);
632         mwindow->gui->unlock_window();
633         return result;
634 }
635
636 int64_t PluginServer::get_written_samples()
637 {
638         if(!plugin_open) return 0;
639         return written_samples;
640 }
641
642 int64_t PluginServer::get_written_frames()
643 {
644         if(!plugin_open) return 0;
645         return written_frames;
646 }
647
648
649
650
651
652
653
654
655
656
657 // ======================= Non-realtime plugin
658
659 int PluginServer::get_parameters(int64_t start, int64_t end, int channels)
660 {
661         if(!plugin_open) return 0;
662
663         client->start = start;
664         client->end = end;
665         client->source_start = start;
666         client->total_len = end - start;
667         client->total_in_buffers = channels;
668
669 //PRINT_TRACE
670 //printf(" source_start=%ld total_len=%ld\n", client->source_start, client->total_len);
671
672         return client->plugin_get_parameters();
673 }
674
675 int PluginServer::set_interactive()
676 {
677         if(!plugin_open) return 0;
678         client->set_interactive();
679         return 0;
680 }
681
682 void PluginServer::append_module(Module *module)
683 {
684         modules->append(module);
685 }
686
687 void PluginServer::append_node(VirtualNode *node)
688 {
689         nodes->append(node);
690 }
691
692 void PluginServer::reset_nodes()
693 {
694         nodes->remove_all();
695 }
696
697 int PluginServer::set_error()
698 {
699         error_flag = 1;
700         return 0;
701 }
702
703 int PluginServer::set_realtime_sched()
704 {
705         //struct sched_param params;
706         //params.sched_priority = 1;
707         //sched_setscheduler(0, SCHED_RR, &param);
708         return 0;
709 }
710
711
712 int PluginServer::process_loop(VFrame **buffers, int64_t &write_length)
713 {
714         if(!plugin_open) return 1;
715         return client->plugin_process_loop(buffers, write_length);
716 }
717
718 int PluginServer::process_loop(Samples **buffers, int64_t &write_length)
719 {
720         if(!plugin_open) return 1;
721         return client->plugin_process_loop(buffers, write_length);
722 }
723
724
725 int PluginServer::start_loop(int64_t start,
726         int64_t end,
727         int64_t buffer_size,
728         int total_buffers)
729 {
730         if(!plugin_open) return 0;
731         client->plugin_start_loop(start, end, buffer_size, total_buffers);
732         return 0;
733 }
734
735 int PluginServer::stop_loop()
736 {
737         if(!plugin_open) return 0;
738         return client->plugin_stop_loop();
739 }
740
741 int PluginServer::read_frame(VFrame *buffer,
742         int channel,
743         int64_t start_position)
744 {
745         ((VModule*)modules->values[channel])->render(buffer,
746                 start_position,
747                 PLAY_FORWARD,
748                 mwindow->edl->session->frame_rate,
749                 0,
750                 0);
751         return 0;
752 }
753
754 int PluginServer::read_samples(Samples *buffer,
755         int channel,
756         int64_t sample_rate,
757         int64_t start_position,
758         int64_t len)
759 {
760 // len is now in buffer
761         if(!multichannel) channel = 0;
762
763         if(nodes->total > channel)
764                 return ((VirtualANode*)nodes->values[channel])->read_data(buffer,
765                         len,
766                         start_position,
767                         sample_rate);
768         else
769         if(modules->total > channel)
770                 return ((AModule*)modules->values[channel])->render(buffer,
771                         len,
772                         start_position,
773                         PLAY_FORWARD,
774                         sample_rate,
775                         0);
776         else
777         {
778                 printf("PluginServer::read_samples no object available for channel=%d\n",
779                         channel);
780         }
781
782         return -1;
783 }
784
785
786 int PluginServer::read_samples(Samples *buffer,
787         int channel,
788         int64_t start_position,
789         int64_t size)
790 {
791 // total_samples is now set in buffer
792         ((AModule*)modules->values[channel])->render(buffer,
793                 size,
794                 start_position,
795                 PLAY_FORWARD,
796                 mwindow->edl->session->sample_rate,
797                 0);
798         return 0;
799 }
800
801 int PluginServer::read_frame(VFrame *buffer,
802         int channel,
803         int64_t start_position,
804         double frame_rate,
805         int use_opengl)
806 {
807 // Data source depends on whether we're part of a virtual console or a
808 // plugin array.
809 //     VirtualNode
810 //     Module
811 // If we're a VirtualNode, read_data in the virtual plugin node handles
812 //     backward propogation and produces the data.
813 // If we're a Module, render in the module produces the data.
814 //PRINT_TRACE
815
816         int result = -1;
817         if(!multichannel) channel = 0;
818
819 // Push our name on the next effect stack
820         buffer->push_next_effect(title);
821 //printf("PluginServer::read_frame %p\n", buffer);
822 //buffer->dump_stacks();
823
824         if(nodes->total > channel)
825         {
826 //printf("PluginServer::read_frame %d\n", __LINE__);
827                 result = ((VirtualVNode*)nodes->values[channel])->read_data(buffer,
828                         start_position,
829                         frame_rate,
830                         use_opengl);
831         }
832         else
833         if(modules->total > channel)
834         {
835 //printf("PluginServer::read_frame %d\n", __LINE__);
836                 result = ((VModule*)modules->values[channel])->render(buffer,
837                         start_position,
838 //                      PLAY_FORWARD,
839                         client->direction,
840                         frame_rate,
841                         0,
842                         0,
843                         use_opengl);
844         }
845         else
846         {
847                 printf("PluginServer::read_frame no object available for channel=%d\n",
848                         channel);
849         }
850
851 // Pop our name from the next effect stack
852         buffer->pop_next_effect();
853
854         return result;
855 }
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876 // Called by client
877 int PluginServer::get_gui_status()
878 {
879         if(plugin)
880                 return plugin->show ? GUI_ON : GUI_OFF;
881         else
882                 return GUI_OFF;
883 }
884
885 void PluginServer::raise_window()
886 {
887         if(!plugin_open) return;
888         client->raise_window();
889 }
890
891 void PluginServer::show_gui()
892 {
893         if(!plugin_open) return;
894         if(plugin) client->total_len = plugin->length;
895         if(plugin) client->source_start = plugin->startproject;
896         if(video)
897         {
898                 client->source_position = Units::to_int64(
899                         mwindow->edl->local_session->get_selectionstart(1) *
900                                 mwindow->edl->session->frame_rate);
901         }
902         else
903         if(audio)
904         {
905                 client->source_position = Units::to_int64(
906                         mwindow->edl->local_session->get_selectionstart(1) *
907                                 mwindow->edl->session->sample_rate);
908         }
909
910         client->update_display_title();
911         client->show_gui();
912 }
913
914 void PluginServer::hide_gui()
915 {
916         if(!plugin_open) return;
917         if(client->defaults) client->save_defaults();
918         client->hide_gui();
919 }
920
921 void PluginServer::update_gui()
922 {
923         if(!plugin_open || !plugin) return;
924
925         client->total_len = plugin->length;
926         client->source_start = plugin->startproject;
927
928         if(video)
929         {
930                 client->source_position = Units::to_int64(
931                         mwindow->edl->local_session->get_selectionstart(1) *
932                                 mwindow->edl->session->frame_rate);
933         }
934         else
935         if(audio)
936         {
937                 client->source_position = Units::to_int64(
938                         mwindow->edl->local_session->get_selectionstart(1) *
939                                 mwindow->edl->session->sample_rate);
940         }
941
942         client->plugin_update_gui();
943 }
944
945 void PluginServer::update_title()
946 {
947         if(!plugin_open) return;
948
949         client->update_display_title();
950 }
951
952
953 int PluginServer::set_string(char *string)
954 {
955         if(!plugin_open) return 0;
956
957         client->set_string_client(string);
958         return 0;
959 }
960
961 int PluginServer::gui_open()
962 {
963         if(attachmentpoint) return attachmentpoint->gui_open();
964         return 0;
965 }
966
967 void PluginServer::set_use_opengl(int value, VideoDevice *vdevice)
968 {
969         this->use_opengl = value;
970         this->vdevice = vdevice;
971 }
972
973 int PluginServer::get_use_opengl()
974 {
975         return use_opengl;
976 }
977
978
979 void PluginServer::run_opengl(PluginClient *plugin_client)
980 {
981         if(vdevice)
982                 ((VDeviceX11*)vdevice->get_output_base())->run_plugin(plugin_client);
983 }
984
985 // ============================= queries
986
987 void PluginServer::get_defaults_path(char *path)
988 {
989 // Get plugin name from path
990         char *ptr1 = strrchr(get_path(), '/');
991         char *ptr2 = strrchr(get_path(), '.');
992         if(!ptr1) ptr1 = get_path();
993         if(!ptr2) ptr2 = get_path() + strlen(get_path());
994         char string2[BCTEXTLEN], *ptr3 = string2;
995         while( ptr1 < ptr2 ) *ptr3++ = *ptr1++;
996         *ptr3 = 0;
997         sprintf(path, "%s/%s.xml", File::get_config_path(), string2);
998 }
999
1000 void PluginServer::save_defaults()
1001 {
1002         if(client) client->save_defaults();
1003 }
1004
1005 int PluginServer::get_samplerate()
1006 {
1007         if(!plugin_open) return 0;
1008         if(audio)
1009         {
1010                 return client->get_samplerate();
1011         }
1012         else
1013         if(mwindow)
1014                 return mwindow->edl->session->sample_rate;
1015         else
1016         {
1017                 printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
1018                 return 1;
1019         }
1020 }
1021
1022
1023 double PluginServer::get_framerate()
1024 {
1025         if(!plugin_open) return 0;
1026         if(video)
1027         {
1028                 return client->get_framerate();
1029         }
1030         else
1031         if(mwindow)
1032                 return mwindow->edl->session->frame_rate;
1033         else
1034         {
1035                 printf("PluginServer::get_framerate video and mwindow == NULL\n");
1036                 return 1;
1037         }
1038 }
1039
1040 int PluginServer::get_project_samplerate()
1041 {
1042         if(mwindow)
1043                 return mwindow->edl->session->sample_rate;
1044         else
1045         if(edl)
1046                 return edl->session->sample_rate;
1047         else
1048         {
1049                 printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
1050                 return 1;
1051         }
1052 }
1053
1054 double PluginServer::get_project_framerate()
1055 {
1056         if(mwindow)
1057                 return mwindow->edl->session->frame_rate;
1058         else
1059         if(edl)
1060                 return edl->session->frame_rate;
1061         else
1062         {
1063                 printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
1064                 return 1;
1065         }
1066 }
1067
1068
1069
1070 int PluginServer::detach_buffers()
1071 {
1072         ring_buffers_out.remove_all();
1073         offset_out_render.remove_all();
1074         double_buffer_out_render.remove_all();
1075         realtime_out_size.remove_all();
1076
1077         ring_buffers_in.remove_all();
1078         offset_in_render.remove_all();
1079         double_buffer_in_render.remove_all();
1080         realtime_in_size.remove_all();
1081
1082         out_buffer_size = 0;
1083         shared_buffers = 0;
1084         total_out_buffers = 0;
1085         in_buffer_size = 0;
1086         total_in_buffers = 0;
1087         return 0;
1088 }
1089
1090 int PluginServer::arm_buffer(int buffer_number,
1091                 int64_t offset_in,
1092                 int64_t offset_out,
1093                 int double_buffer_in,
1094                 int double_buffer_out)
1095 {
1096         offset_in_render.values[buffer_number] = offset_in;
1097         offset_out_render.values[buffer_number] = offset_out;
1098         double_buffer_in_render.values[buffer_number] = double_buffer_in;
1099         double_buffer_out_render.values[buffer_number] = double_buffer_out;
1100         return 0;
1101 }
1102
1103
1104 int PluginServer::set_automation(FloatAutos *autos, FloatAuto **start_auto, FloatAuto **end_auto, int reverse)
1105 {
1106         this->autos = autos;
1107         this->start_auto = start_auto;
1108         this->end_auto = end_auto;
1109         this->reverse = reverse;
1110         return 0;
1111 }
1112
1113
1114
1115 void PluginServer::save_data(KeyFrame *keyframe)
1116 {
1117         if(!plugin_open) return;
1118         client->save_data(keyframe);
1119 }
1120
1121 KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
1122 {
1123         KeyFrame *result = 0;
1124         if(plugin)
1125                 result = plugin->get_prev_keyframe(position, client->direction);
1126         else
1127                 result = keyframe;
1128         return result;
1129 }
1130
1131 KeyFrame* PluginServer::get_next_keyframe(int64_t position)
1132 {
1133         KeyFrame *result = 0;
1134         if(plugin)
1135                 result = plugin->get_next_keyframe(position, client->direction);
1136         else
1137                 result = keyframe;
1138         return result;
1139 }
1140
1141 // Called for
1142 KeyFrame* PluginServer::get_keyframe()
1143 {
1144         if(plugin)
1145 // Realtime plugin case
1146                 return plugin->get_keyframe();
1147         else
1148 // Rendered plugin case
1149                 return keyframe;
1150 }
1151
1152
1153 void PluginServer::apply_keyframe(KeyFrame *src)
1154 {
1155         if(!plugin)
1156         {
1157                 keyframe->copy_data(src);
1158         }
1159         else
1160         {
1161 // Span keyframes
1162                 plugin->keyframes->update_parameter(src);
1163         }
1164 }
1165
1166
1167
1168
1169
1170 void PluginServer::get_camera(float *x, float *y, float *z,
1171         int64_t position, int direction)
1172 {
1173         plugin->track->automation->get_camera(x, y, z, position, direction);
1174 }
1175
1176 void PluginServer::get_projector(float *x, float *y, float *z,
1177         int64_t position, int direction)
1178 {
1179         plugin->track->automation->get_projector(x, y, z, position, direction);
1180 }
1181
1182
1183 int PluginServer::get_interpolation_type()
1184 {
1185         return plugin->edl->session->interpolation_type;
1186 }
1187
1188 Theme* PluginServer::new_theme()
1189 {
1190         if(theme)
1191         {
1192                 return client->new_theme();
1193         }
1194         else
1195                 return 0;
1196 }
1197
1198 Theme* PluginServer::get_theme()
1199 {
1200         if(mwindow) return mwindow->theme;
1201         printf("PluginServer::get_theme mwindow not set\n");
1202         return 0;
1203 }
1204
1205
1206 int PluginServer::get_theme_png_path(char *png_path, const char *theme_dir)
1207 {
1208         char *bp = strrchr(path, '/');
1209         if( !bp ) bp = path; else ++bp;
1210         char *sp = strrchr(bp,'.');
1211         if( !sp ) sp = bp + strlen(bp);
1212         char *cp = png_path, *dp = bp;
1213         cp += sprintf(cp,"%s/%s/", mwindow->preferences->plugin_dir, theme_dir);
1214         while( dp < sp ) *cp++ = *dp++;
1215         strcpy(cp, ".png");
1216         struct stat st;
1217         if( stat(png_path, &st) ) return 0;
1218         if( !S_ISREG(st.st_mode) ) return 0;
1219         if( st.st_size == 0 ) return 0;
1220         return st.st_size;
1221 }
1222
1223 int PluginServer::get_theme_png_path(char *png_path, Theme *theme)
1224 {
1225         char *bp = strrchr(theme->path, '/');
1226         if( !bp ) bp = theme->path; else ++bp;
1227         char *sp = strrchr(bp,'.');
1228         if( !sp || ( strcmp(sp, ".plugin") && strcmp(sp,".so") ) ) return 0;
1229         char theme_dir[BCTEXTLEN], *cp = theme_dir;
1230         while( bp < sp ) *cp++ = *bp++;
1231         *cp = 0;
1232         return get_theme_png_path(png_path, theme_dir);
1233 }
1234
1235 int PluginServer::get_plugin_png_path(char *png_path)
1236 {
1237         int len = get_theme_png_path(png_path, mwindow->theme);
1238         if( !len )
1239                 len = get_theme_png_path(png_path, "picon");
1240         return len;
1241 }
1242
1243 VFrame *PluginServer::get_plugin_images()
1244 {
1245         char png_path[BCTEXTLEN];
1246         int len = get_plugin_png_path(png_path);
1247         if( !len ) return 0;
1248         int ret = 0, w = 0, h = 0;
1249         unsigned char *bfr = 0;
1250         int fd = ::open(png_path, O_RDONLY);
1251         if( fd < 0 ) ret = 1;
1252         if( !ret ) {
1253                 bfr = (unsigned char *) ::mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
1254                 if( bfr == MAP_FAILED ) ret = 1;
1255         }
1256         VFrame *vframe = 0;
1257         if( !ret ) {
1258                 double scale = BC_WindowBase::get_resources()->icon_scale;
1259                 vframe = new VFramePng(bfr, len, scale, scale);
1260                 if( (w=vframe->get_w()) <= 0 || (h=vframe->get_h()) <= 0 ||
1261                     vframe->get_data() == 0 ) ret = 1;
1262         }
1263         if( bfr && bfr != MAP_FAILED ) ::munmap(bfr, len);
1264         if( fd >= 0 ) ::close(fd);
1265         if( ret ) { delete vframe;  vframe = 0; }
1266         return vframe;
1267 }
1268
1269 VFrame *PluginServer::get_picon()
1270 {
1271         if( !picon )
1272                 picon = get_plugin_images();
1273         return picon;
1274 }
1275
1276 // Called when plugin interface is tweeked
1277 void PluginServer::sync_parameters()
1278 {
1279         if(video) mwindow->restart_brender();
1280         mwindow->sync_parameters();
1281         mwindow->update_keyframe_guis();
1282         if(mwindow->edl->session->auto_conf->plugins)
1283         {
1284                 mwindow->gui->lock_window("PluginServer::sync_parameters");
1285                 mwindow->gui->draw_overlays(1);
1286                 mwindow->gui->unlock_window();
1287         }
1288 }
1289
1290
1291
1292 void PluginServer::dump(FILE *fp)
1293 {
1294         fprintf(fp,"    PluginServer %d %p %s %s %d\n",
1295                 __LINE__, this, path, title, realtime);
1296 }