fix awdw solo vicon crash, fix nested clip for binfolders, open edit edl
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindow.C
index 78bc2bec395e56c3147ad3758565025fee45fa90..7fd092a6ec82a2fde019668e2184db679b02e4f7 100644 (file)
 #include "wavecache.h"
 #include "wintv.h"
 #include "wwindow.h"
+#include "x10tv.h"
 #include "zoombar.h"
 #include "zwindow.h"
 #include "zwindowgui.h"
@@ -244,6 +245,7 @@ MWindow::MWindow()
        beeper = 0;
        shuttle = 0;
        wintv = 0;
+       x10tv = 0;
        mixers_align = 0;
 }
 
@@ -266,9 +268,14 @@ MWindow::~MWindow()
        delete beeper;
        delete create_bd;       create_bd = 0;
        delete create_dvd;      create_dvd = 0;
+#ifdef HAVE_SHUTTLE
        delete shuttle;         shuttle = 0;
+#endif
 #ifdef HAVE_WINTV
        delete wintv;           wintv = 0;
+#endif
+#ifdef HAVE_X10TV
+       delete x10tv;           x10tv = 0;
 #endif
        delete batch_render;    batch_render = 0;
        delete convert_render;  convert_render = 0;
@@ -670,6 +677,7 @@ int MWindow::init_plugins(MWindow *mwindow, Preferences *preferences)
 
 int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences)
 {
+#ifdef HAVE_LADSPA
        char *path = getenv("LADSPA_PATH");
        char ladspa_path[BCTEXTLEN];
        if( !path ) {
@@ -714,6 +722,7 @@ int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences)
                }
                fclose(fp);
        }
+#endif
        return 1;
 }
 
@@ -737,7 +746,7 @@ void MWindow::scan_plugin_index(MWindow *mwindow, Preferences *preferences, FILE
        char plugin_path[BCTEXTLEN];
        sprintf(plugin_path, "%s/%s", plug_dir, plug_path);
        FileSystem fs;
-       fs.set_filter( "[*.plugin][*.so]" );
+       fs.set_filter( "[*.plugin][*.so][*.dll]" );
        int result = fs.update(plugin_path);
        if( result || !fs.dir_list.total ) return;
        int vis_id = idx++;
@@ -1608,6 +1617,14 @@ void MWindow::init_wintv()
                wintv->start();
 #endif
 }
+void MWindow::init_x10tv()
+{
+#ifdef HAVE_X10TV
+       x10tv = X10TV::probe(this);
+       if( x10tv )
+               x10tv->start();
+#endif
+}
 
 
 void MWindow::init_brender()
@@ -2126,14 +2143,12 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                        session->group_number += groups;
                        switch( edl_mode ) {
                        case LOADMODE_EDL_CLIP: {
-                               sprintf(new_edl->local_session->clip_title, _("Clip %d"),
-                                       session->clip_number++);
-                               char string[BCSTRLEN];
-                               time_t t;  time(&t);
-                               ctime_r(&t, string);
-                               snprintf(new_edl->local_session->clip_notes,
-                                       sizeof(new_edl->local_session->clip_notes),
-                                       +("%sFrom: %s"), string, filename);
+                               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);
                                switch( load_mode ) {
                                case LOADMODE_REPLACE:
                                case LOADMODE_REPLACE_CONCATENATE:
@@ -2246,27 +2261,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        if(got_indexes) mainindexes->start_build();
 
 // Open plugin GUIs
-       Track *track = edl->tracks->first;
-       while( track ) {
-               for( int j = 0; j < track->plugin_set.size(); j++ ) {
-                       PluginSet *plugins = track->plugin_set[j];
-                       Plugin *plugin = plugins->get_first_plugin();
-
-                       while(plugin) {
-                               if( load_mode == LOADMODE_REPLACE ||
-                                   load_mode == LOADMODE_REPLACE_CONCATENATE ) {
-                                       if( plugin->plugin_type == PLUGIN_STANDALONE &&
-                                           plugin->show ) {
-                                               show_plugin(plugin);
-                                       }
-                               }
-
-                               plugin = (Plugin*)plugin->next;
-                       }
-               }
-
-               track = track->next;
-       }
+       show_plugins();
 
        // opening new session
        if( ( load_mode == LOADMODE_REPLACE ||
@@ -2683,7 +2678,10 @@ void MWindow::create_objects(int want_gui,
        strcat(string, "/" FONT_SEARCHPATH);
        BC_Resources::init_fontconfig(string);
        if(debug) PRINT_TRACE
-       init_wintv();
+// use if plugged
+       init_x10tv();
+       if( !x10tv )
+               init_wintv();
 
 // Default project created here
        init_edl();
@@ -3083,7 +3081,6 @@ void MWindow::set_auto_keyframes(int value)
        gui->mbuttons->edit_panel->keyframe->update(value);
        gui->flush();
        cwindow->gui->lock_window("MWindow::set_auto_keyframes");
-       cwindow->gui->edit_panel->keyframe->update(value);
        cwindow->gui->flush();
        cwindow->gui->unlock_window();
 }
@@ -3094,7 +3091,6 @@ void MWindow::set_span_keyframes(int value)
        gui->mbuttons->edit_panel->span_keyframe->update(value);
        gui->flush();
        cwindow->gui->lock_window("MWindow::set_span_keyframes");
-       cwindow->gui->edit_panel->span_keyframe->update(value);
        cwindow->gui->flush();
        cwindow->gui->unlock_window();
 }
@@ -3240,10 +3236,9 @@ void MWindow::show_keyframe_gui(Plugin *plugin)
 {
        keyframe_gui_lock->lock("MWindow::show_keyframe_gui");
 // Find existing thread
-       for(int i = 0; i < keyframe_threads->size(); i++)
-       {
-               if(keyframe_threads->get(i)->plugin == plugin)
-               {
+       for( int i=0; i<keyframe_threads->size(); ++i ) {
+               int plugin_id = keyframe_threads->get(i)->plugin_id;
+               if( plugin_id == plugin->orig_id ) {
                        keyframe_threads->get(i)->start_window(plugin, 0);
                        keyframe_gui_lock->unlock();
                        return;
@@ -3251,10 +3246,8 @@ void MWindow::show_keyframe_gui(Plugin *plugin)
        }
 
 // Find unused thread
-       for(int i = 0; i < keyframe_threads->size(); i++)
-       {
-               if(!keyframe_threads->get(i)->plugin)
-               {
+       for( int i=0; i<keyframe_threads->size(); ++i ) {
+               if( keyframe_threads->get(i)->plugin_id < 0 ) {
                        keyframe_threads->get(i)->start_window(plugin, 0);
                        keyframe_gui_lock->unlock();
                        return;
@@ -3265,7 +3258,6 @@ void MWindow::show_keyframe_gui(Plugin *plugin)
        KeyFrameThread *thread = new KeyFrameThread(this);
        keyframe_threads->append(thread);
        thread->start_window(plugin, 0);
-
        keyframe_gui_lock->unlock();
 }
 
@@ -3283,14 +3275,12 @@ SET_TRACE
 //printf("MWindow::show_plugin %d\n", __LINE__);
 SET_TRACE
 
-
        plugin_gui_lock->lock("MWindow::show_plugin");
-       for(int i = 0; i < plugin_guis->total; i++)
-       {
-// Pointer comparison
-               if(plugin_guis->get(i)->plugin == plugin)
-               {
-                       plugin_guis->get(i)->raise_window();
+       for( int i=0; i<plugin_guis->total; ++i ) {
+// Pointer/id comparison
+               PluginServer *plugin_gui = plugin_guis->get(i);
+               if( plugin_gui->plugin_id == plugin->orig_id ) {
+                       plugin_gui->raise_window();
                        done = 1;
                        break;
                }
@@ -3330,23 +3320,26 @@ SET_TRACE
 void MWindow::hide_plugin(Plugin *plugin, int lock)
 {
        plugin->show = 0;
+       return hide_plugin(plugin->orig_id, lock);
+}
+
+void MWindow::hide_plugin(int plugin_id, int lock)
+{
 // Update the toggle
        gui->lock_window("MWindow::hide_plugin");
        gui->update(0, NORMAL_DRAW, 0, 0, 0, 0, 0);
        gui->unlock_window();
 
        if(lock) plugin_gui_lock->lock("MWindow::hide_plugin");
-       for(int i = 0; i < plugin_guis->total; i++)
-       {
-               if(plugin_guis->get(i)->plugin == plugin)
-               {
-                       PluginServer *ptr = plugin_guis->get(i);
-                       plugin_guis->remove(ptr);
+       for( int i=0; i<plugin_guis->total; ++i ) {
+               PluginServer *plugin_gui = plugin_guis->get(i);
+               if( plugin_gui->plugin_id == plugin_id ) {
+                       plugin_guis->remove(plugin_gui);
                        if(lock) plugin_gui_lock->unlock();
 // Last command executed in client side close
 // Schedule for deletion
-                       ptr->hide_gui();
-                       delete_plugin(ptr);
+                       plugin_gui->hide_gui();
+                       delete_plugin(plugin_gui);
 //sleep(1);
                        return;
                }
@@ -3395,11 +3388,10 @@ void MWindow::hide_keyframe_guis()
 void MWindow::hide_keyframe_gui(Plugin *plugin)
 {
        keyframe_gui_lock->lock("MWindow::hide_keyframe_gui");
-       for(int i = 0; i < keyframe_threads->size(); i++)
-       {
-               if(keyframe_threads->get(i)->plugin == plugin)
-               {
-                       keyframe_threads->get(i)->close_window();
+       for( int i = 0; i < keyframe_threads->size(); i++) {
+               KeyFrameThread *keyframe_gui = keyframe_threads->get(i);
+               if( keyframe_gui->plugin_id == plugin->orig_id ) {
+                       keyframe_gui->close_window();
                        break;
                }
        }
@@ -3473,15 +3465,13 @@ void MWindow::update_keyframe_guis()
 {
 // Send new configuration to keyframe GUI's
        keyframe_gui_lock->lock("MWindow::update_keyframe_guis");
-       for(int i = 0; i < keyframe_threads->size(); i++)
-       {
-               KeyFrameThread *ptr = keyframe_threads->get(i);
-               if(edl->tracks->plugin_exists(ptr->plugin))
-                       ptr->update_gui(1);
+       for( int i=0; i<keyframe_threads->size(); ++i ) {
+               KeyFrameThread *keyframe_gui = keyframe_threads->get(i);
+               Plugin *plugin = edl->tracks->plugin_exists(keyframe_gui->plugin_id);
+               if( plugin )
+                       keyframe_gui->update_gui(1);
                else
-               {
-                       ptr->close_window();
-               }
+                       keyframe_gui->close_window();
        }
        keyframe_gui_lock->unlock();
 }
@@ -3491,55 +3481,42 @@ void MWindow::update_plugin_guis(int do_keyframe_guis)
 // Send new configuration to plugin GUI's
        plugin_gui_lock->lock("MWindow::update_plugin_guis");
 
-       for(int i = 0; i < plugin_guis->size(); i++)
-       {
-               PluginServer *ptr = plugin_guis->get(i);
-               if(edl->tracks->plugin_exists(ptr->plugin))
-                       ptr->update_gui();
-               else
-               {
-// Schedule for deletion if no plugin
-                       plugin_guis->remove_number(i);
-                       i--;
-
-                       ptr->hide_gui();
-                       delete_plugin(ptr);
+       for( int i=0; i<plugin_guis->size(); ++i ) {
+               PluginServer *plugin_gui = plugin_guis->get(i);
+               Plugin *plugin = edl->tracks->plugin_exists(plugin_gui->plugin_id);
+               if( plugin && plugin->show )
+                       plugin_gui->update_gui();
+               else {
+// Schedule for deletion if no plugin or not shown
+                       plugin_guis->remove_number(i--);
+                       plugin_gui->hide_gui();
+                       delete_plugin(plugin_gui);
                }
        }
 
 
 // Change plugin variable if not visible
        Track *track = edl->tracks->first;
-       while(track)
-       {
-               for(int i = 0; i < track->plugin_set.size(); i++)
-               {
+       for( ; track; track=track->next ) {
+               for( int i=0; i < track->plugin_set.size(); ++i ) {
                        Plugin *plugin = (Plugin*)track->plugin_set[i]->first;
-                       while(plugin)
-                       {
+                       for( ; plugin; plugin = (Plugin*)plugin->next ) {
                                int got_it = 0;
-                               for(int i = 0; i < plugin_guis->size(); i++)
-                               {
+                               for( int i=0; i<plugin_guis->size(); ++i ) {
                                        PluginServer *server = plugin_guis->get(i);
-                                       if(server->plugin == plugin)
-                                       {
+                                       if( server->plugin_id == plugin->orig_id ) {
                                                got_it = 1;
                                                break;
                                        }
                                }
-
-                               if(!got_it) plugin->show = 0;
-                               plugin = (Plugin*)plugin->next;
+                               if( !got_it ) plugin->show = 0;
                        }
                }
-
-               track = track->next;
        }
 
        plugin_gui_lock->unlock();
-
-
-       if(do_keyframe_guis) update_keyframe_guis();
+       if( do_keyframe_guis )
+               update_keyframe_guis();
 }
 
 void MWindow::stop_plugin_guis()
@@ -3548,10 +3525,8 @@ void MWindow::stop_plugin_guis()
        plugin_gui_lock->lock("MWindow::stop_plugin_guis");
 
        for( int i=0; i<plugin_guis->size(); ++i ) {
-               PluginServer *ptr = plugin_guis->get(i);
-               if( edl->tracks->plugin_exists(ptr->plugin) ) {
-                       ptr->render_stop();
-               }
+               PluginServer *plugin_gui = plugin_guis->get(i);
+               plugin_gui->render_stop();
        }
        plugin_gui_lock->unlock(); 
 }
@@ -3625,39 +3600,15 @@ int MWindow::get_tracking_direction()
 void MWindow::update_plugin_states()
 {
        plugin_gui_lock->lock("MWindow::update_plugin_states");
-       for(int i = 0; i < plugin_guis->total; i++)
-       {
-               int result = 0;
+       for( int i=0; i<plugin_guis->total; ++i ) {
 // Get a plugin GUI
-               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;
-                       track && !result;
-                       track = track->next)
-               {
-                       for(int j = 0;
-                               j < track->plugin_set.total && !result;
-                               j++)
-                       {
-                               PluginSet *plugin_set = track->plugin_set[j];
-                               for(Plugin *plugin = (Plugin*)plugin_set->first;
-                                       plugin && !result;
-                                       plugin = (Plugin*)plugin->next)
-                               {
-                                       if(plugin == src_plugin &&
-                                               !strcmp(plugin->title, src_plugingui->title)) result = 1;
-                               }
-                       }
-               }
-
-
+               int plugin_id = src_plugingui->plugin_id;
+               Plugin *src_plugin = edl->tracks->plugin_exists(plugin_id);
 // Doesn't exist anymore
-               if(!result)
-               {
-                       hide_plugin(src_plugin, 0);
-                       i--;
+               if( !src_plugin ) {
+                       hide_plugin(plugin_id, 0);
+                       --i;
                }
        }
        plugin_gui_lock->unlock();
@@ -3666,10 +3617,8 @@ void MWindow::update_plugin_states()
 
 void MWindow::update_plugin_titles()
 {
-       for(int i = 0; i < plugin_guis->total; i++)
-       {
+       for( int i=0; i<plugin_guis->total; ++i )
                plugin_guis->get(i)->update_title();
-       }
 }
 
 int MWindow::asset_to_edl(EDL *new_edl,
@@ -3830,7 +3779,7 @@ void MWindow::update_project(int load_mode)
        if(debug) PRINT_TRACE
 }
 
-void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
+void MWindow::stack_push(EDL *new_edl, Indexable *idxbl, Edit *edit)
 {
        int got_indexes = 0;
        for( int i=0; i<new_edl->nested_edls.size(); ++i ) {
@@ -3852,10 +3801,13 @@ void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
        gui->lock_window("MWindow::stack_push");
        if( stack.size() < 9 ) {
                save_backup();
+               hide_plugins();
                undo_before();
                StackItem &item = stack.append();
                item.edl = edl;
+               item.edit = edit;
                item.new_edl = new_edl;
+               item.duration = new_edl->tracks->total_length();
                item.undo = undo;
                item.idxbl = idxbl;
                item.mtime = 0;
@@ -3874,6 +3826,7 @@ void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
                update_project(LOADMODE_REPLACE);
        }
        gui->unlock_window();
+       show_plugins();
 }
 
 void MWindow::stack_pop()
@@ -3881,11 +3834,23 @@ void MWindow::stack_pop()
        if( !stack.size() ) return;
 // writes on config_path/backup%d.xml
        save_backup();
+       hide_plugins();
 // already have gui lock
        StackItem &item = stack.last();
 // session edl replaced, overwrite and save clip data
        if( item.new_edl != edl )
                item.new_edl->overwrite_clip(edl);
+       Edit *edit = item.edit;
+// resize the referring edit if the edl duration changed
+       if( edit ) {
+               double duration = item.new_edl->tracks->total_length();
+               double dt = duration - item.duration;
+               if( fabs(dt) > 1e-4 ) {
+                       int64_t du = edit->track->to_units(dt,0);
+                       if( (edit->length+=du) < 0 )
+                               edit->length = 0;
+               }
+       }
        edl->remove_user();
        edl = item.edl;
        delete undo;
@@ -3905,6 +3870,7 @@ void MWindow::stack_pop()
        strcpy(session->filename, edl->path);
        update_project(LOADMODE_REPLACE);
        undo_after(_("open edl"), LOAD_ALL);
+       show_plugins();
        gui->stack_button->update();
        if( mtime && idxbl && idxbl->is_asset ) {
                struct stat st;
@@ -3919,6 +3885,77 @@ void MWindow::stack_pop()
        }
 }
 
+int MWindow::save(EDL *edl, char *filename, int stat)
+{
+       FileXML file;
+       edl->save_xml(&file, filename);
+       file.terminate_string();
+       if( file.write_to_file(filename) ) {
+               eprintf(_("Couldn't open %s"), filename);
+               return 1;
+       }
+       if( stat ) {
+               char string[BCTEXTLEN];
+               char *filename = stack.size() ?
+                       stack[0].edl->path : session->filename;
+               sprintf(string, _("\"%s\" %jdC written"),
+                        filename, file.length());
+               gui->lock_window("SaveAs::run");
+               gui->show_message(string);
+               gui->unlock_window();
+       }
+       return 0;
+}
+
+int MWindow::save(int save_as)
+{
+       char new_path[BCTEXTLEN];  new_path[0] = 0;
+       char *path = stack.size() ? stack[0].edl->path : session->filename;
+       if( save_as || !path[0] ) {
+               if( ConfirmSave::get_save_path(this, new_path) )
+                       return 1;
+               if( stack.size() ) {
+                       strcpy(path, new_path);
+                       set_titlebar(new_path);
+               }
+               else
+                       set_filename(new_path);
+               gui->mainmenu->add_load(new_path);
+               path = new_path;
+       }
+       for( int i=stack.size(); --i>=0;  ) {
+               StackItem &item = stack[i];
+               Indexable *idxbl = item.idxbl;
+               if( idxbl->is_asset ) {
+                       Asset *asset = (Asset *)idxbl;
+                       if( asset->format == FILE_REF ) {
+                               if( save(item.new_edl, asset->path, 0) )
+                                       return 1;
+                       }
+               }
+               else if( item.new_edl != item.idxbl )
+                       item.new_edl->overwrite_clip((EDL*)item.idxbl);
+       }
+       EDL *new_edl = stack.size() ? stack[0].edl : edl;
+       save(new_edl, path, 1);
+       return 0;
+}
+
+void MWindow::show_plugins()
+{
+       for( Track *track=edl->tracks->first; track; track=track->next ) {
+               for( int i=0; i<track->plugin_set.size(); ++i ) {
+                       PluginSet *plugins = track->plugin_set[i];
+                       Plugin *plugin = plugins->get_first_plugin();
+                       for( ; plugin; plugin=(Plugin*)plugin->next ) {
+                               if( plugin->plugin_type == PLUGIN_STANDALONE &&
+                                   plugin->show )
+                                       show_plugin(plugin);
+                       }
+               }
+       }
+}
+
 void MWindow::clip_to_media()
 {
        if( edl->session->proxy_scale != 1 ) {
@@ -3926,6 +3963,7 @@ void MWindow::clip_to_media()
                return;
        }
        undo_before();
+       awindow->gui->stop_vicon_drawing();
        int clips_total = session->drag_clips->total;
        for( int i=0; i<clips_total; ++i ) {
                EDL *clip = session->drag_clips->values[i];
@@ -4108,6 +4146,7 @@ void MWindow::save_backup()
                sprintf(string2, _("Couldn't open %s for writing."), backup_path);
                gui->show_message(string2);
        }
+       save_undo_data();
 }
 
 void MWindow::load_backup()
@@ -4135,8 +4174,8 @@ void MWindow::load_backup()
 
 void MWindow::save_undo_data()
 {
-       undo_before();
-       undo_after(_("perpetual session"), LOAD_ALL);
+       if( stack.size() > 0 ) return;
+       if( !preferences->perpetual_session ) return;
        char perpetual_path[BCTEXTLEN];
        snprintf(perpetual_path, sizeof(perpetual_path), "%s/%s",
                File::get_config_path(), PERPETUAL_FILE);
@@ -4148,15 +4187,27 @@ void MWindow::save_undo_data()
 
 void MWindow::load_undo_data()
 {
+       if( stack.size() > 0 ) return;
+       if( !preferences->perpetual_session ) return;
        char perpetual_path[BCTEXTLEN];
        snprintf(perpetual_path, sizeof(perpetual_path), "%s/%s",
                File::get_config_path(), PERPETUAL_FILE);
        FILE *fp = fopen(perpetual_path,"r");
        if( !fp ) return;
        undo->load(fp);
+       undo_before();
+       undo_after(_("perpetual load"), LOAD_ALL);
        fclose(fp);
 }
 
+void MWindow::remove_undo_data()
+{
+       if( stack.size() > 0 ) return;
+       char perpetual_path[BCTEXTLEN];
+       snprintf(perpetual_path, sizeof(perpetual_path), "%s/%s",
+               File::get_config_path(), PERPETUAL_FILE);
+       ::remove(perpetual_path);
+}
 
 int MWindow::copy_target(const char *path, const char *target)
 {
@@ -4260,7 +4311,10 @@ void MWindow::save_project(const char *dir, int save_mode, int overwrite, int re
        char progress_title[BCTEXTLEN];
        sprintf(progress_title, _("Saving to %s:\n"), dir);
        int total_assets = save_edl->assets->total();
+       gui->lock_window("MWindow::save_project");
        MainProgressBar *progress = mainprogress->start_progress(progress_title, total_assets);
+       gui->unlock_window();
+
        int ret = 0;
        Asset *current = save_edl->assets->first;
        for( int i=0; !ret && current; ++i, current=NEXT ) {
@@ -4416,11 +4470,7 @@ void MWindow::remove_from_caches(Indexable *idxbl)
                delete gui->render_engine;
                gui->render_engine = 0;
        }
-       if( gui->resource_thread->render_engine_id == idxbl->id ) {
-               gui->resource_thread->render_engine_id = -1;
-               delete gui->resource_thread->render_engine;
-               gui->resource_thread->render_engine = 0;
-       }
+       gui->resource_thread->close_indexable(idxbl);
        if( !idxbl->is_asset ) return;
        Asset *asset = (Asset *)idxbl;
        audio_cache->delete_entry(asset);
@@ -4606,6 +4656,14 @@ void MWindow::dump_exe(FILE *fp)
        fprintf(fp, "\n");
 }
 
+void MWindow::dump_caches(FILE *fp)
+{
+       fprintf(fp, "audio cache: ");
+       audio_cache->dump(fp);
+       fprintf(fp, "video cache: ");
+       video_cache->dump(fp);
+}
+
 void MWindow::trap_hook(FILE *fp, void *vp)
 {
        MWindow *mwindow = (MWindow *)vp;
@@ -4617,6 +4675,8 @@ void MWindow::trap_hook(FILE *fp, void *vp)
        mwindow->dump_undo(fp);
        fprintf(fp, "\nEXE: %s\n", AboutPrefs::build_timestamp);
        mwindow->dump_exe(fp);
+       fprintf(fp, "\nCACHES:\n");
+       mwindow->dump_caches(fp);
 }
 
 
@@ -4737,32 +4797,25 @@ int MWindow::set_filename(const char *filename)
                strcpy(session->filename, filename);
        if( filename != edl->path )
                strcpy(edl->path, filename);
+       return set_titlebar(filename);
+}
 
-       if(gui)
-       {
-               if(filename[0] == 0)
-               {
-                       gui->set_title(PROGRAM_NAME);
-               }
-               else
-               {
-                       FileSystem dir;
-                       char string[BCTEXTLEN], string2[BCTEXTLEN];
-                       dir.extract_name(string, filename);
-                       sprintf(string2, PROGRAM_NAME ": %s", string);
-                       gui->set_title(string2);
-               }
+int MWindow::set_titlebar(const char *filename)
+{
+       if( !gui ) return 0;
+       if( filename[0] ) {
+               FileSystem dir;
+               char string[BCTEXTLEN], string2[BCTEXTLEN];
+               dir.extract_name(string, filename);
+               sprintf(string2, PROGRAM_NAME ": %s", string);
+               gui->set_title(string2);
        }
+       else
+               gui->set_title(PROGRAM_NAME);
        return 0;
 }
 
 
-
-
-
-
-
-
 int MWindow::set_loop_boundaries()
 {
        double start = edl->local_session->get_selectionstart();
@@ -5050,3 +5103,17 @@ PatchGUI *MWindow::get_patchgui(Track *track)
         return patchgui;
 }
 
+int MWindow::get_cpus(int out_w, int out_h)
+{
+       if( !out_w ) out_w = edl->session->output_w;
+       if( !out_h ) out_h = edl->session->output_h;
+       int cpus = out_w*out_h/0x80000 + 1;
+       if( cpus > preferences->processors )
+               cpus = preferences->processors;
+       return cpus;
+}
+int MWindow::get_cpus()
+{
+       return get_cpus(edl->session->output_w, edl->session->output_h);
+}
+