r793: Small API addon, so plugins can 'see' camera and projector automation
[cinelerra_cv/mob.git] / cinelerra / pluginserver.C
blob0ce0f91620cdbf87d38d859d012e7635c1f5a280
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 "mainundo.h"
14 #include "menueffects.h"
15 #include "mwindow.h"
16 #include "mwindowgui.h"
17 #include "playbackengine.h"
18 #include "plugin.h"
19 #include "pluginaclient.h"
20 #include "pluginaclientlad.h"
21 #include "pluginclient.h"
22 #include "plugincommands.h"
23 #include "pluginserver.h"
24 #include "pluginvclient.h"
25 #include "preferences.h"
26 #include "sema.h"
27 #include "mainsession.h"
28 #include "trackcanvas.h"
29 #include "transportque.h"
30 #include "vframe.h"
31 #include "virtualanode.h"
32 #include "virtualvnode.h"
33 #include "vmodule.h"
34 #include "vtrack.h"
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <dlfcn.h>
42 PluginServer::PluginServer()
44         reset_parameters();
45         modules = new ArrayList<Module*>;
46         nodes = new ArrayList<VirtualNode*>;
49 PluginServer::PluginServer(char *path)
51         reset_parameters();
52         set_path(path);
53         modules = new ArrayList<Module*>;
54         nodes = new ArrayList<VirtualNode*>;
57 PluginServer::PluginServer(PluginServer &that)
59         reset_parameters();
61         if(that.title)
62         {
63                 title = new char[strlen(that.title) + 1];
64                 strcpy(title, that.title);
65         }
67         if(that.path)
68         {
69                 path = new char[strlen(that.path) + 1];
70                 strcpy(path, that.path);
71         }
73         modules = new ArrayList<Module*>;
74         nodes = new ArrayList<VirtualNode*>;
76         attachment = that.attachment;   
77         realtime = that.realtime;
78         multichannel = that.multichannel;
79         preferences = that.preferences;
80         synthesis = that.synthesis;
81         audio = that.audio;
82         video = that.video;
83         theme = that.theme;
84         fileio = that.fileio;
85         uses_gui = that.uses_gui;
86         mwindow = that.mwindow;
87         keyframe = that.keyframe;
88         plugin_fd = that.plugin_fd;
89         new_plugin = that.new_plugin;
91         is_lad = that.is_lad;
92         lad_descriptor = that.lad_descriptor;
93         lad_descriptor_function = that.lad_descriptor_function;
96 PluginServer::~PluginServer()
98         close_plugin();
99         if(path) delete [] path;
100         if(title) delete [] title;
101         if(modules) delete modules;
102         if(nodes) delete nodes;
103         if(picon) delete picon;
106 // Done only once at creation
107 int PluginServer::reset_parameters()
109         mwindow = 0;
110         keyframe = 0;
111         prompt = 0;
112         cleanup_plugin();
113         plugin_fd = 0;
114         autos = 0;
115         plugin = 0;
116         edl = 0;
117         preferences = 0;
118         title = 0;
119         path = 0;
120         audio = video = theme = 0;
121         uses_gui = 0;
122         realtime = multichannel = fileio = 0;
123         synthesis = 0;
124         start_auto = end_auto = 0;
125         picon = 0;
126         transition = 0;
127         new_plugin = 0;
128         client = 0;
130         is_lad = 0;
131         lad_descriptor_function = 0;
132         lad_descriptor = 0;
136 // Done every time the plugin is opened or closed
137 int PluginServer::cleanup_plugin()
139         in_buffer_size = out_buffer_size = 0;
140         total_in_buffers = total_out_buffers = 0;
141         error_flag = 0;
142         written_samples = 0;
143         shared_buffers = 0;
144         new_buffers = 0;
145         written_samples = written_frames = 0;
146         gui_on = 0;
147         plugin = 0;
148         plugin_open = 0;
151 void PluginServer::set_mwindow(MWindow *mwindow)
153         this->mwindow = mwindow;
156 void PluginServer::set_attachmentpoint(AttachmentPoint *attachmentpoint)
158         this->attachmentpoint = attachmentpoint;
161 void PluginServer::set_keyframe(KeyFrame *keyframe)
163         this->keyframe = keyframe;
166 void PluginServer::set_prompt(MenuEffectPrompt *prompt)
168         this->prompt = prompt;
172 int PluginServer::set_path(char *path)
174         if(this->path) delete [] this->path;
175         this->path = new char[strlen(path) + 1];
176         strcpy(this->path, path);
179 void PluginServer::set_title(char *string)
181         if(title) delete [] title;
182         title = new char[strlen(string) + 1];
183         strcpy(title, string);
186 void PluginServer::generate_display_title(char *string)
188         if(plugin && plugin->track) 
189                 sprintf(string, "%s: %s", plugin->track->title, title);
190         else
191                 strcpy(string, title);
194 // Open plugin for signal processing
195 int PluginServer::open_plugin(int master, 
196         Preferences *preferences,
197         EDL *edl, 
198         Plugin *plugin,
199         int lad_index)
201         if(plugin_open) return 0;
203         this->preferences = preferences;
204         this->plugin = plugin;
205         this->edl = edl;
209         if(!new_plugin && !plugin_fd) plugin_fd = dlopen(path, RTLD_NOW);
211         if(!new_plugin && !plugin_fd)
212         {
213 // If the dlopen failed it may still be an executable tool for a specific
214 // file format, in which case we just store the path.
215                 set_title(path);
216                 char string[BCTEXTLEN];
217                 strcpy(string, dlerror());
219                 if(!strstr(string, "executable"))
220                         printf("PluginServer::open_plugin: %s\n", string);
221                 
222                 return 0;
223         }
226         if(!new_plugin && !lad_descriptor)
227         {
228                 new_plugin = (PluginClient* (*)(PluginServer*))dlsym(plugin_fd, "new_plugin");
230 // Probably a LAD plugin but we're not going to instantiate it here anyway.
231                 if(!new_plugin)
232                 {
233                         lad_descriptor_function = (LADSPA_Descriptor_Function)dlsym(
234                                 plugin_fd,
235                                 "ladspa_descriptor");
237                         if(!lad_descriptor_function)
238                         {
239 // Not a recognized plugin
240                                 fprintf(stderr, "PluginServer::open_plugin: new_plugin undefined in %s\n", path);
241                                 dlclose(plugin_fd);
242                                 plugin_fd = 0;
243                                 return PLUGINSERVER_NOT_RECOGNIZED;
244                         }
245                         else
246                         {
247 // LAD plugin,  Load the descriptor and get parameters.
248                                 is_lad = 1;
249                                 if(lad_index >= 0)
250                                 {
251                                         lad_descriptor = lad_descriptor_function(lad_index);
252                                 }
254 // make plugin initializer handle the subplugins in the LAD plugin or stop
255 // trying subplugins.
256                                 if(!lad_descriptor)
257                                 {
258                                         dlclose(plugin_fd);
259                                         plugin_fd = 0;
260                                         return PLUGINSERVER_IS_LAD;
261                                 }
262                         }
263                 }
264         }
267         if(is_lad)
268         {
269                 client = new PluginAClientLAD(this);
270         }
271         else
272         {
273                 client = new_plugin(this);
274         }
276         realtime = client->is_realtime();
277         audio = client->is_audio();
278         video = client->is_video();
279         theme = client->is_theme();
280         fileio = client->is_fileio();
281         uses_gui = client->uses_gui();
282         multichannel = client->is_multichannel();
283         synthesis = client->is_synthesis();
284         transition = client->is_transition();
285         set_title(client->plugin_title());
287         if(master)
288         {
289                 picon = client->new_picon();
290         }
292 //printf("PluginServer::open_plugin 2\n");
293         plugin_open = 1;
294         return PLUGINSERVER_OK;
297 int PluginServer::close_plugin()
299         if(!plugin_open) return 0;
301         int plugin_status, result;
302         if(client) delete client;
304 // shared object is persistent since plugin deletion would unlink its own object
305 //      dlclose(plugin_fd);
306         plugin_open = 0;
308         cleanup_plugin();
310         return 0;
313 void PluginServer::client_side_close()
315 // Last command executed in client thread
316         if(plugin)
317                 mwindow->hide_plugin(plugin, 1);
318         else
319         if(prompt)
320         {
321                 prompt->lock_window();
322                 prompt->set_done(1);
323                 prompt->unlock_window();
324         }
327 int PluginServer::init_realtime(int realtime_sched,
328                 int total_in_buffers, 
329                 int buffer_size)
331 SET_TRACE
332         if(!plugin_open) return 0;
333 SET_TRACE
334 // set for realtime priority
335 // initialize plugin
336 // Call start_realtime
337         client->plugin_init_realtime(realtime_sched, 
338                 total_in_buffers, 
339                 buffer_size);
340 SET_TRACE
344 // Replaced by pull method but still needed for transitions
345 void PluginServer::process_transition(VFrame *input, 
346                 VFrame *output, 
347                 int64_t current_position,
348                 int64_t total_len)
350         if(!plugin_open) return;
351         PluginVClient *vclient = (PluginVClient*)client;
353         vclient->source_position = current_position;
354         vclient->source_start = 0;
355         vclient->total_len = total_len;
356         vclient->process_realtime(input, output);
357         vclient->age_temp();
360 void PluginServer::process_transition(double *input, 
361                 double *output,
362                 int64_t current_position, 
363                 int64_t fragment_size,
364                 int64_t total_len)
366         if(!plugin_open) return;
367         PluginAClient *aclient = (PluginAClient*)client;
369         aclient->source_position = current_position;
370         aclient->total_len = total_len;
371         aclient->source_start = 0;
372         aclient->process_realtime(fragment_size,
373                 input, 
374                 output);
378 void PluginServer::process_buffer(VFrame **frame, 
379         int64_t current_position,
380         double frame_rate,
381         int64_t total_len,
382         int direction)
384         if(!plugin_open) return;
385         PluginVClient *vclient = (PluginVClient*)client;
387         vclient->source_position = current_position;
388         vclient->total_len = total_len;
389         vclient->frame_rate = frame_rate;
390         vclient->source_start = (int64_t)(plugin ? 
391                 plugin->startproject * 
392                 frame_rate /
393                 vclient->project_frame_rate :
394                 0);
395         vclient->direction = direction;
397         if(multichannel)
398         {
399                 vclient->process_buffer(frame, current_position, frame_rate);
400         }
401         else
402         {
403                 vclient->process_buffer(frame[0], current_position, frame_rate);
404         }
407     vclient->age_temp();
410 void PluginServer::process_buffer(double **buffer,
411         int64_t current_position,
412         int64_t fragment_size,
413         int64_t sample_rate,
414         int64_t total_len,
415         int direction)
417         if(!plugin_open) return;
418         PluginAClient *aclient = (PluginAClient*)client;
419         aclient->source_position = current_position;
420         aclient->total_len = total_len;
421         aclient->sample_rate = sample_rate;
422         if(plugin)
423                 aclient->source_start = plugin->startproject * 
424                         sample_rate /
425                         aclient->project_sample_rate;
426         aclient->direction = direction;
427         if(multichannel)
428                 aclient->process_buffer(fragment_size, 
429                         buffer, 
430                         current_position, 
431                         sample_rate);
432         else
433         {
434                 aclient->process_buffer(fragment_size, 
435                         buffer[0], 
436                         current_position, 
437                         sample_rate);
438         }
442 void PluginServer::send_render_gui(void *data)
444 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
445         if(attachmentpoint) attachmentpoint->render_gui(data);
448 void PluginServer::send_render_gui(void *data, int size)
450 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
451         if(attachmentpoint) attachmentpoint->render_gui(data, size);
454 void PluginServer::render_gui(void *data)
456         if(client) client->plugin_render_gui(data);
459 void PluginServer::render_gui(void *data, int size)
461         if(client) client->plugin_render_gui(data, size);
464 MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
466         mwindow->gui->lock_window();
467         MainProgressBar *result = mwindow->mainprogress->start_progress(string, length);
468         mwindow->gui->unlock_window();
469         return result;
472 int64_t PluginServer::get_written_samples()
474         if(!plugin_open) return 0;
475         return written_samples;
478 int64_t PluginServer::get_written_frames()
480         if(!plugin_open) return 0;
481         return written_frames;
493 // ======================= Non-realtime plugin
495 int PluginServer::get_parameters(int64_t start, int64_t end, int channels)      
497         if(!plugin_open) return 0;
499         client->start = start;
500         client->end = end;
501         client->source_start = start;
502         client->total_len = end - start;
503         client->total_in_buffers = channels;
504         return client->plugin_get_parameters();
507 int PluginServer::set_interactive()
509         if(!plugin_open) return 0;
510         client->set_interactive();
511         return 0;
514 void PluginServer::append_module(Module *module)
516         modules->append(module);
519 void PluginServer::append_node(VirtualNode *node)
521         nodes->append(node);
524 void PluginServer::reset_nodes()
526         nodes->remove_all();
529 int PluginServer::set_error()
531         error_flag = 1;
532         return 0;
535 int PluginServer::set_realtime_sched()
537         struct sched_param params;
538         params.sched_priority = 1;
539         return 0;
543 int PluginServer::process_loop(VFrame **buffers, int64_t &write_length)
545         if(!plugin_open) return 1;
546         return client->plugin_process_loop(buffers, write_length);
549 int PluginServer::process_loop(double **buffers, int64_t &write_length)
551         if(!plugin_open) return 1;
552         return client->plugin_process_loop(buffers, write_length);
556 int PluginServer::start_loop(int64_t start, 
557         int64_t end, 
558         int64_t buffer_size, 
559         int total_buffers)
561         if(!plugin_open) return 0;
562         client->plugin_start_loop(start, end, buffer_size, total_buffers);
563         return 0;
566 int PluginServer::stop_loop()
568         if(!plugin_open) return 0;
569         return client->plugin_stop_loop();
572 int PluginServer::read_frame(VFrame *buffer, 
573         int channel, 
574         int64_t start_position)
576         ((VModule*)modules->values[channel])->render(buffer,
577                 start_position,
578                 PLAY_FORWARD,
579                 mwindow->edl->session->frame_rate,
580                 0,
581                 0);
582         return 0;
585 int PluginServer::read_samples(double *buffer, 
586         int channel, 
587         int64_t start_position, 
588         int64_t total_samples)
590         ((AModule*)modules->values[channel])->render(buffer, 
591                 start_position,
592                 total_samples, 
593                 PLAY_FORWARD,
594                 mwindow->edl->session->sample_rate,
595                 0);
596         return 0;
599 int PluginServer::read_frame(VFrame *buffer, 
600         int channel, 
601         int64_t start_position, 
602         double frame_rate)
604 // Data source depends on whether we're part of a virtual console or a
605 // plugin array.
606 //     VirtualNode
607 //     Module
608 // If we're a VirtualNode, read_data in the virtual plugin node handles
609 //     backward propogation and produces the data.
610 // If we're a Module, render in the module produces the data.
612         if(!multichannel) channel = 0;
615         if(nodes->total > channel)
616         {
617                 return ((VirtualVNode*)nodes->values[channel])->read_data(buffer,
618                         start_position,
619                         frame_rate);
620         }
621         else
622         if(modules->total > channel)
623         {
624                 return ((VModule*)modules->values[channel])->render(buffer,
625                         start_position,
626                         PLAY_FORWARD,
627                         frame_rate,
628                         0,
629                         0);
630         }
631         else
632         {
633                 printf("PluginServer::read_frame no object available for channel=%d\n",
634                         channel);
635         }
636 //printf("PluginServer::read_frame 10\n");
638         return -1;
641 int PluginServer::read_samples(double *buffer,
642         int channel,
643         int64_t sample_rate,
644         int64_t start_position, 
645         int64_t len)
647         if(!multichannel) channel = 0;
649         if(nodes->total > channel)
650                 return ((VirtualANode*)nodes->values[channel])->read_data(buffer,
651                         start_position,
652                         len,
653                         sample_rate);
654         else
655         if(modules->total > channel)
656                 return ((AModule*)modules->values[channel])->render(buffer,
657                         start_position,
658                         len,
659                         PLAY_FORWARD,
660                         sample_rate,
661                         0);
662         else
663         {
664                 printf("PluginServer::read_samples no object available for channel=%d\n",
665                         channel);
666         }
668         return -1;
690 // Called by client
691 int PluginServer::get_gui_status()
693         if(plugin)
694                 return plugin->show ? GUI_ON : GUI_OFF;
695         else
696                 return GUI_OFF;
699 void PluginServer::raise_window()
701         if(!plugin_open) return;
702         client->raise_window();
705 void PluginServer::show_gui()
707         if(!plugin_open) return;
708         client->smp = preferences->processors - 1;
709         if(plugin) client->total_len = plugin->length;
710         if(plugin) client->source_start = plugin->startproject;
711         if(video)
712         {
713                 client->source_position = Units::to_int64(
714                         mwindow->edl->local_session->get_selectionstart(1) * 
715                                 mwindow->edl->session->frame_rate);
716         }
717         else
718         if(audio)
719         {
720                 client->source_position = Units::to_int64(
721                         mwindow->edl->local_session->get_selectionstart(1) * 
722                                 mwindow->edl->session->sample_rate);
723         }
724         client->update_display_title();
725         client->show_gui();
728 void PluginServer::update_gui()
730         if(!plugin_open || !plugin) return;
732         client->total_len = plugin->length;
733         client->source_start = plugin->startproject;
734         if(video)
735         {
736                 client->source_position = Units::to_int64(
737                         mwindow->edl->local_session->get_selectionstart(1) * 
738                                 mwindow->edl->session->frame_rate);
739         }
740         else
741         if(audio)
742         {
743                 client->source_position = Units::to_int64(
744                         mwindow->edl->local_session->get_selectionstart(1) * 
745                                 mwindow->edl->session->sample_rate);
746         }
747         client->update_gui();
750 void PluginServer::update_title()
752         if(!plugin_open) return;
753         
754         client->update_display_title();
758 int PluginServer::set_string(char *string)
760         if(!plugin_open) return 0;
762         client->set_string_client(string);
763         return 0;
767 // ============================= queries
769 int PluginServer::get_samplerate()
771         if(!plugin_open) return 0;
772         if(audio)
773         {
774                 return client->get_samplerate();
775         }
776         else
777         if(mwindow)
778                 return mwindow->edl->session->sample_rate;
779         else
780         {
781                 printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
782                 return 1;
783         }
787 double PluginServer::get_framerate()
789         if(!plugin_open) return 0;
790         if(video)
791         {
792                 return client->get_framerate();
793         }
794         else
795         if(mwindow)
796                 return mwindow->edl->session->frame_rate;
797         else 
798         {
799                 printf("PluginServer::get_framerate video and mwindow == NULL\n");
800                 return 1;
801         }
804 int PluginServer::get_project_samplerate()
806         if(mwindow)
807                 return mwindow->edl->session->sample_rate;
808         else
809         if(edl)
810                 return edl->session->sample_rate;
811         else
812         {
813                 printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
814                 return 1;
815         }
818 double PluginServer::get_project_framerate()
820         if(mwindow)
821                 return mwindow->edl->session->frame_rate;
822         else
823         if(edl)
824                 return edl->session->frame_rate;
825         else
826         {
827                 printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
828                 return 1;
829         }
834 int PluginServer::detach_buffers()
836         ring_buffers_out.remove_all();
837         offset_out_render.remove_all();
838         double_buffer_out_render.remove_all();
839         realtime_out_size.remove_all();
841         ring_buffers_in.remove_all();
842         offset_in_render.remove_all();
843         double_buffer_in_render.remove_all();
844         realtime_in_size.remove_all();
845         
846         out_buffer_size = 0;
847         shared_buffers = 0;
848         total_out_buffers = 0;
849         in_buffer_size = 0;
850         total_in_buffers = 0;
851         return 0;
854 int PluginServer::arm_buffer(int buffer_number, 
855                 int64_t offset_in, 
856                 int64_t offset_out,
857                 int double_buffer_in,
858                 int double_buffer_out)
860         offset_in_render.values[buffer_number] = offset_in;
861         offset_out_render.values[buffer_number] = offset_out;
862         double_buffer_in_render.values[buffer_number] = double_buffer_in;
863         double_buffer_out_render.values[buffer_number] = double_buffer_out;
867 int PluginServer::set_automation(FloatAutos *autos, FloatAuto **start_auto, FloatAuto **end_auto, int reverse)
869         this->autos = autos;
870         this->start_auto = start_auto;
871         this->end_auto = end_auto;
872         this->reverse = reverse;
877 void PluginServer::save_data(KeyFrame *keyframe)
879         if(!plugin_open) return;
880         client->save_data(keyframe);
883 KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
885         KeyFrame *result = 0;
886         if(plugin)
887                 result = plugin->get_prev_keyframe(position, client->direction);
888         else
889                 result = keyframe;
890         return result;
893 KeyFrame* PluginServer::get_next_keyframe(int64_t position)
895         KeyFrame *result = 0;
896         if(plugin)
897                 result = plugin->get_next_keyframe(position, client->direction);
898         else
899                 result = keyframe;
900         return result;
903 KeyFrame* PluginServer::get_keyframe()
905         if(plugin)
906                 return plugin->get_keyframe();
907         else
908                 return keyframe;
912 int PluginServer::get_interpolation_type()
914         return plugin->edl->session->interpolation_type;
917 Theme* PluginServer::new_theme()
919         if(theme)
920         {
921                 return client->new_theme();
922         }
923         else
924                 return 0;
927 Theme* PluginServer::get_theme()
929         if(mwindow) return mwindow->theme;
930         printf("PluginServer::get_theme mwindow not set\n");
931         return 0;
935 // Called when plugin interface is tweeked
936 void PluginServer::sync_parameters()
938         if(video) mwindow->restart_brender();
939         mwindow->sync_parameters();
940         if(mwindow->edl->session->auto_conf->plugins)
941         {
942                 mwindow->gui->lock_window("PluginServer::sync_parameters");
943                 mwindow->gui->canvas->draw_overlays();
944                 mwindow->gui->canvas->flash();
945                 mwindow->gui->unlock_window();
946         }
951 void PluginServer::dump()
953         printf("    PluginServer %s %s\n", path, title);
956 void PluginServer::get_camera(float *x, float *y, float *z,
957                                 int64_t position, int direction)
959         plugin->track->automation->get_camera(x, y, z, position, direction);
962 void PluginServer::get_projector(float *x, float *y, float *z,
963                                 int64_t position, int direction)
965         plugin->track->automation->get_projector(x, y, z, position, direction);