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