fix awdw solo vicon crash, fix nested clip for binfolders, open edit edl
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / pluginserver.C
index f3240ceae49dd877b15dba5f045bfb40b450dd80..f10cec05742a4a1ceb679d3da7b96c183a65388a 100644 (file)
@@ -53,6 +53,7 @@
 #include "mainsession.h"
 #include "theme.h"
 #include "trackcanvas.h"
+#include "tracks.h"
 #include "transportque.h"
 #include "vdevicex11.h"
 #include "vframe.h"
@@ -80,6 +81,8 @@ void PluginServer::init()
        modules = new ArrayList<Module*>;
        nodes = new ArrayList<VirtualNode*>;
        tip = 0;
+       gui_id = -1;
+       plugin_id = -1;
 }
 
 PluginServer::PluginServer()
@@ -91,8 +94,8 @@ PluginServer::PluginServer(MWindow *mwindow, const char *path, int type)
 {
        char fpath[BCTEXTLEN];
        init();
-        this->plugin_type = type;
-        this->mwindow = mwindow;
+       this->plugin_type = type;
+       this->mwindow = mwindow;
        if( type == PLUGIN_TYPE_FFMPEG ) {
                ff_name = cstrdup(path);
                sprintf(fpath, "ff_%s", path);
@@ -203,7 +206,7 @@ int PluginServer::cleanup_plugin()
        new_buffers = 0;
        written_samples = written_frames = 0;
        gui_on = 0;
-       plugin = 0;
+       plugin_id = -1;
        plugin_open = 0;
        return 0;
 }
@@ -294,12 +297,13 @@ void PluginServer::set_title(const char *string)
 void PluginServer::generate_display_title(char *string)
 {
        char ltitle[BCTEXTLEN];
-       if(BC_Resources::locale_utf8)
+       if( BC_Resources::locale_utf8 )
                strcpy(ltitle, _(title));
        else
                BC_Resources::encode(BC_Resources::encoding, 0,
                                _(title),strlen(title)+1, ltitle,BCTEXTLEN);
-       if(plugin && plugin->track)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin && plugin->track )
                sprintf(string, "%s: %s", plugin->track->title, ltitle);
        else
                strcpy(string, ltitle);
@@ -343,10 +347,10 @@ int PluginServer::open_plugin(int master,
        EDL *edl,
        Plugin *plugin)
 {
-       if(plugin_open) return 0;
+       if( plugin_open ) return 0;
 
        this->preferences = preferences;
-       this->plugin = plugin;
+       this->plugin_id = plugin ? plugin->orig_id : -1;
        this->edl = edl;
        if( !is_ffmpeg() && !is_lv2() && !is_executable() && !load_obj() ) {
 // If the load failed, can't use error string to detect executable
@@ -402,8 +406,8 @@ int PluginServer::open_plugin(int master,
 // Run initialization functions
        realtime = client->is_realtime();
 // Don't load defaults when probing the directory.
-       if(!master) {
-               if(realtime)
+       if( !master ) {
+               if( realtime )
                        client->load_defaults_xml();
                else
                        client->load_defaults();
@@ -425,16 +429,8 @@ int PluginServer::open_plugin(int master,
 
 int PluginServer::close_plugin()
 {
-       if(!plugin_open) return 0;
-
-       if(client)
-       {
-// Defaults are saved in the thread.
-//             if(client->defaults) client->save_defaults();
-               delete client;
-       }
-
-// shared object is persistent since plugin deletion would unlink its own object
+       if( !plugin_open ) return 0;
+       delete client;
        plugin_open = 0;
        cleanup_plugin();
        return 0;
@@ -443,11 +439,10 @@ int PluginServer::close_plugin()
 void PluginServer::client_side_close()
 {
 // Last command executed in client thread
-       if(plugin)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
                mwindow->hide_plugin(plugin, 1);
-       else
-       if(prompt)
-       {
+       else if( prompt ) {
                prompt->lock_window();
                prompt->set_done(1);
                prompt->unlock_window();
@@ -456,13 +451,14 @@ void PluginServer::client_side_close()
 
 void PluginServer::render_stop()
 {
-       if(client)
+       if( client )
                client->render_stop();
+       send_reset_gui_frames();
 }
 
 void PluginServer::write_table(FILE *fp, const char *path, int idx, int64_t mtime)
 {
-       if(!fp) return;
+       if( !fp ) return;
        fprintf(fp, "%d \"%s\" \"%s\" %jd %d %d %d %d %d %d %d %d %d %d %d\n",
                plugin_type, path, title, mtime, idx, audio, video, theme, realtime,
                fileio, uses_gui, multichannel, synthesis, transition, lad_index);
@@ -491,7 +487,7 @@ int PluginServer::init_realtime(int realtime_sched,
                int buffer_size)
 {
 
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
 
 // set for realtime priority
 // initialize plugin
@@ -511,8 +507,10 @@ void PluginServer::process_transition(VFrame *input,
                int64_t current_position,
                int64_t total_len)
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        PluginVClient *vclient = (PluginVClient*)client;
+       to_ram(input);
+       to_ram(output);
 
        vclient->source_position = current_position;
        vclient->source_start = 0;
@@ -537,7 +535,7 @@ void PluginServer::process_transition(Samples *input,
                int64_t fragment_size,
                int64_t total_len)
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        PluginAClient *aclient = (PluginAClient*)client;
 
        aclient->source_position = current_position;
@@ -555,50 +553,42 @@ void PluginServer::process_buffer(VFrame **frame,
        int64_t total_len,
        int direction)
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        PluginVClient *vclient = (PluginVClient*)client;
-
+       vclient->in_buffer_size = vclient->out_buffer_size = 1;
        vclient->source_position = current_position;
        vclient->total_len = total_len;
        vclient->frame_rate = frame_rate;
        vclient->input = new VFrame*[total_in_buffers];
        vclient->output = new VFrame*[total_in_buffers];
-       for(int i = 0; i < total_in_buffers; i++)
-       {
+       for( int i = 0; i < total_in_buffers; i++ ) {
                vclient->input[i] = frame[i];
                vclient->output[i] = frame[i];
        }
 
-       if(plugin)
-       {
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin ) {
                vclient->source_start = (int64_t)plugin->startproject *
-                       frame_rate /
-                       vclient->project_frame_rate;
+                       frame_rate / vclient->project_frame_rate;
        }
        vclient->direction = direction;
 
-
 //PRINT_TRACE
 //printf("plugin=%p source_start=%ld\n", plugin, vclient->source_start);
-
-       vclient->begin_process_buffer();
-       if(multichannel)
-       {
+//     vclient->begin_process_buffer();
+       if( multichannel )
                vclient->process_buffer(frame, current_position, frame_rate);
-       }
        else
-       {
                vclient->process_buffer(frame[0], current_position, frame_rate);
-       }
-       vclient->end_process_buffer();
+//     vclient->end_process_buffer();
 
-       for(int i = 0; i < total_in_buffers; i++)
+       for( int i = 0; i < total_in_buffers; i++ )
                frame[i]->push_prev_effect(title);
 
        delete [] vclient->input;
        delete [] vclient->output;
 
-    vclient->age_temp();
+       vclient->age_temp();
        use_opengl = 0;
 }
 
@@ -609,58 +599,115 @@ void PluginServer::process_buffer(Samples **buffer,
        int64_t total_len,
        int direction)
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        PluginAClient *aclient = (PluginAClient*)client;
-
        aclient->source_position = current_position;
        aclient->total_len = total_len;
        aclient->sample_rate = sample_rate;
+       aclient->in_buffer_size = aclient->out_buffer_size = fragment_size;
+       aclient->output_buffers = buffer;
 
-       if(plugin)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
                aclient->source_start = plugin->startproject *
                        sample_rate /
                        aclient->project_sample_rate;
 
        aclient->direction = direction;
        aclient->begin_process_buffer();
-       if(multichannel)
-       {
+       if( multichannel ) {
                aclient->process_buffer(fragment_size,
-                       buffer,
-                       current_position,
-                       sample_rate);
+                       buffer, current_position, sample_rate);
        }
-       else
-       {
+       else {
                aclient->process_buffer(fragment_size,
-                       buffer[0],
-                       current_position,
-                       sample_rate);
+                       buffer[0], current_position, sample_rate);
        }
        aclient->end_process_buffer();
 }
 
 
+void PluginServer::send_reset_gui_frames()
+{
+       if( !attachmentpoint ) return;
+       attachmentpoint->reset_gui_frames(this);
+}
+
 void PluginServer::send_render_gui(void *data)
 {
-//printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
-       if(attachmentpoint) attachmentpoint->render_gui(data, this);
+       if( !attachmentpoint ) return;
+       attachmentpoint->render_gui(data, this);
 }
 
 void PluginServer::send_render_gui(void *data, int size)
 {
-//printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
-       if(attachmentpoint) attachmentpoint->render_gui(data, size, this);
+       if( !attachmentpoint ) return;
+       attachmentpoint->render_gui(data, size, this);
 }
 
 void PluginServer::render_gui(void *data)
 {
-       if(client) client->plugin_render_gui(data);
+       if( !client ) return;
+       client->plugin_render_gui(data);
 }
 
 void PluginServer::render_gui(void *data, int size)
 {
-       if(client) client->plugin_render_gui(data, size);
+       if( !client ) return;
+       client->plugin_render_gui(data, size);
+}
+
+
+PluginGUIs::PluginGUIs(MWindow *mwindow)
+{
+       this->mwindow = mwindow;
+       this->next_id = 0;
+}
+PluginGUIs::~PluginGUIs()
+{
+}
+
+void PluginGUIs::append(PluginServer *server)
+{
+       server->gui_id = next_id++;
+       ArrayList<PluginServer*>::append(server);
+}
+
+PluginServer *PluginGUIs::gui_server(int gui_id)
+{
+       for( int i=0; i<size(); ++i ) {
+               PluginServer *plugin_server = get(i);
+               if( plugin_server->gui_id == gui_id )
+                       return plugin_server;
+       }
+       return 0;
+}
+
+
+void PluginServer::reset_gui_frames()
+{
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
+               mwindow->reset_plugin_gui_frames(plugin);
+}
+
+void PluginServer::reset_plugin_gui_frames()
+{
+       if( !client ) return;
+       client->plugin_reset_gui_frames();
+}
+
+void PluginServer::render_gui_frames(PluginClientFrames *frames)
+{
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
+               mwindow->render_plugin_gui_frames(frames, plugin);
+}
+
+void PluginServer::render_plugin_gui_frames(PluginClientFrames *frames)
+{
+       if( !client ) return;
+       client->plugin_render_gui_frames(frames);
 }
 
 MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
@@ -673,30 +720,22 @@ MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
 
 int64_t PluginServer::get_written_samples()
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
        return written_samples;
 }
 
 int64_t PluginServer::get_written_frames()
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
        return written_frames;
 }
 
 
-
-
-
-
-
-
-
-
 // ======================= Non-realtime plugin
 
 int PluginServer::get_parameters(int64_t start, int64_t end, int channels)
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
 
        client->start = start;
        client->end = end;
@@ -712,7 +751,7 @@ int PluginServer::get_parameters(int64_t start, int64_t end, int channels)
 
 int PluginServer::set_interactive()
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
        client->set_interactive();
        return 0;
 }
@@ -749,13 +788,13 @@ int PluginServer::set_realtime_sched()
 
 int PluginServer::process_loop(VFrame **buffers, int64_t &write_length)
 {
-       if(!plugin_open) return 1;
+       if( !plugin_open ) return 1;
        return client->plugin_process_loop(buffers, write_length);
 }
 
 int PluginServer::process_loop(Samples **buffers, int64_t &write_length)
 {
-       if(!plugin_open) return 1;
+       if( !plugin_open ) return 1;
        return client->plugin_process_loop(buffers, write_length);
 }
 
@@ -765,14 +804,14 @@ int PluginServer::start_loop(int64_t start,
        int64_t buffer_size,
        int total_buffers)
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
        client->plugin_start_loop(start, end, buffer_size, total_buffers);
        return 0;
 }
 
 int PluginServer::stop_loop()
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
        return client->plugin_stop_loop();
 }
 
@@ -781,66 +820,42 @@ int PluginServer::read_frame(VFrame *buffer,
        int64_t start_position)
 {
        ((VModule*)modules->values[channel])->render(buffer,
-               start_position,
-               PLAY_FORWARD,
-               mwindow->edl->session->frame_rate,
-               0,
-               0);
+               start_position, PLAY_FORWARD,
+               mwindow->edl->session->frame_rate, 0, 0);
        return 0;
 }
 
 int PluginServer::read_samples(Samples *buffer,
-       int channel,
-       int64_t sample_rate,
-       int64_t start_position,
-       int64_t len)
+       int channel, int64_t sample_rate, int64_t start_position, int64_t len)
 {
 // len is now in buffer
-       if(!multichannel) channel = 0;
+       if( !multichannel ) channel = 0;
 
-       if(nodes->total > channel)
+       if( nodes->total > channel )
                return ((VirtualANode*)nodes->values[channel])->read_data(buffer,
-                       len,
-                       start_position,
-                       sample_rate);
-       else
-       if(modules->total > channel)
+                       len, start_position, sample_rate);
+       if( modules->total > channel )
                return ((AModule*)modules->values[channel])->render(buffer,
-                       len,
-                       start_position,
-                       PLAY_FORWARD,
-                       sample_rate,
-                       0);
-       else
-       {
-               printf("PluginServer::read_samples no object available for channel=%d\n",
-                       channel);
-       }
-
+                       len, start_position, PLAY_FORWARD, sample_rate, 0);
+       printf("PluginServer::read_samples no object available for channel=%d\n",
+               channel);
        return -1;
 }
 
 
 int PluginServer::read_samples(Samples *buffer,
-       int channel,
-       int64_t start_position,
-       int64_t size)
+               int channel, int64_t start_position, int64_t size)
 {
 // total_samples is now set in buffer
        ((AModule*)modules->values[channel])->render(buffer,
-               size,
-               start_position,
-               PLAY_FORWARD,
-               mwindow->edl->session->sample_rate,
-               0);
+               size, start_position, PLAY_FORWARD,
+               mwindow->edl->session->sample_rate, 0);
        return 0;
 }
 
 int PluginServer::read_frame(VFrame *buffer,
-       int channel,
-       int64_t start_position,
-       double frame_rate,
-       int use_opengl)
+               int channel, int64_t start_position, double frame_rate,
+               int use_opengl)
 {
 // Data source depends on whether we're part of a virtual console or a
 // plugin array.
@@ -852,36 +867,26 @@ int PluginServer::read_frame(VFrame *buffer,
 //PRINT_TRACE
 
        int result = -1;
-       if(!multichannel) channel = 0;
+       if( !multichannel ) channel = 0;
 
 // Push our name on the next effect stack
        buffer->push_next_effect(title);
 //printf("PluginServer::read_frame %p\n", buffer);
 //buffer->dump_stacks();
 
-       if(nodes->total > channel)
-       {
+       if( nodes->total > channel ) {
 //printf("PluginServer::read_frame %d\n", __LINE__);
                result = ((VirtualVNode*)nodes->values[channel])->read_data(buffer,
-                       start_position,
-                       frame_rate,
-                       use_opengl);
+                       start_position, frame_rate, use_opengl);
        }
        else
-       if(modules->total > channel)
-       {
+       if( modules->total > channel ) {
 //printf("PluginServer::read_frame %d\n", __LINE__);
                result = ((VModule*)modules->values[channel])->render(buffer,
-                       start_position,
-//                     PLAY_FORWARD,
-                       client->direction,
-                       frame_rate,
-                       0,
-                       0,
-                       use_opengl);
+                       start_position, //                      PLAY_FORWARD,
+                       client->direction, frame_rate, 0, 0, use_opengl);
        }
-       else
-       {
+       else {
                printf("PluginServer::read_frame no object available for channel=%d\n",
                        channel);
        }
@@ -893,28 +898,11 @@ int PluginServer::read_frame(VFrame *buffer,
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 // Called by client
 int PluginServer::get_gui_status()
 {
-       if(plugin)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
                return plugin->show ? GUI_ON : GUI_OFF;
        else
                return GUI_OFF;
@@ -922,24 +910,26 @@ int PluginServer::get_gui_status()
 
 void PluginServer::raise_window()
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        client->raise_window();
 }
 
 void PluginServer::show_gui()
 {
-       if(!plugin_open) return;
-       if(plugin) client->total_len = plugin->length;
-       if(plugin) client->source_start = plugin->startproject;
-       if(video)
-       {
+       if( !plugin_open ) return;
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin ) {
+               plugin->gui_id = gui_id;
+               client->total_len = plugin->length;
+               client->source_start = plugin->startproject;
+       }
+       if( video ) {
                client->source_position = Units::to_int64(
                        mwindow->edl->local_session->get_selectionstart(1) *
                                mwindow->edl->session->frame_rate);
        }
        else
-       if(audio)
-       {
+       if( audio ) {
                client->source_position = Units::to_int64(
                        mwindow->edl->local_session->get_selectionstart(1) *
                                mwindow->edl->session->sample_rate);
@@ -951,27 +941,28 @@ void PluginServer::show_gui()
 
 void PluginServer::hide_gui()
 {
-       if(!plugin_open) return;
-       if(client->defaults) client->save_defaults();
+       if( !plugin_open ) return;
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin ) plugin->gui_id = -1;
+       if( client->defaults ) client->save_defaults();
        client->hide_gui();
 }
 
 void PluginServer::update_gui()
 {
-       if(!plugin_open || !plugin) return;
+       if( !plugin_open ) return;
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( !plugin ) return;
 
        client->total_len = plugin->length;
        client->source_start = plugin->startproject;
 
-       if(video)
-       {
+       if( video ) {
                client->source_position = Units::to_int64(
                        mwindow->edl->local_session->get_selectionstart(1) *
                                mwindow->edl->session->frame_rate);
        }
-       else
-       if(audio)
-       {
+       else if( audio ) {
                client->source_position = Units::to_int64(
                        mwindow->edl->local_session->get_selectionstart(1) *
                                mwindow->edl->session->sample_rate);
@@ -982,7 +973,7 @@ void PluginServer::update_gui()
 
 void PluginServer::update_title()
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
 
        client->update_display_title();
 }
@@ -990,7 +981,7 @@ void PluginServer::update_title()
 
 int PluginServer::set_string(char *string)
 {
-       if(!plugin_open) return 0;
+       if( !plugin_open ) return 0;
 
        client->set_string_client(string);
        return 0;
@@ -998,7 +989,7 @@ int PluginServer::set_string(char *string)
 
 int PluginServer::gui_open()
 {
-       if(attachmentpoint) return attachmentpoint->gui_open();
+       if( attachmentpoint ) return attachmentpoint->gui_open();
        return 0;
 }
 
@@ -1013,10 +1004,19 @@ int PluginServer::get_use_opengl()
        return use_opengl;
 }
 
+int PluginServer::to_ram(VFrame *vframe)
+{
+       if( vframe->get_opengl_state() == VFrame::RAM ) return 0;
+       if( !vdevice ) return -1;
+       VDeviceX11 *vdevice_x11 = (VDeviceX11*) vdevice->get_output_base();
+       int vw = vframe->get_w(), vh = vframe->get_h();
+       vdevice_x11->do_camera(vframe, vframe, 0,0,vw,vh, 0,0,vw,vh); // copy to ram
+       return 1;
+}
 
 void PluginServer::run_opengl(PluginClient *plugin_client)
 {
-       if(vdevice)
+       if( vdevice )
                ((VDeviceX11*)vdevice->get_output_base())->run_plugin(plugin_client);
 }
 
@@ -1024,87 +1024,76 @@ void PluginServer::run_opengl(PluginClient *plugin_client)
 
 void PluginServer::get_defaults_path(char *path)
 {
-// Get plugin name from path
-       char *ptr1 = strrchr(get_path(), '/');
-       char *ptr2 = strrchr(get_path(), '.');
-       if(!ptr1) ptr1 = get_path();
-       if(!ptr2) ptr2 = get_path() + strlen(get_path());
-       char string2[BCTEXTLEN], *ptr3 = string2;
-       while( ptr1 < ptr2 ) *ptr3++ = *ptr1++;
-       *ptr3 = 0;
+       char string2[BCTEXTLEN];
+       switch( plugin_type ) {
+       case PLUGIN_TYPE_FFMPEG:
+       case PLUGIN_TYPE_LV2:
+               strcpy(string2, title);
+               break;
+       case PLUGIN_TYPE_BUILTIN:
+       case PLUGIN_TYPE_LADSPA:
+       default: { // Get plugin name from path
+               char *ptr1 = strrchr(get_path(), '/');
+               char *ptr2 = strrchr(get_path(), '.');
+               if( !ptr1 ) ptr1 = get_path();
+               if( !ptr2 ) ptr2 = get_path() + strlen(get_path());
+               char *ptr3 = string2;
+               while( ptr1 < ptr2 ) *ptr3++ = *ptr1++;
+               *ptr3 = 0;
+               break; }
+       }
        sprintf(path, "%s/%s.xml", File::get_config_path(), string2);
 }
 
 void PluginServer::save_defaults()
 {
-       if(client) client->save_defaults();
+       if( client ) client->save_defaults();
 }
 
 int PluginServer::get_samplerate()
 {
-       if(!plugin_open) return 0;
-       if(audio)
-       {
+       if( !plugin_open ) return 0;
+       if( audio )
                return client->get_samplerate();
-       }
-       else
-       if(mwindow)
+       if( mwindow )
                return mwindow->edl->session->sample_rate;
-       else
-       {
-               printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
-               return 1;
-       }
+       printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
+       return 1;
 }
 
 
 double PluginServer::get_framerate()
 {
-       if(!plugin_open) return 0;
-       if(video)
-       {
+       if( !plugin_open ) return 0;
+       if( video )
                return client->get_framerate();
-       }
-       else
-       if(mwindow)
+       if( mwindow )
                return mwindow->edl->session->frame_rate;
-       else
-       {
-               printf("PluginServer::get_framerate video and mwindow == NULL\n");
-               return 1;
-       }
+       printf("PluginServer::get_framerate video and mwindow == NULL\n");
+       return 1;
 }
 
 int PluginServer::get_project_samplerate()
 {
-       if(mwindow)
+       if( mwindow )
                return mwindow->edl->session->sample_rate;
-       else
-       if(edl)
+       if( edl )
                return edl->session->sample_rate;
-       else
-       {
-               printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
-               return 1;
-       }
+       printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
+       return 1;
 }
 
 double PluginServer::get_project_framerate()
 {
-       if(mwindow)
+       if( mwindow )
                return mwindow->edl->session->frame_rate;
-       else
-       if(edl)
+       if( edl )
                return edl->session->frame_rate;
-       else
-       {
-               printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
-               return 1;
-       }
+       printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
+       return 1;
 }
 
 
-
 int PluginServer::detach_buffers()
 {
        ring_buffers_out.remove_all();
@@ -1126,10 +1115,8 @@ int PluginServer::detach_buffers()
 }
 
 int PluginServer::arm_buffer(int buffer_number,
-               int64_t offset_in,
-               int64_t offset_out,
-               int double_buffer_in,
-               int double_buffer_out)
+               int64_t offset_in, int64_t offset_out,
+               int double_buffer_in, int double_buffer_out)
 {
        offset_in_render.values[buffer_number] = offset_in;
        offset_out_render.values[buffer_number] = offset_out;
@@ -1152,14 +1139,15 @@ int PluginServer::set_automation(FloatAutos *autos, FloatAuto **start_auto, Floa
 
 void PluginServer::save_data(KeyFrame *keyframe)
 {
-       if(!plugin_open) return;
+       if( !plugin_open ) return;
        client->save_data(keyframe);
 }
 
 KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
 {
        KeyFrame *result = 0;
-       if(plugin)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
                result = plugin->get_prev_keyframe(position, client->direction);
        else
                result = keyframe;
@@ -1168,74 +1156,72 @@ KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
 
 KeyFrame* PluginServer::get_next_keyframe(int64_t position)
 {
-       KeyFrame *result = 0;
-       if(plugin)
-               result = plugin->get_next_keyframe(position, client->direction);
-       else
-               result = keyframe;
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       KeyFrame *result = !plugin ? 0 :
+               plugin->get_next_keyframe(position, client->direction);
        return result;
 }
 
 // Called for
 KeyFrame* PluginServer::get_keyframe()
 {
-       if(plugin)
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
 // Realtime plugin case
                return plugin->get_keyframe();
-       else
 // Rendered plugin case
-               return keyframe;
+       return keyframe;
 }
 
 
 void PluginServer::apply_keyframe(KeyFrame *src)
 {
-       if(!plugin)
-       {
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( !plugin )
                keyframe->copy_data(src);
-       }
+       else if( plugin->is_transition() )
+               plugin->get_keyframe()->copy_data(src);
        else
-       {
 // Span keyframes
                plugin->keyframes->update_parameter(src);
-       }
 }
 
 
-
-
-
 void PluginServer::get_camera(float *x, float *y, float *z,
        int64_t position, int direction)
 {
-       plugin->track->automation->get_camera(x, y, z, position, direction);
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
+               plugin->track->automation->get_camera(x, y, z, position, direction);
 }
 
 void PluginServer::get_projector(float *x, float *y, float *z,
        int64_t position, int direction)
 {
-       plugin->track->automation->get_projector(x, y, z, position, direction);
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
+               plugin->track->automation->get_projector(x, y, z, position, direction);
 }
 
 
 int PluginServer::get_interpolation_type()
 {
-       return plugin->edl->session->interpolation_type;
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
+       if( plugin )
+               return plugin->edl->session->interpolation_type;
+       return NEAREST_NEIGHBOR;
 }
 
 Theme* PluginServer::new_theme()
 {
-       if(theme)
-       {
+       if( theme )
                return client->new_theme();
-       }
-       else
-               return 0;
+       return 0;
 }
 
 Theme* PluginServer::get_theme()
 {
-       if(mwindow) return mwindow->theme;
+       if( mwindow ) return mwindow->theme;
        printf("PluginServer::get_theme mwindow not set\n");
        return 0;
 }
@@ -1290,11 +1276,10 @@ VFrame *PluginServer::get_picon()
 // Called when plugin interface is tweeked
 void PluginServer::sync_parameters()
 {
-       if(video) mwindow->restart_brender();
+       if( video ) mwindow->restart_brender();
        mwindow->sync_parameters();
        mwindow->update_keyframe_guis();
-       if(mwindow->edl->session->auto_conf->plugins)
-       {
+       if( mwindow->edl->session->auto_conf->plugins ) {
                mwindow->gui->lock_window("PluginServer::sync_parameters");
                mwindow->gui->draw_overlays(1);
                mwindow->gui->unlock_window();
@@ -1303,10 +1288,12 @@ void PluginServer::sync_parameters()
 
 int64_t PluginServer::get_startproject()
 {
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
        return !plugin ? -1 : plugin->startproject;
 }
 int64_t PluginServer::get_endproject()
 {
+       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
        return !plugin ? -1 : plugin->startproject + plugin->length;
 }