#include "bcdisplayinfo.h"
#include "bchash.h"
#include "bcsignals.h"
+#include "attachmentpoint.h"
#include "clip.h"
#include "condition.h"
#include "edits.h"
#include "pluginclient.h"
#include "pluginserver.h"
#include "preferences.h"
+#include "renderengine.h"
#include "track.h"
-#include "transportque.inc"
-
+#include "tracks.h"
+#include "transportque.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
#include <ctype.h>
#include <errno.h>
-#include <string.h>
-
+PluginClientFrame::PluginClientFrame()
+{
+ position = -1;
+}
+PluginClientFrame::~PluginClientFrame()
+{
+}
PluginClientThread::PluginClientThread(PluginClient *client)
PluginClientThread::~PluginClientThread()
{
- join();
-//printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
- delete window; window = 0;
-//printf("PluginClientThread::~PluginClientThread %p %d\n", this, __LINE__);
+ delete window;
delete init_complete;
}
window->lock_window("PluginClientThread::run");
//printf("PluginClientThread::run %p %d\n", this, __LINE__);
window->hide_window(1);
+ client->save_defaults_xml(); // needs window lock
window->unlock_window();
window->done_event(result);
-// Can't save defaults in the destructor because it's not called immediately
-// after closing.
- /* if(client->defaults) */ client->save_defaults_xml();
/* This is needed when the GUI is closed from itself */
if(result) client->client_side_close();
}
}
-
-
-
-
-PluginClientFrame::PluginClientFrame(int data_size,
- int period_n,
- int period_d)
-{
- this->data_size = data_size;
- force = 0;
- this->period_n = period_n;
- this->period_d = period_d;
-}
-
-PluginClientFrame::~PluginClientFrame()
-{
-
-}
-
-
-
-
-
PluginClientWindow::PluginClientWindow(PluginClient *client,
int w, int h, int min_w, int min_h, int allow_resize)
: BC_Window(client->gui_string,
- client->window_x /* - w / 2 */,
- client->window_y /* - h / 2 */,
- (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
- (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
- allow_resize, 0, 1)
+ client->window_x /* - w / 2 */, client->window_y /* - h / 2 */,
+ w, h, min_w, min_h, allow_resize, 0, 1)
{
this->client = client;
}
PluginClientWindow::PluginClientWindow(const char *title,
int x, int y, int w, int h, int min_w, int min_h, int allow_resize)
- : BC_Window(title, x, y,
- (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
- (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
- allow_resize, 0, 1)
+ : BC_Window(title, x, y, w, h, min_w, min_h, allow_resize, 0, 1)
{
this->client = 0;
}
return 1;
}
+void PluginClientWindow::param_updated()
+{
+ printf("PluginClientWindow::param_updated %d undefined\n", __LINE__);
+}
+
+//phyllis
+PluginParam::PluginParam(PluginClient *plugin, PluginClientWindow *gui,
+ int x1, int x2, int x3, int y, int text_w,
+ int *output_i, float *output_f, int *output_q,
+ const char *title, float min, float max)
+{
+ this->output_i = output_i;
+ this->output_f = output_f;
+ this->output_q = output_q;
+ this->title = cstrdup(title);
+ this->plugin = plugin;
+ this->gui = gui;
+ this->x1 = x1;
+ this->x2 = x2;
+ this->x3 = x3;
+ this->text_w = text_w;
+ this->y = y;
+ this->min = min;
+ this->max = max;
+ fpot = 0;
+ ipot = 0;
+ qpot = 0;
+ text = 0;
+ precision = 2;
+}
+PluginParam::~PluginParam()
+{
+ delete fpot;
+ delete ipot;
+ delete qpot;
+ delete text;
+ delete title;
+}
+
+
+void PluginParam::initialize()
+{
+ BC_Title *title_;
+ int y2 = y +
+ (BC_Pot::calculate_h() -
+ BC_Title::calculate_h(gui, _(title), MEDIUMFONT)) / 2;
+ gui->add_tool(title_ = new BC_Title(x1, y2, _(title)));
+
+ if(output_f)
+ {
+ gui->add_tool(fpot = new PluginFPot(this, x2, y));
+ }
+
+ if(output_i)
+ {
+ gui->add_tool(ipot = new PluginIPot(this, x2, y));
+ }
+
+ if(output_q)
+ {
+ gui->add_tool(qpot = new PluginQPot(this, x2, y));
+ }
+
+ int y3 = y +
+ (BC_Pot::calculate_h() -
+ BC_TextBox::calculate_h(gui, MEDIUMFONT, 1, 1)) / 2;
+ if(output_i)
+ {
+ gui->add_tool(text = new PluginText(this, x3, y3, *output_i));
+ }
+ if(output_f)
+ {
+ gui->add_tool(text = new PluginText(this, x3, y3, *output_f));
+ }
+ if(output_q)
+ {
+ gui->add_tool(text = new PluginText(this, x3, y3, *output_q));
+ }
+
+ set_precision(precision);
+}
+
+void PluginParam::update(int skip_text, int skip_pot)
+{
+ if(!skip_text)
+ {
+ if(output_i)
+ {
+ text->update((int64_t)*output_i);
+ }
+ if(output_q)
+ {
+ text->update((int64_t)*output_q);
+ }
+ if(output_f)
+ {
+ text->update((float)*output_f);
+ }
+ }
+
+ if(!skip_pot)
+ {
+ if(ipot)
+ {
+ ipot->update((int64_t)*output_i);
+ }
+ if(qpot)
+ {
+ qpot->update((int64_t)*output_q);
+ }
+ if(fpot)
+ {
+ fpot->update((float)*output_f);
+ }
+ }
+}
+
+void PluginParam::set_precision(int digits)
+{
+ this->precision = digits;
+ if(fpot)
+ {
+ if(text)
+ {
+ text->set_precision(digits);
+ }
+
+ fpot->set_precision(1.0f / pow(10, digits));
+ }
+}
+
+
+PluginFPot::PluginFPot(PluginParam *param, int x, int y)
+ : BC_FPot(x,
+ y,
+ *param->output_f,
+ param->min,
+ param->max)
+{
+ this->param = param;
+ set_use_caption(0);
+}
+
+int PluginFPot::handle_event()
+{
+ *param->output_f = get_value();
+ param->update(0, 1);
+ param->plugin->send_configure_change();
+ param->gui->param_updated();
+ return 1;
+}
+
+PluginIPot::PluginIPot(PluginParam *param, int x, int y)
+ : BC_IPot(x,
+ y,
+ *param->output_i,
+ (int)param->min,
+ (int)param->max)
+{
+ this->param = param;
+ set_use_caption(0);
+}
+
+int PluginIPot::handle_event()
+{
+ *param->output_i = get_value();
+ param->update(0, 1);
+ param->plugin->send_configure_change();
+ param->gui->param_updated();
+ return 1;
+}
+
+
+PluginQPot::PluginQPot(PluginParam *param, int x, int y)
+ : BC_QPot(x,
+ y,
+ *param->output_q)
+{
+ this->param = param;
+ set_use_caption(0);
+}
+
+int PluginQPot::handle_event()
+{
+ *param->output_q = get_value();
+ param->update(0, 1);
+ param->plugin->send_configure_change();
+ param->gui->param_updated();
+ return 1;
+}
+
+PluginText::PluginText(PluginParam *param, int x, int y, int value)
+ : BC_TextBox(x,
+ y,
+ param->text_w,
+ 1,
+ (int64_t)value,
+ 1,
+ MEDIUMFONT)
+{
+ this->param = param;
+}
+
+PluginText::PluginText(PluginParam *param, int x, int y, float value)
+ : BC_TextBox(x,
+ y,
+ param->text_w,
+ 1,
+ (float)value,
+ 1,
+ MEDIUMFONT,
+ param->precision)
+{
+ this->param = param;
+}
+
+int PluginText::handle_event()
+{
+ if(param->output_i)
+ {
+ *param->output_i = atoi(get_text());
+ }
+ if(param->output_f)
+ {
+ *param->output_f = atof(get_text());
+ }
+ if(param->output_q)
+ {
+ *param->output_q = atoi(get_text());
+ }
+ param->update(1, 0);
+ param->plugin->send_configure_change();
+ param->gui->param_updated();
+ return 1;
+}
PluginClient::PluginClient(PluginServer *server)
// Virtual functions don't work here.
if(defaults) delete defaults;
- frame_buffer.remove_all_objects();
delete update_timer;
}
{
if(thread && thread->window)
{
-//printf("PluginClient::delete_thread %d\n", __LINE__);
-/* This is needed when the GUI is closed from elsewhere than itself */
-/* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */
-/* Thread join will wait if this was not called from the thread itself or go on if it was */
thread->window->lock_window("PluginClient::hide_gui");
thread->window->set_done(0);
-//printf("PluginClient::hide_gui %d thread->window=%p\n", __LINE__, thread->window);
thread->window->unlock_window();
}
}
int PluginClient::is_synthesis() { return 0; }
int PluginClient::is_realtime() { return 0; }
int PluginClient::is_fileio() { return 0; }
-int PluginClient::delete_buffer_ptrs() { return 0; }
const char* PluginClient::plugin_title() { return _("Untitled"); }
Theme* PluginClient::new_theme() { return 0; }
-void PluginClient::begin_process_buffer()
+PluginClientFrames::PluginClientFrames()
+{
+ count = 0;
+}
+PluginClientFrames::~PluginClientFrames()
{
-// Delete all unused GUI frames
- frame_buffer.remove_all_objects();
}
+int PluginClientFrames::fwd_cmpr(PluginClientFrame *a, PluginClientFrame *b)
+{
+ double d = a->position - b->position;
+ return d < 0 ? -1 : !d ? 0 : 1;
+}
-void PluginClient::end_process_buffer()
+int PluginClientFrames::rev_cmpr(PluginClientFrame *a, PluginClientFrame *b)
{
- if(frame_buffer.size())
- {
- send_render_gui();
- }
+ double d = b->position - a->position;
+ return d < 0 ? -1 : !d ? 0 : 1;
}
+void PluginClientFrames::reset()
+{
+ destroy();
+ count = 0;
+}
+void PluginClientFrames::add_gui_frame(PluginClientFrame *frame)
+{
+ append(frame);
+ ++count;
+}
-void PluginClient::plugin_update_gui()
+void PluginClientFrames::concatenate(PluginClientFrames *frames)
{
+ concat(*frames);
+ count += frames->count;
+ frames->count = 0;
+}
- update_gui();
+void PluginClientFrames::sort_position(int dir)
+{
+// enforce order
+ if( dir == PLAY_REVERSE )
+ rev_sort();
+ else
+ fwd_sort();
+}
-// Delete unused GUI frames
- while(frame_buffer.size() > MAX_FRAME_BUFFER)
- frame_buffer.remove_object_number(0);
+// pop frames until buffer passes position=pos in direction=dir
+// dir==0, pop frame; pos<0, pop all frames
+// delete past frames, return last popped frame
+PluginClientFrame* PluginClientFrames::get_gui_frame(double pos, int dir)
+{
+ if( dir ) {
+ while( first != last ) {
+ if( pos >= 0 && dir*(first->next->position - pos) > 0 ) break;
+ delete first; --count;
+ }
+ }
+ PluginClientFrame *frame = first;
+ if( frame ) { remove_pointer(frame); --count; }
+ return frame;
+}
+PluginClientFrame* PluginClient::get_gui_frame(double pos, int dir)
+{
+ return client_frames.get_gui_frame(pos, dir);
+}
+PluginClientFrame* PluginClient::next_gui_frame()
+{
+ return client_frames.first;
+}
+
+
+void PluginClient::plugin_update_gui()
+{
+ update_gui();
}
void PluginClient::update_gui()
{
}
-int PluginClient::get_gui_update_frames()
+int PluginClient::pending_gui_frame()
{
- if(frame_buffer.size())
- {
- PluginClientFrame *frame = frame_buffer.get(0);
- int total_frames = update_timer->get_difference() *
- frame->period_d /
- frame->period_n /
- 1000;
- if(total_frames) update_timer->subtract(total_frames *
- frame->period_n *
- 1000 /
- frame->period_d);
-
-// printf("PluginClient::get_gui_update_frames %d %ld %d %d %d\n",
-// __LINE__,
-// update_timer->get_difference(),
-// frame->period_n * 1000 / frame->period_d,
-// total_frames,
-// frame_buffer.size());
-
-// Add forced frames
- for(int i = 0; i < frame_buffer.size(); i++)
- if(frame_buffer.get(i)->force) total_frames++;
- total_frames = MIN(frame_buffer.size(), total_frames);
-
-
- return total_frames;
- }
- else
- {
- return 0;
- }
+ PluginClientFrame *frame = client_frames.first;
+ if( !frame ) return 0;
+ double tracking_position = get_tracking_position();
+ int direction = get_tracking_direction();
+ int ret = !(direction == PLAY_REVERSE ?
+ frame->position < tracking_position :
+ frame->position > tracking_position);
+ return ret;
}
-PluginClientFrame* PluginClient::get_gui_frame()
+int PluginClient::pending_gui_frames()
{
- if(frame_buffer.size())
- {
- PluginClientFrame *frame = frame_buffer.get(0);
- frame_buffer.remove_number(0);
- return frame;
- }
- else
- {
- return 0;
+ PluginClientFrame *frame = client_frames.first;
+ if( !frame ) return 0;
+ double tracking_position = get_tracking_position();
+ int direction = get_tracking_direction();
+ int count = 0;
+ while( frame && !(direction == PLAY_REVERSE ?
+ frame->position < tracking_position :
+ frame->position > tracking_position) ) {
+ ++count; frame=frame->next;
}
+ return count;
}
void PluginClient::add_gui_frame(PluginClientFrame *frame)
{
- frame_buffer.append(frame);
+ client_frames.add_gui_frame(frame);
+}
+int PluginClient::get_gui_frames()
+{
+ return client_frames.total();
+}
+
+double PluginClient::get_tracking_position()
+{
+ return server->mwindow->get_tracking_position();
+}
+
+int PluginClient::get_tracking_direction()
+{
+ return server->mwindow->get_tracking_direction();
}
void PluginClient::send_render_gui()
{
- server->send_render_gui(&frame_buffer);
+ server->send_render_gui(&client_frames);
}
void PluginClient::send_render_gui(void *data)
server->send_render_gui(data, size);
}
-void PluginClient::plugin_render_gui(void *data, int size)
+
+void PluginClient::plugin_reset_gui_frames()
{
- render_gui(data, size);
+ if( !thread ) return;
+ BC_WindowBase *window = thread->get_window();
+ if( !window ) return;
+ window->lock_window("PluginClient::plugin_reset_gui_frames");
+ client_frames.reset();
+ window->unlock_window();
}
+void PluginClient::plugin_render_gui_frames(PluginClientFrames *frames)
+{
+ if( !thread ) return;
+ BC_WindowBase *window = thread->get_window();
+ if( !window ) return;
+ window->lock_window("PluginClient::render_gui");
+ while( client_frames.count > MAX_FRAME_BUFFER )
+ delete get_gui_frame(0, 0);
+// append client frames to gui client_frames, consumes frames
+ client_frames.concatenate(frames);
+ client_frames.sort_position(get_tracking_direction());
+ update_timer->update();
+ window->unlock_window();
+}
void PluginClient::plugin_render_gui(void *data)
{
render_gui(data);
}
-void PluginClient::render_gui(void *data)
+void PluginClient::plugin_render_gui(void *data, int size)
{
- if(thread)
- {
- thread->get_window()->lock_window("PluginClient::render_gui");
-
-// Set all previous frames to draw immediately
- for(int i = 0; i < frame_buffer.size(); i++)
- frame_buffer.get(i)->force = 1;
-
- ArrayList<PluginClientFrame*> *src =
- (ArrayList<PluginClientFrame*>*)data;
-
-// Shift GUI data to GUI client
- while(src->size())
- {
- this->frame_buffer.append(src->get(0));
- src->remove_number(0);
- }
+ render_gui(data, size);
+}
-// Start the timer for the current buffer
- update_timer->update();
- thread->get_window()->unlock_window();
- }
+void PluginClient::render_gui(void *data)
+{
+ printf("PluginClient::render_gui %d\n", __LINE__);
}
void PluginClient::render_gui(void *data, int size)
{
- printf("PluginClient::render_gui %d\n", __LINE__);
+ printf("PluginClient::render_gui %d\n", __LINE__);
}
-
-
-
-
-
-
+void PluginClient::reset_gui_frames()
+{
+ server->reset_gui_frames();
+}
int PluginClient::is_audio() { return 0; }
int PluginClient::is_video() { return 0; }
using_defaults = 1;
//printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
- KeyFrame temp_keyframe;
- FILE *fp = fopen(path, "r");
- if( fp ) {
- struct stat st; int fd = fileno(fp);
- int64_t sz = !fstat(fd, &st) ? st.st_size : BCTEXTLEN;
- char *data = temp_keyframe.get_data(sz+1);
- int data_size = fread(data, 1, sz, fp);
- if( data_size < 0 ) data_size = 0;
- if( data_size > 0 ) {
- data[data_size] = 0;
- temp_keyframe.xbuf->oseek(data_size);
+ char *data = 0;
+ int64_t len = -1;
+ struct stat st;
+ int fd = open(path, O_RDONLY);
+ if( fd >= 0 && !fstat(fd, &st) ) {
+ int64_t sz = st.st_size;
+ data = new char[sz+1];
+ len = read(fd, data, sz);
+ close(fd);
+ }
+ if( data && len >= 0 ) {
+ data[len] = 0;
// Get window extents
- int i = 0;
- for( int state=0; i<(data_size-8) && state>=0; ++i ) {
- if( !data[i] || data[i] == '<' ) break;
- if( !isdigit(data[i]) ) continue;
- if( !state ) {
- window_x = atoi(data + i);
- state = 1;
- }
- else {
- window_y = atoi(data + i);
- state = -1;
- }
- while( i<data_size && isdigit(data[i]) ) ++i;
+ int i = 0;
+ for( int state=0; i<len && state>=0; ++i ) {
+ if( !data[i] || data[i] == '<' ) break;
+ if( !isdigit(data[i]) ) continue;
+ if( !state ) {
+ window_x = atoi(data+i);
+ state = 1;
}
- temp_keyframe.xbuf->iseek(i);
- read_data(&temp_keyframe);
+ else {
+ window_y = atoi(data+i);
+ state = -1;
+ }
+ while( i<len && isdigit(data[i]) ) ++i;
}
-
- fclose(fp);
+ KeyFrame keyframe(data+i, len-i);
+ read_data(&keyframe);
}
+ delete [] data;
+
using_defaults = 0;
//printf("PluginClient::load_defaults_xml %d %s\n", __LINE__, path);
}
const char *PluginClient::get_source_path()
{
- int64_t source_position = server->plugin->startproject;
- Edit *edit = server->plugin->track->edits->editof(source_position,PLAY_FORWARD,0);
+ EDL *edl = get_edl();
+ Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+ int64_t source_position = plugin->startproject;
+ Edit *edit = plugin->track->edits->editof(source_position,PLAY_FORWARD,0);
Indexable *indexable = edit ? edit->get_source() : 0;
return indexable ? indexable->path : 0;
}
float PluginClient::get_red()
{
- EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
- return !edl ? 0 : edl->local_session->use_max ?
+ EDL *edl = get_edl();
+ return edl->local_session->use_max ?
edl->local_session->red_max :
edl->local_session->red;
}
float PluginClient::get_green()
{
- EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
- return !edl ? 0 : edl->local_session->use_max ?
+ EDL *edl = get_edl();
+ return edl->local_session->use_max ?
edl->local_session->green_max :
edl->local_session->green;
}
float PluginClient::get_blue()
{
- EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
- return !edl ? 0 : edl->local_session->use_max ?
+ EDL *edl = get_edl();
+ return edl->local_session->use_max ?
edl->local_session->blue_max :
edl->local_session->blue;
}
return direction;
}
-
int64_t PluginClient::local_to_edl(int64_t position)
{
return position;
return server->get_use_opengl();
}
+int PluginClient::to_ram(VFrame *vframe)
+{
+ return server->to_ram(vframe);
+}
+
int PluginClient::get_total_buffers()
{
return total_in_buffers;
if(server->mwindow)
server->mwindow->undo->update_undo_before(_("tweek"), this);
#ifdef USE_KEYFRAME_SPANNING
- KeyFrame keyframe;
+ EDL *edl = server->edl;
+ Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+ KeyFrames *keyframes = plugin ? plugin->keyframes : 0;
+ KeyFrame keyframe(edl, keyframes);
save_data(&keyframe);
- server->apply_keyframe(&keyframe);
+ server->apply_keyframe(plugin, &keyframe);
#else
KeyFrame* keyframe = server->get_keyframe();
// Call save routine in plugin
return 0;
}
+// virtual default spanning keyframe update. If a range is selected,
+// then changed parameters are copied to (prev + selected) keyframes.
+// redefine per client for custom keyframe updates, see tracer, sketcher, crikey
+void PluginClient::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+ src->span_keyframes(start, end);
+}
+
KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
{
}
-EDLSession* PluginClient::get_edlsession()
+void PluginClient::output_to_track(float ox, float oy, float &tx, float &ty)
{
- if(server->edl)
- return server->edl->session;
- return 0;
+ float projector_x, projector_y, projector_z;
+ int64_t position = get_source_position();
+ get_projector(&projector_x, &projector_y, &projector_z, position);
+ EDL *edl = get_edl();
+ projector_x += edl->session->output_w / 2;
+ projector_y += edl->session->output_h / 2;
+ Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+ Track *track = plugin ? plugin->track : 0;
+ int track_w = track ? track->track_w : edl->session->output_w;
+ int track_h = track ? track->track_h : edl->session->output_h;
+ tx = (ox - projector_x) / projector_z + track_w / 2;
+ ty = (oy - projector_y) / projector_z + track_h / 2;
+}
+
+void PluginClient::track_to_output(float tx, float ty, float &ox, float &oy)
+{
+ float projector_x, projector_y, projector_z;
+ int64_t position = get_source_position();
+ get_projector(&projector_x, &projector_y, &projector_z, position);
+ EDL *edl = get_edl();
+ projector_x += edl->session->output_w / 2;
+ projector_y += edl->session->output_h / 2;
+ Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+ Track *track = plugin ? plugin->track : 0;
+ int track_w = track ? track->track_w : edl->session->output_w;
+ int track_h = track ? track->track_h : edl->session->output_h;
+ ox = (tx - track_w / 2) * projector_z + projector_x;
+ oy = (ty - track_h / 2) * projector_z + projector_y;
+}
+
+
+EDL *PluginClient::get_edl()
+{
+ return server->mwindow ? server->mwindow->edl : server->edl;
}
int PluginClient::gui_open()
{
return server->gui_open();
}
+
+