prevent popup deactivation while button_down
[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 //printf("PluginClient::plugin_start_loop %d %ld %ld %ld %d\n",
297 // __LINE__, start, end, buffer_size, total_buffers);
298         this->source_start = start;
299         this->total_len = end - start;
300         this->start = start;
301         this->end = end;
302         this->in_buffer_size = this->out_buffer_size = buffer_size;
303         this->total_in_buffers = this->total_out_buffers = total_buffers;
304         start_loop();
305         return 0;
306 }
307
308 int PluginClient::plugin_process_loop()
309 {
310         return process_loop();
311 }
312
313 int PluginClient::plugin_stop_loop()
314 {
315         return stop_loop();
316 }
317
318 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
319 {
320         return server->start_progress(string, length);
321 }
322
323
324 // Non realtime parameters
325 int PluginClient::plugin_get_parameters()
326 {
327         int result = get_parameters();
328         if(defaults) save_defaults();
329         return result;
330 }
331
332 // ========================= main loop
333
334 int PluginClient::is_multichannel() { return 0; }
335 int PluginClient::is_synthesis() { return 0; }
336 int PluginClient::is_realtime() { return 0; }
337 int PluginClient::is_fileio() { return 0; }
338 int PluginClient::delete_buffer_ptrs() { return 0; }
339 const char* PluginClient::plugin_title() { return _("Untitled"); }
340
341 Theme* PluginClient::new_theme() { return 0; }
342
343 int PluginClient::load_configuration()
344 {
345         return 0;
346 }
347
348 Theme* PluginClient::get_theme()
349 {
350         return server->get_theme();
351 }
352
353 int PluginClient::show_gui()
354 {
355         load_configuration();
356         thread = new PluginClientThread(this);
357         thread->start();
358         thread->init_complete->lock("PluginClient::show_gui");
359 // Must wait before sending any hide_gui
360         if(thread->window)
361         {
362                 thread->window->init_wait();
363         }
364         else
365         {
366                 return 1;
367         }
368         return 0;
369 }
370
371 void PluginClient::raise_window()
372 {
373         if(thread && thread->window)
374         {
375                 thread->window->lock_window("PluginClient::raise_window");
376                 thread->window->raise_window();
377                 thread->window->flush();
378                 thread->window->unlock_window();
379         }
380 }
381
382 int PluginClient::set_string()
383 {
384         if(thread)
385         {
386                 thread->window->lock_window("PluginClient::set_string");
387                 thread->window->set_title(gui_string);
388                 thread->window->unlock_window();
389         }
390         return 0;
391 }
392
393
394
395
396
397 void PluginClient::begin_process_buffer()
398 {
399 // Delete all unused GUI frames
400         frame_buffer.remove_all_objects();
401 }
402
403
404 void PluginClient::end_process_buffer()
405 {
406         if(frame_buffer.size())
407         {
408                 send_render_gui();
409         }
410 }
411
412
413
414 void PluginClient::plugin_update_gui()
415 {
416         
417         update_gui();
418         
419 // Delete unused GUI frames
420         while(frame_buffer.size() > MAX_FRAME_BUFFER)
421                 frame_buffer.remove_object_number(0);
422
423 }
424
425 void PluginClient::update_gui()
426 {
427 }
428
429 int PluginClient::get_gui_update_frames()
430 {
431         if(frame_buffer.size())
432         {
433                 PluginClientFrame *frame = frame_buffer.get(0);
434                 int total_frames = update_timer->get_difference() * 
435                         frame->period_d / 
436                         frame->period_n / 
437                         1000;
438                 if(total_frames) update_timer->subtract(total_frames * 
439                         frame->period_n * 
440                         1000 / 
441                         frame->period_d);
442
443 // printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n", 
444 // __LINE__, 
445 // update_timer->get_difference(),
446 // frame->period_n * 1000 / frame->period_d,
447 // total_frames,
448 // frame_buffer.size());
449
450 // Add forced frames
451                 for(int i = 0; i < frame_buffer.size(); i++)
452                         if(frame_buffer.get(i)->force) total_frames++;
453                 total_frames = MIN(frame_buffer.size(), total_frames);
454
455
456                 return total_frames;
457         }
458         else
459         {
460                 return 0;
461         }
462 }
463
464 PluginClientFrame* PluginClient::get_gui_frame()
465 {
466         if(frame_buffer.size())
467         {
468                 PluginClientFrame *frame = frame_buffer.get(0);
469                 frame_buffer.remove_number(0);
470                 return frame;
471         }
472         else
473         {
474                 return 0;
475         }
476 }
477
478 void PluginClient::add_gui_frame(PluginClientFrame *frame)
479 {
480         frame_buffer.append(frame);
481 }
482
483 void PluginClient::send_render_gui()
484 {
485         server->send_render_gui(&frame_buffer);
486 }
487
488 void PluginClient::send_render_gui(void *data)
489 {
490         server->send_render_gui(data);
491 }
492
493 void PluginClient::send_render_gui(void *data, int size)
494 {
495         server->send_render_gui(data, size);
496 }
497
498 void PluginClient::plugin_render_gui(void *data, int size)
499 {
500         render_gui(data, size);
501 }
502
503
504 void PluginClient::plugin_render_gui(void *data)
505 {
506         render_gui(data);
507 }
508
509 void PluginClient::render_gui(void *data)
510 {
511         if(thread)
512         {
513                 thread->get_window()->lock_window("PluginClient::render_gui");
514                 
515 // Set all previous frames to draw immediately
516                 for(int i = 0; i < frame_buffer.size(); i++)
517                         frame_buffer.get(i)->force = 1;
518
519                 ArrayList<PluginClientFrame*> *src = 
520                         (ArrayList<PluginClientFrame*>*)data;
521
522 // Shift GUI data to GUI client
523                 while(src->size())
524                 {
525                         this->frame_buffer.append(src->get(0));
526                         src->remove_number(0);
527                 }
528                 
529 // Start the timer for the current buffer
530                 update_timer->update();
531                 thread->get_window()->unlock_window();
532         }
533 }
534
535 void PluginClient::render_gui(void *data, int size)
536 {
537         printf("PluginClient::render_gui %d\n", __LINE__);
538 }
539
540
541
542
543
544
545
546
547 int PluginClient::is_audio() { return 0; }
548 int PluginClient::is_video() { return 0; }
549 int PluginClient::is_theme() { return 0; }
550 int PluginClient::uses_gui() { return 1; }
551 int PluginClient::is_transition() { return 0; }
552 int PluginClient::load_defaults() 
553 {
554 //      printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
555         return 0; 
556 }
557
558 int PluginClient::save_defaults() 
559
560         save_defaults_xml();
561 //      printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
562         return 0; 
563 }
564
565 void PluginClient::load_defaults_xml() 
566 {
567         char path[BCTEXTLEN];
568         server->get_defaults_path(path);
569         FileSystem fs;
570         fs.complete_path(path);
571         using_defaults = 1;
572 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
573         
574         KeyFrame temp_keyframe;
575         FILE *fd = fopen(path, "r");
576         if(fd)
577         {
578                 char *data = temp_keyframe.get_data();
579                 int data_size = fread(data, 1, MESSAGESIZE-1, fd);
580                 if( data_size < 0 ) data_size = 0;
581                 if( data_size > 0 )
582                 {
583 // Get window extents
584                         int state = 0;
585                         for(int i = 0; i < data_size - 8; i++)
586                         {
587                                 if(data[i] == '<') break;
588                                 if(isdigit(data[i]))
589                                 {
590                                         if(state == 0)
591                                         {
592                                                 window_x = atoi(data + i);
593                                                 state++;
594                                         }
595                                         else
596                                         {
597                                                 window_y = atoi(data + i);
598                                                 break;
599                                         }
600                                         while(i < data_size && isdigit(data[i])) i++;
601                                 }
602                         }
603                         data[data_size] = 0;
604                         read_data(&temp_keyframe);
605                 }
606
607                 fclose(fd);
608         }
609         using_defaults = 0;
610 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
611 }
612
613 void PluginClient::save_defaults_xml() 
614 {
615         char path[BCTEXTLEN];
616         server->get_defaults_path(path);
617         FileSystem fs;
618         fs.complete_path(path);
619         using_defaults = 1;
620
621         KeyFrame temp_keyframe;
622
623         save_data(&temp_keyframe);
624         FILE *fd = fopen(path, "w");
625         if(fd)
626         {
627                 fprintf(fd, "%d\n%d\n", window_x, window_y);
628                 if(!fwrite(temp_keyframe.get_data(), strlen(temp_keyframe.get_data()), 1, fd))
629                 {
630                         fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
631                                 __LINE__,
632                                 path,
633                                 (int)strlen(temp_keyframe.get_data()),
634                                 strerror(errno));
635                 }
636
637                 fclose(fd);
638         }
639         using_defaults = 0;
640 }
641
642 int PluginClient::is_defaults()
643 {
644         return using_defaults;
645 }
646
647 BC_Hash* PluginClient::get_defaults()
648 {
649         return defaults;
650 }
651 PluginClientThread* PluginClient::get_thread()
652 {
653         return thread;
654 }
655
656 BC_WindowBase* PluginClient::new_window() 
657
658         printf("PluginClient::new_window undefined in %s.\n", plugin_title());
659         return 0; 
660 }
661 int PluginClient::get_parameters() { return 0; }
662 int PluginClient::get_samplerate() { return get_project_samplerate(); }
663 double PluginClient::get_framerate() { return get_project_framerate(); }
664 int PluginClient::init_realtime_parameters() { return 0; }
665 int PluginClient::delete_nonrealtime_parameters() { return 0; }
666 int PluginClient::start_loop() { return 0; };
667 int PluginClient::process_loop() { return 0; };
668 int PluginClient::stop_loop() { return 0; };
669
670 void PluginClient::set_interactive()
671 {
672         interactive = 1;
673 }
674
675 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
676 {
677         return recommended_size;
678 }
679
680 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
681 {
682         return recommended_size;
683 }
684
685 int PluginClient::get_gui_status()
686 {
687         return server->get_gui_status();
688 }
689
690 int PluginClient::start_plugin()
691 {
692         printf(_("No processing defined for this plugin.\n"));
693         return 0;
694 }
695
696 // close event from client side
697 void PluginClient::client_side_close()
698 {
699 // Last command executed
700         server->client_side_close();
701 }
702
703 int PluginClient::stop_gui_client()
704 {
705         if(!client_gui_on) return 0;
706         client_gui_on = 0;
707         return 0;
708 }
709
710 int PluginClient::get_project_samplerate()
711 {
712         return server->get_project_samplerate();
713 }
714
715 double PluginClient::get_project_framerate()
716 {
717         return server->get_project_framerate();
718 }
719
720
721 void PluginClient::update_display_title()
722 {
723         server->generate_display_title(gui_string);
724         set_string();
725 }
726
727 char* PluginClient::get_gui_string()
728 {
729         return gui_string;
730 }
731
732
733 char* PluginClient::get_path()
734 {
735         return server->path;
736 }
737
738 char* PluginClient::get_plugin_dir()
739 {
740         return server->preferences->plugin_dir;
741 }
742
743 int PluginClient::set_string_client(char *string)
744 {
745         strcpy(gui_string, string);
746         set_string();
747         return 0;
748 }
749
750
751 int PluginClient::get_interpolation_type()
752 {
753         return server->get_interpolation_type();
754 }
755
756
757 float PluginClient::get_red()
758 {
759         if(server->mwindow)
760                 return server->mwindow->edl->local_session->red;
761         else
762         if(server->edl)
763                 return server->edl->local_session->red;
764         else
765                 return 0;
766 }
767
768 float PluginClient::get_green()
769 {
770         if(server->mwindow)
771                 return server->mwindow->edl->local_session->green;
772         else
773         if(server->edl)
774                 return server->edl->local_session->green;
775         else
776                 return 0;
777 }
778
779 float PluginClient::get_blue()
780 {
781         if(server->mwindow)
782                 return server->mwindow->edl->local_session->blue;
783         else
784         if(server->edl)
785                 return server->edl->local_session->blue;
786         else
787                 return 0;
788 }
789
790
791
792 int64_t PluginClient::get_source_position()
793 {
794         return source_position;
795 }
796
797 int64_t PluginClient::get_source_start()
798 {
799         return source_start;
800 }
801
802 int64_t PluginClient::get_total_len()
803 {
804         return total_len;
805 }
806
807 int PluginClient::get_direction()
808 {
809         return direction;
810 }
811
812
813 int64_t PluginClient::local_to_edl(int64_t position)
814 {
815         return position;
816 }
817
818 int64_t PluginClient::edl_to_local(int64_t position)
819 {
820         return position;
821 }
822
823 int PluginClient::get_use_opengl()
824 {
825         return server->get_use_opengl();
826 }
827
828 int PluginClient::get_total_buffers()
829 {
830         return total_in_buffers;
831 }
832
833 int PluginClient::get_buffer_size()
834 {
835         return in_buffer_size;
836 }
837
838 int PluginClient::get_project_smp()
839 {
840 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
841         return smp;
842 }
843
844 const char* PluginClient::get_defaultdir()
845 {
846         return BCASTDIR;
847 }
848
849
850 int PluginClient::send_hide_gui()
851 {
852 // Stop the GUI server and delete GUI messages
853         client_gui_on = 0;
854         return 0;
855 }
856
857 int PluginClient::send_configure_change()
858 {
859         if(server->mwindow)
860                 server->mwindow->undo->update_undo_before(_("tweek"), this);
861 #ifdef USE_KEYFRAME_SPANNING
862         KeyFrame keyframe;
863         keyframe.copy_from(server->get_keyframe());
864         save_data(&keyframe);
865         server->apply_keyframe(&keyframe);
866 #else
867         KeyFrame* keyframe = server->get_keyframe();
868 // Call save routine in plugin
869         save_data(keyframe);
870 #endif
871         if(server->mwindow)
872                 server->mwindow->undo->update_undo_after(_("tweek"), LOAD_AUTOMATION);
873         server->sync_parameters();
874         return 0;
875 }
876
877
878 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
879 {
880         if(is_local) position = local_to_edl(position);
881         return server->get_prev_keyframe(position);
882 }
883
884 KeyFrame* PluginClient::get_next_keyframe(int64_t position, int is_local)
885 {
886         if(is_local) position = local_to_edl(position);
887         return server->get_next_keyframe(position);
888 }
889
890 void PluginClient::get_camera(float *x, float *y, float *z, int64_t position)
891 {
892         server->get_camera(x, y, z, position, direction);
893 }
894
895 void PluginClient::get_projector(float *x, float *y, float *z, int64_t position)
896 {
897         server->get_projector(x, y, z, position, direction);
898 }
899
900
901 EDLSession* PluginClient::get_edlsession()
902 {
903         if(server->edl) 
904                 return server->edl->session;
905         return 0;
906 }
907
908 int PluginClient::gui_open()
909 {
910         return server->gui_open();
911 }