r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / pluginserver.C
blobf64e1b23101cc74e2fd8eea8d2260e04d19bdbb5
1 #include "amodule.h"
2 #include "atrack.h"
3 #include "attachmentpoint.h"
4 #include "autoconf.h"
5 #include "bcsignals.h"
6 #include "cplayback.h"
7 #include "cwindow.h"
8 #include "edl.h"
9 #include "edlsession.h"
10 #include "floatautos.h"
11 #include "localsession.h"
12 #include "mainprogress.h"
13 #include "menueffects.h"
14 #include "mwindow.h"
15 #include "mwindowgui.h"
16 #include "playbackengine.h"
17 #include "plugin.h"
18 #include "pluginaclient.h"
19 #include "pluginaclientlad.h"
20 #include "pluginclient.h"
21 #include "plugincommands.h"
22 #include "pluginserver.h"
23 #include "pluginvclient.h"
24 #include "preferences.h"
25 #include "sema.h"
26 #include "mainsession.h"
27 #include "trackcanvas.h"
28 #include "transportque.h"
29 #include "vframe.h"
30 #include "virtualanode.h"
31 #include "virtualvnode.h"
32 #include "vmodule.h"
33 #include "vtrack.h"
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <dlfcn.h>
41 PluginServer::PluginServer()
43         reset_parameters();
44         modules = new ArrayList<Module*>;
45         nodes = new ArrayList<VirtualNode*>;
48 PluginServer::PluginServer(char *path)
50         reset_parameters();
51         set_path(path);
52         modules = new ArrayList<Module*>;
53         nodes = new ArrayList<VirtualNode*>;
56 PluginServer::PluginServer(PluginServer &that)
58         reset_parameters();
60         if(that.title)
61         {
62                 title = new char[strlen(that.title) + 1];
63                 strcpy(title, that.title);
64         }
66         if(that.path)
67         {
68                 path = new char[strlen(that.path) + 1];
69                 strcpy(path, that.path);
70         }
72         modules = new ArrayList<Module*>;
73         nodes = new ArrayList<VirtualNode*>;
75         attachment = that.attachment;   
76         realtime = that.realtime;
77         multichannel = that.multichannel;
78         preferences = that.preferences;
79         synthesis = that.synthesis;
80         audio = that.audio;
81         video = that.video;
82         theme = that.theme;
83         fileio = that.fileio;
84         uses_gui = that.uses_gui;
85         mwindow = that.mwindow;
86         keyframe = that.keyframe;
87         plugin_fd = that.plugin_fd;
88         new_plugin = that.new_plugin;
90         is_lad = that.is_lad;
91         lad_descriptor = that.lad_descriptor;
92         lad_descriptor_function = that.lad_descriptor_function;
95 PluginServer::~PluginServer()
97         close_plugin();
98         if(path) delete [] path;
99         if(title) delete [] title;
100         if(modules) delete modules;
101         if(nodes) delete nodes;
102         if(picon) delete picon;
105 // Done only once at creation
106 int PluginServer::reset_parameters()
108         mwindow = 0;
109         keyframe = 0;
110         prompt = 0;
111         cleanup_plugin();
112         plugin_fd = 0;
113         autos = 0;
114         plugin = 0;
115         edl = 0;
116         preferences = 0;
117         title = 0;
118         path = 0;
119         audio = video = theme = 0;
120         uses_gui = 0;
121         realtime = multichannel = fileio = 0;
122         synthesis = 0;
123         start_auto = end_auto = 0;
124         picon = 0;
125         transition = 0;
126         new_plugin = 0;
127         client = 0;
129         is_lad = 0;
130         lad_descriptor_function = 0;
131         lad_descriptor = 0;
135 // Done every time the plugin is opened or closed
136 int PluginServer::cleanup_plugin()
138         in_buffer_size = out_buffer_size = 0;
139         total_in_buffers = total_out_buffers = 0;
140         error_flag = 0;
141         written_samples = 0;
142         shared_buffers = 0;
143         new_buffers = 0;
144         written_samples = written_frames = 0;
145         gui_on = 0;
146         plugin = 0;
147         plugin_open = 0;
150 void PluginServer::set_mwindow(MWindow *mwindow)
152         this->mwindow = mwindow;
155 void PluginServer::set_attachmentpoint(AttachmentPoint *attachmentpoint)
157         this->attachmentpoint = attachmentpoint;
160 void PluginServer::set_keyframe(KeyFrame *keyframe)
162         this->keyframe = keyframe;
165 void PluginServer::set_prompt(MenuEffectPrompt *prompt)
167         this->prompt = prompt;
171 int PluginServer::set_path(char *path)
173         if(this->path) delete [] this->path;
174         this->path = new char[strlen(path) + 1];
175         strcpy(this->path, path);
178 void PluginServer::set_title(char *string)
180         if(title) delete [] title;
181         title = new char[strlen(string) + 1];
182         strcpy(title, string);
185 void PluginServer::generate_display_title(char *string)
187         if(plugin && plugin->track) 
188                 sprintf(string, "%s: %s", plugin->track->title, title);
189         else
190                 strcpy(string, title);
193 // Open plugin for signal processing
194 int PluginServer::open_plugin(int master, 
195         Preferences *preferences,
196         EDL *edl, 
197         Plugin *plugin,
198         int lad_index)
200         if(plugin_open) return 0;
202         this->preferences = preferences;
203         this->plugin = plugin;
204         this->edl = edl;
208         if(!new_plugin && !plugin_fd) plugin_fd = dlopen(path, RTLD_NOW);
210         if(!new_plugin && !plugin_fd)
211         {
212 // If the dlopen failed it may still be an executable tool for a specific
213 // file format, in which case we just store the path.
214                 set_title(path);
215                 char string[BCTEXTLEN];
216                 strcpy(string, dlerror());
218                 if(!strstr(string, "executable"))
219                         printf("PluginServer::open_plugin: %s\n", string);
220                 
221                 return 0;
222         }
225         if(!new_plugin && !lad_descriptor)
226         {
227                 new_plugin = (PluginClient* (*)(PluginServer*))dlsym(plugin_fd, "new_plugin");
229 // Probably a LAD plugin but we're not going to instantiate it here anyway.
230                 if(!new_plugin)
231                 {
232                         lad_descriptor_function = (LADSPA_Descriptor_Function)dlsym(
233                                 plugin_fd,
234                                 "ladspa_descriptor");
236                         if(!lad_descriptor_function)
237                         {
238 // Not a recognized plugin
239                                 fprintf(stderr, "PluginServer::open_plugin: new_plugin undefined in %s\n", path);
240                                 dlclose(plugin_fd);
241                                 plugin_fd = 0;
242                                 return PLUGINSERVER_NOT_RECOGNIZED;
243                         }
244                         else
245                         {
246 // LAD plugin,  Load the descriptor and get parameters.
247                                 is_lad = 1;
248                                 if(lad_index >= 0)
249                                 {
250                                         lad_descriptor = lad_descriptor_function(lad_index);
251                                 }
253 // make plugin initializer handle the subplugins in the LAD plugin or stop
254 // trying subplugins.
255                                 if(!lad_descriptor)
256                                 {
257                                         dlclose(plugin_fd);
258                                         plugin_fd = 0;
259                                         return PLUGINSERVER_IS_LAD;
260                                 }
261                         }
262                 }
263         }
266         if(is_lad)
267         {
268                 client = new PluginAClientLAD(this);
269         }
270         else
271         {
272                 client = new_plugin(this);
273         }
275         realtime = client->is_realtime();
276         audio = client->is_audio();
277         video = client->is_video();
278         theme = client->is_theme();
279         fileio = client->is_fileio();
280         uses_gui = client->uses_gui();
281         multichannel = client->is_multichannel();
282         synthesis = client->is_synthesis();
283         transition = client->is_transition();
284         set_title(client->plugin_title());
286         if(master)
287         {
288                 picon = client->new_picon();
289         }
291 //printf("PluginServer::open_plugin 2\n");
292         plugin_open = 1;
293         return PLUGINSERVER_OK;
296 int PluginServer::close_plugin()
298         if(!plugin_open) return 0;
300         int plugin_status, result;
301         if(client) delete client;
303 // shared object is persistent since plugin deletion would unlink its own object
304 //      dlclose(plugin_fd);
305         plugin_open = 0;
307         cleanup_plugin();
309         return 0;
312 void PluginServer::client_side_close()
314 // Last command executed in client thread
315         if(plugin)
316                 mwindow->hide_plugin(plugin, 1);
317         else
318         if(prompt)
319         {
320                 prompt->lock_window();
321                 prompt->set_done(1);
322                 prompt->unlock_window();
323         }
326 int PluginServer::init_realtime(int realtime_sched,
327                 int total_in_buffers, 
328                 int buffer_size)
330         if(!plugin_open) return 0;
331 // set for realtime priority
332 // initialize plugin
333 // Call start_realtime
334         client->plugin_init_realtime(realtime_sched, 
335                 total_in_buffers, 
336                 buffer_size);
340 // Replaced by pull method but still needed for transitions
341 void PluginServer::process_transition(VFrame *input, 
342                 VFrame *output, 
343                 int64_t current_position,
344                 int64_t total_len)
346         if(!plugin_open) return;
347         PluginVClient *vclient = (PluginVClient*)client;
349         vclient->source_position = current_position;
350         vclient->source_start = 0;
351         vclient->total_len = total_len;
352         vclient->process_realtime(input, output);
353         vclient->age_temp();
356 void PluginServer::process_transition(double *input, 
357                 double *output,
358                 int64_t current_position, 
359                 int64_t fragment_size,
360                 int64_t total_len)
362         if(!plugin_open) return;
363         PluginAClient *aclient = (PluginAClient*)client;
365         aclient->source_position = current_position;
366         aclient->total_len = total_len;
367         aclient->source_start = 0;
368         aclient->process_realtime(fragment_size,
369                 input, 
370                 output);
374 void PluginServer::process_buffer(VFrame **frame, 
375         int64_t current_position,
376         double frame_rate,
377         int64_t total_len,
378         int direction)
380         if(!plugin_open) return;
381         PluginVClient *vclient = (PluginVClient*)client;
383         vclient->source_position = current_position;
384         vclient->total_len = total_len;
385         vclient->frame_rate = frame_rate;
386         vclient->source_start = (int64_t)(plugin ? 
387                 plugin->startproject * 
388                 frame_rate /
389                 vclient->project_frame_rate :
390                 0);
391         vclient->direction = direction;
393         if(multichannel)
394         {
395                 vclient->process_buffer(frame, current_position, frame_rate);
396         }
397         else
398         {
399                 vclient->process_buffer(frame[0], current_position, frame_rate);
400         }
403     vclient->age_temp();
406 void PluginServer::process_buffer(double **buffer,
407         int64_t current_position,
408         int64_t fragment_size,
409         int64_t sample_rate,
410         int64_t total_len,
411         int direction)
413         if(!plugin_open) return;
414         PluginAClient *aclient = (PluginAClient*)client;
415         aclient->source_position = current_position;
416         aclient->total_len = total_len;
417         aclient->sample_rate = sample_rate;
418         if(plugin)
419                 aclient->source_start = plugin->startproject * 
420                         sample_rate /
421                         aclient->project_sample_rate;
422         aclient->direction = direction;
423         if(multichannel)
424                 aclient->process_buffer(fragment_size, 
425                         buffer, 
426                         current_position, 
427                         sample_rate);
428         else
429         {
430                 aclient->process_buffer(fragment_size, 
431                         buffer[0], 
432                         current_position, 
433                         sample_rate);
434         }
438 void PluginServer::send_render_gui(void *data)
440 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
441         if(attachmentpoint) attachmentpoint->render_gui(data);
444 void PluginServer::send_render_gui(void *data, int size)
446 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
447         if(attachmentpoint) attachmentpoint->render_gui(data, size);
450 void PluginServer::render_gui(void *data)
452         if(client) client->plugin_render_gui(data);
455 void PluginServer::render_gui(void *data, int size)
457         if(client) client->plugin_render_gui(data, size);
460 MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
462         mwindow->gui->lock_window();
463         MainProgressBar *result = mwindow->mainprogress->start_progress(string, length);
464         mwindow->gui->unlock_window();
465         return result;
468 int64_t PluginServer::get_written_samples()
470         if(!plugin_open) return 0;
471         return written_samples;
474 int64_t PluginServer::get_written_frames()
476         if(!plugin_open) return 0;
477         return written_frames;
489 // ======================= Non-realtime plugin
491 int PluginServer::get_parameters(int64_t start, int64_t end, int channels)      
493         if(!plugin_open) return 0;
495         client->start = start;
496         client->end = end;
497         client->source_start = start;
498         client->total_len = end - start;
499         client->total_in_buffers = channels;
500         return client->plugin_get_parameters();
503 int PluginServer::set_interactive()
505         if(!plugin_open) return 0;
506         client->set_interactive();
507         return 0;
510 void PluginServer::append_module(Module *module)
512         modules->append(module);
515 void PluginServer::append_node(VirtualNode *node)
517         nodes->append(node);
520 void PluginServer::reset_nodes()
522         nodes->remove_all();
525 int PluginServer::set_error()
527         error_flag = 1;
528         return 0;
531 int PluginServer::set_realtime_sched()
533         struct sched_param params;
534         params.sched_priority = 1;
535         return 0;
539 int PluginServer::process_loop(VFrame **buffers, int64_t &write_length)
541         if(!plugin_open) return 1;
542         return client->plugin_process_loop(buffers, write_length);
545 int PluginServer::process_loop(double **buffers, int64_t &write_length)
547         if(!plugin_open) return 1;
548         return client->plugin_process_loop(buffers, write_length);
552 int PluginServer::start_loop(int64_t start, 
553         int64_t end, 
554         int64_t buffer_size, 
555         int total_buffers)
557         if(!plugin_open) return 0;
558         client->plugin_start_loop(start, end, buffer_size, total_buffers);
559         return 0;
562 int PluginServer::stop_loop()
564         if(!plugin_open) return 0;
565         return client->plugin_stop_loop();
568 int PluginServer::read_frame(VFrame *buffer, 
569         int channel, 
570         int64_t start_position)
572         ((VModule*)modules->values[channel])->render(buffer,
573                 start_position,
574                 PLAY_FORWARD,
575                 mwindow->edl->session->frame_rate,
576                 0,
577                 0);
578         return 0;
581 int PluginServer::read_samples(double *buffer, 
582         int channel, 
583         int64_t start_position, 
584         int64_t total_samples)
586         ((AModule*)modules->values[channel])->render(buffer, 
587                 start_position,
588                 total_samples, 
589                 PLAY_FORWARD,
590                 mwindow->edl->session->sample_rate,
591                 0);
592         return 0;
595 int PluginServer::read_frame(VFrame *buffer, 
596         int channel, 
597         int64_t start_position, 
598         double frame_rate)
600 // Data source depends on whether we're part of a virtual console or a
601 // plugin array.
602 //     VirtualNode
603 //     Module
604 // If we're a VirtualNode, read_data in the virtual plugin node handles
605 //     backward propogation and produces the data.
606 // If we're a Module, render in the module produces the data.
608         if(!multichannel) channel = 0;
611         if(nodes->total > channel)
612         {
613                 return ((VirtualVNode*)nodes->values[channel])->read_data(buffer,
614                         start_position,
615                         frame_rate);
616         }
617         else
618         if(modules->total > channel)
619         {
620                 return ((VModule*)modules->values[channel])->render(buffer,
621                         start_position,
622                         PLAY_FORWARD,
623                         frame_rate,
624                         0,
625                         0);
626         }
627         else
628         {
629                 printf("PluginServer::read_frame no object available for channel=%d\n",
630                         channel);
631         }
632 //printf("PluginServer::read_frame 10\n");
634         return -1;
637 int PluginServer::read_samples(double *buffer,
638         int channel,
639         int64_t sample_rate,
640         int64_t start_position, 
641         int64_t len)
643         if(!multichannel) channel = 0;
645         if(nodes->total > channel)
646                 return ((VirtualANode*)nodes->values[channel])->read_data(buffer,
647                         start_position,
648                         len,
649                         sample_rate);
650         else
651         if(modules->total > channel)
652                 return ((AModule*)modules->values[channel])->render(buffer,
653                         start_position,
654                         len,
655                         PLAY_FORWARD,
656                         sample_rate,
657                         0);
658         else
659         {
660                 printf("PluginServer::read_samples no object available for channel=%d\n",
661                         channel);
662         }
664         return -1;
686 // Called by client
687 int PluginServer::get_gui_status()
689         if(plugin)
690                 return plugin->show ? GUI_ON : GUI_OFF;
691         else
692                 return GUI_OFF;
695 void PluginServer::raise_window()
697         if(!plugin_open) return;
698         client->raise_window();
701 void PluginServer::show_gui()
703         if(!plugin_open) return;
704         client->smp = preferences->processors - 1;
705         if(plugin) client->total_len = plugin->length;
706         if(plugin) client->source_start = plugin->startproject;
707         if(video)
708         {
709                 client->source_position = Units::to_int64(
710                         mwindow->edl->local_session->selectionstart * 
711                                 mwindow->edl->session->frame_rate);
712         }
713         else
714         if(audio)
715         {
716                 client->source_position = Units::to_int64(
717                         mwindow->edl->local_session->selectionstart * 
718                                 mwindow->edl->session->sample_rate);
719         }
720         client->update_display_title();
721         client->show_gui();
724 void PluginServer::update_gui()
726         if(!plugin_open || !plugin) return;
728         client->total_len = plugin->length;
729         client->source_start = plugin->startproject;
730         if(video)
731         {
732                 client->source_position = Units::to_int64(
733                         mwindow->edl->local_session->selectionstart * 
734                                 mwindow->edl->session->frame_rate);
735         }
736         else
737         if(audio)
738         {
739                 client->source_position = Units::to_int64(
740                         mwindow->edl->local_session->selectionstart * 
741                                 mwindow->edl->session->sample_rate);
742         }
743         client->update_gui();
746 void PluginServer::update_title()
748         if(!plugin_open) return;
749         
750         client->update_display_title();
754 int PluginServer::set_string(char *string)
756         if(!plugin_open) return 0;
758         client->set_string_client(string);
759         return 0;
763 // ============================= queries
765 int PluginServer::get_samplerate()
767         if(!plugin_open) return 0;
768         if(audio)
769         {
770                 return client->get_samplerate();
771         }
772         else
773         if(mwindow)
774                 return mwindow->edl->session->sample_rate;
775         else
776         {
777                 printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
778                 return 1;
779         }
783 double PluginServer::get_framerate()
785         if(!plugin_open) return 0;
786         if(video)
787         {
788                 return client->get_framerate();
789         }
790         else
791         if(mwindow)
792                 return mwindow->edl->session->frame_rate;
793         else 
794         {
795                 printf("PluginServer::get_framerate video and mwindow == NULL\n");
796                 return 1;
797         }
800 int PluginServer::get_project_samplerate()
802         if(mwindow)
803                 return mwindow->edl->session->sample_rate;
804         else
805         if(edl)
806                 return edl->session->sample_rate;
807         else
808         {
809                 printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
810                 return 1;
811         }
814 double PluginServer::get_project_framerate()
816         if(mwindow)
817                 return mwindow->edl->session->frame_rate;
818         else
819         if(edl)
820                 return edl->session->frame_rate;
821         else
822         {
823                 printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
824                 return 1;
825         }
830 int PluginServer::detach_buffers()
832         ring_buffers_out.remove_all();
833         offset_out_render.remove_all();
834         double_buffer_out_render.remove_all();
835         realtime_out_size.remove_all();
837         ring_buffers_in.remove_all();
838         offset_in_render.remove_all();
839         double_buffer_in_render.remove_all();
840         realtime_in_size.remove_all();
841         
842         out_buffer_size = 0;
843         shared_buffers = 0;
844         total_out_buffers = 0;
845         in_buffer_size = 0;
846         total_in_buffers = 0;
847         return 0;
850 int PluginServer::arm_buffer(int buffer_number, 
851                 int64_t offset_in, 
852                 int64_t offset_out,
853                 int double_buffer_in,
854                 int double_buffer_out)
856         offset_in_render.values[buffer_number] = offset_in;
857         offset_out_render.values[buffer_number] = offset_out;
858         double_buffer_in_render.values[buffer_number] = double_buffer_in;
859         double_buffer_out_render.values[buffer_number] = double_buffer_out;
863 int PluginServer::set_automation(FloatAutos *autos, FloatAuto **start_auto, FloatAuto **end_auto, int reverse)
865         this->autos = autos;
866         this->start_auto = start_auto;
867         this->end_auto = end_auto;
868         this->reverse = reverse;
873 void PluginServer::save_data(KeyFrame *keyframe)
875         if(!plugin_open) return;
876         client->save_data(keyframe);
879 KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
881         KeyFrame *result = 0;
882         if(plugin)
883                 result = plugin->get_prev_keyframe(position, client->direction);
884         else
885                 result = keyframe;
886         return result;
889 KeyFrame* PluginServer::get_next_keyframe(int64_t position)
891         KeyFrame *result = 0;
892         if(plugin)
893                 result = plugin->get_next_keyframe(position, client->direction);
894         else
895                 result = keyframe;
896         return result;
899 KeyFrame* PluginServer::get_keyframe()
901         if(plugin)
902                 return plugin->get_keyframe();
903         else
904                 return keyframe;
908 int PluginServer::get_interpolation_type()
910         return plugin->edl->session->interpolation_type;
913 Theme* PluginServer::new_theme()
915         if(theme)
916         {
917                 return client->new_theme();
918         }
919         else
920                 return 0;
923 Theme* PluginServer::get_theme()
925         if(mwindow) return mwindow->theme;
926         printf("PluginServer::get_theme mwindow not set\n");
927         return 0;
931 // Called when plugin interface is tweeked
932 void PluginServer::sync_parameters()
934         if(video) mwindow->restart_brender();
935         mwindow->sync_parameters();
936         if(mwindow->edl->session->auto_conf->plugins)
937         {
938                 mwindow->gui->lock_window("PluginServer::sync_parameters");
939                 mwindow->gui->canvas->draw_overlays();
940                 mwindow->gui->canvas->flash();
941                 mwindow->gui->unlock_window();
942         }
947 void PluginServer::dump()
949         printf("    PluginServer %s %s\n", path, title);