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