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