4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "bcdisplayinfo.h"
24 #include "bcsignals.h"
26 #include "condition.h"
30 #include "edlsession.h"
32 #include "filesystem.h"
34 #include "indexable.h"
36 #include "localsession.h"
40 #include "pluginclient.h"
41 #include "pluginserver.h"
42 #include "preferences.h"
44 #include "transportque.inc"
55 PluginClientThread::PluginClientThread(PluginClient *client)
58 this->client = client;
60 init_complete = new Condition(0, "PluginClientThread::init_complete");
63 PluginClientThread::~PluginClientThread()
66 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
67 delete window; window = 0;
68 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
72 void PluginClientThread::run()
76 if(client->window_x < 0) client->window_x = info.get_abs_cursor_x();
77 if(client->window_y < 0) client->window_y = info.get_abs_cursor_y();
79 window = (PluginClientWindow*)client->new_window();
82 window->lock_window("PluginClientThread::run");
83 window->create_objects();
84 VFrame *picon = client->server->get_picon();
85 if( picon ) window->set_icon(picon);
86 window->unlock_window();
88 /* Only set it here so tracking doesn't update it until everything is created. */
89 client->thread = this;
90 init_complete->unlock();
92 result = window->run_window();
93 window->lock_window("PluginClientThread::run");
94 //printf("PluginClientThread::run %p %d\n", this, __LINE__);
95 window->hide_window(1);
96 window->unlock_window();
97 window->done_event(result);
98 // Can't save defaults in the destructor because it's not called immediately
100 /* if(client->defaults) */ client->save_defaults_xml();
101 /* This is needed when the GUI is closed from itself */
102 if(result) client->client_side_close();
107 client->thread = this;
108 init_complete->unlock();
112 BC_WindowBase* PluginClientThread::get_window()
117 PluginClient* PluginClientThread::get_client()
127 PluginClientFrame::PluginClientFrame(int data_size,
131 this->data_size = data_size;
133 this->period_n = period_n;
134 this->period_d = period_d;
137 PluginClientFrame::~PluginClientFrame()
146 PluginClientWindow::PluginClientWindow(PluginClient *client,
147 int w, int h, int min_w, int min_h, int allow_resize)
148 : BC_Window(client->gui_string,
149 client->window_x /* - w / 2 */,
150 client->window_y /* - h / 2 */,
151 (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
152 (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
155 this->client = client;
158 PluginClientWindow::PluginClientWindow(const char *title,
159 int x, int y, int w, int h, int min_w, int min_h, int allow_resize)
160 : BC_Window(title, x, y,
161 (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
162 (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
168 PluginClientWindow::~PluginClientWindow()
173 int PluginClientWindow::translation_event()
177 client->window_x = get_x();
178 client->window_y = get_y();
184 int PluginClientWindow::close_event()
186 /* Set result to 1 to indicate a client side close */
195 PluginClient::PluginClient(PluginServer *server)
198 this->server = server;
199 smp = server->preferences->project_smp;
201 update_timer = new Timer;
202 // Virtual functions don't work here.
205 PluginClient::~PluginClient()
213 // Virtual functions don't work here.
214 if(defaults) delete defaults;
215 frame_buffer.remove_all_objects();
219 int PluginClient::reset()
228 realtime_priority = 0;
230 total_in_buffers = 0;
231 total_out_buffers = 0;
235 direction = PLAY_FORWARD;
242 void PluginClient::hide_gui()
244 if(thread && thread->window)
246 //printf("PluginClient::delete_thread %d\n", __LINE__);
247 /* This is needed when the GUI is closed from elsewhere than itself */
248 /* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */
249 /* Thread join will wait if this was not called from the thread itself or go on if it was */
250 thread->window->lock_window("PluginClient::hide_gui");
251 thread->window->set_done(0);
252 //printf("PluginClient::hide_gui %d thread->window=%p\n", __LINE__, thread->window);
253 thread->window->unlock_window();
257 // For realtime plugins initialize buffers
258 int PluginClient::plugin_init_realtime(int realtime_priority,
259 int total_in_buffers,
263 // Get parameters for all
264 master_gui_on = get_gui_status();
268 // get parameters depending on video or audio
269 init_realtime_parameters();
271 this->realtime_priority = realtime_priority;
272 this->total_in_buffers = this->total_out_buffers = total_in_buffers;
273 this->out_buffer_size = this->in_buffer_size = buffer_size;
277 int PluginClient::plugin_start_loop(int64_t start,
282 //printf("PluginClient::plugin_start_loop %d %ld %ld %ld %d\n",
283 // __LINE__, start, end, buffer_size, total_buffers);
284 this->source_start = start;
285 this->total_len = end - start;
288 this->in_buffer_size = this->out_buffer_size = buffer_size;
289 this->total_in_buffers = this->total_out_buffers = total_buffers;
294 int PluginClient::plugin_process_loop()
296 return process_loop();
299 int PluginClient::plugin_stop_loop()
304 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
306 return server->start_progress(string, length);
310 // Non realtime parameters
311 int PluginClient::plugin_get_parameters()
313 int result = get_parameters();
314 if(defaults) save_defaults();
318 // ========================= main loop
320 int PluginClient::is_multichannel() { return 0; }
321 int PluginClient::is_synthesis() { return 0; }
322 int PluginClient::is_realtime() { return 0; }
323 int PluginClient::is_fileio() { return 0; }
324 int PluginClient::delete_buffer_ptrs() { return 0; }
325 const char* PluginClient::plugin_title() { return _("Untitled"); }
327 Theme* PluginClient::new_theme() { return 0; }
329 int PluginClient::load_configuration()
334 Theme* PluginClient::get_theme()
336 return server->get_theme();
339 int PluginClient::show_gui()
341 load_configuration();
342 thread = new PluginClientThread(this);
344 thread->init_complete->lock("PluginClient::show_gui");
345 // Must wait before sending any hide_gui
346 if( !thread->window ) return 1;
347 thread->window->init_wait();
351 void PluginClient::raise_window()
353 if(thread && thread->window)
355 thread->window->lock_window("PluginClient::raise_window");
356 thread->window->raise_window();
357 thread->window->flush();
358 thread->window->unlock_window();
362 int PluginClient::set_string()
366 thread->window->lock_window("PluginClient::set_string");
367 thread->window->put_title(gui_string);
368 thread->window->unlock_window();
377 void PluginClient::begin_process_buffer()
379 // Delete all unused GUI frames
380 frame_buffer.remove_all_objects();
384 void PluginClient::end_process_buffer()
386 if(frame_buffer.size())
394 void PluginClient::plugin_update_gui()
399 // Delete unused GUI frames
400 while(frame_buffer.size() > MAX_FRAME_BUFFER)
401 frame_buffer.remove_object_number(0);
405 void PluginClient::update_gui()
409 int PluginClient::get_gui_update_frames()
411 if(frame_buffer.size())
413 PluginClientFrame *frame = frame_buffer.get(0);
414 int total_frames = update_timer->get_difference() *
418 if(total_frames) update_timer->subtract(total_frames *
423 // printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n",
425 // update_timer->get_difference(),
426 // frame->period_n * 1000 / frame->period_d,
428 // frame_buffer.size());
431 for(int i = 0; i < frame_buffer.size(); i++)
432 if(frame_buffer.get(i)->force) total_frames++;
433 total_frames = MIN(frame_buffer.size(), total_frames);
444 PluginClientFrame* PluginClient::get_gui_frame()
446 if(frame_buffer.size())
448 PluginClientFrame *frame = frame_buffer.get(0);
449 frame_buffer.remove_number(0);
458 void PluginClient::add_gui_frame(PluginClientFrame *frame)
460 frame_buffer.append(frame);
463 void PluginClient::send_render_gui()
465 server->send_render_gui(&frame_buffer);
468 void PluginClient::send_render_gui(void *data)
470 server->send_render_gui(data);
473 void PluginClient::send_render_gui(void *data, int size)
475 server->send_render_gui(data, size);
478 void PluginClient::plugin_render_gui(void *data, int size)
480 render_gui(data, size);
484 void PluginClient::plugin_render_gui(void *data)
489 void PluginClient::render_gui(void *data)
493 thread->get_window()->lock_window("PluginClient::render_gui");
495 // Set all previous frames to draw immediately
496 for(int i = 0; i < frame_buffer.size(); i++)
497 frame_buffer.get(i)->force = 1;
499 ArrayList<PluginClientFrame*> *src =
500 (ArrayList<PluginClientFrame*>*)data;
502 // Shift GUI data to GUI client
505 this->frame_buffer.append(src->get(0));
506 src->remove_number(0);
509 // Start the timer for the current buffer
510 update_timer->update();
511 thread->get_window()->unlock_window();
515 void PluginClient::render_gui(void *data, int size)
517 printf("PluginClient::render_gui %d\n", __LINE__);
527 int PluginClient::is_audio() { return 0; }
528 int PluginClient::is_video() { return 0; }
529 int PluginClient::is_theme() { return 0; }
530 int PluginClient::uses_gui() { return 1; }
531 int PluginClient::is_transition() { return 0; }
532 int PluginClient::load_defaults()
534 // printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
538 int PluginClient::save_defaults()
541 // printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
545 void PluginClient::load_defaults_xml()
547 char path[BCTEXTLEN];
548 server->get_defaults_path(path);
550 fs.complete_path(path);
552 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
557 int fd = open(path, O_RDONLY);
558 if( fd >= 0 && !fstat(fd, &st) ) {
559 int64_t sz = st.st_size;
560 data = new char[sz+1];
561 len = read(fd, data, sz);
564 if( data && len >= 0 ) {
566 // Get window extents
568 for( int state=0; i<len && state>=0; ++i ) {
569 if( !data[i] || data[i] == '<' ) break;
570 if( !isdigit(data[i]) ) continue;
572 window_x = atoi(data+i);
576 window_y = atoi(data+i);
579 while( i<len && isdigit(data[i]) ) ++i;
581 KeyFrame keyframe(data+i, len-i);
582 read_data(&keyframe);
587 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
590 void PluginClient::save_defaults_xml()
592 char path[BCTEXTLEN];
593 server->get_defaults_path(path);
595 fs.complete_path(path);
598 KeyFrame temp_keyframe;
599 save_data(&temp_keyframe);
601 const char *data = temp_keyframe.get_data();
602 int len = strlen(data);
603 FILE *fp = fopen(path, "w");
606 fprintf(fp, "%d\n%d\n", window_x, window_y);
607 if( len > 0 && !fwrite(data, len, 1, fp) ) {
608 fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
609 __LINE__, path, len, strerror(errno));
617 int PluginClient::is_defaults()
619 return using_defaults;
622 BC_Hash* PluginClient::get_defaults()
626 PluginClientThread* PluginClient::get_thread()
631 BC_WindowBase* PluginClient::new_window()
633 printf("PluginClient::new_window undefined in %s.\n", plugin_title());
636 int PluginClient::get_parameters() { return 0; }
637 int PluginClient::get_samplerate() { return get_project_samplerate(); }
638 double PluginClient::get_framerate() { return get_project_framerate(); }
639 int PluginClient::init_realtime_parameters() { return 0; }
640 int PluginClient::delete_nonrealtime_parameters() { return 0; }
641 int PluginClient::start_loop() { return 0; };
642 int PluginClient::process_loop() { return 0; };
643 int PluginClient::stop_loop() { return 0; };
645 void PluginClient::set_interactive()
650 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
652 return recommended_size;
655 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
657 return recommended_size;
660 int PluginClient::get_gui_status()
662 return server->get_gui_status();
665 // close event from client side
666 void PluginClient::client_side_close()
668 // Last command executed
669 server->client_side_close();
672 int PluginClient::stop_gui_client()
674 if(!client_gui_on) return 0;
679 int PluginClient::get_project_samplerate()
681 return server->get_project_samplerate();
684 double PluginClient::get_project_framerate()
686 return server->get_project_framerate();
689 const char *PluginClient::get_source_path()
691 int64_t source_position = server->plugin->startproject;
692 Edit *edit = server->plugin->track->edits->editof(source_position,PLAY_FORWARD,0);
693 Indexable *indexable = edit ? edit->get_source() : 0;
694 return indexable ? indexable->path : 0;
698 void PluginClient::update_display_title()
700 server->generate_display_title(gui_string);
704 char* PluginClient::get_gui_string()
710 char* PluginClient::get_path()
715 char* PluginClient::get_plugin_dir()
717 return server->preferences->plugin_dir;
720 int PluginClient::set_string_client(char *string)
722 strcpy(gui_string, string);
728 int PluginClient::get_interpolation_type()
730 return server->get_interpolation_type();
734 float PluginClient::get_red()
736 EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
737 return !edl ? 0 : edl->local_session->use_max ?
738 edl->local_session->red_max :
739 edl->local_session->red;
742 float PluginClient::get_green()
744 EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
745 return !edl ? 0 : edl->local_session->use_max ?
746 edl->local_session->green_max :
747 edl->local_session->green;
750 float PluginClient::get_blue()
752 EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
753 return !edl ? 0 : edl->local_session->use_max ?
754 edl->local_session->blue_max :
755 edl->local_session->blue;
759 int64_t PluginClient::get_source_position()
761 return source_position;
764 int64_t PluginClient::get_source_start()
769 int64_t PluginClient::get_total_len()
774 int PluginClient::get_direction()
780 int64_t PluginClient::local_to_edl(int64_t position)
785 int64_t PluginClient::edl_to_local(int64_t position)
790 int PluginClient::get_use_opengl()
792 return server->get_use_opengl();
795 int PluginClient::get_total_buffers()
797 return total_in_buffers;
800 int PluginClient::get_buffer_size()
802 return in_buffer_size;
805 int PluginClient::get_project_smp()
807 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
811 const char* PluginClient::get_defaultdir()
813 return File::get_plugin_path();
817 int PluginClient::send_hide_gui()
819 // Stop the GUI server and delete GUI messages
824 int PluginClient::send_configure_change()
827 server->mwindow->undo->update_undo_before(_("tweek"), this);
828 #ifdef USE_KEYFRAME_SPANNING
830 save_data(&keyframe);
831 server->apply_keyframe(&keyframe);
833 KeyFrame* keyframe = server->get_keyframe();
834 // Call save routine in plugin
838 server->mwindow->undo->update_undo_after(_("tweek"), LOAD_AUTOMATION);
839 server->sync_parameters();
844 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
846 if(is_local) position = local_to_edl(position);
847 return server->get_prev_keyframe(position);
850 KeyFrame* PluginClient::get_next_keyframe(int64_t position, int is_local)
852 if(is_local) position = local_to_edl(position);
853 return server->get_next_keyframe(position);
856 void PluginClient::get_camera(float *x, float *y, float *z, int64_t position)
858 server->get_camera(x, y, z, position, direction);
861 void PluginClient::get_projector(float *x, float *y, float *z, int64_t position)
863 server->get_projector(x, y, z, position, direction);
867 EDLSession* PluginClient::get_edlsession()
870 return server->edl->session;
874 int PluginClient::gui_open()
876 return server->gui_open();