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