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