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"
28 #include "edlsession.h"
30 #include "filesystem.h"
32 #include "localsession.h"
35 #include "pluginclient.h"
36 #include "pluginserver.h"
37 #include "preferences.h"
38 #include "transportque.inc"
49 PluginClientThread::PluginClientThread(PluginClient *client)
52 this->client = client;
54 init_complete = new Condition(0, "PluginClientThread::init_complete");
57 PluginClientThread::~PluginClientThread()
60 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
61 delete window; window = 0;
62 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
66 void PluginClientThread::run()
70 if(client->window_x < 0) client->window_x = info.get_abs_cursor_x();
71 if(client->window_y < 0) client->window_y = info.get_abs_cursor_y();
73 window = client->new_window();
76 window->lock_window("PluginClientThread::run");
77 window->create_objects();
78 window->unlock_window();
80 /* Only set it here so tracking doesn't update it until everything is created. */
81 client->thread = this;
82 init_complete->unlock();
84 result = window->run_window();
85 window->lock_window("PluginClientThread::run");
86 //printf("PluginClientThread::run %p %d\n", this, __LINE__);
87 window->hide_window(1);
88 window->unlock_window();
89 // Can't save defaults in the destructor because it's not called immediately
91 /* if(client->defaults) */ client->save_defaults_xml();
92 /* This is needed when the GUI is closed from itself */
93 if(result) client->client_side_close();
98 client->thread = this;
99 init_complete->unlock();
103 BC_WindowBase* PluginClientThread::get_window()
108 PluginClient* PluginClientThread::get_client()
118 PluginClientFrame::PluginClientFrame(int data_size,
122 this->data_size = data_size;
124 this->period_n = period_n;
125 this->period_d = period_d;
128 PluginClientFrame::~PluginClientFrame()
137 PluginClientWindow::PluginClientWindow(PluginClient *client,
143 : BC_Window(client->gui_string,
144 client->window_x /* - w / 2 */,
145 client->window_y /* - h / 2 */,
146 w, h, min_w, min_h, allow_resize, 0, 1)
148 this->client = client;
151 PluginClientWindow::PluginClientWindow(const char *title,
152 int x, int y, int w, int h, int min_w, int min_h, int allow_resize)
153 : BC_Window(title, x, y, w, h, min_w, min_h, allow_resize, 0, 1)
158 PluginClientWindow::~PluginClientWindow()
163 int PluginClientWindow::translation_event()
167 client->window_x = get_x();
168 client->window_y = get_y();
174 int PluginClientWindow::close_event()
176 /* Set result to 1 to indicate a client side close */
185 PluginClient::PluginClient(PluginServer *server)
188 this->server = server;
189 smp = server->preferences->processors;
191 update_timer = new Timer;
192 // Virtual functions don't work here.
195 PluginClient::~PluginClient()
197 // Delete the GUI thread. The GUI must be hidden with hide_gui first.
200 // Virtual functions don't work here.
201 if(defaults) delete defaults;
202 frame_buffer.remove_all_objects();
206 int PluginClient::reset()
215 realtime_priority = 0;
217 total_in_buffers = 0;
218 total_out_buffers = 0;
222 direction = PLAY_FORWARD;
229 void PluginClient::hide_gui()
231 if(thread && thread->window)
233 //printf("PluginClient::delete_thread %d\n", __LINE__);
234 /* This is needed when the GUI is closed from elsewhere than itself */
235 /* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */
236 /* Thread join will wait if this was not called from the thread itself or go on if it was */
237 thread->window->lock_window("PluginClient::hide_gui");
238 thread->window->set_done(0);
239 //printf("PluginClient::hide_gui %d thread->window=%p\n", __LINE__, thread->window);
240 thread->window->unlock_window();
241 //printf("PluginClient::delete_thread %d\n", __LINE__);
245 // For realtime plugins initialize buffers
246 int PluginClient::plugin_init_realtime(int realtime_priority,
247 int total_in_buffers,
251 // Get parameters for all
252 master_gui_on = get_gui_status();
256 // get parameters depending on video or audio
257 init_realtime_parameters();
259 this->realtime_priority = realtime_priority;
260 this->total_in_buffers = this->total_out_buffers = total_in_buffers;
261 this->out_buffer_size = this->in_buffer_size = buffer_size;
265 int PluginClient::plugin_start_loop(int64_t start,
270 //printf("PluginClient::plugin_start_loop %d %ld %ld %ld %d\n",
271 // __LINE__, start, end, buffer_size, total_buffers);
272 this->source_start = start;
273 this->total_len = end - start;
276 this->in_buffer_size = this->out_buffer_size = buffer_size;
277 this->total_in_buffers = this->total_out_buffers = total_buffers;
282 int PluginClient::plugin_process_loop()
284 return process_loop();
287 int PluginClient::plugin_stop_loop()
292 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
294 return server->start_progress(string, length);
298 // Non realtime parameters
299 int PluginClient::plugin_get_parameters()
301 int result = get_parameters();
302 if(defaults) save_defaults();
306 // ========================= main loop
308 int PluginClient::is_multichannel() { return 0; }
309 int PluginClient::is_synthesis() { return 0; }
310 int PluginClient::is_realtime() { return 0; }
311 int PluginClient::is_fileio() { return 0; }
312 int PluginClient::delete_buffer_ptrs() { return 0; }
313 const char* PluginClient::plugin_title() { return _("Untitled"); }
315 Theme* PluginClient::new_theme() { return 0; }
317 int PluginClient::load_configuration()
322 Theme* PluginClient::get_theme()
324 return server->get_theme();
327 int PluginClient::show_gui()
329 load_configuration();
330 thread = new PluginClientThread(this);
332 thread->init_complete->lock("PluginClient::show_gui");
333 // Must wait before sending any hide_gui
336 thread->window->init_wait();
345 void PluginClient::raise_window()
347 if(thread && thread->window)
349 thread->window->lock_window("PluginClient::raise_window");
350 thread->window->raise_window();
351 thread->window->flush();
352 thread->window->unlock_window();
356 int PluginClient::set_string()
360 thread->window->lock_window("PluginClient::set_string");
361 thread->window->put_title(gui_string);
362 thread->window->unlock_window();
371 void PluginClient::begin_process_buffer()
373 // Delete all unused GUI frames
374 frame_buffer.remove_all_objects();
378 void PluginClient::end_process_buffer()
380 if(frame_buffer.size())
388 void PluginClient::plugin_update_gui()
393 // Delete unused GUI frames
394 while(frame_buffer.size() > MAX_FRAME_BUFFER)
395 frame_buffer.remove_object_number(0);
399 void PluginClient::update_gui()
403 int PluginClient::get_gui_update_frames()
405 if(frame_buffer.size())
407 PluginClientFrame *frame = frame_buffer.get(0);
408 int total_frames = update_timer->get_difference() *
412 if(total_frames) update_timer->subtract(total_frames *
417 // printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n",
419 // update_timer->get_difference(),
420 // frame->period_n * 1000 / frame->period_d,
422 // frame_buffer.size());
425 for(int i = 0; i < frame_buffer.size(); i++)
426 if(frame_buffer.get(i)->force) total_frames++;
427 total_frames = MIN(frame_buffer.size(), total_frames);
438 PluginClientFrame* PluginClient::get_gui_frame()
440 if(frame_buffer.size())
442 PluginClientFrame *frame = frame_buffer.get(0);
443 frame_buffer.remove_number(0);
452 void PluginClient::add_gui_frame(PluginClientFrame *frame)
454 frame_buffer.append(frame);
457 void PluginClient::send_render_gui()
459 server->send_render_gui(&frame_buffer);
462 void PluginClient::send_render_gui(void *data)
464 server->send_render_gui(data);
467 void PluginClient::send_render_gui(void *data, int size)
469 server->send_render_gui(data, size);
472 void PluginClient::plugin_render_gui(void *data, int size)
474 render_gui(data, size);
478 void PluginClient::plugin_render_gui(void *data)
483 void PluginClient::render_gui(void *data)
487 thread->get_window()->lock_window("PluginClient::render_gui");
489 // Set all previous frames to draw immediately
490 for(int i = 0; i < frame_buffer.size(); i++)
491 frame_buffer.get(i)->force = 1;
493 ArrayList<PluginClientFrame*> *src =
494 (ArrayList<PluginClientFrame*>*)data;
496 // Shift GUI data to GUI client
499 this->frame_buffer.append(src->get(0));
500 src->remove_number(0);
503 // Start the timer for the current buffer
504 update_timer->update();
505 thread->get_window()->unlock_window();
509 void PluginClient::render_gui(void *data, int size)
511 printf("PluginClient::render_gui %d\n", __LINE__);
521 int PluginClient::is_audio() { return 0; }
522 int PluginClient::is_video() { return 0; }
523 int PluginClient::is_theme() { return 0; }
524 int PluginClient::uses_gui() { return 1; }
525 int PluginClient::is_transition() { return 0; }
526 int PluginClient::load_defaults()
528 // printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
532 int PluginClient::save_defaults()
535 // printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
539 void PluginClient::load_defaults_xml()
541 char path[BCTEXTLEN];
542 server->get_defaults_path(path);
544 fs.complete_path(path);
546 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
548 KeyFrame temp_keyframe;
549 FILE *fd = fopen(path, "r");
552 char *data = temp_keyframe.get_data();
553 int data_size = fread(data, 1, MESSAGESIZE-1, fd);
554 if( data_size < 0 ) data_size = 0;
557 // Get window extents
559 for(int i = 0; i < data_size - 8; i++)
561 if(data[i] == '<') break;
566 window_x = atoi(data + i);
571 window_y = atoi(data + i);
574 while(i < data_size && isdigit(data[i])) i++;
578 read_data(&temp_keyframe);
584 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
587 void PluginClient::save_defaults_xml()
589 char path[BCTEXTLEN];
590 server->get_defaults_path(path);
592 fs.complete_path(path);
595 KeyFrame temp_keyframe;
596 save_data(&temp_keyframe);
598 const char *data = temp_keyframe.get_data();
599 int len = strlen(data);
600 FILE *fp = fopen(path, "w");
603 fprintf(fp, "%d\n%d\n", window_x, window_y);
604 if( len > 0 && !fwrite(data, len, 1, fp) ) {
605 fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
606 __LINE__, path, len, strerror(errno));
614 int PluginClient::is_defaults()
616 return using_defaults;
619 BC_Hash* PluginClient::get_defaults()
623 PluginClientThread* PluginClient::get_thread()
628 BC_WindowBase* PluginClient::new_window()
630 printf("PluginClient::new_window undefined in %s.\n", plugin_title());
633 int PluginClient::get_parameters() { return 0; }
634 int PluginClient::get_samplerate() { return get_project_samplerate(); }
635 double PluginClient::get_framerate() { return get_project_framerate(); }
636 int PluginClient::init_realtime_parameters() { return 0; }
637 int PluginClient::delete_nonrealtime_parameters() { return 0; }
638 int PluginClient::start_loop() { return 0; };
639 int PluginClient::process_loop() { return 0; };
640 int PluginClient::stop_loop() { return 0; };
642 void PluginClient::set_interactive()
647 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
649 return recommended_size;
652 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
654 return recommended_size;
657 int PluginClient::get_gui_status()
659 return server->get_gui_status();
662 // close event from client side
663 void PluginClient::client_side_close()
665 // Last command executed
666 server->client_side_close();
669 int PluginClient::stop_gui_client()
671 if(!client_gui_on) return 0;
676 int PluginClient::get_project_samplerate()
678 return server->get_project_samplerate();
681 double PluginClient::get_project_framerate()
683 return server->get_project_framerate();
687 void PluginClient::update_display_title()
689 server->generate_display_title(gui_string);
693 char* PluginClient::get_gui_string()
699 char* PluginClient::get_path()
704 char* PluginClient::get_plugin_dir()
706 return server->preferences->plugin_dir;
709 int PluginClient::set_string_client(char *string)
711 strcpy(gui_string, string);
717 int PluginClient::get_interpolation_type()
719 return server->get_interpolation_type();
723 float PluginClient::get_red()
726 return server->mwindow->edl->local_session->red;
729 return server->edl->local_session->red;
734 float PluginClient::get_green()
737 return server->mwindow->edl->local_session->green;
740 return server->edl->local_session->green;
745 float PluginClient::get_blue()
748 return server->mwindow->edl->local_session->blue;
751 return server->edl->local_session->blue;
758 int64_t PluginClient::get_source_position()
760 return source_position;
763 int64_t PluginClient::get_source_start()
768 int64_t PluginClient::get_total_len()
773 int PluginClient::get_direction()
779 int64_t PluginClient::local_to_edl(int64_t position)
784 int64_t PluginClient::edl_to_local(int64_t position)
789 int PluginClient::get_use_opengl()
791 return server->get_use_opengl();
794 int PluginClient::get_total_buffers()
796 return total_in_buffers;
799 int PluginClient::get_buffer_size()
801 return in_buffer_size;
804 int PluginClient::get_project_smp()
806 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
810 const char* PluginClient::get_defaultdir()
812 return File::get_plugin_path();
816 int PluginClient::send_hide_gui()
818 // Stop the GUI server and delete GUI messages
823 int PluginClient::send_configure_change()
826 server->mwindow->undo->update_undo_before(_("tweek"), this);
827 #ifdef USE_KEYFRAME_SPANNING
829 keyframe.copy_from(server->get_keyframe());
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();