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