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