initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / pluginclient.C
1  
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 "bcdisplayinfo.h"
23 #include "bchash.h"
24 #include "bcsignals.h"
25 #include "clip.h"
26 #include "condition.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "filesystem.h"
30 #include "language.h"
31 #include "localsession.h"
32 #include "mainundo.h"
33 #include "mwindow.h"
34 #include "pluginclient.h"
35 #include "pluginserver.h"
36 #include "preferences.h"
37 #include "transportque.inc"
38
39
40 #include <ctype.h>
41 #include <errno.h>
42 #include <string.h>
43
44
45
46
47
48 PluginClientThread::PluginClientThread(PluginClient *client)
49  : Thread(1, 0, 0)
50 {
51         this->client = client;
52         window = 0;
53         init_complete = new Condition(0, "PluginClientThread::init_complete");
54 }
55
56 PluginClientThread::~PluginClientThread()
57 {
58 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
59         delete window;
60 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
61         window = 0;
62         delete init_complete;
63 }
64
65 void PluginClientThread::run()
66 {
67         BC_DisplayInfo info;
68         int result = 0;
69         if(client->window_x < 0) client->window_x = info.get_abs_cursor_x();
70         if(client->window_y < 0) client->window_y = info.get_abs_cursor_y();
71         window = client->new_window();
72
73         if(window)
74         {
75                 window->lock_window("PluginClientThread::run");
76                 window->create_objects();
77                 window->unlock_window();
78
79 /* Only set it here so tracking doesn't update it until everything is created. */
80                 client->thread = this;
81                 init_complete->unlock();
82
83                 result = window->run_window();
84                 window->lock_window("PluginClientThread::run");
85 //printf("PluginClientThread::run %p %d\n", this, __LINE__);
86                 window->hide_window(1);
87                 window->unlock_window();
88
89
90 // Can't save defaults in the destructor because it's not called immediately
91 // after closing.
92                 /* if(client->defaults) */ client->save_defaults_xml();
93 /* This is needed when the GUI is closed from itself */
94                 if(result) client->client_side_close();
95         }
96         else
97 // No window
98         {
99                 client->thread = this;
100                 init_complete->unlock();
101         }
102 }
103
104 BC_WindowBase* PluginClientThread::get_window()
105 {
106         return window;
107 }
108
109 PluginClient* PluginClientThread::get_client()
110 {
111         return client;
112 }
113
114
115
116
117
118
119 PluginClientFrame::PluginClientFrame(int data_size, 
120         int period_n, 
121         int period_d)
122 {
123         this->data_size = data_size;
124         force = 0;
125         this->period_n = period_n;
126         this->period_d = period_d;
127 }
128
129 PluginClientFrame::~PluginClientFrame()
130 {
131         
132 }
133
134
135
136
137
138 PluginClientWindow::PluginClientWindow(PluginClient *client, 
139         int w,
140         int h,
141         int min_w,
142         int min_h,
143         int allow_resize)
144  : BC_Window(client->gui_string, 
145         client->window_x /* - w / 2 */, 
146         client->window_y /* - h / 2 */, 
147         w, 
148         h, 
149         min_w, 
150         min_h,
151         allow_resize, 
152         0,
153         1)
154 {
155         this->client = client;
156 }
157
158 PluginClientWindow::PluginClientWindow(const char *title, 
159         int x,
160         int y,
161         int w,
162         int h,
163         int min_w,
164         int min_h,
165         int allow_resize)
166  : BC_Window(title, 
167         x, 
168         y, 
169         w, 
170         h, 
171         min_w, 
172         min_h,
173         allow_resize, 
174         0,
175         1)
176 {
177         this->client = 0;
178 }
179
180 PluginClientWindow::~PluginClientWindow()
181 {
182 }
183
184
185 int PluginClientWindow::translation_event()
186 {
187         if(client)
188         {
189                 client->window_x = get_x();
190                 client->window_y = get_y();
191         }
192
193         return 1;
194 }
195
196 int PluginClientWindow::close_event()
197 {
198 /* Set result to 1 to indicate a client side close */
199         set_done(1);
200         return 1;
201 }
202
203
204
205
206
207 PluginClient::PluginClient(PluginServer *server)
208 {
209         reset();
210         this->server = server;
211         smp = server->preferences->processors;
212         defaults = 0;
213         update_timer = new Timer;
214 // Virtual functions don't work here.
215 }
216
217 PluginClient::~PluginClient()
218 {
219 // Delete the GUI thread.  The GUI must be hidden with hide_gui first.
220         if(thread) 
221         {
222                 thread->join();
223                 delete thread;
224         }
225
226 // Virtual functions don't work here.
227         if(defaults) delete defaults;
228         frame_buffer.remove_all_objects();
229         delete update_timer;
230 }
231
232 int PluginClient::reset()
233 {
234         window_x = -1;
235         window_y = -1;
236         interactive = 0;
237         show_initially = 0;
238         wr = rd = 0;
239         master_gui_on = 0;
240         client_gui_on = 0;
241         realtime_priority = 0;
242         gui_string[0] = 0;
243         total_in_buffers = 0;
244         total_out_buffers = 0;
245         source_position = 0;
246         source_start = 0;
247         total_len = 0;
248         direction = PLAY_FORWARD;
249         thread = 0;
250         using_defaults = 0;
251         return 0;
252 }
253
254
255 void PluginClient::hide_gui()
256 {
257         if(thread && thread->window)
258         {
259 //printf("PluginClient::delete_thread %d\n", __LINE__);
260 /* This is needed when the GUI is closed from elsewhere than itself */
261 /* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */
262 /* Thread join will wait if this was not called from the thread itself or go on if it was */
263                 thread->window->lock_window("PluginClient::hide_gui");
264                 thread->window->set_done(0);
265 //printf("PluginClient::hide_gui %d thread->window=%p\n", __LINE__, thread->window);
266                 thread->window->unlock_window();
267 //printf("PluginClient::delete_thread %d\n", __LINE__);
268         }
269 }
270
271 // For realtime plugins initialize buffers
272 int PluginClient::plugin_init_realtime(int realtime_priority, 
273         int total_in_buffers,
274         int buffer_size)
275 {
276
277 // Get parameters for all
278         master_gui_on = get_gui_status();
279
280
281
282 // get parameters depending on video or audio
283         init_realtime_parameters();
284
285         this->realtime_priority = realtime_priority;
286         this->total_in_buffers = this->total_out_buffers = total_in_buffers;
287         this->out_buffer_size = this->in_buffer_size = buffer_size;
288         return 0;
289 }
290
291 int PluginClient::plugin_start_loop(int64_t start, 
292         int64_t end, 
293         int64_t buffer_size, 
294         int total_buffers)
295 {
296         this->source_start = start;
297         this->total_len = end - start;
298         this->start = start;
299         this->end = end;
300         this->in_buffer_size = this->out_buffer_size = buffer_size;
301         this->total_in_buffers = this->total_out_buffers = total_buffers;
302         start_loop();
303         return 0;
304 }
305
306 int PluginClient::plugin_process_loop()
307 {
308         return process_loop();
309 }
310
311 int PluginClient::plugin_stop_loop()
312 {
313         return stop_loop();
314 }
315
316 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
317 {
318         return server->start_progress(string, length);
319 }
320
321
322 // Non realtime parameters
323 int PluginClient::plugin_get_parameters()
324 {
325         int result = get_parameters();
326         if(defaults) save_defaults();
327         return result;
328 }
329
330 // ========================= main loop
331
332 int PluginClient::is_multichannel() { return 0; }
333 int PluginClient::is_synthesis() { return 0; }
334 int PluginClient::is_realtime() { return 0; }
335 int PluginClient::is_fileio() { return 0; }
336 int PluginClient::delete_buffer_ptrs() { return 0; }
337 const char* PluginClient::plugin_title() { return _("Untitled"); }
338
339 Theme* PluginClient::new_theme() { return 0; }
340
341 int PluginClient::load_configuration()
342 {
343         return 0;
344 }
345
346 Theme* PluginClient::get_theme()
347 {
348         return server->get_theme();
349 }
350
351 int PluginClient::show_gui()
352 {
353         load_configuration();
354         thread = new PluginClientThread(this);
355         thread->start();
356         thread->init_complete->lock("PluginClient::show_gui");
357 // Must wait before sending any hide_gui
358         if(thread->window)
359         {
360                 thread->window->init_wait();
361         }
362         else
363         {
364                 return 1;
365         }
366         return 0;
367 }
368
369 void PluginClient::raise_window()
370 {
371         if(thread && thread->window)
372         {
373                 thread->window->lock_window("PluginClient::raise_window");
374                 thread->window->raise_window();
375                 thread->window->flush();
376                 thread->window->unlock_window();
377         }
378 }
379
380 int PluginClient::set_string()
381 {
382         if(thread)
383         {
384                 thread->window->lock_window("PluginClient::set_string");
385                 thread->window->set_title(gui_string);
386                 thread->window->unlock_window();
387         }
388         return 0;
389 }
390
391
392
393
394
395 void PluginClient::begin_process_buffer()
396 {
397 // Delete all unused GUI frames
398         frame_buffer.remove_all_objects();
399 }
400
401
402 void PluginClient::end_process_buffer()
403 {
404         if(frame_buffer.size())
405         {
406                 send_render_gui();
407         }
408 }
409
410
411
412 void PluginClient::plugin_update_gui()
413 {
414         
415         update_gui();
416         
417 // Delete unused GUI frames
418         while(frame_buffer.size() > MAX_FRAME_BUFFER)
419                 frame_buffer.remove_object_number(0);
420
421 }
422
423 void PluginClient::update_gui()
424 {
425 }
426
427 int PluginClient::get_gui_update_frames()
428 {
429         if(frame_buffer.size())
430         {
431                 PluginClientFrame *frame = frame_buffer.get(0);
432                 int total_frames = update_timer->get_difference() * 
433                         frame->period_d / 
434                         frame->period_n / 
435                         1000;
436                 if(total_frames) update_timer->subtract(total_frames * 
437                         frame->period_n * 
438                         1000 / 
439                         frame->period_d);
440
441 // printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n", 
442 // __LINE__, 
443 // update_timer->get_difference(),
444 // frame->period_n * 1000 / frame->period_d,
445 // total_frames,
446 // frame_buffer.size());
447
448 // Add forced frames
449                 for(int i = 0; i < frame_buffer.size(); i++)
450                         if(frame_buffer.get(i)->force) total_frames++;
451                 total_frames = MIN(frame_buffer.size(), total_frames);
452
453
454                 return total_frames;
455         }
456         else
457         {
458                 return 0;
459         }
460 }
461
462 PluginClientFrame* PluginClient::get_gui_frame()
463 {
464         if(frame_buffer.size())
465         {
466                 PluginClientFrame *frame = frame_buffer.get(0);
467                 frame_buffer.remove_number(0);
468                 return frame;
469         }
470         else
471         {
472                 return 0;
473         }
474 }
475
476 void PluginClient::add_gui_frame(PluginClientFrame *frame)
477 {
478         frame_buffer.append(frame);
479 }
480
481 void PluginClient::send_render_gui()
482 {
483         server->send_render_gui(&frame_buffer);
484 }
485
486 void PluginClient::send_render_gui(void *data)
487 {
488         server->send_render_gui(data);
489 }
490
491 void PluginClient::send_render_gui(void *data, int size)
492 {
493         server->send_render_gui(data, size);
494 }
495
496 void PluginClient::plugin_render_gui(void *data, int size)
497 {
498         render_gui(data, size);
499 }
500
501
502 void PluginClient::plugin_render_gui(void *data)
503 {
504         render_gui(data);
505 }
506
507 void PluginClient::render_gui(void *data)
508 {
509         if(thread)
510         {
511                 thread->get_window()->lock_window("PluginClient::render_gui");
512                 
513 // Set all previous frames to draw immediately
514                 for(int i = 0; i < frame_buffer.size(); i++)
515                         frame_buffer.get(i)->force = 1;
516
517                 ArrayList<PluginClientFrame*> *src = 
518                         (ArrayList<PluginClientFrame*>*)data;
519
520 // Shift GUI data to GUI client
521                 while(src->size())
522                 {
523                         this->frame_buffer.append(src->get(0));
524                         src->remove_number(0);
525                 }
526                 
527 // Start the timer for the current buffer
528                 update_timer->update();
529                 thread->get_window()->unlock_window();
530         }
531 }
532
533 void PluginClient::render_gui(void *data, int size)
534 {
535         printf("PluginClient::render_gui %d\n", __LINE__);
536 }
537
538
539
540
541
542
543
544
545 int PluginClient::is_audio() { return 0; }
546 int PluginClient::is_video() { return 0; }
547 int PluginClient::is_theme() { return 0; }
548 int PluginClient::uses_gui() { return 1; }
549 int PluginClient::is_transition() { return 0; }
550 int PluginClient::load_defaults() 
551 {
552 //      printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
553         return 0; 
554 }
555
556 int PluginClient::save_defaults() 
557
558         save_defaults_xml();
559 //      printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
560         return 0; 
561 }
562
563 void PluginClient::load_defaults_xml() 
564 {
565         char path[BCTEXTLEN];
566         server->get_defaults_path(path);
567         FileSystem fs;
568         fs.complete_path(path);
569         using_defaults = 1;
570 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
571         
572         KeyFrame temp_keyframe;
573         FILE *fd = fopen(path, "r");
574         if(fd)
575         {
576                 char *data = temp_keyframe.get_data();
577                 int data_size = fread(data, 1, MESSAGESIZE-1, fd);
578                 if( data_size < 0 ) data_size = 0;
579                 if( data_size > 0 )
580                 {
581 // Get window extents
582                         int state = 0;
583                         for(int i = 0; i < data_size - 8; i++)
584                         {
585                                 if(data[i] == '<') break;
586                                 if(isdigit(data[i]))
587                                 {
588                                         if(state == 0)
589                                         {
590                                                 window_x = atoi(data + i);
591                                                 state++;
592                                         }
593                                         else
594                                         {
595                                                 window_y = atoi(data + i);
596                                                 break;
597                                         }
598                                         while(i < data_size && isdigit(data[i])) i++;
599                                 }
600                         }
601                         data[data_size] = 0;
602                         read_data(&temp_keyframe);
603                 }
604
605                 fclose(fd);
606         }
607         using_defaults = 0;
608 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
609 }
610
611 void PluginClient::save_defaults_xml() 
612 {
613         char path[BCTEXTLEN];
614         server->get_defaults_path(path);
615         FileSystem fs;
616         fs.complete_path(path);
617         using_defaults = 1;
618
619         KeyFrame temp_keyframe;
620
621         save_data(&temp_keyframe);
622         FILE *fd = fopen(path, "w");
623         if(fd)
624         {
625                 fprintf(fd, "%d\n%d\n", window_x, window_y);
626                 if(!fwrite(temp_keyframe.get_data(), strlen(temp_keyframe.get_data()), 1, fd))
627                 {
628                         fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
629                                 __LINE__,
630                                 path,
631                                 (int)strlen(temp_keyframe.get_data()),
632                                 strerror(errno));
633                 }
634
635                 fclose(fd);
636         }
637         using_defaults = 0;
638 }
639
640 int PluginClient::is_defaults()
641 {
642         return using_defaults;
643 }
644
645 BC_Hash* PluginClient::get_defaults()
646 {
647         return defaults;
648 }
649 PluginClientThread* PluginClient::get_thread()
650 {
651         return thread;
652 }
653
654 BC_WindowBase* PluginClient::new_window() 
655
656         printf("PluginClient::new_window undefined in %s.\n", plugin_title());
657         return 0; 
658 }
659 int PluginClient::get_parameters() { return 0; }
660 int PluginClient::get_samplerate() { return get_project_samplerate(); }
661 double PluginClient::get_framerate() { return get_project_framerate(); }
662 int PluginClient::init_realtime_parameters() { return 0; }
663 int PluginClient::delete_nonrealtime_parameters() { return 0; }
664 int PluginClient::start_loop() { return 0; };
665 int PluginClient::process_loop() { return 0; };
666 int PluginClient::stop_loop() { return 0; };
667
668 void PluginClient::set_interactive()
669 {
670         interactive = 1;
671 }
672
673 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
674 {
675         return recommended_size;
676 }
677
678 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
679 {
680         return recommended_size;
681 }
682
683 int PluginClient::get_gui_status()
684 {
685         return server->get_gui_status();
686 }
687
688 int PluginClient::start_plugin()
689 {
690         printf(_("No processing defined for this plugin.\n"));
691         return 0;
692 }
693
694 // close event from client side
695 void PluginClient::client_side_close()
696 {
697 // Last command executed
698         server->client_side_close();
699 }
700
701 int PluginClient::stop_gui_client()
702 {
703         if(!client_gui_on) return 0;
704         client_gui_on = 0;
705         return 0;
706 }
707
708 int PluginClient::get_project_samplerate()
709 {
710         return server->get_project_samplerate();
711 }
712
713 double PluginClient::get_project_framerate()
714 {
715         return server->get_project_framerate();
716 }
717
718
719 void PluginClient::update_display_title()
720 {
721         server->generate_display_title(gui_string);
722         set_string();
723 }
724
725 char* PluginClient::get_gui_string()
726 {
727         return gui_string;
728 }
729
730
731 char* PluginClient::get_path()
732 {
733         return server->path;
734 }
735
736 char* PluginClient::get_plugin_dir()
737 {
738         return server->preferences->plugin_dir;
739 }
740
741 int PluginClient::set_string_client(char *string)
742 {
743         strcpy(gui_string, string);
744         set_string();
745         return 0;
746 }
747
748
749 int PluginClient::get_interpolation_type()
750 {
751         return server->get_interpolation_type();
752 }
753
754
755 float PluginClient::get_red()
756 {
757         if(server->mwindow)
758                 return server->mwindow->edl->local_session->red;
759         else
760         if(server->edl)
761                 return server->edl->local_session->red;
762         else
763                 return 0;
764 }
765
766 float PluginClient::get_green()
767 {
768         if(server->mwindow)
769                 return server->mwindow->edl->local_session->green;
770         else
771         if(server->edl)
772                 return server->edl->local_session->green;
773         else
774                 return 0;
775 }
776
777 float PluginClient::get_blue()
778 {
779         if(server->mwindow)
780                 return server->mwindow->edl->local_session->blue;
781         else
782         if(server->edl)
783                 return server->edl->local_session->blue;
784         else
785                 return 0;
786 }
787
788
789
790 int64_t PluginClient::get_source_position()
791 {
792         return source_position;
793 }
794
795 int64_t PluginClient::get_source_start()
796 {
797         return source_start;
798 }
799
800 int64_t PluginClient::get_total_len()
801 {
802         return total_len;
803 }
804
805 int PluginClient::get_direction()
806 {
807         return direction;
808 }
809
810
811 int64_t PluginClient::local_to_edl(int64_t position)
812 {
813         return position;
814 }
815
816 int64_t PluginClient::edl_to_local(int64_t position)
817 {
818         return position;
819 }
820
821 int PluginClient::get_use_opengl()
822 {
823         return server->get_use_opengl();
824 }
825
826 int PluginClient::get_total_buffers()
827 {
828         return total_in_buffers;
829 }
830
831 int PluginClient::get_buffer_size()
832 {
833         return in_buffer_size;
834 }
835
836 int PluginClient::get_project_smp()
837 {
838 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
839         return smp;
840 }
841
842 const char* PluginClient::get_defaultdir()
843 {
844         return BCASTDIR;
845 }
846
847
848 int PluginClient::send_hide_gui()
849 {
850 // Stop the GUI server and delete GUI messages
851         client_gui_on = 0;
852         return 0;
853 }
854
855 int PluginClient::send_configure_change()
856 {
857         if(server->mwindow)
858                 server->mwindow->undo->update_undo_before("tweek", this);
859 #ifdef USE_KEYFRAME_SPANNING
860         KeyFrame keyframe;
861         keyframe.copy_from(server->get_keyframe());
862         save_data(&keyframe);
863         server->apply_keyframe(&keyframe);
864 #else
865         KeyFrame* keyframe = server->get_keyframe();
866 // Call save routine in plugin
867         save_data(keyframe);
868 #endif
869         if(server->mwindow)
870                 server->mwindow->undo->update_undo_after("tweek", LOAD_AUTOMATION);
871         server->sync_parameters();
872         return 0;
873 }
874
875
876 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
877 {
878         if(is_local) position = local_to_edl(position);
879         return server->get_prev_keyframe(position);
880 }
881
882 KeyFrame* PluginClient::get_next_keyframe(int64_t position, int is_local)
883 {
884         if(is_local) position = local_to_edl(position);
885         return server->get_next_keyframe(position);
886 }
887
888 void PluginClient::get_camera(float *x, float *y, float *z, int64_t position)
889 {
890         server->get_camera(x, y, z, position, direction);
891 }
892
893 void PluginClient::get_projector(float *x, float *y, float *z, int64_t position)
894 {
895         server->get_projector(x, y, z, position, direction);
896 }
897
898
899 EDLSession* PluginClient::get_edlsession()
900 {
901         if(server->edl) 
902                 return server->edl->session;
903         return 0;
904 }
905
906 int PluginClient::gui_open()
907 {
908         return server->gui_open();
909 }