cut with active speed auto correction, add locale pref, mod prores dft profile to...
[goodguy/cinelerra.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 "attachmentpoint.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "edits.h"
29 #include "edit.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "file.h"
33 #include "filesystem.h"
34 #include "filexml.h"
35 #include "indexable.h"
36 #include "language.h"
37 #include "localsession.h"
38 #include "mainundo.h"
39 #include "mwindow.h"
40 #include "plugin.h"
41 #include "pluginclient.h"
42 #include "pluginserver.h"
43 #include "preferences.h"
44 #include "renderengine.h"
45 #include "track.h"
46 #include "tracks.h"
47 #include "transportque.h"
48
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <fcntl.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <errno.h>
56
57 PluginClientFrame::PluginClientFrame()
58 {
59         position = -1;
60 }
61
62 PluginClientFrame::~PluginClientFrame()
63 {
64 }
65
66
67 PluginClientThread::PluginClientThread(PluginClient *client)
68  : Thread(1, 0, 0)
69 {
70         this->client = client;
71         window = 0;
72         init_complete = new Condition(0, "PluginClientThread::init_complete");
73 }
74
75 PluginClientThread::~PluginClientThread()
76 {
77         delete window;
78         delete init_complete;
79 }
80
81 void PluginClientThread::run()
82 {
83         BC_DisplayInfo info;
84         int result = 0;
85         if(client->window_x < 0) client->window_x = info.get_abs_cursor_x();
86         if(client->window_y < 0) client->window_y = info.get_abs_cursor_y();
87         if(!window)
88                 window = (PluginClientWindow*)client->new_window();
89
90         if(window) {
91                 window->lock_window("PluginClientThread::run");
92                 window->create_objects();
93                 VFrame *picon = client->server->get_picon();
94                 if( picon ) window->set_icon(picon);
95                 window->unlock_window();
96
97 /* Only set it here so tracking doesn't update it until everything is created. */
98                 client->thread = this;
99                 init_complete->unlock();
100
101                 result = window->run_window();
102                 window->lock_window("PluginClientThread::run");
103 //printf("PluginClientThread::run %p %d\n", this, __LINE__);
104                 window->hide_window(1);
105                 client->save_defaults_xml(); // needs window lock
106                 window->unlock_window();
107                 window->done_event(result);
108 /* This is needed when the GUI is closed from itself */
109                 if(result) client->client_side_close();
110         }
111         else
112 // No window
113         {
114                 client->thread = this;
115                 init_complete->unlock();
116         }
117 }
118
119 BC_WindowBase* PluginClientThread::get_window()
120 {
121         return window;
122 }
123
124 PluginClient* PluginClientThread::get_client()
125 {
126         return client;
127 }
128
129
130 PluginClientWindow::PluginClientWindow(PluginClient *client,
131         int w, int h, int min_w, int min_h, int allow_resize)
132  : BC_Window(client->gui_string,
133         client->window_x /* - w / 2 */, client->window_y /* - h / 2 */,
134         w, h, min_w, min_h, allow_resize, 0, 1)
135 {
136         this->client = client;
137 }
138
139 PluginClientWindow::PluginClientWindow(const char *title,
140         int x, int y, int w, int h, int min_w, int min_h, int allow_resize)
141  : BC_Window(title, x, y, w, h, min_w, min_h, allow_resize, 0, 1)
142 {
143         this->client = 0;
144 }
145
146 PluginClientWindow::~PluginClientWindow()
147 {
148 }
149
150
151 int PluginClientWindow::translation_event()
152 {
153         if(client)
154         {
155                 client->window_x = get_x();
156                 client->window_y = get_y();
157         }
158
159         return 1;
160 }
161
162 int PluginClientWindow::close_event()
163 {
164 /* Set result to 1 to indicate a client side close */
165         set_done(1);
166         return 1;
167 }
168
169 void PluginClientWindow::param_updated()
170 {
171     printf("PluginClientWindow::param_updated %d undefined\n", __LINE__);
172 }
173
174 //phyllis
175 PluginParam::PluginParam(PluginClient *plugin, PluginClientWindow *gui,
176     int x1, int x2, int x3, int y, int text_w,
177     int *output_i, float *output_f, int *output_q,
178     const char *title, float min, float max)
179 {
180     this->output_i = output_i;
181     this->output_f = output_f;
182     this->output_q = output_q;
183     this->title = cstrdup(title);
184     this->plugin = plugin;
185     this->gui = gui;
186     this->x1 = x1;
187     this->x2 = x2;
188     this->x3 = x3;
189     this->text_w = text_w;
190     this->y = y;
191     this->min = min;
192     this->max = max;
193     fpot = 0;
194     ipot = 0;
195     qpot = 0;
196     text = 0;
197     precision = 2;
198 }
199 PluginParam::~PluginParam()
200 {
201     delete fpot;
202     delete ipot;
203     delete qpot;
204     delete text;
205     delete title;
206 }
207
208
209 void PluginParam::initialize()
210 {
211     BC_Title *title_;
212     int y2 = y +
213         (BC_Pot::calculate_h() -
214         BC_Title::calculate_h(gui, _(title), MEDIUMFONT)) / 2;
215     gui->add_tool(title_ = new BC_Title(x1, y2, _(title)));
216
217     if(output_f)
218     {
219         gui->add_tool(fpot = new PluginFPot(this, x2, y));
220     }
221
222     if(output_i)
223     {
224         gui->add_tool(ipot = new PluginIPot(this, x2, y));
225     }
226
227     if(output_q)
228     {
229         gui->add_tool(qpot = new PluginQPot(this, x2, y));
230     }
231
232     int y3 = y +
233         (BC_Pot::calculate_h() -
234         BC_TextBox::calculate_h(gui, MEDIUMFONT, 1, 1)) / 2;
235     if(output_i)
236     {
237         gui->add_tool(text = new PluginText(this, x3, y3, *output_i));
238     }
239     if(output_f)
240     {
241         gui->add_tool(text = new PluginText(this, x3, y3, *output_f));
242     }
243     if(output_q)
244     {
245         gui->add_tool(text = new PluginText(this, x3, y3, *output_q));
246     }
247
248     set_precision(precision);
249 }
250
251 void PluginParam::update(int skip_text, int skip_pot)
252 {
253     if(!skip_text)
254     {
255         if(output_i)
256         {
257             text->update((int64_t)*output_i);
258         }
259         if(output_q)
260         {
261             text->update((int64_t)*output_q);
262         }
263         if(output_f)
264         {
265             text->update((float)*output_f);
266         }
267     }
268
269     if(!skip_pot)
270     {
271         if(ipot)
272         {
273             ipot->update((int64_t)*output_i);
274         }
275         if(qpot)
276         {
277             qpot->update((int64_t)*output_q);
278         }
279         if(fpot)
280         {
281             fpot->update((float)*output_f);
282         }
283     }
284 }
285
286 void PluginParam::set_precision(int digits)
287 {
288     this->precision = digits;
289     if(fpot)
290     {
291         if(text)
292         {
293             text->set_precision(digits);
294         }
295
296         fpot->set_precision(1.0f / pow(10, digits));
297     }
298 }
299
300
301 PluginFPot::PluginFPot(PluginParam *param, int x, int y)
302  : BC_FPot(x,
303         y,
304         *param->output_f,
305         param->min,
306         param->max)
307 {
308     this->param = param;
309     set_use_caption(0);
310 }
311
312 int PluginFPot::handle_event()
313 {
314         *param->output_f = get_value();
315     param->update(0, 1);
316         param->plugin->send_configure_change();
317     param->gui->param_updated();
318     return 1;
319 }
320
321 PluginIPot::PluginIPot(PluginParam *param, int x, int y)
322  : BC_IPot(x,
323         y,
324         *param->output_i,
325         (int)param->min,
326         (int)param->max)
327 {
328     this->param = param;
329     set_use_caption(0);
330 }
331
332 int PluginIPot::handle_event()
333 {
334         *param->output_i = get_value();
335     param->update(0, 1);
336         param->plugin->send_configure_change();
337     param->gui->param_updated();
338     return 1;
339 }
340
341
342 PluginQPot::PluginQPot(PluginParam *param, int x, int y)
343  : BC_QPot(x,
344         y,
345         *param->output_q)
346 {
347     this->param = param;
348     set_use_caption(0);
349 }
350
351 int PluginQPot::handle_event()
352 {
353         *param->output_q = get_value();
354     param->update(0, 1);
355         param->plugin->send_configure_change();
356     param->gui->param_updated();
357     return 1;
358 }
359
360 PluginText::PluginText(PluginParam *param, int x, int y, int value)
361  : BC_TextBox(x,
362     y,
363     param->text_w,
364     1,
365     (int64_t)value,
366     1,
367     MEDIUMFONT)
368 {
369     this->param = param;
370 }
371
372 PluginText::PluginText(PluginParam *param, int x, int y, float value)
373  : BC_TextBox(x,
374     y,
375     param->text_w,
376     1,
377     (float)value,
378     1,
379     MEDIUMFONT,
380     param->precision)
381 {
382     this->param = param;
383 }
384
385 int PluginText::handle_event()
386 {
387     if(param->output_i)
388     {
389         *param->output_i = atoi(get_text());
390     }
391
392     if(param->output_f)
393     {
394         *param->output_f = atof(get_text());
395     }
396
397     if(param->output_q)
398     {
399         *param->output_q = atoi(get_text());
400     }
401     param->update(1, 0);
402     param->plugin->send_configure_change();
403     param->gui->param_updated();
404     return 1;
405 }
406
407
408 PluginClient::PluginClient(PluginServer *server)
409 {
410         reset();
411         this->server = server;
412         smp = server->preferences->project_smp;
413         defaults = 0;
414         update_timer = new Timer;
415 // Virtual functions don't work here.
416 }
417
418 PluginClient::~PluginClient()
419 {
420         if( thread ) {
421                 hide_gui();
422                 thread->join();
423                 delete thread;
424         }
425
426 // Virtual functions don't work here.
427         if(defaults) delete defaults;
428         delete update_timer;
429 }
430
431 int PluginClient::reset()
432 {
433         window_x = -1;
434         window_y = -1;
435         interactive = 0;
436         show_initially = 0;
437         wr = rd = 0;
438         master_gui_on = 0;
439         client_gui_on = 0;
440         realtime_priority = 0;
441         gui_string[0] = 0;
442         total_in_buffers = 0;
443         total_out_buffers = 0;
444         source_position = 0;
445         source_start = 0;
446         total_len = 0;
447         direction = PLAY_FORWARD;
448         thread = 0;
449         using_defaults = 0;
450         return 0;
451 }
452
453
454 void PluginClient::hide_gui()
455 {
456         if(thread && thread->window)
457         {
458                 thread->window->lock_window("PluginClient::hide_gui");
459                 thread->window->set_done(0);
460                 thread->window->unlock_window();
461         }
462 }
463
464 // For realtime plugins initialize buffers
465 int PluginClient::plugin_init_realtime(int realtime_priority,
466         int total_in_buffers,
467         int buffer_size)
468 {
469
470 // Get parameters for all
471         master_gui_on = get_gui_status();
472
473
474
475 // get parameters depending on video or audio
476         init_realtime_parameters();
477
478         this->realtime_priority = realtime_priority;
479         this->total_in_buffers = this->total_out_buffers = total_in_buffers;
480         this->out_buffer_size = this->in_buffer_size = buffer_size;
481         return 0;
482 }
483
484 int PluginClient::plugin_start_loop(int64_t start,
485         int64_t end,
486         int64_t buffer_size,
487         int total_buffers)
488 {
489 //printf("PluginClient::plugin_start_loop %d %ld %ld %ld %d\n",
490 // __LINE__, start, end, buffer_size, total_buffers);
491         this->source_start = start;
492         this->total_len = end - start;
493         this->start = start;
494         this->end = end;
495         this->in_buffer_size = this->out_buffer_size = buffer_size;
496         this->total_in_buffers = this->total_out_buffers = total_buffers;
497         start_loop();
498         return 0;
499 }
500
501 int PluginClient::plugin_process_loop()
502 {
503         return process_loop();
504 }
505
506 int PluginClient::plugin_stop_loop()
507 {
508         return stop_loop();
509 }
510
511 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
512 {
513         return server->start_progress(string, length);
514 }
515
516
517 // Non realtime parameters
518 int PluginClient::plugin_get_parameters()
519 {
520         int result = get_parameters();
521         if(defaults) save_defaults();
522         return result;
523 }
524
525 // ========================= main loop
526
527 int PluginClient::is_multichannel() { return 0; }
528 int PluginClient::is_synthesis() { return 0; }
529 int PluginClient::is_realtime() { return 0; }
530 int PluginClient::is_fileio() { return 0; }
531 const char* PluginClient::plugin_title() { return _("Untitled"); }
532
533 Theme* PluginClient::new_theme() { return 0; }
534
535 int PluginClient::load_configuration()
536 {
537         return 0;
538 }
539
540 Theme* PluginClient::get_theme()
541 {
542         return server->get_theme();
543 }
544
545 int PluginClient::show_gui()
546 {
547         load_configuration();
548         thread = new PluginClientThread(this);
549         thread->start();
550         thread->init_complete->lock("PluginClient::show_gui");
551 // Must wait before sending any hide_gui
552         if( !thread->window ) return 1;
553         thread->window->init_wait();
554         return 0;
555 }
556
557 void PluginClient::raise_window()
558 {
559         if(thread && thread->window)
560         {
561                 thread->window->lock_window("PluginClient::raise_window");
562                 thread->window->raise_window();
563                 thread->window->flush();
564                 thread->window->unlock_window();
565         }
566 }
567
568 int PluginClient::set_string()
569 {
570         if(thread)
571         {
572                 thread->window->lock_window("PluginClient::set_string");
573                 thread->window->put_title(gui_string);
574                 thread->window->unlock_window();
575         }
576         return 0;
577 }
578
579
580
581
582
583 PluginClientFrames::PluginClientFrames()
584 {
585         count = 0;
586 }
587 PluginClientFrames::~PluginClientFrames()
588 {
589 }
590
591 int PluginClientFrames::fwd_cmpr(PluginClientFrame *a, PluginClientFrame *b)
592 {
593         double d = a->position - b->position;
594         return d < 0 ? -1 : !d ? 0 : 1;
595 }
596
597 int PluginClientFrames::rev_cmpr(PluginClientFrame *a, PluginClientFrame *b)
598 {
599         double d = b->position - a->position;
600         return d < 0 ? -1 : !d ? 0 : 1;
601 }
602
603 void PluginClientFrames::reset()
604 {
605         destroy();
606         count = 0;
607 }
608
609 void PluginClientFrames::add_gui_frame(PluginClientFrame *frame)
610 {
611         append(frame);
612         ++count;
613 }
614
615 void PluginClientFrames::concatenate(PluginClientFrames *frames)
616 {
617         concat(*frames);
618         count += frames->count;
619         frames->count = 0;
620 }
621
622 void PluginClientFrames::sort_position(int dir)
623 {
624 // enforce order
625         if( dir == PLAY_REVERSE )
626                 rev_sort();
627         else
628                 fwd_sort();
629 }
630
631 // pop frames until buffer passes position=pos in direction=dir
632 // dir==0, pop frame; pos<0, pop all frames
633 // delete past frames, return last popped frame
634 PluginClientFrame* PluginClientFrames::get_gui_frame(double pos, int dir)
635 {
636         if( dir ) {
637                 while( first != last ) {
638                         if( pos >= 0 && dir*(first->next->position - pos) > 0 ) break;
639                         delete first;  --count;
640                 }
641         }
642         PluginClientFrame *frame = first;
643         if( frame ) { remove_pointer(frame);  --count; }
644         return frame;
645 }
646
647 PluginClientFrame* PluginClient::get_gui_frame(double pos, int dir)
648 {
649         return client_frames.get_gui_frame(pos, dir);
650 }
651 PluginClientFrame* PluginClient::next_gui_frame()
652 {
653         return client_frames.first;
654 }
655
656
657 void PluginClient::plugin_update_gui()
658 {
659         update_gui();
660 }
661
662 void PluginClient::update_gui()
663 {
664 }
665
666 int PluginClient::pending_gui_frame()
667 {
668         PluginClientFrame *frame = client_frames.first;
669         if( !frame ) return 0;
670         double tracking_position = get_tracking_position();
671         int direction = get_tracking_direction();
672         int ret = !(direction == PLAY_REVERSE ?
673                 frame->position < tracking_position :
674                 frame->position > tracking_position);
675         return ret;
676 }
677
678 int PluginClient::pending_gui_frames()
679 {
680         PluginClientFrame *frame = client_frames.first;
681         if( !frame ) return 0;
682         double tracking_position = get_tracking_position();
683         int direction = get_tracking_direction();
684         int count = 0;
685         while( frame && !(direction == PLAY_REVERSE ?
686             frame->position < tracking_position :
687             frame->position > tracking_position) ) {
688                 ++count;  frame=frame->next;
689         }
690         return count;
691 }
692
693 void PluginClient::add_gui_frame(PluginClientFrame *frame)
694 {
695         client_frames.add_gui_frame(frame);
696 }
697 int PluginClient::get_gui_frames()
698 {
699         return client_frames.total();
700 }
701
702 double PluginClient::get_tracking_position()
703 {
704         return server->mwindow->get_tracking_position();
705 }
706
707 int PluginClient::get_tracking_direction()
708 {
709         return server->mwindow->get_tracking_direction();
710 }
711
712 void PluginClient::send_render_gui()
713 {
714         server->send_render_gui(&client_frames);
715 }
716
717 void PluginClient::send_render_gui(void *data)
718 {
719         server->send_render_gui(data);
720 }
721
722 void PluginClient::send_render_gui(void *data, int size)
723 {
724         server->send_render_gui(data, size);
725 }
726
727
728 void PluginClient::plugin_reset_gui_frames()
729 {
730         if( !thread ) return;
731         BC_WindowBase *window = thread->get_window();
732         if( !window ) return;
733         window->lock_window("PluginClient::plugin_reset_gui_frames");
734         client_frames.reset();
735         window->unlock_window();
736 }
737
738 void PluginClient::plugin_render_gui_frames(PluginClientFrames *frames)
739 {
740         if( !thread ) return;
741         BC_WindowBase *window = thread->get_window();
742         if( !window ) return;
743         window->lock_window("PluginClient::render_gui");
744         while( client_frames.count > MAX_FRAME_BUFFER )
745                 delete get_gui_frame(0, 0);
746 // append client frames to gui client_frames, consumes frames
747         client_frames.concatenate(frames);
748         client_frames.sort_position(get_tracking_direction());
749         update_timer->update();
750         window->unlock_window();
751 }
752
753 void PluginClient::plugin_render_gui(void *data)
754 {
755         render_gui(data);
756 }
757
758 void PluginClient::plugin_render_gui(void *data, int size)
759 {
760         render_gui(data, size);
761 }
762
763 void PluginClient::render_gui(void *data)
764 {
765         printf("PluginClient::render_gui %d\n", __LINE__);
766 }
767
768 void PluginClient::render_gui(void *data, int size)
769 {
770         printf("PluginClient::render_gui %d\n", __LINE__);
771 }
772
773 void PluginClient::reset_gui_frames()
774 {
775         server->reset_gui_frames();
776 }
777
778 int PluginClient::is_audio() { return 0; }
779 int PluginClient::is_video() { return 0; }
780 int PluginClient::is_theme() { return 0; }
781 int PluginClient::uses_gui() { return 1; }
782 int PluginClient::is_transition() { return 0; }
783 int PluginClient::load_defaults()
784 {
785 //      printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
786         return 0;
787 }
788
789 int PluginClient::save_defaults()
790 {
791         save_defaults_xml();
792 //      printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
793         return 0;
794 }
795
796 void PluginClient::load_defaults_xml()
797 {
798         char path[BCTEXTLEN];
799         server->get_defaults_path(path);
800         FileSystem fs;
801         fs.complete_path(path);
802         using_defaults = 1;
803 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
804
805         char *data = 0;
806         int64_t len = -1;
807         struct stat st;
808         int fd = open(path, O_RDONLY);
809         if( fd >= 0 && !fstat(fd, &st) ) {
810                 int64_t sz = st.st_size;
811                 data = new char[sz+1];
812                 len = read(fd, data, sz);
813                 close(fd);
814         }
815         if( data && len >= 0 ) {
816                 data[len] = 0;
817 // Get window extents
818                 int i = 0;
819                 for( int state=0; i<len && state>=0; ++i ) {
820                         if( !data[i] || data[i] == '<' ) break;
821                         if( !isdigit(data[i]) ) continue;
822                         if( !state ) {
823                                 window_x = atoi(data+i);
824                                 state = 1;
825                         }
826                         else {
827                                 window_y = atoi(data+i);
828                                 state = -1;
829                         }
830                         while( i<len && isdigit(data[i]) ) ++i;
831                 }
832                 KeyFrame keyframe(data+i, len-i);
833                 read_data(&keyframe);
834         }
835         delete [] data;
836
837         using_defaults = 0;
838 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
839 }
840
841 void PluginClient::save_defaults_xml()
842 {
843         char path[BCTEXTLEN];
844         server->get_defaults_path(path);
845         FileSystem fs;
846         fs.complete_path(path);
847         using_defaults = 1;
848
849         KeyFrame temp_keyframe;
850         save_data(&temp_keyframe);
851
852         const char *data = temp_keyframe.get_data();
853         int len = strlen(data);
854         FILE *fp = fopen(path, "w");
855
856         if( fp ) {
857                 fprintf(fp, "%d\n%d\n", window_x, window_y);
858                 if( len > 0 && !fwrite(data, len, 1, fp) ) {
859                         fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
860                                 __LINE__, path, len, strerror(errno));
861                 }
862                 fclose(fp);
863         }
864
865         using_defaults = 0;
866 }
867
868 int PluginClient::is_defaults()
869 {
870         return using_defaults;
871 }
872
873 BC_Hash* PluginClient::get_defaults()
874 {
875         return defaults;
876 }
877 PluginClientThread* PluginClient::get_thread()
878 {
879         return thread;
880 }
881
882 BC_WindowBase* PluginClient::new_window()
883 {
884         printf("PluginClient::new_window undefined in %s.\n", plugin_title());
885         return 0;
886 }
887 int PluginClient::get_parameters() { return 0; }
888 int PluginClient::get_samplerate() { return get_project_samplerate(); }
889 double PluginClient::get_framerate() { return get_project_framerate(); }
890 int PluginClient::init_realtime_parameters() { return 0; }
891 int PluginClient::delete_nonrealtime_parameters() { return 0; }
892 int PluginClient::start_loop() { return 0; };
893 int PluginClient::process_loop() { return 0; };
894 int PluginClient::stop_loop() { return 0; };
895
896 void PluginClient::set_interactive()
897 {
898         interactive = 1;
899 }
900
901 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
902 {
903         return recommended_size;
904 }
905
906 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
907 {
908         return recommended_size;
909 }
910
911 int PluginClient::get_gui_status()
912 {
913         return server->get_gui_status();
914 }
915
916 // close event from client side
917 void PluginClient::client_side_close()
918 {
919 // Last command executed
920         server->client_side_close();
921 }
922
923 int PluginClient::stop_gui_client()
924 {
925         if(!client_gui_on) return 0;
926         client_gui_on = 0;
927         return 0;
928 }
929
930 int PluginClient::get_project_samplerate()
931 {
932         return server->get_project_samplerate();
933 }
934
935 double PluginClient::get_project_framerate()
936 {
937         return server->get_project_framerate();
938 }
939
940 const char *PluginClient::get_source_path()
941 {
942         EDL *edl = get_edl();
943         Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
944         int64_t source_position = plugin->startproject;
945         Edit *edit = plugin->track->edits->editof(source_position,PLAY_FORWARD,0);
946         Indexable *indexable = edit ? edit->get_source() : 0;
947         return indexable ? indexable->path : 0;
948 }
949
950
951 void PluginClient::update_display_title()
952 {
953         server->generate_display_title(gui_string);
954         set_string();
955 }
956
957 char* PluginClient::get_gui_string()
958 {
959         return gui_string;
960 }
961
962
963 char* PluginClient::get_path()
964 {
965         return server->path;
966 }
967
968 char* PluginClient::get_plugin_dir()
969 {
970         return server->preferences->plugin_dir;
971 }
972
973 int PluginClient::set_string_client(char *string)
974 {
975         strcpy(gui_string, string);
976         set_string();
977         return 0;
978 }
979
980
981 int PluginClient::get_interpolation_type()
982 {
983         return server->get_interpolation_type();
984 }
985
986
987 float PluginClient::get_red()
988 {
989         EDL *edl = get_edl();
990         return edl->local_session->use_max ?
991                 edl->local_session->red_max :
992                 edl->local_session->red;
993 }
994
995 float PluginClient::get_green()
996 {
997         EDL *edl = get_edl();
998         return edl->local_session->use_max ?
999                 edl->local_session->green_max :
1000                 edl->local_session->green;
1001 }
1002
1003 float PluginClient::get_blue()
1004 {
1005         EDL *edl = get_edl();
1006         return edl->local_session->use_max ?
1007                 edl->local_session->blue_max :
1008                 edl->local_session->blue;
1009 }
1010
1011
1012 int64_t PluginClient::get_source_position()
1013 {
1014         return source_position;
1015 }
1016
1017 int64_t PluginClient::get_source_start()
1018 {
1019         return source_start;
1020 }
1021
1022 int64_t PluginClient::get_total_len()
1023 {
1024         return total_len;
1025 }
1026
1027 int PluginClient::get_direction()
1028 {
1029         return direction;
1030 }
1031
1032 int64_t PluginClient::local_to_edl(int64_t position)
1033 {
1034         return position;
1035 }
1036
1037 int64_t PluginClient::edl_to_local(int64_t position)
1038 {
1039         return position;
1040 }
1041
1042 int PluginClient::get_use_opengl()
1043 {
1044         return server->get_use_opengl();
1045 }
1046
1047 int PluginClient::to_ram(VFrame *vframe)
1048 {
1049         return server->to_ram(vframe);
1050 }
1051
1052 int PluginClient::get_total_buffers()
1053 {
1054         return total_in_buffers;
1055 }
1056
1057 int PluginClient::get_buffer_size()
1058 {
1059         return in_buffer_size;
1060 }
1061
1062 int PluginClient::get_project_smp()
1063 {
1064 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
1065         return smp;
1066 }
1067
1068 const char* PluginClient::get_defaultdir()
1069 {
1070         return File::get_plugin_path();
1071 }
1072
1073
1074 int PluginClient::send_hide_gui()
1075 {
1076 // Stop the GUI server and delete GUI messages
1077         client_gui_on = 0;
1078         return 0;
1079 }
1080
1081 int PluginClient::send_configure_change()
1082 {
1083         if(server->mwindow)
1084                 server->mwindow->undo->update_undo_before(_("tweek"), this);
1085 #ifdef USE_KEYFRAME_SPANNING
1086         EDL *edl = server->edl;
1087         Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
1088         KeyFrames *keyframes = plugin ? plugin->keyframes : 0;
1089         KeyFrame keyframe(edl, keyframes);
1090         save_data(&keyframe);
1091         server->apply_keyframe(plugin, &keyframe);
1092 #else
1093         KeyFrame* keyframe = server->get_keyframe();
1094 // Call save routine in plugin
1095         save_data(keyframe);
1096 #endif
1097         if(server->mwindow)
1098                 server->mwindow->undo->update_undo_after(_("tweek"), LOAD_AUTOMATION);
1099         server->sync_parameters();
1100         return 0;
1101 }
1102
1103 // virtual default spanning keyframe update.  If a range is selected,
1104 // then changed parameters are copied to (prev + selected) keyframes.
1105 // redefine per client for custom keyframe updates, see tracer, sketcher, crikey
1106 void PluginClient::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
1107 {
1108         src->span_keyframes(start, end);
1109 }
1110
1111
1112 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
1113 {
1114         if(is_local) position = local_to_edl(position);
1115         return server->get_prev_keyframe(position);
1116 }
1117
1118 KeyFrame* PluginClient::get_next_keyframe(int64_t position, int is_local)
1119 {
1120         if(is_local) position = local_to_edl(position);
1121         return server->get_next_keyframe(position);
1122 }
1123
1124 void PluginClient::get_camera(float *x, float *y, float *z, int64_t position)
1125 {
1126         server->get_camera(x, y, z, position, direction);
1127 }
1128
1129 void PluginClient::get_projector(float *x, float *y, float *z, int64_t position)
1130 {
1131         server->get_projector(x, y, z, position, direction);
1132 }
1133
1134
1135 void PluginClient::output_to_track(float ox, float oy, float &tx, float &ty)
1136 {
1137         float projector_x, projector_y, projector_z;
1138         int64_t position = get_source_position();
1139         get_projector(&projector_x, &projector_y, &projector_z, position);
1140         EDL *edl = get_edl();
1141         projector_x += edl->session->output_w / 2;
1142         projector_y += edl->session->output_h / 2;
1143         Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
1144         Track *track = plugin ? plugin->track : 0;
1145         int track_w = track ? track->track_w : edl->session->output_w;
1146         int track_h = track ? track->track_h : edl->session->output_h;
1147         tx = (ox - projector_x) / projector_z + track_w / 2;
1148         ty = (oy - projector_y) / projector_z + track_h / 2;
1149 }
1150
1151 void PluginClient::track_to_output(float tx, float ty, float &ox, float &oy)
1152 {
1153         float projector_x, projector_y, projector_z;
1154         int64_t position = get_source_position();
1155         get_projector(&projector_x, &projector_y, &projector_z, position);
1156         EDL *edl = get_edl();
1157         projector_x += edl->session->output_w / 2;
1158         projector_y += edl->session->output_h / 2;
1159         Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
1160         Track *track = plugin ? plugin->track : 0;
1161         int track_w = track ? track->track_w : edl->session->output_w;
1162         int track_h = track ? track->track_h : edl->session->output_h;
1163         ox = (tx - track_w / 2) * projector_z + projector_x;
1164         oy = (ty - track_h / 2) * projector_z + projector_y;
1165 }
1166
1167
1168 EDL *PluginClient::get_edl()
1169 {
1170         return server->mwindow ? server->mwindow->edl : server->edl;
1171 }
1172
1173 int PluginClient::gui_open()
1174 {
1175         return server->gui_open();
1176 }
1177
1178