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