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