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