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"
29 #include "filesystem.h"
31 #include "localsession.h"
34 #include "pluginclient.h"
35 #include "pluginserver.h"
36 #include "preferences.h"
37 #include "transportque.inc"
48 PluginClientThread::PluginClientThread(PluginClient *client)
51 this->client = client;
53 init_complete = new Condition(0, "PluginClientThread::init_complete");
56 PluginClientThread::~PluginClientThread()
58 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
60 //printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
65 void PluginClientThread::run()
69 if(client->window_x < 0) client->window_x = info.get_abs_cursor_x();
70 if(client->window_y < 0) client->window_y = info.get_abs_cursor_y();
71 window = client->new_window();
75 window->lock_window("PluginClientThread::run");
76 window->create_objects();
77 window->unlock_window();
79 /* Only set it here so tracking doesn't update it until everything is created. */
80 client->thread = this;
81 init_complete->unlock();
83 result = window->run_window();
84 window->lock_window("PluginClientThread::run");
85 //printf("PluginClientThread::run %p %d\n", this, __LINE__);
86 window->hide_window(1);
87 window->unlock_window();
90 // Can't save defaults in the destructor because it's not called immediately
92 /* if(client->defaults) */ client->save_defaults_xml();
93 /* This is needed when the GUI is closed from itself */
94 if(result) client->client_side_close();
99 client->thread = this;
100 init_complete->unlock();
104 BC_WindowBase* PluginClientThread::get_window()
109 PluginClient* PluginClientThread::get_client()
119 PluginClientFrame::PluginClientFrame(int data_size,
123 this->data_size = data_size;
125 this->period_n = period_n;
126 this->period_d = period_d;
129 PluginClientFrame::~PluginClientFrame()
138 PluginClientWindow::PluginClientWindow(PluginClient *client,
144 : BC_Window(client->gui_string,
145 client->window_x /* - w / 2 */,
146 client->window_y /* - h / 2 */,
155 this->client = client;
158 PluginClientWindow::PluginClientWindow(const char *title,
180 PluginClientWindow::~PluginClientWindow()
185 int PluginClientWindow::translation_event()
189 client->window_x = get_x();
190 client->window_y = get_y();
196 int PluginClientWindow::close_event()
198 /* Set result to 1 to indicate a client side close */
207 PluginClient::PluginClient(PluginServer *server)
210 this->server = server;
211 smp = server->preferences->processors;
213 update_timer = new Timer;
214 // Virtual functions don't work here.
217 PluginClient::~PluginClient()
219 // Delete the GUI thread. The GUI must be hidden with hide_gui first.
226 // Virtual functions don't work here.
227 if(defaults) delete defaults;
228 frame_buffer.remove_all_objects();
232 int PluginClient::reset()
241 realtime_priority = 0;
243 total_in_buffers = 0;
244 total_out_buffers = 0;
248 direction = PLAY_FORWARD;
255 void PluginClient::hide_gui()
257 if(thread && thread->window)
259 //printf("PluginClient::delete_thread %d\n", __LINE__);
260 /* This is needed when the GUI is closed from elsewhere than itself */
261 /* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */
262 /* Thread join will wait if this was not called from the thread itself or go on if it was */
263 thread->window->lock_window("PluginClient::hide_gui");
264 thread->window->set_done(0);
265 //printf("PluginClient::hide_gui %d thread->window=%p\n", __LINE__, thread->window);
266 thread->window->unlock_window();
267 //printf("PluginClient::delete_thread %d\n", __LINE__);
271 // For realtime plugins initialize buffers
272 int PluginClient::plugin_init_realtime(int realtime_priority,
273 int total_in_buffers,
277 // Get parameters for all
278 master_gui_on = get_gui_status();
282 // get parameters depending on video or audio
283 init_realtime_parameters();
285 this->realtime_priority = realtime_priority;
286 this->total_in_buffers = this->total_out_buffers = total_in_buffers;
287 this->out_buffer_size = this->in_buffer_size = buffer_size;
291 int PluginClient::plugin_start_loop(int64_t start,
296 this->source_start = start;
297 this->total_len = end - start;
300 this->in_buffer_size = this->out_buffer_size = buffer_size;
301 this->total_in_buffers = this->total_out_buffers = total_buffers;
306 int PluginClient::plugin_process_loop()
308 return process_loop();
311 int PluginClient::plugin_stop_loop()
316 MainProgressBar* PluginClient::start_progress(char *string, int64_t length)
318 return server->start_progress(string, length);
322 // Non realtime parameters
323 int PluginClient::plugin_get_parameters()
325 int result = get_parameters();
326 if(defaults) save_defaults();
330 // ========================= main loop
332 int PluginClient::is_multichannel() { return 0; }
333 int PluginClient::is_synthesis() { return 0; }
334 int PluginClient::is_realtime() { return 0; }
335 int PluginClient::is_fileio() { return 0; }
336 int PluginClient::delete_buffer_ptrs() { return 0; }
337 const char* PluginClient::plugin_title() { return _("Untitled"); }
339 Theme* PluginClient::new_theme() { return 0; }
341 int PluginClient::load_configuration()
346 Theme* PluginClient::get_theme()
348 return server->get_theme();
351 int PluginClient::show_gui()
353 load_configuration();
354 thread = new PluginClientThread(this);
356 thread->init_complete->lock("PluginClient::show_gui");
357 // Must wait before sending any hide_gui
360 thread->window->init_wait();
369 void PluginClient::raise_window()
371 if(thread && thread->window)
373 thread->window->lock_window("PluginClient::raise_window");
374 thread->window->raise_window();
375 thread->window->flush();
376 thread->window->unlock_window();
380 int PluginClient::set_string()
384 thread->window->lock_window("PluginClient::set_string");
385 thread->window->set_title(gui_string);
386 thread->window->unlock_window();
395 void PluginClient::begin_process_buffer()
397 // Delete all unused GUI frames
398 frame_buffer.remove_all_objects();
402 void PluginClient::end_process_buffer()
404 if(frame_buffer.size())
412 void PluginClient::plugin_update_gui()
417 // Delete unused GUI frames
418 while(frame_buffer.size() > MAX_FRAME_BUFFER)
419 frame_buffer.remove_object_number(0);
423 void PluginClient::update_gui()
427 int PluginClient::get_gui_update_frames()
429 if(frame_buffer.size())
431 PluginClientFrame *frame = frame_buffer.get(0);
432 int total_frames = update_timer->get_difference() *
436 if(total_frames) update_timer->subtract(total_frames *
441 // printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n",
443 // update_timer->get_difference(),
444 // frame->period_n * 1000 / frame->period_d,
446 // frame_buffer.size());
449 for(int i = 0; i < frame_buffer.size(); i++)
450 if(frame_buffer.get(i)->force) total_frames++;
451 total_frames = MIN(frame_buffer.size(), total_frames);
462 PluginClientFrame* PluginClient::get_gui_frame()
464 if(frame_buffer.size())
466 PluginClientFrame *frame = frame_buffer.get(0);
467 frame_buffer.remove_number(0);
476 void PluginClient::add_gui_frame(PluginClientFrame *frame)
478 frame_buffer.append(frame);
481 void PluginClient::send_render_gui()
483 server->send_render_gui(&frame_buffer);
486 void PluginClient::send_render_gui(void *data)
488 server->send_render_gui(data);
491 void PluginClient::send_render_gui(void *data, int size)
493 server->send_render_gui(data, size);
496 void PluginClient::plugin_render_gui(void *data, int size)
498 render_gui(data, size);
502 void PluginClient::plugin_render_gui(void *data)
507 void PluginClient::render_gui(void *data)
511 thread->get_window()->lock_window("PluginClient::render_gui");
513 // Set all previous frames to draw immediately
514 for(int i = 0; i < frame_buffer.size(); i++)
515 frame_buffer.get(i)->force = 1;
517 ArrayList<PluginClientFrame*> *src =
518 (ArrayList<PluginClientFrame*>*)data;
520 // Shift GUI data to GUI client
523 this->frame_buffer.append(src->get(0));
524 src->remove_number(0);
527 // Start the timer for the current buffer
528 update_timer->update();
529 thread->get_window()->unlock_window();
533 void PluginClient::render_gui(void *data, int size)
535 printf("PluginClient::render_gui %d\n", __LINE__);
545 int PluginClient::is_audio() { return 0; }
546 int PluginClient::is_video() { return 0; }
547 int PluginClient::is_theme() { return 0; }
548 int PluginClient::uses_gui() { return 1; }
549 int PluginClient::is_transition() { return 0; }
550 int PluginClient::load_defaults()
552 // printf("PluginClient::load_defaults undefined in %s.\n", plugin_title());
556 int PluginClient::save_defaults()
559 // printf("PluginClient::save_defaults undefined in %s.\n", plugin_title());
563 void PluginClient::load_defaults_xml()
565 char path[BCTEXTLEN];
566 server->get_defaults_path(path);
568 fs.complete_path(path);
570 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
572 KeyFrame temp_keyframe;
573 FILE *fd = fopen(path, "r");
576 char *data = temp_keyframe.get_data();
577 int data_size = fread(data, 1, MESSAGESIZE-1, fd);
578 if( data_size < 0 ) data_size = 0;
581 // Get window extents
583 for(int i = 0; i < data_size - 8; i++)
585 if(data[i] == '<') break;
590 window_x = atoi(data + i);
595 window_y = atoi(data + i);
598 while(i < data_size && isdigit(data[i])) i++;
602 read_data(&temp_keyframe);
608 //printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
611 void PluginClient::save_defaults_xml()
613 char path[BCTEXTLEN];
614 server->get_defaults_path(path);
616 fs.complete_path(path);
619 KeyFrame temp_keyframe;
621 save_data(&temp_keyframe);
622 FILE *fd = fopen(path, "w");
625 fprintf(fd, "%d\n%d\n", window_x, window_y);
626 if(!fwrite(temp_keyframe.get_data(), strlen(temp_keyframe.get_data()), 1, fd))
628 fprintf(stderr, "PluginClient::save_defaults_xml %d \"%s\" %d bytes: %s\n",
631 (int)strlen(temp_keyframe.get_data()),
640 int PluginClient::is_defaults()
642 return using_defaults;
645 BC_Hash* PluginClient::get_defaults()
649 PluginClientThread* PluginClient::get_thread()
654 BC_WindowBase* PluginClient::new_window()
656 printf("PluginClient::new_window undefined in %s.\n", plugin_title());
659 int PluginClient::get_parameters() { return 0; }
660 int PluginClient::get_samplerate() { return get_project_samplerate(); }
661 double PluginClient::get_framerate() { return get_project_framerate(); }
662 int PluginClient::init_realtime_parameters() { return 0; }
663 int PluginClient::delete_nonrealtime_parameters() { return 0; }
664 int PluginClient::start_loop() { return 0; };
665 int PluginClient::process_loop() { return 0; };
666 int PluginClient::stop_loop() { return 0; };
668 void PluginClient::set_interactive()
673 int64_t PluginClient::get_in_buffers(int64_t recommended_size)
675 return recommended_size;
678 int64_t PluginClient::get_out_buffers(int64_t recommended_size)
680 return recommended_size;
683 int PluginClient::get_gui_status()
685 return server->get_gui_status();
688 int PluginClient::start_plugin()
690 printf(_("No processing defined for this plugin.\n"));
694 // close event from client side
695 void PluginClient::client_side_close()
697 // Last command executed
698 server->client_side_close();
701 int PluginClient::stop_gui_client()
703 if(!client_gui_on) return 0;
708 int PluginClient::get_project_samplerate()
710 return server->get_project_samplerate();
713 double PluginClient::get_project_framerate()
715 return server->get_project_framerate();
719 void PluginClient::update_display_title()
721 server->generate_display_title(gui_string);
725 char* PluginClient::get_gui_string()
731 char* PluginClient::get_path()
736 char* PluginClient::get_plugin_dir()
738 return server->preferences->plugin_dir;
741 int PluginClient::set_string_client(char *string)
743 strcpy(gui_string, string);
749 int PluginClient::get_interpolation_type()
751 return server->get_interpolation_type();
755 float PluginClient::get_red()
758 return server->mwindow->edl->local_session->red;
761 return server->edl->local_session->red;
766 float PluginClient::get_green()
769 return server->mwindow->edl->local_session->green;
772 return server->edl->local_session->green;
777 float PluginClient::get_blue()
780 return server->mwindow->edl->local_session->blue;
783 return server->edl->local_session->blue;
790 int64_t PluginClient::get_source_position()
792 return source_position;
795 int64_t PluginClient::get_source_start()
800 int64_t PluginClient::get_total_len()
805 int PluginClient::get_direction()
811 int64_t PluginClient::local_to_edl(int64_t position)
816 int64_t PluginClient::edl_to_local(int64_t position)
821 int PluginClient::get_use_opengl()
823 return server->get_use_opengl();
826 int PluginClient::get_total_buffers()
828 return total_in_buffers;
831 int PluginClient::get_buffer_size()
833 return in_buffer_size;
836 int PluginClient::get_project_smp()
838 //printf("PluginClient::get_project_smp %d %d\n", __LINE__, smp);
842 const char* PluginClient::get_defaultdir()
848 int PluginClient::send_hide_gui()
850 // Stop the GUI server and delete GUI messages
855 int PluginClient::send_configure_change()
858 server->mwindow->undo->update_undo_before(_("tweek"), this);
859 #ifdef USE_KEYFRAME_SPANNING
861 keyframe.copy_from(server->get_keyframe());
862 save_data(&keyframe);
863 server->apply_keyframe(&keyframe);
865 KeyFrame* keyframe = server->get_keyframe();
866 // Call save routine in plugin
870 server->mwindow->undo->update_undo_after(_("tweek"), LOAD_AUTOMATION);
871 server->sync_parameters();
876 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
878 if(is_local) position = local_to_edl(position);
879 return server->get_prev_keyframe(position);
882 KeyFrame* PluginClient::get_next_keyframe(int64_t position, int is_local)
884 if(is_local) position = local_to_edl(position);
885 return server->get_next_keyframe(position);
888 void PluginClient::get_camera(float *x, float *y, float *z, int64_t position)
890 server->get_camera(x, y, z, position, direction);
893 void PluginClient::get_projector(float *x, float *y, float *z, int64_t position)
895 server->get_projector(x, y, z, position, direction);
899 EDLSession* PluginClient::get_edlsession()
902 return server->edl->session;
906 int PluginClient::gui_open()
908 return server->gui_open();