LADSPA_PATH env var processing
[goodguy/history.git] / cinelerra-5.0 / cinelerra / mwindow.C
index 7ad079b382fba0341bb98dd34ed51c8aad5fca49..7c619b798341ce4c4e84945e3f68093c5aae13e0 100644 (file)
 #include "bcdisplayinfo.h"
 #include "bcsignals.h"
 #include "bctimer.h"
+#include "bdcreate.h"
 #include "brender.h"
 #include "cache.h"
 #include "channel.h"
 #include "channeldb.h"
 #include "channelinfo.h"
 #include "clip.h"
-#include "colormodels.h"
+#include "bccmodels.h"
 #include "commercials.h"
 #include "cplayback.h"
 #include "ctimebar.h"
 #include "cwindow.h"
 #include "bchash.h"
 #include "devicedvbinput.inc"
+#include "dvdcreate.h"
 #include "editpanel.h"
 #include "edl.h"
 #include "edlsession.h"
 #include "errorbox.h"
 #include "fileformat.h"
 #include "file.h"
-#include "fileserver.h"
 #include "filesystem.h"
 #include "filexml.h"
 #include "format.inc"
 #include "vwindowgui.h"
 #include "vwindow.h"
 #include "wavecache.h"
+#include "wwindow.h"
 #include "zoombar.h"
 
 #include <string.h>
@@ -155,7 +157,6 @@ int atexit(void (*function)(void))
 
 
 ArrayList<PluginServer*>* MWindow::plugindb = 0;
-FileServer* MWindow::file_server = 0;
 Commercials* MWindow::commercials = 0;
 
 
@@ -191,6 +192,7 @@ MWindow::MWindow()
        plugin_guis = 0;
        dead_plugins = 0;
        keyframe_threads = 0;
+       create_bd = 0;
        create_dvd = 0;
        batch_render = 0;
        render = 0;
@@ -200,6 +202,7 @@ MWindow::MWindow()
        awindow = 0;
        gwindow = 0;
        twindow = 0;
+       wwindow = 0;
        lwindow = 0;
        sighandler = 0;
        reload_status = 0;
@@ -220,6 +223,7 @@ MWindow::~MWindow()
        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;
        commit_commercial();
@@ -235,7 +239,6 @@ MWindow::~MWindow()
        hide_keyframe_guis();
        clean_indexes();
        save_defaults();
-
 // Give up and go to a movie
 //  cant run valgrind if this is used
 //     if( !reload_status ) exit(0);
@@ -250,12 +253,14 @@ MWindow::~MWindow()
        if( lwindow && lwindow->gui ) lwindow->gui->close(0);
        if( gwindow && gwindow->gui ) gwindow->gui->close(0);
        if( twindow && twindow->is_running() ) twindow->close_window();
+       if( wwindow && wwindow->is_running() ) wwindow->close_window();
        vwindows.remove_all_objects();
        gui->close(0);
        if( awindow ) awindow->join();
        if( cwindow ) cwindow->join();
        if( lwindow ) lwindow->join();
        if( twindow ) twindow->join();
+       if( wwindow ) wwindow->join();
        if( gwindow ) gwindow->join();
        join();
 #else
@@ -268,12 +273,12 @@ MWindow::~MWindow()
        close_gui(lwindow);
        close_gui(gwindow);
        close_gui(twindow);
+       close_gui(wwindow);
        vwindows.remove_all_objects();
        gui->close(0);
        join();
 #endif
        reset_caches();
-       delete_plugins();
        dead_plugins->remove_all();
        finit_error();
        keyframe_threads->remove_all_objects();
@@ -284,6 +289,7 @@ MWindow::~MWindow()
        delete awindow;         awindow = 0;
        delete lwindow;         lwindow = 0;
        delete twindow;         twindow = 0;
+       delete wwindow;         wwindow = 0;
        delete gwindow;         gwindow = 0;
        // must be last or nouveau chokes
        delete cwindow;         cwindow = 0;
@@ -304,6 +310,7 @@ MWindow::~MWindow()
        delete assets;          assets = 0;
        delete splash_window;   splash_window = 0;
        delete theme;           theme = 0;
+       delete_plugins();
        delete channeldb_buz;
        delete channeldb_v4l2jpeg;
 // This must be last thread to exit
@@ -330,8 +337,7 @@ void MWindow::quit(int unlock)
        interrupt_indexes();
        clean_indexes();
        save_defaults();
-// This is the last thread to exit
-       playback_3d->quit();
+       gui->set_done(0);
        if(unlock) gui->lock_window("MWindow::quit");
 }
 
@@ -372,108 +378,240 @@ void MWindow::init_defaults(BC_Hash* &defaults, char *config_path)
        defaults->load();
 }
 
-int MWindow::load_plugin_index(MWindow *mwindow, char *path)
+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;
+       if( plug_dir ) {
+               const char *dp = plug_dir;
+               while( *bp && *dp && *bp == *dp ) { ++bp; ++dp; }
+               bp = !*dp && *bp == '/' ? bp+1 : base_path;
+       }
+       strcpy(path, bp);
+       delete [] base_path;
+}
+
+int MWindow::load_plugin_index(MWindow *mwindow, const char *index_path, const char *plugin_dir)
 {
 // load index
-       FILE *fp = fopen(path, "r");
-       if( !fp ) return 1;
+       FILE *fp = fopen(index_path, "r");
+       if( !fp ) return -1;
+
+       int ret = 0;
        char index_line[BCTEXTLEN];
-       int index_version = -1, ret = 0;
+       int index_version = -1, len = strlen(plugin_dir);
        if( !fgets(index_line, BCTEXTLEN, fp) ||
            sscanf(index_line, "%d", &index_version) != 1 ||
-           index_version != PLUGIN_FILE_VERSION ) ret = 1;
-
-       while( !ret && !feof(fp)) {
-               char *sp = index_line, *plugin_path = 0, *plugin_title = 0;
-               if( fgets(sp, BCTEXTLEN, fp) ) {
-                       plugin_path = PluginServer::table_quoted_field(sp);
-                       if( plugin_exists(plugin_path) ) continue;
-                       plugin_title = PluginServer::table_quoted_field(sp);
+           index_version != PLUGIN_FILE_VERSION ||
+           !fgets(index_line, BCTEXTLEN, fp) ||
+           (int)strlen(index_line)-1 != len || index_line[len] != '\n' ||
+           strncmp(index_line, plugin_dir, len) != 0 ) ret = 1;
+
+       ArrayList<PluginServer*> plugins;
+       while( !ret && !feof(fp) && fgets(index_line, BCTEXTLEN, fp) ) {
+               if( index_line[0] == ';' ) continue;
+               if( index_line[0] == '#' ) continue;
+               int type = PLUGIN_TYPE_UNKNOWN;
+               char path[BCTEXTLEN], title[BCTEXTLEN];
+               int64_t mtime = 0;
+               if( PluginServer::scan_table(index_line, type, path, title, mtime) ) {
+                       ret = 1; continue;
                }
-               if( plugin_path && plugin_title ) {
-// Create plugin server from index entry
-                       PluginServer *new_plugin = new PluginServer(path, mwindow);
-                       new_plugin->set_path(plugin_path);
-                       new_plugin->set_title(plugin_title);
-                       if( new_plugin->read_table(sp) ) {
-                               delete new_plugin;
-                               ret = 1;  break;
+               PluginServer *server = 0;
+               switch( type ) {
+               case PLUGIN_TYPE_BUILTIN:
+               case PLUGIN_TYPE_EXECUTABLE:
+               case PLUGIN_TYPE_LADSPA: {
+                       char plugin_path[BCTEXTLEN];  struct stat st;
+                       sprintf(plugin_path, "%s/%s", plugin_dir, path);
+                       if( stat(plugin_path, &st) || st.st_mtime != mtime ) {
+                               ret = 1; continue;
                        }
-                       plugindb->append(new_plugin);
+                       server = new PluginServer(mwindow, plugin_path, type);
+                       break; }
+               case PLUGIN_TYPE_FFMPEG: {
+                       server = new_ffmpeg_server(mwindow, path);
+                       break; }
+               }
+               if( !server ) continue;
+               plugins.append(server);
+// Create plugin server from index entry
+               server->set_title(title);
+               if( server->read_table(index_line) ) {
+                       ret = 1;  continue;
                }
        }
-
        fclose(fp);
+
+       if( !ret )
+               ret = check_plugin_index(plugins, plugin_dir, ".");
+
+       if( !ret )
+               add_plugins(plugins);
+       else
+               plugins.remove_all_objects();
+
        return ret;
 }
 
-void MWindow::init_plugin_index(MWindow *mwindow, Preferences *preferences, FILE *fp,
-       const char *plug_dir, const char *plug_path, int &idx)
+int MWindow::check_plugin_index(ArrayList<PluginServer*> &plugins,
+       const char *plug_dir, const char *plug_path)
 {
        char plugin_path[BCTEXTLEN];
-       if( *plug_path != '/' )
-               sprintf(plugin_path, "%s/%s", plug_dir, plug_path);
-       else
-               strcpy(plugin_path, plug_path);
+       sprintf(plugin_path, "%s/%s", plug_dir, plug_path);
        FileSystem fs;
        fs.set_filter( "[*.plugin][*.so]" );
-       int result = fs.update(plugin_path);
-       if( result || !fs.dir_list.total ) return;
-       int vis_id = ++idx;
+       if( fs.update(plugin_path) )
+               return 1;
 
        for( int i=0; i<fs.dir_list.total; ++i ) {
-               char *fs_path = fs.dir_list.values[i]->path;
-               char *base_path = FileSystem::basepath(fs_path), *bp = base_path;
-               const char *dp = plug_dir;
-               while( *bp && *dp && *bp == *dp ) { ++bp; ++dp; }
-               strcpy(plugin_path, !*dp && *bp == '/' ? bp+1 : base_path);
-               delete [] base_path;
+               char fs_path[BCTEXTLEN];
+               get_plugin_path(fs_path, 0, fs.dir_list[i]->path);
                if( fs.is_dir(fs_path) ) {
-                       init_plugin_index(mwindow, preferences, fp, plug_dir, plugin_path, idx);
-                       continue;
-               }
-               if( plugin_exists(plugin_path) ) continue;
-               PluginServer *new_plugin = new PluginServer(plugin_path, mwindow);
-               result = new_plugin->open_plugin(1, preferences, 0, 0);
-               if( !result ) {
-                       new_plugin->write_table(fp,vis_id);
-                       new_plugin->close_plugin();
-                       new_plugin->delete_this();
-                       continue;
-               }
-               if( result != PLUGINSERVER_IS_LAD ) continue;
-               int lad_index = 0;
-               for(;;) {
-                       PluginServer *new_plugin = new PluginServer(plugin_path, mwindow);
-                       new_plugin->set_lad_index(lad_index++);
-                       result = new_plugin->open_plugin(1, preferences, 0, 0);
-                       if( result ) break;
-                       new_plugin->write_table(fp,vis_id);
-                       new_plugin->close_plugin();
-                       new_plugin->delete_this();
+                       get_plugin_path(plugin_path, plug_dir, fs_path);
+                       if( check_plugin_index(plugins, plug_dir, plugin_path) )
+                               return 1;
                }
+               else if( !plugin_exists(fs_path, plugins) )
+                       return 1;
        }
+       return 0;
 }
 
+
 int MWindow::init_plugins(MWindow *mwindow, Preferences *preferences)
 {
-       if( !plugindb ) plugindb = new ArrayList<PluginServer*>;
-       char index_path[BCTEXTLEN];
-       sprintf(index_path, "%s/%s", preferences->plugin_dir, PLUGIN_FILE);
-       if( !load_plugin_index(mwindow, index_path) ) return 1;
+       if( !plugindb )
+               plugindb = new ArrayList<PluginServer*>;
+       init_ffmpeg();
+       char index_path[BCTEXTLEN], plugin_path[BCTEXTLEN];
+       create_defaults_path(index_path, PLUGIN_FILE);
+       char *plugin_dir = FileSystem::basepath(preferences->plugin_dir);
+       strcpy(plugin_path, plugin_dir);  delete [] plugin_dir;
+       if( !load_plugin_index(mwindow, index_path, plugin_path) ) return 1;
+       printf("init plugin index: %s\n", plugin_path);
        FILE *fp = fopen(index_path,"w");
        if( !fp ) {
-               fprintf(stderr," MWindow::init_plugins: "
-                       "can't create plugin index: %s\n", index_path);
+               fprintf(stderr,_("MWindow::init_plugins: "
+                       "can't create plugin index: %s\n"), index_path);
+               return 1;
+       }
+       fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
+       fprintf(fp, "%s\n", plugin_path);
+       init_plugin_index(mwindow, preferences, fp, plugin_path);
+       init_ffmpeg_index(mwindow, preferences, fp);
+       fclose(fp);
+       return load_plugin_index(mwindow, index_path, plugin_path);
+}
+
+int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences)
+{
+       char *path = getenv("LADSPA_PATH");
+       char ladspa_path[BCTEXTLEN];
+       if( !path ) {
+               get_exe_path(ladspa_path);
+               strcat(ladspa_path, "/ladspa");
+               path = ladspa_path;
+       }
+       for( int len=0; *path; path+=len ) {
+               char *cp = strchr(path,':');
+               len = !cp ? strlen(path) : cp-path;
+               char index_path[BCTEXTLEN], plugin_path[BCTEXTLEN];
+               memcpy(plugin_path, path, len);  plugin_path[len] = 0;
+               char *plugin_dir = FileSystem::basepath(plugin_path);
+               strcpy(plugin_path, plugin_dir);  delete [] plugin_dir;
+               create_defaults_path(index_path, LADSPA_FILE);
+               cp = index_path + strlen(index_path);
+               for( char *bp=plugin_path; *bp!=0; ++bp )
+                       *cp++ = *bp=='/' ? '_' : *bp;
+               *cp = 0;
+               if( !load_plugin_index(mwindow, index_path, plugin_path) ) continue;
+               if( init_ladspa_index(mwindow, preferences, index_path, plugin_path) ) continue;
+               load_plugin_index(mwindow, index_path, plugin_path);
+       }
+       return 1;
+}
+
+void MWindow::init_plugin_index(MWindow *mwindow, Preferences *preferences,
+       FILE *fp, const char *plugin_dir)
+{
+       int idx = PLUGIN_IDS;
+       if( plugindb ) {
+               for( int i=0; i<plugindb->size(); ++i ) {
+                       PluginServer *server = plugindb->get(i);
+                       if( server->dir_idx >= idx )
+                               idx = server->dir_idx+1;
+               }
+       }
+       scan_plugin_index(mwindow, preferences, fp, plugin_dir, ".", idx);
+}
+
+int MWindow::init_ladspa_index(MWindow *mwindow, Preferences *preferences,
+       const char *index_path, const char *plugin_dir)
+{
+       char plugin_path[BCTEXTLEN], *path = FileSystem::basepath(plugin_dir);
+       strcpy(plugin_path, path);  delete [] path;
+       printf("init ladspa index: %s\n", plugin_dir);
+       FILE *fp = fopen(index_path,"w");
+        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);
-       char *plug_path = FileSystem::basepath(preferences->plugin_dir);
-       int dir_id = 0;
-       init_plugin_index(mwindow, preferences, fp, plug_path, ".", dir_id);
+       fprintf(fp, "%s\n", plugin_dir);
+        init_plugin_index(mwindow, preferences, fp, plugin_path);
        fclose(fp);
-       delete [] plug_path;
-       return load_plugin_index(mwindow, index_path);
+       return 0;
+}
+
+void MWindow::scan_plugin_index(MWindow *mwindow, Preferences *preferences, FILE *fp,
+       const char *plug_dir, const char *plug_path, int &idx)
+{
+       char plugin_path[BCTEXTLEN];
+       sprintf(plugin_path, "%s/%s", plug_dir, plug_path);
+       FileSystem fs;
+       fs.set_filter( "[*.plugin][*.so]" );
+       int result = fs.update(plugin_path);
+       if( result || !fs.dir_list.total ) return;
+       int vis_id = idx++;
+
+       for( int i=0; i<fs.dir_list.total; ++i ) {
+               char fs_path[BCTEXTLEN], path[BCTEXTLEN];
+               get_plugin_path(fs_path, 0, fs.dir_list[i]->path);
+               get_plugin_path(path, plug_dir, fs_path);
+               if( fs.is_dir(fs_path) ) {
+                       scan_plugin_index(mwindow, preferences, fp, plug_dir, path, idx);
+                       continue;
+               }
+               if( plugin_exists(path) ) continue;
+               struct stat st;
+               if( stat(fs_path, &st) ) continue;
+               int64_t mtime = st.st_mtime;
+               PluginServer server(mwindow, fs_path, PLUGIN_TYPE_UNKNOWN);
+               result = server.open_plugin(1, preferences, 0, 0);
+               if( !result ) {
+                       server.write_table(fp, path, vis_id, mtime);
+                       server.close_plugin();
+               }
+               else if( result == PLUGINSERVER_IS_LAD ) {
+                       int lad_index = 0;
+                       for(;;) {
+                               PluginServer ladspa(mwindow, fs_path, PLUGIN_TYPE_LADSPA);
+                               ladspa.set_lad_index(lad_index++);
+                               result = ladspa.open_plugin(1, preferences, 0, 0);
+                               if( result ) break;
+                               ladspa.write_table(fp, path, PLUGIN_LADSPA_ID, mtime);
+                               ladspa.close_plugin();
+                       }
+               }
+       }
+}
+
+void MWindow::add_plugins(ArrayList<PluginServer*> &plugins)
+{
+       for( int i=0; i<plugins.size(); ++i )
+               plugindb->append(plugins[i]);
+       plugins.remove_all();
 }
 
 void MWindow::delete_plugins()
@@ -493,7 +631,7 @@ void MWindow::search_plugindb(int do_audio,
 // Get plugins
        for(int i = 0; i < MWindow::plugindb->total; i++)
        {
-               PluginServer *current = MWindow::plugindb->values[i];
+               PluginServer *current = MWindow::plugindb->get(i);
 
                if(current->audio == do_audio &&
                        current->video == do_video &&
@@ -511,13 +649,13 @@ void MWindow::search_plugindb(int do_audio,
                
                for(int i = 0; i < results.total - 1; i++)
                {
-                       PluginServer *value1 = results.values[i];
-                       PluginServer *value2 = results.values[i + 1];
+                       PluginServer *value1 = results[i];
+                       PluginServer *value2 = results[i + 1];
                        if(strcmp(_(value1->title), _(value2->title)) > 0)
                        {
                                done = 0;
-                               results.values[i] = value2;
-                               results.values[i + 1] = value1;
+                               results[i] = value2;
+                               results[i + 1] = value1;
                        }
                }
        }
@@ -534,26 +672,29 @@ PluginServer* MWindow::scan_plugindb(char *title,
 
        for(int i = 0; i < plugindb->total; i++)
        {
-               PluginServer *server = plugindb->values[i];
+               PluginServer *server = plugindb->get(i);
                if(server->title &&
                        !strcasecmp(server->title, title) &&
                        (data_type < 0 ||
                                (data_type == TRACK_AUDIO && server->audio) ||
                                (data_type == TRACK_VIDEO && server->video))) 
-                       return plugindb->values[i];
+                       return plugindb->get(i);
        }
        return 0;
 }
 
-int MWindow::plugin_exists(char *plugin_path)
+int MWindow::plugin_exists(const char *plugin_path, ArrayList<PluginServer*> &plugins)
 {
-       for( int i=0; i<plugindb->total; ++i ) {
-               PluginServer *server = plugindb->values[i];
-               if( !strcmp(plugin_path, server->get_path()) ) return 1;
-       }
+       for( int i=0; i<plugins.size(); ++i )
+               if( !strcmp(plugin_path, plugins[i]->get_path()) ) return 1;
        return 0;
 }
 
+int MWindow::plugin_exists(char *plugin_path)
+{
+       return !plugindb ? 0 : plugin_exists(plugin_path, *plugindb);
+}
+
 void MWindow::init_preferences()
 {
        preferences = new Preferences;
@@ -591,10 +732,10 @@ void MWindow::clean_indexes()
                result = 0;
                for(int i = 0; i < fs.dir_list.total && !result; i++)
                {
-                       fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
+                       fs.join_names(string, preferences->index_directory, fs.dir_list[i]->name);
                        if(fs.is_dir(string))
                        {
-                               delete fs.dir_list.values[i];
+                               delete fs.dir_list[i];
                                fs.dir_list.remove_number(i);
                                result = 1;
                        }
@@ -608,7 +749,7 @@ void MWindow::clean_indexes()
 // Get oldest
                for(int i = 0; i < fs.dir_list.total; i++)
                {
-                       fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
+                       fs.join_names(string, preferences->index_directory, fs.dir_list[i]->name);
 
                        if(i == 0 || fs.get_date(string) <= oldest)
                        {
@@ -622,11 +763,11 @@ void MWindow::clean_indexes()
 // Remove index file
                        fs.join_names(string, 
                                preferences->index_directory, 
-                               fs.dir_list.values[oldest_item]->name);
+                               fs.dir_list[oldest_item]->name);
 //printf("MWindow::clean_indexes 1 %s\n", string);
                        if(remove(string))
                                perror("delete_indexes");
-                       delete fs.dir_list.values[oldest_item];
+                       delete fs.dir_list[oldest_item];
                        fs.dir_list.remove_number(oldest_item);
 
 // Remove table of contents if it exists
@@ -637,6 +778,8 @@ void MWindow::clean_indexes()
 //printf("MWindow::clean_indexes 2 %s\n", string2);
                                sprintf(ptr, ".toc");
                                remove(string2);
+                               sprintf(ptr, ".mkr");
+                               remove(string2);
                        }
                }
 
@@ -658,40 +801,62 @@ void MWindow::init_gwindow()
 
 void MWindow::init_tipwindow()
 {
-       twindow = new TipWindow(this);
+       if( !twindow )
+               twindow = new TipWindow(this);
        twindow->start();
 }
 
+void MWindow::show_warning(int *do_warning, const char *text)
+{
+       if( do_warning && !*do_warning ) return;
+       if( !wwindow )
+               wwindow = new WWindow(this);
+       wwindow->show_warning(do_warning, text);
+}
+
 void MWindow::init_theme()
 {
        Timer timer;
        theme = 0;
 
-// Replace blond theme with SUV since it doesn't work
-       if(!strcasecmp(preferences->theme, "Blond"))
-               strcpy(preferences->theme, DEFAULT_THEME);
+       PluginServer *theme_plugin = 0;
+       for(int i = 0; i < plugindb->total && !theme_plugin; i++) {
+               if( plugindb->get(i)->theme &&
+                   !strcasecmp(preferences->theme, plugindb->get(i)->title) )
+                       theme_plugin = plugindb->get(i);
+       }
 
-       for(int i = 0; i < plugindb->total; i++)
-       {
-               if(plugindb->values[i]->theme &&
-                       !strcasecmp(preferences->theme, plugindb->values[i]->title))
-               {
-                       PluginServer plugin = *plugindb->values[i];
-                       plugin.open_plugin(0, preferences, 0, 0);
-                       theme = plugin.new_theme();
-                       theme->mwindow = this;
-                       strcpy(theme->path, plugin.path);
-                       plugin.close_plugin();
-                       break;
+       if( !theme_plugin )
+               fprintf(stderr, _("MWindow::init_theme: prefered theme %s not found.\n"),
+                        preferences->theme);
+
+       if( !theme_plugin && strcasecmp(preferences->theme, DEFAULT_THEME) ) {
+               fprintf(stderr, _("MWindow::init_theme: trying default theme %s\n"),
+                       DEFAULT_THEME);
+               for(int i = 0; i < plugindb->total && !theme_plugin; i++) {
+                       if( plugindb->get(i)->theme &&
+                           !strcasecmp(DEFAULT_THEME, plugindb->get(i)->title) )
+                               theme_plugin = plugindb->get(i);
                }
        }
 
-       if(!theme)
-       {
-               fprintf(stderr, _("MWindow::init_theme: theme %s not found.\n"), preferences->theme);
+       if(!theme_plugin) {
+               fprintf(stderr, _("MWindow::init_theme: theme_plugin not found.\n"));
                exit(1);
        }
 
+       PluginServer *plugin = new PluginServer(*theme_plugin);
+       if( plugin->open_plugin(0, preferences, 0, 0) ) {
+               fprintf(stderr, _("MWindow::init_theme: unable to load theme %s\n"),
+                       theme_plugin->title);
+               exit(1);
+       }
+
+       theme = plugin->new_theme();
+       theme->mwindow = this;
+       strcpy(theme->path, plugin->path);
+       delete plugin;
+
 // Load default images & settings
        theme->Theme::initialize();
 // Load user images & settings
@@ -735,10 +900,10 @@ void MWindow::init_levelwindow()
 VWindow *MWindow::get_viewer(int start_it, int idx)
 {
        vwindows_lock->lock("MWindow::get_viewer");
-       VWindow *vwindow = idx >= 0 && idx < vwindows.size() ? vwindows.get(idx) : 0;
+       VWindow *vwindow = idx >= 0 && idx < vwindows.size() ? vwindows[idx] : 0;
        if( !vwindow ) idx = vwindows.size();
        while( !vwindow && --idx >= 0 ) {
-               VWindow *vwin = vwindows.get(idx);
+               VWindow *vwin = vwindows[idx];
                if( !vwin->is_running() || !vwin->get_edl() )
                        vwindow = vwin;
        }
@@ -770,25 +935,25 @@ void MWindow::init_channeldb()
 void MWindow::init_menus()
 {
        char string[BCTEXTLEN];
-       cmodel_to_text(string, BC_RGB888);
+       BC_CModels::to_text(string, BC_RGB888);
        colormodels.append(new ColormodelItem(string, BC_RGB888));
-       cmodel_to_text(string, BC_RGBA8888);
+       BC_CModels::to_text(string, BC_RGBA8888);
        colormodels.append(new ColormodelItem(string, BC_RGBA8888));
-//     cmodel_to_text(string, BC_RGB161616);
+//     BC_CModels::to_text(string, BC_RGB161616);
 //     colormodels.append(new ColormodelItem(string, BC_RGB161616));
-//     cmodel_to_text(string, BC_RGBA16161616);
+//     BC_CModels::to_text(string, BC_RGBA16161616);
 //     colormodels.append(new ColormodelItem(string, BC_RGBA16161616));
-       cmodel_to_text(string, BC_RGB_FLOAT);
+       BC_CModels::to_text(string, BC_RGB_FLOAT);
        colormodels.append(new ColormodelItem(string, BC_RGB_FLOAT));
-       cmodel_to_text(string, BC_RGBA_FLOAT);
+       BC_CModels::to_text(string, BC_RGBA_FLOAT);
        colormodels.append(new ColormodelItem(string, BC_RGBA_FLOAT));
-       cmodel_to_text(string, BC_YUV888);
+       BC_CModels::to_text(string, BC_YUV888);
        colormodels.append(new ColormodelItem(string, BC_YUV888));
-       cmodel_to_text(string, BC_YUVA8888);
+       BC_CModels::to_text(string, BC_YUVA8888);
        colormodels.append(new ColormodelItem(string, BC_YUVA8888));
-//     cmodel_to_text(string, BC_YUV161616);
+//     BC_CModels::to_text(string, BC_YUV161616);
 //     colormodels.append(new ColormodelItem(string, BC_YUV161616));
-//     cmodel_to_text(string, BC_YUVA16161616);
+//     BC_CModels::to_text(string, BC_YUVA16161616);
 //     colormodels.append(new ColormodelItem(string, BC_YUVA16161616));
 }
 
@@ -817,6 +982,7 @@ ENABLE_BUFFER
 void MWindow::init_render()
 {
        render = new Render(this);
+       create_bd = new CreateBD_Thread(this);
        create_dvd = new CreateDVD_Thread(this);
        batch_render = new BatchRenderThread(this);
 }
@@ -930,7 +1096,7 @@ int MWindow::put_commercial()
        for(Track *track=tracks->first; track && !errmsg; track=track->next) {
                if( track->data_type != TRACK_VIDEO ) continue;
                if( !track->record ) continue;
-               if( count > 0 ) { errmsg = "multiple video tracks"; break; }
+               if( count > 0 ) { errmsg = _("multiple video tracks"); break; }
                ++count;
                int64_t units_start = track->to_units(start,0);
                int64_t units_end = track->to_units(end,0);
@@ -942,9 +1108,9 @@ int MWindow::put_commercial()
                        edit2 = edits->last;
                        units_end = edits->length();
                }
-               if(edit1 != edit2) { errmsg = "crosses edits"; break; }
+               if(edit1 != edit2) { errmsg = _("crosses edits"); break; }
                Indexable *indexable = edit1->get_source();
-               if( !indexable->is_asset ) { errmsg = "not asset"; break; }
+               if( !indexable->is_asset ) { errmsg = _("not asset"); break; }
        }
        //run it
        for(Track *track=tracks->first; track && !errmsg; track=track->next) {
@@ -963,17 +1129,17 @@ int MWindow::put_commercial()
                Indexable *indexable = edit1->get_source();
                Asset *asset = (Asset *)indexable;
                File *file = video_cache->check_out(asset, edl);
-               if( !file ) { errmsg = "no file"; break; }
+               if( !file ) { errmsg = _("no file"); break; }
                int64_t edit_length = units_end - units_start;
                int64_t edit_start = units_start - edit1->startproject + edit1->startsource;
                result = commercials->put_clip(file, edit1->channel,
                        track->from_units(edit_start), track->from_units(edit_length));
                video_cache->check_in(asset);
-               if( result ) { errmsg = "db failed"; break; }
+               if( result ) { errmsg = _("db failed"); break; }
        }
        if( errmsg ) {
                char string[BCTEXTLEN];
-               sprintf(string, "put_commercial: %s", errmsg);
+               sprintf(string, _("put_commercial: %s"), errmsg);
                MainError::show_error(string);
                undo_commercial();
                result = 1;
@@ -992,17 +1158,11 @@ void MWindow::stop_playback(int wait)
                0);
        cwindow->playback_engine->interrupt_playback(wait);
 
-       for(int i = 0; i < vwindows.size(); i++)
-       {
-               VWindow *vwindow = vwindows.get(i);
-               if(vwindow->running())
-               {
-                       vwindow->playback_engine->que->send_command(STOP,
-                               CHANGE_NONE, 
-                               0,
-                               0);
-                       vwindow->playback_engine->interrupt_playback(wait);
-               }
+       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);
        }
         if( locked ) gui->lock_window("MWindow::stop_playback");
 }
@@ -1024,6 +1184,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 // deleted.
        stop_playback(1);
 
+if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        undo->update_undo_before();
 
 
@@ -1031,11 +1192,11 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
 // Define new_edls and new_assets to load
        int result = 0, ftype = -1;
-       for(int i = 0; i < filenames->total; i++)
+       for(int i = 0; i < filenames->size(); i++)
        {
 // Get type of file
                File *new_file = new File;
-               Asset *new_asset = new Asset(filenames->values[i]);
+               Asset *new_asset = new Asset(filenames->get(i));
                EDL *new_edl = new EDL;
                char string[BCTEXTLEN];
 
@@ -1043,7 +1204,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                new_edl->copy_session(edl);
                new_file->set_program(edl->session->program_no);
 
-               sprintf(string, "Loading %s", new_asset->path);
+               sprintf(string, _("Loading %s"), new_asset->path);
                gui->show_message(string);
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
@@ -1061,7 +1222,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                                        (new_asset->height % 2)))
                                {
                                        char string[BCTEXTLEN];
-                                       sprintf(string, "%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly.",
+                                       sprintf(string, _("%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly."),
                                                new_asset->path,
                                                new_asset->width,
                                                new_asset->height);
@@ -1072,8 +1233,8 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                                        edl->session->program_no != new_asset->program)
                                {
                                        char string[BCTEXTLEN];
-                                       sprintf(string, "%s's index was built for program number %d\n"
-                                               "Playback preference is %d.\n  Using program %d.",
+                                       sprintf(string, _("%s's index was built for program number %d\n"
+                                               "Playback preference is %d.\n  Using program %d."),
                                                new_asset->path, new_asset->program,
                                                edl->session->program_no, new_asset->program);
                                        MainError::show_error(string);
@@ -1150,7 +1311,7 @@ SET_TRACE
                                                }
                                                else
                                                {
-                                                       old_asset = new_edls.values[j]->assets->get_asset(new_asset->path);
+                                                       old_asset = new_edls[j]->assets->get_asset(new_asset->path);
                                                        if( old_asset )
                                                        {
                                                                *new_asset = *old_asset;
@@ -1226,7 +1387,7 @@ SET_TRACE
                        {
                                FileXML xml_file;
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
-                               xml_file.read_from_file(filenames->values[i]);
+                               xml_file.read_from_file(filenames->get(i));
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
                                if(load_mode == LOADMODE_NESTED)
@@ -1234,7 +1395,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 // Load temporary EDL for nesting.
                                        EDL *nested_edl = new EDL;
                                        nested_edl->create_objects();
-                                       nested_edl->set_path(filenames->values[i]);
+                                       nested_edl->set_path(filenames->get(i));
                                        nested_edl->load_xml(&xml_file, LOAD_ALL);
 //printf("MWindow::load_filenames %p %s\n", nested_edl, nested_edl->project_path);
                                        edl_to_nested(new_edl, nested_edl);
@@ -1245,15 +1406,15 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 // Load EDL for pasting
                                        new_edl->load_xml(&xml_file, LOAD_ALL);
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
-                                       test_plugins(new_edl, filenames->values[i]);
+                                       test_plugins(new_edl, filenames->get(i));
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
                                        if(load_mode == LOADMODE_REPLACE || 
                                                load_mode == LOADMODE_REPLACE_CONCATENATE)
                                        {
-                                               strcpy(session->filename, filenames->values[i]);
+                                               strcpy(session->filename, filenames->get(i));
                                                strcpy(new_edl->local_session->clip_title, 
-                                                       filenames->values[i]);
+                                                       filenames->get(i));
                                                if(update_filename)
                                                        set_filename(new_edl->local_session->clip_title);
                                        }
@@ -1323,7 +1484,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        int got_indexes = 0;
        for(int i = 0; i < new_edls.size(); i++)
        {
-               EDL *new_edl = new_edls.get(i);
+               EDL *new_edl = new_edls[i];
                for(int j = 0; j < new_edl->nested_edls->size(); j++)
                {
                        mainindexes->add_next_asset(0, 
@@ -1339,13 +1500,13 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        {
                for(int i = 0; i < new_assets.size(); i++)
                {
-                       Asset *new_asset = new_assets.get(i);
+                       Asset *new_asset = new_assets[i];
 
                        File *new_file = 0;
                        int got_it = 0;
                        for(int j = 0; j < new_files.size(); j++)
                        {
-                               new_file = new_files.get(j);
+                               new_file = new_files[j];
                                if(!strcmp(new_file->asset->path,
                                        new_asset->path))
                                {
@@ -1374,7 +1535,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        {
                for(int j = 0; j < track->plugin_set.size(); j++)
                {
-                       PluginSet *plugins = track->plugin_set.get(j);
+                       PluginSet *plugins = track->plugin_set[j];
                        Plugin *plugin = plugins->get_first_plugin();
 
                        while(plugin)
@@ -1407,20 +1568,21 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                select_asset(0, 0);
                edl->local_session->preview_start = 0;
                edl->local_session->preview_end = edl->tracks->total_playable_length();
+               edl->local_session->loop_playback = 0;
                edl->local_session->set_selectionstart(0);
                edl->local_session->set_selectionend(0);
                fit_selection();
                goto_start();
        }
 
-
-       update_project(load_mode);
-
+// need to update undo before project, since mwindow is unlocked & a new load
+// can begin here.  Should really prevent loading until we're done.
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
+       undo->update_undo_after(_("load"), LOAD_ALL);
 
        for(int i = 0; i < new_edls.size(); i++)
        {
-               new_edls.get(i)->remove_user();
+               new_edls[i]->remove_user();
        }
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
@@ -1428,14 +1590,14 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
        for(int i = 0; i < new_assets.size(); i++)
        {
-               new_assets.get(i)->Garbage::remove_user();
+               new_assets[i]->Garbage::remove_user();
        }
 
        new_assets.remove_all();
        new_files.remove_all_objects();
 
-       undo->update_undo_after(_("load"), LOAD_ALL);
 
+if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        if(load_mode == LOADMODE_REPLACE ||
                load_mode == LOADMODE_REPLACE_CONCATENATE)
        {
@@ -1450,6 +1612,10 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
 
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
+       update_project(load_mode);
+
+if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
+
        return 0;
 }
 
@@ -1465,7 +1631,7 @@ void MWindow::test_plugins(EDL *new_edl, char *path)
        {
                for(int k = 0; k < track->plugin_set.total; k++)
                {
-                       PluginSet *plugin_set = track->plugin_set.values[k];
+                       PluginSet *plugin_set = track->plugin_set[k];
                        for(Plugin *plugin = (Plugin*)plugin_set->first; 
                                plugin; 
                                plugin = (Plugin*)plugin->next)
@@ -1489,9 +1655,9 @@ void MWindow::test_plugins(EDL *new_edl, char *path)
                                        if (!plugin_found) 
                                        {
                                                sprintf(string, 
-                                                       "The effect '%s' in file '%s' is not part of your installation of Cinelerra.\n"
-                                                       "The project won't be rendered as it was meant and Cinelerra might crash.\n",
-                                                       plugin->title, 
+       _("The %s '%s' in file '%s' is not part of your installation of Cinelerra.\n"
+         "The project won't be rendered as it was meant and Cinelerra might crash.\n"),
+                                                       "effect", plugin->title, 
                                                        path); 
                                                MainError::show_error(string);
                                        }
@@ -1522,9 +1688,9 @@ void MWindow::test_plugins(EDL *new_edl, char *path)
                                if (!transition_found) 
                                {
                                        sprintf(string, 
-                                               "The transition '%s' in file '%s' is not part of your installation of Cinelerra.\n"
-                                               "The project won't be rendered as it was meant and Cinelerra might crash.\n",
-                                               edit->transition->title, 
+       _("The %s '%s' in file '%s' is not part of your installation of Cinelerra.\n"
+         "The project won't be rendered as it was meant and Cinelerra might crash.\n"),
+                                               "transition", edit->transition->title, 
                                                path); 
                                        MainError::show_error(string);
                                }
@@ -1556,26 +1722,16 @@ void MWindow::init_shm()
        fd = 0;
        if(result < 0x7fffffff) {
                char string[BCTEXTLEN];
-               sprintf(string, "MWindow::init_shm: /proc/sys/kernel/shmmax is 0x" _LX ".\n"
+               sprintf(string, _("MWindow::init_shm: /proc/sys/kernel/shmmax is 0x" _LX ".\n"
                        "you probably need to be root, or:\n"
                        "as root, run: echo 0x7fffffff > /proc/sys/kernel/shmmax\n"
                        "before trying to start cinelerra.\n"
-                       "It should be at least 0x7fffffff for Cinelerra.\n", result);
+                       "It should be at least 0x7fffffff for Cinelerra.\n"), result);
                MainError::show_error(string);
        }
 }
 
 
-void MWindow::init_fileserver(Preferences *preferences)
-{
-#ifdef USE_FILEFORK
-       if( !file_server && preferences->file_forking ) {
-               file_server = new FileServer(preferences);
-               file_server->start();
-       }
-#endif
-}
-
 void MWindow::create_objects(int want_gui, 
        int want_new,
        char *config_path)
@@ -1591,19 +1747,26 @@ void MWindow::create_objects(int want_gui,
        init_3d();
 
        if(debug) PRINT_TRACE
-//     show_splash();
+       show_splash();
 
-       init_error();
        if(debug) PRINT_TRACE
        init_defaults(defaults, config_path);
        init_preferences();
+       if(splash_window)
+               splash_window->operation->update(_("Initializing Plugins"));
        init_plugins(this, preferences);
        if(debug) PRINT_TRACE
-       if(splash_window) splash_window->operation->update(_("Initializing GUI"));
+       init_ladspa_plugins(this, preferences);
+       if(debug) PRINT_TRACE
+       if(splash_window)
+               splash_window->operation->update(_("Initializing GUI"));
        if(debug) PRINT_TRACE
        init_theme();
        if(debug) PRINT_TRACE
+       init_error();
 
+       if(splash_window)
+               splash_window->operation->update(_("Initializing Fonts"));
        char string[BCTEXTLEN];
        strcpy(string, preferences->plugin_dir);
        strcat(string, "/fonts");
@@ -1612,7 +1775,6 @@ void MWindow::create_objects(int want_gui,
 
 // Initialize before too much else is running
 // Preferences & theme are required for building MPEG table of contents
-       init_fileserver(preferences);
 
 // Default project created here
        init_edl();
@@ -1671,11 +1833,10 @@ void MWindow::create_objects(int want_gui,
                session->show_vwindow);
 
 // Show all vwindows
-//     if(session->show_vwindow)
-//     {
-//             for(int j = 0; j < vwindows.size(); j++)
-//             {
-//                     VWindow *vwindow = vwindows.get(j);
+//     if(session->show_vwindow) {
+//             for(int j = 0; j < vwindows.size(); j++) {
+//                     VWindow *vwindow = vwindows[j];
+//                     if( !vwindow->is_running() ) continue;
 //                     if(debug) printf("MWindow::create_objects %d vwindow=%p\n", 
 //                             __LINE__, 
 //                             vwindow);
@@ -1760,12 +1921,12 @@ void MWindow::create_objects(int want_gui,
 
 void MWindow::show_splash()
 {
-#include "data/heroine_logo11_png.h"
-       VFrame *frame = new VFrame(heroine_logo11_png);
-       BC_DisplayInfo display_info;
-       splash_window = new SplashGUI(frame, 
-               display_info.get_root_w() / 2 - frame->get_w() / 2,
-               display_info.get_root_h() / 2 - frame->get_h() / 2);
+#include "data/heroine_logo9_png.h"
+       VFrame *frame = new VFramePng(heroine_logo9_png);
+       BC_DisplayInfo dpyi;
+       int rw = dpyi.get_root_w(), rh = dpyi.get_root_h();
+       int rr = (rw < rh ? rw : rh) / 4;
+       splash_window = new SplashGUI(frame, rr, rr);
        splash_window->create_objects();
 }
 
@@ -1781,7 +1942,7 @@ void MWindow::start()
 {
 ENABLE_BUFFER
 //PRINT_TRACE
-//     vwindows.get(DEFAULT_VWINDOW)->start();
+//     vwindows[DEFAULT_VWINDOW]->start();
        awindow->start();
 //PRINT_TRACE
        cwindow->start();
@@ -1790,7 +1951,7 @@ ENABLE_BUFFER
 //PRINT_TRACE
        gwindow->start();
 //PRINT_TRACE
-       Thread::start();
+//     Thread::start();
 //PRINT_TRACE
        playback_3d->start();
 //PRINT_TRACE
@@ -1806,23 +1967,19 @@ void MWindow::show_vwindow()
        int total_running = 0;
        session->show_vwindow = 1;
 
-
+//printf("MWindow::show_vwindow %d %d\n", __LINE__, vwindows.size());
 // Raise all windows which are visible
-       for(int j = 0; j < vwindows.size(); j++)
-       {
-               VWindow *vwindow = vwindows.get(j);
-               if(vwindow->is_running())
-               {
-                       vwindow->gui->lock_window("MWindow::show_vwindow");
-                       vwindow->gui->show_window(0);
-                       vwindow->gui->raise_window();
-                       vwindow->gui->flush();
-                       vwindow->gui->unlock_window();
-                       total_running++;
-               }
+       for(int j = 0; j < vwindows.size(); j++) {
+               VWindow *vwindow = vwindows[j];
+               if( !vwindow->is_running() ) continue;
+               vwindow->gui->lock_window("MWindow::show_vwindow");
+               vwindow->gui->show_window(0);
+               vwindow->gui->raise_window();
+               vwindow->gui->flush();
+               vwindow->gui->unlock_window();
+               total_running++;
        }
 
-//printf("MWindow::show_vwindow %d %d\n", __LINE__, vwindows.size());
 // If no windows visible
        if(!total_running)
        {
@@ -1959,6 +2116,7 @@ int MWindow::set_editing_mode(int new_editing_mode, int lock_mwindow, int lock_c
 
 void MWindow::sync_parameters(int change_type)
 {
+       if( in_destructor ) return;
 
 // Sync engines which are playing back
        if(cwindow->playback_engine->is_playing_back)
@@ -2097,9 +2255,9 @@ SET_TRACE
        for(int i = 0; i < plugin_guis->total; i++)
        {
 // Pointer comparison
-               if(plugin_guis->values[i]->plugin == plugin)
+               if(plugin_guis->get(i)->plugin == plugin)
                {
-                       plugin_guis->values[i]->raise_window();
+                       plugin_guis->get(i)->raise_window();
                        done = 1;
                        break;
                }
@@ -2145,9 +2303,9 @@ void MWindow::hide_plugin(Plugin *plugin, int lock)
        if(lock) plugin_gui_lock->lock("MWindow::hide_plugin");
        for(int i = 0; i < plugin_guis->total; i++)
        {
-               if(plugin_guis->values[i]->plugin == plugin)
+               if(plugin_guis->get(i)->plugin == plugin)
                {
-                       PluginServer *ptr = plugin_guis->values[i];
+                       PluginServer *ptr = plugin_guis->get(i);
                        plugin_guis->remove(ptr);
                        if(lock) plugin_gui_lock->unlock();
 // Last command executed in client side close
@@ -2256,7 +2414,7 @@ void MWindow::update_plugin_guis(int do_keyframe_guis)
        {
                for(int i = 0; i < track->plugin_set.size(); i++)
                {
-                       Plugin *plugin = (Plugin*)track->plugin_set.get(i)->first;
+                       Plugin *plugin = (Plugin*)track->plugin_set[i]->first;
                        while(plugin)
                        {
                                int got_it = 0;
@@ -2291,7 +2449,7 @@ int MWindow::plugin_gui_open(Plugin *plugin)
        plugin_gui_lock->lock("MWindow::plugin_gui_open");
        for(int i = 0; i < plugin_guis->total; i++)
        {
-               if(plugin_guis->values[i]->plugin->identical_location(plugin))
+               if(plugin_guis->get(i)->plugin->identical_location(plugin))
                {
                        result = 1;
                        break;
@@ -2306,9 +2464,9 @@ void MWindow::render_plugin_gui(void *data, Plugin *plugin)
        plugin_gui_lock->lock("MWindow::render_plugin_gui");
        for(int i = 0; i < plugin_guis->total; i++)
        {
-               if(plugin_guis->values[i]->plugin->identical_location(plugin))
+               if(plugin_guis->get(i)->plugin->identical_location(plugin))
                {
-                       plugin_guis->values[i]->render_gui(data);
+                       plugin_guis->get(i)->render_gui(data);
                        break;
                }
        }
@@ -2320,9 +2478,9 @@ void MWindow::render_plugin_gui(void *data, int size, Plugin *plugin)
        plugin_gui_lock->lock("MWindow::render_plugin_gui");
        for(int i = 0; i < plugin_guis->total; i++)
        {
-               if(plugin_guis->values[i]->plugin->identical_location(plugin))
+               if(plugin_guis->get(i)->plugin->identical_location(plugin))
                {
-                       plugin_guis->values[i]->render_gui(data, size);
+                       plugin_guis->get(i)->render_gui(data, size);
                        break;
                }
        }
@@ -2337,8 +2495,8 @@ void MWindow::update_plugin_states()
        {
                int result = 0;
 // Get a plugin GUI
-               Plugin *src_plugin = plugin_guis->values[i]->plugin;
-               PluginServer *src_plugingui = plugin_guis->values[i];
+               Plugin *src_plugin = plugin_guis->get(i)->plugin;
+               PluginServer *src_plugingui = plugin_guis->get(i);
 
 // Search for plugin in EDL.  Only the master EDL shows plugin GUIs.
                for(Track *track = edl->tracks->first; 
@@ -2349,7 +2507,7 @@ void MWindow::update_plugin_states()
                                j < track->plugin_set.total && !result; 
                                j++)
                        {
-                               PluginSet *plugin_set = track->plugin_set.values[j];
+                               PluginSet *plugin_set = track->plugin_set[j];
                                for(Plugin *plugin = (Plugin*)plugin_set->first; 
                                        plugin && !result; 
                                        plugin = (Plugin*)plugin->next)
@@ -2376,7 +2534,7 @@ void MWindow::update_plugin_titles()
 {
        for(int i = 0; i < plugin_guis->total; i++)
        {
-               plugin_guis->values[i]->update_title();
+               plugin_guis->get(i)->update_title();
        }
 }
 
@@ -2506,30 +2664,28 @@ void MWindow::update_project(int load_mode)
 
 // Close all the vwindows
        if(load_mode == LOADMODE_REPLACE ||
-               load_mode == LOADMODE_REPLACE_CONCATENATE)
-       {
+               load_mode == LOADMODE_REPLACE_CONCATENATE) {
                if(debug) PRINT_TRACE
                int first_vwindow = 0;
                if(session->show_vwindow) first_vwindow = 1;
 // Change visible windows to no source
-               for(int i = 0; i < first_vwindow && i < vwindows.size(); i++)
-               {
-                       vwindows.get(i)->change_source(-1);
+               for(int i = 0; i < first_vwindow && i < vwindows.size(); i++) {
+                       VWindow *vwindow = vwindows[i];
+                       if( !vwindow->is_running() ) continue;
+                       vwindow->change_source(-1);
                }
 
 // Close remaining windows
-               for(int i = first_vwindow; i < vwindows.size(); i++)
-               {
-                       vwindows.get(i)->close_window();
+               for(int i = first_vwindow; i < vwindows.size(); i++) {
+                       VWindow *vwindow = vwindows[i];
+                       if( !vwindow->is_running() ) continue;
+                       vwindow->close_window();
                }
                if(debug) PRINT_TRACE
        }
-       else
-       if(vwindows.size())
-       {
-               VWindow *vwindow = vwindows.get(DEFAULT_VWINDOW);
-               if(vwindow->is_running())
-               {
+       else if(vwindows.size()) {
+               VWindow *vwindow = vwindows[DEFAULT_VWINDOW];
+               if( vwindow->is_running() ) {
                        vwindow->gui->lock_window("MWindow::update_project");
                        vwindow->update(1);
                        vwindow->gui->unlock_window();
@@ -2568,13 +2724,14 @@ void MWindow::remove_indexfile(Indexable *indexable)
 // Erase file
        IndexFile::delete_index(preferences, asset, ".toc");
        IndexFile::delete_index(preferences, asset, ".idx");
+       IndexFile::delete_index(preferences, asset, ".mkr");
 }
 
 void MWindow::rebuild_indices()
 {
        for(int i = 0; i < session->drag_assets->total; i++)
        {
-               Indexable *indexable = session->drag_assets->values[i];
+               Indexable *indexable = session->drag_assets->get(i);
 //printf("MWindow::rebuild_indices 1 %s\n", indexable->path);
                remove_indexfile(indexable);
 // Schedule index build
@@ -2646,8 +2803,16 @@ static inline int gcd(int m, int n)
 
 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
 {
+       w = 1;  h = 1;
        if(!width || !height) return 1;
        double ar = (double)width / height;
+// square-ish pixels
+       if( EQUIV(ar, 1.0000) ) return 0;
+       if( EQUIV(ar, 1.3333) ) { w = 4;  h = 3;  return 0; }
+       if( EQUIV(ar, 1.7777) ) { w = 16; h = 9;  return 0; }
+       if( EQUIV(ar, 2.1111) ) { w = 19; h = 9;  return 0; }
+       if( EQUIV(ar, 2.2222) ) { w = 20; h = 9;  return 0; }
+       if( EQUIV(ar, 2.3333) ) { w = 21; h = 9;  return 0; }
        int ww = width, hh = height;
        // numerator, denominator must be under mx
        int mx = 255, n = gcd(ww, hh);
@@ -2682,16 +2847,13 @@ void MWindow::reset_caches()
        if( cwindow->playback_engine && cwindow->playback_engine->video_cache )
                cwindow->playback_engine->video_cache->remove_all();
        
-       for(int i = 0; i < vwindows.size(); i++)
-       {
-               VWindow *vwindow = vwindows.get(i);
-               if(vwindow->is_running())
-               {
-                       if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
-                               vwindow->playback_engine->audio_cache->remove_all();
-                       if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
-                               vwindow->playback_engine->video_cache->remove_all();
-               }
+       for(int i = 0; i < vwindows.size(); i++) {
+               VWindow *vwindow = vwindows[i];
+               if( !vwindow->is_running() ) continue;
+               if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
+                       vwindow->playback_engine->audio_cache->remove_all();
+               if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
+                       vwindow->playback_engine->video_cache->remove_all();
        }
 }
 
@@ -2705,88 +2867,83 @@ void MWindow::remove_asset_from_caches(Asset *asset)
                cwindow->playback_engine->audio_cache->delete_entry(asset);
        if( cwindow->playback_engine && cwindow->playback_engine->video_cache )
                cwindow->playback_engine->video_cache->delete_entry(asset);
-       for(int i = 0; i < vwindows.size(); i++)
-       {
-               VWindow *vwindow = vwindows.get(i);
-               if(vwindow->is_running())
-               {
-                       if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
-                               vwindow->playback_engine->audio_cache->delete_entry(asset);
-                       if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
-                               vwindow->playback_engine->video_cache->delete_entry(asset);
-               }
+       for(int i = 0; i < vwindows.size(); i++) {
+               VWindow *vwindow = vwindows[i];
+               if( !vwindow->is_running() ) continue;
+               if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
+                       vwindow->playback_engine->audio_cache->delete_entry(asset);
+               if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
+                       vwindow->playback_engine->video_cache->delete_entry(asset);
        }
 }
 
 
-
-void MWindow::remove_assets_from_project(int push_undo)
+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->values[i];
+       for(int i = 0; i < session->drag_assets->total; i++) {
+               Indexable *indexable = session->drag_assets->get(i);
                if(indexable->is_asset) remove_asset_from_caches((Asset*)indexable);
        }
 
 // Remove from VWindow.
-       for(int i = 0; i < session->drag_clips->total; i++)
-       {
-               for(int j = 0; j < vwindows.size(); j++)
-               {
-                       VWindow *vwindow = vwindows.get(j);
-                       if(vwindow->is_running())
-                       {
-                               if(session->drag_clips->values[i] == vwindow->get_edl())
-                               {
-                                       vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
-                                       vwindow->delete_source(1, 1);
-                                       vwindow->gui->unlock_window();
-                               }
+       for(int i = 0; i < session->drag_clips->total; i++) {
+               for(int j = 0; j < vwindows.size(); j++) {
+                       VWindow *vwindow = vwindows[j];
+                       if( !vwindow->is_running() ) continue;
+                       if(session->drag_clips->get(i) == vwindow->get_edl()) {
+                               vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
+                               vwindow->delete_source(1, 1);
+                               vwindow->gui->unlock_window();
                        }
                }
        }
        
-       for(int i = 0; i < session->drag_assets->size(); i++)
-       {
-               for(int j = 0; j < vwindows.size(); j++)
-               {
-                       VWindow *vwindow = vwindows.get(j);
-                       if(vwindow->is_running())
-                       {
-                               if(session->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();
-                               }
+       for(int i = 0; i < session->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()) {
+                               vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
+                               vwindow->delete_source(1, 1);
+                               vwindow->gui->unlock_window();
                        }
                }
        }
        
+       for(int i = 0; i < session->drag_assets->size(); i++) {
+               Indexable *indexable = session->drag_assets->get(i);
+               remove_indexfile(indexable);
+       }
+
+//printf("MWindow::rebuild_indices 1 %s\n", indexable->path);
        if(push_undo) undo->update_undo_before();
-       edl->remove_from_project(session->drag_assets);
-       edl->remove_from_project(session->drag_clips);
-       save_backup();
+       if(drag_assets) edl->remove_from_project(drag_assets);
+       if(drag_clips) edl->remove_from_project(session->drag_clips);
+       if(redraw) save_backup();
        if(push_undo) undo->update_undo_after(_("remove assets"), LOAD_ALL);
-       restart_brender();
-
-       gui->lock_window("MWindow::remove_assets_from_project 3");
-       gui->update(1,
-               1,
-               1,
-               1,
-               0, 
-               1,
-               0);
-       gui->unlock_window();
-
-       awindow->gui->lock_window("MWindow::remove_assets_from_project 4");
-       awindow->gui->update_assets();
-       awindow->gui->flush();
-       awindow->gui->unlock_window();
+       if(redraw) 
+       {
+               restart_brender();
+
+               gui->lock_window("MWindow::remove_assets_from_project 3");
+               gui->update(1,
+                       1,
+                       1,
+                       1,
+                       0, 
+                       1,
+                       0);
+               gui->unlock_window();
+
+               awindow->gui->lock_window("MWindow::remove_assets_from_project 4");
+               awindow->gui->update_assets();
+               awindow->gui->flush();
+               awindow->gui->unlock_window();
 
-// Removes from playback here
-       sync_parameters(CHANGE_ALL);
+       // Removes from playback here
+               sync_parameters(CHANGE_ALL);
+       }
 }
 
 void MWindow::remove_assets_from_disk()
@@ -2794,10 +2951,13 @@ void MWindow::remove_assets_from_disk()
 // Remove from disk
        for(int i = 0; i < session->drag_assets->total; i++)
        {
-               remove(session->drag_assets->values[i]->path);
+               remove(session->drag_assets->get(i)->path);
        }
 
-       remove_assets_from_project(1);
+       remove_assets_from_project(1, 
+               1, 
+               session->drag_assets,
+               session->drag_clips);
 }
 
 void MWindow::dump_plugins(FILE *fp)
@@ -2805,16 +2965,17 @@ void MWindow::dump_plugins(FILE *fp)
        if( !plugindb ) return;
        for(int i = 0; i < plugindb->total; i++)
        {
-               fprintf(fp, "audio=%d video=%d rt=%d multi=%d"
+               fprintf(fp, "type=%d audio=%d video=%d rt=%d multi=%d"
                        " synth=%d transition=%d theme=%d %s\n",
-                       plugindb->values[i]->audio,
-                       plugindb->values[i]->video,
-                       plugindb->values[i]->realtime,
-                       plugindb->values[i]->multichannel,
-                       plugindb->values[i]->get_synthesis(),
-                       plugindb->values[i]->transition,
-                       plugindb->values[i]->theme,
-                       plugindb->values[i]->title);
+                       plugindb->get(i)->plugin_type,
+                       plugindb->get(i)->audio,
+                       plugindb->get(i)->video,
+                       plugindb->get(i)->realtime,
+                       plugindb->get(i)->multichannel,
+                       plugindb->get(i)->get_synthesis(),
+                       plugindb->get(i)->transition,
+                       plugindb->get(i)->theme,
+                       plugindb->get(i)->title);
        }
 }
 
@@ -2882,8 +3043,9 @@ int MWindow::save_defaults()
        for(int i = 0; i < plugin_guis->total; i++)
        {
 // Pointer comparison
-               plugin_guis->values[i]->save_defaults();
+               plugin_guis->get(i)->save_defaults();
        }
+       awindow->save_defaults(defaults);
 
        defaults->save();
        return 0;
@@ -3050,15 +3212,12 @@ int MWindow::reset_meters()
        cwindow->gui->meters->reset_meters();
        cwindow->gui->unlock_window();
 
-       for(int j = 0; j < vwindows.size(); j++)
-       {
-               VWindow *vwindow = vwindows.get(j);
-               if(vwindow->is_running())
-               {
-                       vwindow->gui->lock_window("MWindow::reset_meters 2");
-                       vwindow->gui->meters->reset_meters();
-                       vwindow->gui->unlock_window();
-               }
+       for(int j = 0; j < vwindows.size(); j++) {
+               VWindow *vwindow = vwindows[j];
+               if( !vwindow->is_running() ) continue;
+               vwindow->gui->lock_window("MWindow::reset_meters 2");
+               vwindow->gui->meters->reset_meters();
+               vwindow->gui->unlock_window();
        }
 
        lwindow->gui->lock_window("MWindow::reset_meters 3");
@@ -3088,9 +3247,9 @@ void MWindow::resync_guis()
        cwindow->gui->flush();
        cwindow->gui->unlock_window();
 
-       for(int i = 0; i < vwindows.size(); i++)
-       {
-               VWindow *vwindow = vwindows.get(i);
+       for(int i = 0; i < vwindows.size(); i++) {
+               VWindow *vwindow = vwindows[i];
+               if( !vwindow->is_running() ) continue;
                vwindow->gui->lock_window("MWindow::resync_guis");
                vwindow->gui->resize_event(vwindow->gui->get_w(), 
                        vwindow->gui->get_h());
@@ -3247,6 +3406,6 @@ void MWindow::dump_plugindb(FILE *fp)
 {
        if( !plugindb ) return;
        for(int i = 0; i < plugindb->total; i++)
-               plugindb->values[i]->dump(fp);
+               plugindb->get(i)->dump(fp);
 }