X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fpluginclient.C;h=d31b4b002c787bfbee824f252d40e504ebc29ed6;hp=606f83d95af6ce007aa7d685d5a6fbb730761af3;hb=b104b77f5296719bd5e6de8472eb71542ddaedec;hpb=7fd85fb66168f6b518c5f2d73e04036e87faa0e1 diff --git a/cinelerra-5.1/cinelerra/pluginclient.C b/cinelerra-5.1/cinelerra/pluginclient.C index 606f83d9..d31b4b00 100644 --- a/cinelerra-5.1/cinelerra/pluginclient.C +++ b/cinelerra-5.1/cinelerra/pluginclient.C @@ -22,6 +22,7 @@ #include "bcdisplayinfo.h" #include "bchash.h" #include "bcsignals.h" +#include "attachmentpoint.h" #include "clip.h" #include "condition.h" #include "edits.h" @@ -40,16 +41,27 @@ #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 +#include +#include +#include +#include #include #include -#include - +PluginClientFrame::PluginClientFrame() +{ + position = -1; +} +PluginClientFrame::~PluginClientFrame() +{ +} PluginClientThread::PluginClientThread(PluginClient *client) @@ -62,10 +74,7 @@ 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; } @@ -93,11 +102,9 @@ void PluginClientThread::run() 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(); } @@ -120,49 +127,42 @@ PluginClient* PluginClientThread::get_client() } - - - - -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) { + char title[BCTEXTLEN]; + this->client = client; + +// *** CONTEXT_HELP *** + if(client) { + strcpy(title, client->plugin_title()); + if(! strcmp(title, "Overlay")) { + // "Overlay" plugin title is ambiguous + if(client->is_audio()) strcat(title, " \\(Audio\\)"); + if(client->is_video()) strcat(title, " \\(Video\\)"); + } + if(client->server->is_ffmpeg()) { + // FFmpeg plugins can be audio or video + if(client->is_audio()) + strcpy(title, "FFmpeg Audio Plugins"); + if(client->is_video()) + strcpy(title, "FFmpeg Video Plugins"); + } + context_help_set_keyword(title); + } } 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; +// *** CONTEXT_HELP *** + context_help_set_keyword(title); } PluginClientWindow::~PluginClientWindow() @@ -188,8 +188,243 @@ int PluginClientWindow::close_event() 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) @@ -212,7 +447,6 @@ PluginClient::~PluginClient() // Virtual functions don't work here. if(defaults) delete defaults; - frame_buffer.remove_all_objects(); delete update_timer; } @@ -243,13 +477,8 @@ void PluginClient::hide_gui() { 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(); } } @@ -321,7 +550,6 @@ int PluginClient::is_multichannel() { return 0; } 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; } @@ -374,95 +602,138 @@ int PluginClient::set_string() -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(); +} + +// 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; +} -// Delete unused GUI frames - while(frame_buffer.size() > MAX_FRAME_BUFFER) - frame_buffer.remove_object_number(0); +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) @@ -475,54 +746,56 @@ void PluginClient::send_render_gui(void *data, int size) 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 *src = - (ArrayList*)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; } @@ -551,38 +824,38 @@ void PluginClient::load_defaults_xml() 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=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; } - temp_keyframe.xbuf->iseek(i); - read_data(&temp_keyframe); + while( iplugin->startproject; - Edit *edit = server->plugin->track->edits->editof(source_position,PLAY_FORWARD,0); + Plugin *plugin = server->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; } @@ -733,24 +1007,24 @@ int PluginClient::get_interpolation_type() 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; } @@ -776,7 +1050,6 @@ int PluginClient::get_direction() return direction; } - int64_t PluginClient::local_to_edl(int64_t position) { return position; @@ -792,6 +1065,11 @@ int PluginClient::get_use_opengl() 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; @@ -826,9 +1104,12 @@ int PluginClient::send_configure_change() 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 @@ -840,6 +1121,14 @@ int PluginClient::send_configure_change() 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) { @@ -864,14 +1153,47 @@ void PluginClient::get_projector(float *x, float *y, float *z, int64_t position) } -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(); } + +