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