label edit deadlock, build openexr cfg option, code cleanup
[goodguy/history.git] / cinelerra-5.1 / cinelerra / mwindow.C
index 714e9dddd17d7d6b8441959f1cf1688598c1d0fb..33cee066a515ecfff676d5b8ea90cc600d298f7d 100644 (file)
 
 #include "asset.h"
 #include "assets.h"
+#include "atrack.h"
 #include "audioalsa.h"
+#include "autos.h"
 #include "awindowgui.h"
 #include "awindow.h"
 #include "batchrender.h"
 #include "bcdisplayinfo.h"
 #include "bcsignals.h"
 #include "bctimer.h"
+#include "bctrace.h"
 #include "bdcreate.h"
 #include "brender.h"
 #include "cache.h"
 #include "file.h"
 #include "filesystem.h"
 #include "filexml.h"
+#include "floatautos.h"
 #include "framecache.h"
 #include "gwindow.h"
 #include "gwindowgui.h"
 #include "keyframegui.h"
 #include "indexfile.h"
+#include "intautos.h"
 #include "interlacemodes.h"
 #include "language.h"
 #include "levelwindowgui.h"
@@ -76,6 +81,7 @@
 #include "mwindow.h"
 #include "nestededls.h"
 #include "new.h"
+#include "panautos.h"
 #include "patchbay.h"
 #include "playback3d.h"
 #include "playbackengine.h"
 #include "transition.h"
 #include "transportque.h"
 #include "vframe.h"
+#include "vtrack.h"
+#include "versioninfo.h"
 #include "videodevice.inc"
 #include "videowindow.h"
 #include "vplayback.h"
@@ -168,6 +176,7 @@ Commercials* MWindow::commercials = 0;
 MWindow::MWindow()
  : Thread(1, 0, 0)
 {
+       run_lock = new Mutex("MWindow::run_lock");
        plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
        dead_plugin_lock = new Mutex("MWindow::dead_plugin_lock");
        vwindows_lock = new Mutex("MWindow::vwindows_lock");
@@ -191,6 +200,8 @@ MWindow::MWindow()
        mainindexes = 0;
        mainprogress = 0;
        brender = 0;
+       brender_active = 0;
+       strcpy(cin_lang,"en");
        channeldb_buz =  new ChannelDB;
        channeldb_v4l2jpeg =  new ChannelDB;
        //file_server = 0;
@@ -219,9 +230,9 @@ MWindow::MWindow()
 // Need to delete brender temporary here.
 MWindow::~MWindow()
 {
-       in_destructor = 1;
+       run_lock->lock("MWindow::~MWindow");
        stop_playback(1);
-       stop_brender();
+       in_destructor = 1;
 //printf("MWindow::~MWindow %d\n", __LINE__);
        gui->stop_drawing();
        gui->remote_control->deactivate();
@@ -229,9 +240,6 @@ MWindow::~MWindow()
 #ifdef HAVE_DVB
        gui->channel_info->stop();
 #endif
-       brender_lock->lock("MWindow::quit");
-       delete brender;         brender = 0;
-       brender_lock->unlock();
        delete create_bd;       create_bd = 0;
        delete create_dvd;      create_dvd = 0;
        delete batch_render;    batch_render = 0;
@@ -334,23 +342,13 @@ MWindow::~MWindow()
        interlace_asset_fixmethods.remove_all_objects();
        sighandler->terminate();
        delete sighandler;
+       delete run_lock;
 }
 
 
-void MWindow::quit(int unlock)
+void MWindow::quit()
 {
-       stop_playback(1);
-       if(unlock) gui->unlock_window();
-
-       brender_lock->lock("MWindow::quit");
-       delete brender;         brender = 0;
-       brender_lock->unlock();
-
-       interrupt_indexes();
-       clean_indexes();
-       save_defaults();
        gui->set_done(0);
-       if(unlock) gui->lock_window("MWindow::quit");
 }
 
 void MWindow::init_error()
@@ -466,6 +464,39 @@ void MWindow::init_defaults(BC_Hash* &defaults, char *config_path)
        defaults->load();
 }
 
+
+void MWindow::check_language()
+{
+       char curr_lang[BCTEXTLEN]; curr_lang[0] = 0;
+       const char *env_lang = getenv("LANGUAGE");
+       if( !env_lang ) env_lang = getenv("LC_ALL");
+       if( !env_lang ) env_lang = getenv("LANG");
+       if( !env_lang ) {
+               snprintf(curr_lang, sizeof(curr_lang), "%s_%s-%s",
+                       BC_Resources::language, BC_Resources::region, BC_Resources::encoding);
+               env_lang = curr_lang;
+       }
+       char last_lang[BCTEXTLEN]; last_lang[0] = 0;
+       defaults->get("LAST_LANG",last_lang);
+       if( strcmp(env_lang,last_lang)) {
+               printf("lang changed from '%s' to '%s'\n", last_lang, env_lang);
+               defaults->update("LAST_LANG",env_lang);
+               char plugin_path[BCTEXTLEN];
+               create_defaults_path(plugin_path, PLUGIN_FILE);
+               ::remove(plugin_path);
+               char ladspa_path[BCTEXTLEN];
+               create_defaults_path(ladspa_path, LADSPA_FILE);
+               ::remove(ladspa_path);
+               defaults->save();
+       }
+       if( strlen(env_lang) > 1 &&
+           ( env_lang[2] == 0 || env_lang[2] == '_'  || env_lang[2] == '.' ) ) {
+               cin_lang[0] = env_lang[0];  cin_lang[1] = env_lang[1];  cin_lang[2] = 0;
+       }
+       else
+               strcpy(cin_lang, "en");
+}
+
 void MWindow::get_plugin_path(char *path, const char *plug_dir, const char *fs_path)
 {
        char *base_path = FileSystem::basepath(fs_path), *bp = base_path;
@@ -604,6 +635,7 @@ int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences)
                len = !cp ? strlen(path) : cp-path;
                char index_path[BCTEXTLEN], plugin_path[BCTEXTLEN];
                memcpy(plugin_path, path, len);  plugin_path[len] = 0;
+               if( cp ) ++len;
                char *plugin_dir = FileSystem::basepath(plugin_path);
                strcpy(plugin_path, plugin_dir);  delete [] plugin_dir;
                create_defaults_path(index_path, LADSPA_FILE);
@@ -639,14 +671,14 @@ int MWindow::init_ladspa_index(MWindow *mwindow, Preferences *preferences,
        strcpy(plugin_path, path);  delete [] path;
        printf("init ladspa index: %s\n", plugin_dir);
        FILE *fp = fopen(index_path,"w");
-        if( !fp ) {
+       if( !fp ) {
                fprintf(stderr,_("MWindow::init_ladspa_index: "
                        "can't create plugin index: %s\n"), index_path);
                return 1;
        }
        fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
        fprintf(fp, "%s\n", plugin_dir);
-        init_plugin_index(mwindow, preferences, fp, plugin_path);
+       init_plugin_index(mwindow, preferences, fp, plugin_path);
        fclose(fp);
        return 0;
 }
@@ -790,10 +822,17 @@ void MWindow::init_preferences()
        session->load_defaults(defaults);
        // set x11_host, screens, window_config
        screens = session->set_default_x11_host();
-       BC_Signals::set_trap_path("/tmp/cinelerra_%d.dmp");
        BC_Signals::set_trap_hook(trap_hook, this);
        BC_Signals::set_catch_segv(preferences->trap_sigsegv);
        BC_Signals::set_catch_intr(preferences->trap_sigintr);
+       if( preferences->trap_sigsegv || preferences->trap_sigintr ) {
+               BC_Trace::enable_locks();
+       }
+       else {
+               BC_Trace::disable_locks();
+       }
+       BC_WindowBase::get_resources()->popupmenu_btnup = preferences->popupmenu_btnup;
+       BC_WindowBase::get_resources()->textbox_focus_policy = preferences->textbox_focus_policy;
 }
 
 void MWindow::clean_indexes()
@@ -888,6 +927,7 @@ void MWindow::init_gwindow()
 
 void MWindow::init_tipwindow()
 {
+       TipWindow::load_tips(cin_lang);
        if( !twindow )
                twindow = new TipWindow(this);
        twindow->start();
@@ -974,6 +1014,7 @@ void MWindow::init_edl()
        edl->create_objects();
        fill_preset_defaults(default_standard, edl->session);
        edl->load_defaults(defaults);
+       edl->session->brender_start = edl->session->brender_end = 0;
        edl->create_default_tracks();
        edl->tracks->update_y_pixels(theme);
 }
@@ -1061,21 +1102,21 @@ void MWindow::init_menus()
                            interlace_asset_fixmethods.append(new InterlacefixmethodItem(string, x));
 
        // Interlacing Modes
-       ILACEASSETMODELISTADD(BC_ILACE_MODE_UNDETECTED); // Not included in the list for the project options.
+       ILACEASSETMODELISTADD(ILACE_MODE_UNDETECTED); // Not included in the list for the project options.
 
-       ILACEASSETMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
-       ILACEPROJECTMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
+       ILACEASSETMODELISTADD(ILACE_MODE_TOP_FIRST);
+       ILACEPROJECTMODELISTADD(ILACE_MODE_TOP_FIRST);
 
-       ILACEASSETMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
-       ILACEPROJECTMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
+       ILACEASSETMODELISTADD(ILACE_MODE_BOTTOM_FIRST);
+       ILACEPROJECTMODELISTADD(ILACE_MODE_BOTTOM_FIRST);
 
-       ILACEASSETMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
-       ILACEPROJECTMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
+       ILACEASSETMODELISTADD(ILACE_MODE_NOTINTERLACED);
+       ILACEPROJECTMODELISTADD(ILACE_MODE_NOTINTERLACED);
 
        // Interlacing Fixing Methods
-       ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_NONE);
-       ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_UPONE);
-       ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_DOWNONE);
+       ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_NONE);
+       ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_UPONE);
+       ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_DOWNONE);
 }
 
 void MWindow::init_indexes()
@@ -1096,7 +1137,7 @@ void MWindow::init_gui()
 void MWindow::init_signals()
 {
        sighandler = new SigHandler;
-       sighandler->initialize();
+       sighandler->initialize("/tmp/cinelerra_%d.dmp");
 ENABLE_BUFFER
 }
 
@@ -1132,25 +1173,35 @@ void MWindow::init_brender()
                session->brender_end = 0;
                brender_lock->unlock();
        }
-       if(brender) brender->restart(edl);
+       brender_active = 0;
+       stop_brender();
 }
 
 void MWindow::restart_brender()
 {
 //printf("MWindow::restart_brender 1\n");
-       if(brender) brender->restart(edl);
+       if( !brender_active || !preferences->use_brender ) return;
+       if( !brender ) return;
+       int locked  = gui->get_window_lock();
+       if( locked ) gui->unlock_window();
+       brender->restart(edl);
+       if( locked ) gui->lock_window("MWindow::restart_brender");
 }
 
 void MWindow::stop_brender()
 {
-       if(brender) brender->stop();
+       if( !brender ) return;
+       int locked  = gui->get_window_lock();
+       if( locked ) gui->unlock_window();
+       brender->stop();
+       if( locked ) gui->lock_window("MWindow::stop_brender");
 }
 
 int MWindow::brender_available(int position)
 {
        int result = 0;
        brender_lock->lock("MWindow::brender_available 1");
-       if(brender)
+       if(brender && brender_active)
        {
                if(brender->map_valid)
                {
@@ -1169,13 +1220,29 @@ int MWindow::brender_available(int position)
        return result;
 }
 
-void MWindow::set_brender_start()
+void MWindow::set_brender_active(int v, int update)
 {
-       edl->session->brender_start = edl->local_session->get_selectionstart(1);
-       restart_brender();
-       gui->draw_overlays(1);
-}
+       if( !preferences->use_brender ) v = 0;
+       brender_active = v;
+       gui->mainmenu->brender_active->set_checked(v);
+       if( v != 0 ) {
+               edl->session->brender_start = edl->local_session->get_selectionstart(1);
+               edl->session->brender_end = edl->local_session->get_selectionend(1);
 
+               if(EQUIV(edl->session->brender_end, edl->session->brender_start)) {
+                       edl->session->brender_end = edl->tracks->total_video_length();
+               }
+               restart_brender();
+       }
+       else {
+               edl->session->brender_start = edl->session->brender_end = 0;
+               stop_brender();
+       }
+       if( update ) {
+               gui->update_timebar(0);
+               gui->draw_overlays(1);
+       }
+}
 
 int MWindow::has_commercials()
 {
@@ -1276,21 +1343,16 @@ int MWindow::put_commercial()
 void MWindow::stop_playback(int wait)
 {
        int locked  = gui->get_window_lock();
-        if( locked ) gui->unlock_window();
+       if( locked ) gui->unlock_window();
 
-       cwindow->playback_engine->que->send_command(STOP,
-               CHANGE_NONE,
-               0,
-               0);
-       cwindow->playback_engine->interrupt_playback(wait);
+       cwindow->playback_engine->stop_playback();
 
        for(int i = 0; i < vwindows.size(); i++) {
                VWindow *vwindow = vwindows[i];
                if( !vwindow->is_running() ) continue;
-               vwindow->playback_engine->que->send_command(STOP, CHANGE_NONE, 0, 0);
-               vwindow->playback_engine->interrupt_playback(wait);
+               vwindow->playback_engine->stop_playback();
        }
-        if( locked ) gui->lock_window("MWindow::stop_playback");
+       if( locked ) gui->lock_window("MWindow::stop_playback");
 }
 
 int MWindow::load_filenames(ArrayList<char*> *filenames,
@@ -1413,11 +1475,9 @@ SET_TRACE
                        case FILE_UNRECOGNIZED_CODEC:
                        {
 // Test index file
-                               IndexFile indexfile(this, new_asset);
-                               result = indexfile.open_index();
-                               if(!result)
-                               {
-                                       indexfile.close_index();
+                               {       IndexFile indexfile(this, new_asset);
+                                       if( !(result = indexfile.open_index()) )
+                                               indexfile.close_index();
                                }
 
 // Test existing EDLs
@@ -1426,7 +1486,7 @@ SET_TRACE
                                                new_edls[j]->assets->get_asset(new_asset->path) :
                                                edl->assets->get_asset(new_asset->path);
                                        if( old_asset ) {
-                                               *new_asset = *old_asset;
+                                               new_asset->copy_from(old_asset,1);
                                                result = 0;
                                        }
                                }
@@ -1499,7 +1559,29 @@ SET_TRACE
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                                xml_file.read_from_file(filenames->get(i));
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
-
+                               const char *cin_version = 0;
+                               while( !xml_file.read_tag() ) {
+                                       if( xml_file.tag.title_is("EDL") ) {
+                                               cin_version = xml_file.tag.get_property("VERSION");
+                                               break;
+                                       }
+                               }
+                               xml_file.rewind();
+                               if( !cin_version ) {
+                                       eprintf(_("XML file %s\n not from cinelerra."),filenames->get(i));
+                                       char string[BCTEXTLEN];
+                                       sprintf(string,_("Unknown %s"), filenames->get(i));
+                                       gui->show_message(string);
+                                       result = 1;
+                                       break;
+                               }
+                               if( strcmp(cin_version, CINELERRA_VERSION) ) {
+                                       char string[BCTEXTLEN];
+                                       snprintf(string, sizeof(string),
+                                                _("Warning: XML from cinelerra version %s\n"
+                                               "Session data may be incompatible."), cin_version);
+                                       show_warning(&preferences->warn_version, string);
+                               }
                                if(load_mode == LOADMODE_NESTED)
                                {
 // Load temporary EDL for nesting.
@@ -1528,6 +1610,15 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                                                if(update_filename)
                                                        set_filename(new_edl->local_session->clip_title);
                                        }
+                                       else
+                                       if( load_mode == LOADMODE_RESOURCESONLY ) {
+                                               strcpy(new_edl->local_session->clip_title,
+                                                       filenames->get(i));
+                                               struct stat st;
+                                               time_t t = !stat(filenames->get(i),&st) ?
+                                                       st.st_mtime : time(&t);
+                                               ctime_r(&t, new_edl->local_session->clip_notes);
+                                       }
                                }
 
                                new_edls.append(new_edl);
@@ -1548,12 +1639,10 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
 
-       if(!result) gui->statusbar->default_message();
-
-
-
-
-
+       if(!result) {
+               gui->reset_default_message();
+               gui->default_message();
+       }
 
 
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
@@ -1607,32 +1696,26 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        }
 
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
-       if(new_assets.size())
+       for(int i = 0; i < new_assets.size(); i++)
        {
-               for(int i = 0; i < new_assets.size(); i++)
-               {
-                       Asset *new_asset = new_assets[i];
+               Asset *new_asset = new_assets[i];
 
-                       File *new_file = 0;
-                       int got_it = 0;
-                       for(int j = 0; j < new_files.size(); j++)
+               File *new_file = 0;
+               int got_it = 0;
+               for(int j = 0; j < new_files.size(); j++)
+               {
+                       new_file = new_files[j];
+                       if(!strcmp(new_file->asset->path,
+                               new_asset->path))
                        {
-                               new_file = new_files[j];
-                               if(!strcmp(new_file->asset->path,
-                                       new_asset->path))
-                               {
-                                       got_it = 1;
-                                       break;
-                               }
+                               got_it = 1;
+                               break;
                        }
-
-                       mainindexes->add_next_asset(got_it ? new_file : 0, new_asset);
-                       got_indexes = 1;
-                       edl->assets->update(new_asset);
-
                }
 
-
+               mainindexes->add_next_asset(got_it ? new_file : 0, new_asset);
+               got_indexes = 1;
+               edl->assets->update(new_asset);
        }
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
@@ -1682,6 +1765,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                edl->local_session->loop_playback = 0;
                edl->local_session->set_selectionstart(0);
                edl->local_session->set_selectionend(0);
+               set_brender_active(0, 0);
                fit_selection();
                goto_start();
        }
@@ -1860,6 +1944,7 @@ void MWindow::create_objects(int want_gui,
        if(debug) PRINT_TRACE
        default_standard = default_std();
        init_defaults(defaults, config_path);
+       check_language();
        init_preferences();
        if(splash_window)
                splash_window->operation->update(_("Initializing Plugins"));
@@ -1895,6 +1980,9 @@ void MWindow::create_objects(int want_gui,
 
        Timer timer;
 
+       init_awindow();
+       if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
+
        init_compositor();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 
@@ -1906,24 +1994,21 @@ void MWindow::create_objects(int want_gui,
        init_gui();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 
-       init_awindow();
-       if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
-
        init_levelwindow();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 
-       if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
-
        init_indexes();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 
        init_channeldb();
-
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
+
        init_gwindow();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
+
        init_render();
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
+
        init_brender();
        init_exportedl();
        init_commercials();
@@ -2067,7 +2152,18 @@ ENABLE_BUFFER
 
 void MWindow::run()
 {
+       run_lock->lock("MWindow::run");
        gui->run_window();
+       stop_playback(1);
+
+       brender_lock->lock("MWindow::run 1");
+       delete brender;         brender = 0;
+       brender_lock->unlock();
+
+       interrupt_indexes();
+       clean_indexes();
+       save_defaults();
+       run_lock->unlock();
 }
 
 void MWindow::show_vwindow()
@@ -2134,6 +2230,14 @@ void MWindow::show_gwindow()
 
        gui->mainmenu->show_gwindow->set_checked(1);
 }
+void MWindow::hide_gwindow()
+{
+       session->show_gwindow = 0;
+
+       gwindow->gui->lock_window("MWindow::show_gwindow");
+       gwindow->gui->hide_window();
+       gwindow->gui->unlock_window();
+}
 
 void MWindow::show_lwindow()
 {
@@ -2196,6 +2300,22 @@ void MWindow::set_auto_keyframes(int value, int lock_mwindow, int lock_cwindow)
        if(lock_cwindow) cwindow->gui->unlock_window();
 }
 
+void MWindow::set_auto_visibility(Autos *autos, int value)
+{
+       if( autos->type == Autos::AUTOMATION_TYPE_PLUGIN )
+               edl->session->auto_conf->plugins = value;
+       else if( autos->autoidx >= 0 )
+               edl->session->auto_conf->autos[autos->autoidx] = value;
+       else
+               return;
+
+       gui->update(0, 1, 0, 0, 0, 0, 0);
+       gui->mainmenu->update_toggles(1);
+       gui->unlock_window();
+       gwindow->gui->update_toggles(1);
+       gui->lock_window("MWindow::set_auto_visibility");
+}
+
 void MWindow::set_keyframe_type(int mode)
 {
        gui->lock_window("MWindow::set_keyframe_type");
@@ -2405,8 +2525,8 @@ SET_TRACE
 // Needs mwindow to do GUI
                        gui->set_mwindow(this);
                        gui->open_plugin(0, preferences, edl, plugin);
-                       gui->show_gui();
                        plugin->show = 1;
+                       gui->show_gui();
                }
        }
        plugin_gui_lock->unlock();
@@ -2864,9 +2984,13 @@ void MWindow::rebuild_indices()
                index_state->index_status = INDEX_NOTTESTED;
                if( indexable->is_asset ) {
                        Asset *asset = (Asset *)indexable;
-                       if( asset->format != FILE_PCM )
+                       if( asset->format != FILE_PCM ) {
+                               asset->format = FILE_UNKNOWN;
                                asset->reset_audio();
+                       }
                        asset->reset_video();
+//                     File file; // re-probe the asset
+//                     file.open_file(preferences, asset, 1, 0);
                }
                mainindexes->add_next_asset(0, indexable);
        }
@@ -3011,8 +3135,8 @@ void MWindow::remove_asset_from_caches(Asset *asset)
 void MWindow::remove_assets_from_project(int push_undo, int redraw,
                ArrayList<Indexable*> *drag_assets, ArrayList<EDL*> *drag_clips)
 {
-       for(int i = 0; i < session->drag_assets->total; i++) {
-               Indexable *indexable = session->drag_assets->get(i);
+       for(int i = 0; i < drag_assets->total; i++) {
+               Indexable *indexable = drag_assets->get(i);
                if(indexable->is_asset) remove_asset_from_caches((Asset*)indexable);
        }
 
@@ -3029,11 +3153,11 @@ void MWindow::remove_assets_from_project(int push_undo, int redraw,
                }
        }
 
-       for(int i = 0; i < session->drag_assets->size(); i++) {
+       for(int i = 0; i < drag_assets->size(); i++) {
                for(int j = 0; j < vwindows.size(); j++) {
                        VWindow *vwindow = vwindows[j];
                        if( !vwindow->is_running() ) continue;
-                       if(session->drag_assets->get(i) == vwindow->get_source()) {
+                       if(drag_assets->get(i) == vwindow->get_source()) {
                                vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
                                vwindow->delete_source(1, 1);
                                vwindow->gui->unlock_window();
@@ -3041,29 +3165,22 @@ void MWindow::remove_assets_from_project(int push_undo, int redraw,
                }
        }
 
-       for(int i = 0; i < session->drag_assets->size(); i++) {
-               Indexable *indexable = session->drag_assets->get(i);
+       for(int i = 0; i < drag_assets->size(); i++) {
+               Indexable *indexable = drag_assets->get(i);
                remove_indexfile(indexable);
        }
 
 //printf("MWindow::rebuild_indices 1 %s\n", indexable->path);
        if(push_undo) undo->update_undo_before();
        if(drag_assets) edl->remove_from_project(drag_assets);
-       if(drag_clips) edl->remove_from_project(session->drag_clips);
+       if(drag_clips) edl->remove_from_project(drag_clips);
        if(redraw) save_backup();
        if(push_undo) undo->update_undo_after(_("remove assets"), LOAD_ALL);
-       if(redraw)
-       {
+       if(redraw) {
                restart_brender();
 
                gui->lock_window("MWindow::remove_assets_from_project 3");
-               gui->update(1,
-                       1,
-                       1,
-                       1,
-                       0,
-                       1,
-                       0);
+               gui->update(1, 1, 1, 1, 0, 1, 0);
                gui->unlock_window();
 
        // Removes from playback here
@@ -3120,15 +3237,25 @@ void MWindow::dump_undo(FILE *fp)
 
 void MWindow::dump_exe(FILE *fp)
 {
-        char proc_path[BCTEXTLEN], exe_path[BCTEXTLEN];
-        sprintf(proc_path, "/proc/%d/exe", (int)getpid());
-        int ret = readlink(proc_path, exe_path, sizeof(exe_path));
-       if( ret < 0 ) { fprintf(fp,"readlink: %m\n"); return; }
-       exe_path[ret] = 0;
+       char proc_path[BCTEXTLEN], exe_path[BCTEXTLEN];
+       sprintf(proc_path, "/proc/%d/exe", (int)getpid());
+
+       int ret = -1, n = 100;
+       for( int len; (len=readlink(proc_path, exe_path, sizeof(exe_path)))>0; --n ) {
+               exe_path[len] = 0;  strcpy(proc_path, exe_path);
+               ret = 0;
+       }
+       if( n < 0 || ret < 0 ) { fprintf(fp,"readlink: %m\n"); return; }
+
        struct stat st;
-       if( stat(exe_path,&st) ) { fprintf(fp,"stat: %m\n"); return; }
-       fprintf(fp, "path: %s = %9jd bytes\n",exe_path,st.st_size);
-       int fd = open(exe_path,O_RDONLY+O_NONBLOCK);
+       if( stat(proc_path,&st) ) { fprintf(fp,"stat: %m\n"); return; }
+       fprintf(fp, "path: %s = %9jd bytes\n",proc_path,st.st_size);
+       struct tm *tm = localtime(&st.st_mtime);
+       char mtime[256];
+       strftime(mtime, sizeof(mtime), "%F %T", tm);
+       fprintf(fp,"mtime: %s\n", mtime);
+
+       int fd = open(proc_path,O_RDONLY+O_NONBLOCK);
        if( fd < 0 ) { fprintf(fp,"open: %m\n"); return; }
        uint8_t *bfr = 0;
        int64_t bfrsz = 0;
@@ -3425,6 +3552,8 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
        EDLSession *session = edl->session;
        double old_framerate = session->frame_rate;
        double old_samplerate = session->sample_rate;
+       int old_auto_keyframes = session->auto_keyframes;
+       session->auto_keyframes = 0;
        int result = file->open_file(preferences, asset, 1, 0);
        if( !result && delete_tracks > 0 )
                undo->update_undo_before();
@@ -3467,7 +3596,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                                        next_edit = edit->next;
                                        if( edit->channel != vstream ||
                                            !edit->asset || !edit->asset->is_asset ||
-                                           *asset != *edit->asset )
+                                           !asset->equivalent(*edit->asset,1,1,edl) )
                                                delete edit;
                                }
                        }
@@ -3478,6 +3607,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                        else if( delete_tracks )
                                edl->tracks->delete_track(track);
                }
+               edl->retrack();
                edl->resample(old_framerate, session->frame_rate, TRACK_VIDEO);
        }
        if( !result && asset->audio_data && asset->channels > 0 ) {
@@ -3527,7 +3657,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                                        next_edit = edit->next;
                                        if( !((1<<edit->channel) & channel_mask) ||
                                            !edit->asset || !edit->asset->is_asset ||
-                                           *asset != *edit->asset )
+                                           !asset->equivalent(*edit->asset,1,1,edl) )
                                                delete edit;
                                }
                                if( !track->edits->first )
@@ -3538,6 +3668,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                edl->resample(old_samplerate, session->sample_rate, TRACK_AUDIO);
        }
        delete file;
+       session->auto_keyframes = old_auto_keyframes;
        if( !result && delete_tracks > 0 ) {
                save_backup();
                undo->update_undo_after(_("select asset"), LOAD_ALL);
@@ -3566,3 +3697,34 @@ void MWindow::dump_plugindb(FILE *fp)
                plugindb->get(i)->dump(fp);
 }
 
+FloatAuto* MWindow::get_float_auto(PatchGUI *patch,int idx)
+{
+       Auto *current = 0;
+       double unit_position = edl->local_session->get_selectionstart(1);
+       unit_position = patch->track->to_units(unit_position, 0);
+
+       FloatAutos *ptr = (FloatAutos*)patch->track->automation->autos[idx];
+       return (FloatAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current);
+}
+
+IntAuto* MWindow::get_int_auto(PatchGUI *patch,int idx)
+{
+       Auto *current = 0;
+       double unit_position = edl->local_session->get_selectionstart(1);
+       unit_position = patch->track->to_units(unit_position, 0);
+
+       IntAutos *ptr = (IntAutos*)patch->track->automation->autos[idx];
+       return (IntAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current);
+}
+
+PanAuto* MWindow::get_pan_auto(PatchGUI *patch)
+{
+       Auto *current = 0;
+       double unit_position = edl->local_session->get_selectionstart(1);
+       unit_position = patch->track->to_units(unit_position, 0);
+
+       PanAutos *ptr = (PanAutos*)patch->track->automation->autos[AUTOMATION_PAN];
+       return (PanAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current);
+}
+
+