yuv colorspace/range + prefs, ffmpeg colorrange probe, x11 direct force colormodel...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / mwindow.C
index 8824b86872be7cd9430fbdddff51c639a2035935..84ba6830aa88bd39cfea54d154dd94ead97a07ff 100644 (file)
@@ -18,6 +18,7 @@
  *
  */
 
+#include "aboutprefs.h"
 #include "asset.h"
 #include "assets.h"
 #include "atrack.h"
@@ -89,6 +90,7 @@
 #include "pluginserver.h"
 #include "pluginset.h"
 #include "preferences.h"
+#include "proxy.h"
 #include "record.h"
 #include "recordmonitor.h"
 #include "recordlabel.h"
 #include "theme.h"
 #include "threadloader.h"
 #include "timebar.h"
+#include "timelinepane.h"
 #include "tipwindow.h"
 #include "trackcanvas.h"
 #include "track.h"
 #include "wavecache.h"
 #include "wwindow.h"
 #include "zoombar.h"
+#include "zwindow.h"
+#include "zwindowgui.h"
 #include "exportedl.h"
 
 #include "defaultformats.h"
@@ -180,6 +185,7 @@ MWindow::MWindow()
        plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
        dead_plugin_lock = new Mutex("MWindow::dead_plugin_lock");
        vwindows_lock = new Mutex("MWindow::vwindows_lock");
+       zwindows_lock = new Mutex("MWindow::zwindows_lock");
        brender_lock = new Mutex("MWindow::brender_lock");
        keyframe_gui_lock = new Mutex("MWindow::keyframe_gui_lock");
 
@@ -231,10 +237,8 @@ MWindow::MWindow()
 MWindow::~MWindow()
 {
        run_lock->lock("MWindow::~MWindow");
-       stop_playback(1);
        in_destructor = 1;
 //printf("MWindow::~MWindow %d\n", __LINE__);
-       gui->stop_drawing();
        gui->remote_control->deactivate();
        gui->record->stop();
 #ifdef HAVE_DVB
@@ -246,6 +250,7 @@ MWindow::~MWindow()
        delete render;          render = 0;
        commit_commercial();
        if( commercials && !commercials->remove_user() ) commercials = 0;
+       close_mixers();
 
 // Save defaults for open plugins
        plugin_gui_lock->lock("MWindow::~MWindow");
@@ -272,6 +277,7 @@ MWindow::~MWindow()
        if( twindow && twindow->is_running() ) twindow->close_window();
        if( wwindow && wwindow->is_running() ) wwindow->close_window();
        vwindows.remove_all_objects();
+       zwindows.remove_all_objects();
        gui->close(0);
        if( awindow ) awindow->join();
        if( cwindow ) cwindow->join();
@@ -292,11 +298,15 @@ MWindow::~MWindow()
        close_gui(twindow);
        close_gui(wwindow);
        vwindows.remove_all_objects();
+       zwindows.remove_all_objects();
        gui->close(0);
        join();
 #endif
        reset_caches();
        dead_plugins->remove_all_objects();
+// must delete theme before destroying plugindb
+//  theme destructor will be deleted by delete_plugins
+       delete theme;           theme = 0;
        delete_plugins();
        finit_error();
        keyframe_threads->remove_all_objects();
@@ -325,7 +335,6 @@ MWindow::~MWindow()
        delete defaults;        defaults = 0;
        delete assets;          assets = 0;
        delete splash_window;   splash_window = 0;
-//     delete theme;           theme = 0;      // deleted by delete_plugins
        if( !edl->Garbage::remove_user() ) edl = 0;
        delete channeldb_buz;
        delete channeldb_v4l2jpeg;
@@ -334,6 +343,7 @@ MWindow::~MWindow()
        delete dead_plugin_lock;
        delete plugin_gui_lock;
        delete vwindows_lock;
+       delete zwindows_lock;
        delete brender_lock;
        delete keyframe_gui_lock;
        colormodels.remove_all_objects();
@@ -733,14 +743,14 @@ void MWindow::add_plugins(ArrayList<PluginServer*> &plugins)
        plugins.remove_all();
 }
 
-void MWindow::init_plugin_tips(ArrayList<PluginServer*> &plugins)
+void MWindow::init_plugin_tips(ArrayList<PluginServer*> &plugins, const char *lang)
 {
        const char *cfg_path = File::get_cindat_path();
        char msg_path[BCTEXTLEN];  int txt = 0;
        FILE *fp = 0;
        if( BC_Resources::language[0] ) {
                snprintf(msg_path, sizeof(msg_path), "%s/info/plugins.%s",
-                       cfg_path, BC_Resources::language);
+                       cfg_path, lang);
                fp = fopen(msg_path, "r");
        }
        if( !fp ) {
@@ -893,6 +903,8 @@ void MWindow::init_preferences()
        }
        BC_WindowBase::get_resources()->popupmenu_btnup = preferences->popupmenu_btnup;
        BC_WindowBase::get_resources()->textbox_focus_policy = preferences->textbox_focus_policy;
+       BC_WindowBase::get_resources()->grab_input_focus = preferences->grab_input_focus;
+       YUV::yuv.yuv_set_colors(preferences->yuv_color_space, preferences->yuv_color_range);
 }
 
 void MWindow::clean_indexes()
@@ -1058,8 +1070,8 @@ void MWindow::init_theme()
        theme->build_menus();
        init_menus();
 
+       theme->sort_image_sets();
        theme->check_used();
-
 //printf("MWindow::init_theme %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 }
 
@@ -1113,6 +1125,243 @@ VWindow *MWindow::get_viewer(int start_it, int idx)
        return vwindow;
 }
 
+ZWindow *MWindow::get_mixer(Mixer *&mixer)
+{
+       zwindows_lock->lock("MWindow::get_mixer");
+       if( !mixer ) mixer = edl->mixers.new_mixer();
+       ZWindow *zwindow = 0;
+       for( int i=0; !zwindow && i<zwindows.size(); ++i )
+               if( zwindows[i]->idx < 0 ) zwindow = zwindows[i];
+       if( !zwindow )
+               zwindows.append(zwindow = new ZWindow(this));
+       zwindow->idx = mixer->idx;
+       zwindows_lock->unlock();
+       return zwindow;
+}
+
+void MWindow::del_mixer(ZWindow *zwindow)
+{
+       zwindows_lock->lock("MWindow::del_mixer 0");
+       edl->mixers.del_mixer(zwindow->idx);
+       zwindow->idx = -1;
+       if( session->selected_zwindow >= 0 ) {
+               int i = zwindows.number_of(zwindow);
+               if( i >= 0 && i < session->selected_zwindow )
+                       --session->selected_zwindow;
+               else if( i == session->selected_zwindow )
+                       session->selected_zwindow = -1;
+       }
+       zwindows_lock->unlock();
+       gui->lock_window("MWindow::del_mixer 1");
+       gui->update_mixers(0, -1);
+       gui->unlock_window();
+}
+
+void MWindow::start_mixer()
+{
+       Mixer *mixer = 0;
+       ZWindow *zwindow = get_mixer(mixer);
+       const char *title = 0;
+
+       for( Track *track=edl->tracks->first; track!=0; track=track->next ) {
+               PatchGUI *patchgui = get_patchgui(track);
+               if( !patchgui || !patchgui->mixer ) continue;
+               mixer->mixer_ids.append(track->get_mixer_id());
+               if( !title ) title = track->title;
+       }
+
+       session->selected_zwindow = -1;
+       gui->lock_window("MWindow::start_mixer");
+       gui->update_mixers(0, 0);
+       gui->unlock_window();
+
+       zwindow->set_title(title);
+       zwindow->start();
+       refresh_mixers();
+}
+
+int MWindow::mixer_track_active(Track *track)
+{
+       int i = session->selected_zwindow;
+       if( i < 0 || i >= zwindows.size() ) return 0;
+       ZWindow *zwindow = zwindows[i];
+       Mixer *mixer = edl->mixers.get_mixer(zwindow->idx);
+       if( !mixer ) return 0;
+       int n = mixer->mixer_ids.number_of(track->get_mixer_id());
+       return n >= 0 ? 1 : 0;
+}
+
+void MWindow::update_mixer_tracks()
+{
+       zwindows_lock->lock("MixPatch::handle_event");
+       int i = session->selected_zwindow;
+       if( i >= 0 && i < zwindows.size() ) {
+               ZWindow *zwindow = zwindows[i];
+               zwindow->update_mixer_ids();
+       }
+       zwindows_lock->unlock();
+}
+
+void MWindow::queue_mixers(EDL *edl, int command, int wait_tracking,
+               int use_inout, int update_refresh, int toggle_audio)
+{
+       zwindows_lock->lock("MWindow::queue_mixers");
+       for( int vidx=0; vidx<zwindows.size(); ++vidx ) {
+               ZWindow *zwindow = zwindows[vidx];
+               if( zwindow->idx < 0 ) continue;
+               Mixer *mixer = edl->mixers.get_mixer(zwindow->idx);
+               if( !mixer || !mixer->mixer_ids.size() ) continue;
+               int k = -1;
+               for( Track *track = edl->tracks->first; k<0 && track!=0; track=track->next ) {
+                       if( track->data_type != TRACK_VIDEO ) continue;
+                       int mixer_id = track->get_mixer_id();
+                       k = mixer->mixer_ids.size();
+                       while( --k >= 0 && mixer_id != mixer->mixer_ids[k] );
+               }
+               if( k < 0 ) continue;
+               EDL *mixer_edl = new EDL(this->edl);
+               mixer_edl->create_objects();
+               mixer_edl->copy_all(edl);
+               mixer_edl->remove_vwindow_edls();
+               for( Track *track = mixer_edl->tracks->first; track!=0; track=track->next ) {
+                       k = mixer->mixer_ids.size();
+                       while( --k >= 0 && track->get_mixer_id() != mixer->mixer_ids[k] );
+                       if( k >= 0 ) {
+                               track->record = 1;
+                               track->play = track->data_type == TRACK_VIDEO ? 1 : 0;
+                       }
+                       else
+                               track->record = track->play = 0;
+               }
+               zwindow->change_source(mixer_edl);
+               zwindow->issue_command(command,
+                       wait_tracking, use_inout, update_refresh, toggle_audio);
+       }
+       zwindows_lock->unlock();
+}
+
+void MWindow::refresh_mixers()
+{
+       queue_mixers(edl,CURRENT_FRAME,0,0,1,0);
+}
+
+void MWindow::stop_mixers()
+{
+       for( int vidx=0; vidx<zwindows.size(); ++vidx ) {
+               ZWindow *zwindow = zwindows[vidx];
+               if( zwindow->idx < 0 ) continue;
+               zwindow->issue_command(STOP, 0, 0, 0, 0);
+       }
+}
+
+void MWindow::close_mixers()
+{
+       zwindows_lock->lock("MWindow::close_mixers");
+       for( int i=0; i<zwindows.size(); ++i ) {
+               ZWindow *zwindow = zwindows[i];
+               if( zwindow->idx < 0 ) continue;
+               ZWindowGUI *zgui = zwindow->zgui;
+               zgui->lock_window("MWindow::select_zwindow 0");
+               zgui->set_done(0);
+               zgui->unlock_window();
+       }
+       zwindows_lock->unlock();
+       for( int i=0; i<zwindows.size(); ++i ) {
+               ZWindow *zwindow = zwindows[i];
+               if( zwindow->idx < 0 ) continue;
+               zwindow->close_window();
+       }
+}
+
+void MWindow::open_mixers()
+{
+       for( int i=0; i<edl->mixers.size(); ++i ) {
+               Mixer *mixer = edl->mixers[i];
+               ZWindow *zwindow = get_mixer(mixer);
+               zwindow->set_title(mixer->title);
+               zwindow->start();
+       }
+        refresh_mixers();
+}
+
+int MWindow::select_zwindow(ZWindow *zwindow)
+{
+       int ret = 0, n = zwindows.number_of(zwindow);
+       if( session->selected_zwindow != n ) {
+               session->selected_zwindow = n;
+               for( int i=0; i<zwindows.size(); ++i ) {
+                       ZWindow *zwindow = zwindows[i];
+                       if( zwindow->idx < 0 ) continue;
+                       ZWindowGUI *zgui = zwindow->zgui;
+                       zgui->lock_window("MWindow::select_zwindow 0");
+                       zwindow->highlighted = i == n ? 1 : 0;
+                       if( zgui->draw_overlays() )
+                               zgui->canvas->get_canvas()->flash(1);
+                       zgui->unlock_window();
+               }
+               ret = 1;
+               gui->lock_window("MWindow::select_window 1");
+               gui->update_mixers(0, -1);
+               gui->unlock_window();
+       }
+       return ret;
+}
+
+void MWindow::tile_mixers()
+{
+       int nz = 0;
+       for( int i=0; i<zwindows.size(); ++i ) {
+               ZWindow *zwindow = zwindows[i];
+               if( zwindow->idx < 0 ) continue;
+               ++nz;
+       }
+       if( !nz ) return;
+       int zn = ceil(sqrt(nz));
+       int x1 = 1 + gui->get_x(), x2 = cwindow->gui->get_x();
+       int y1 = 1, y2 = gui->get_y();
+       int rw = gui->get_root_w(0), rh = gui->get_root_h(0);
+       if( x1 < 0 ) x1 = 0;
+       if( y1 < 0 ) y1 = 0;
+       if( x2 > rw ) x2 = rw;
+       if( y2 > rh ) y2 = rh;
+       int dx = x2 - x1, dy = y2 - y1;
+       int zw = dx / zn;
+       int lt = BC_DisplayInfo::get_left_border();
+       int top = BC_DisplayInfo::get_top_border();
+       int bw = lt + BC_DisplayInfo::get_right_border();  // borders
+       int bh = top + BC_DisplayInfo::get_bottom_border();
+       int zx = 0, zy = 0;  // window origins
+       int mw = 10+10, mh = 10+10; // canvas margins
+       int rsz = 0, n = 0, dz = 0;
+       int ow = edl->session->output_w, oh = edl->session->output_h;
+       for( int i=0; i<zwindows.size(); ++i ) {
+               ZWindow *zwindow = zwindows[i];
+               if( zwindow->idx < 0 ) continue;
+               int ww = zw - bw, hh = (ww - mw) * oh / ow + mh, zh = hh + bh;
+               if( rsz < hh ) rsz = hh;
+               int xx = zx + x1, yy = zy + y1;
+               int mx = x2 - zw, my = y2 - zh;
+               if( xx > mx ) xx = mx;
+               if( yy > my ) yy = my;
+               xx += lt + dz;  yy += top + dz;
+               zwindow->reposition(xx,yy, ww,hh);
+               if( zwindow->running() ) {
+                       ZWindowGUI *gui = (ZWindowGUI *)zwindow->get_gui();
+                       gui->lock_window("MWindow::tile_mixers");
+                       gui->BC_WindowBase::reposition_window(xx,yy, ww,hh);
+                       gui->unlock_window();
+               }
+               if( ++n >= zn ) {
+                       n = 0;  rsz += bh;
+                       if( (zy += rsz) > (dy - rsz) ) dz += 10;
+                       rsz = 0;
+                       zx = 0;
+               }
+               else
+                       zx += zw;
+       }
+}
+
 void MWindow::init_cache()
 {
        audio_cache = new CICache(preferences);
@@ -1403,17 +1652,20 @@ int MWindow::put_commercial()
 
 void MWindow::stop_playback(int wait)
 {
-       int locked  = gui->get_window_lock();
-       if( locked ) gui->unlock_window();
+       gui->stop_drawing();
 
-       cwindow->playback_engine->stop_playback();
+       cwindow->stop_playback(wait);
 
        for(int i = 0; i < vwindows.size(); i++) {
                VWindow *vwindow = vwindows[i];
                if( !vwindow->is_running() ) continue;
-               vwindow->playback_engine->stop_playback();
+               vwindow->stop_playback(wait);
+       }
+       for(int i = 0; i < zwindows.size(); i++) {
+               ZWindow *zwindow = zwindows[i];
+               if( zwindow->idx < 0 ) continue;
+               zwindow->stop_playback(wait);
        }
-       if( locked ) gui->lock_window("MWindow::stop_playback");
 }
 
 int MWindow::load_filenames(ArrayList<char*> *filenames,
@@ -1431,7 +1683,9 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
 // Need to stop playback since tracking depends on the EDL not getting
 // deleted.
+       gui->unlock_window();
        stop_playback(1);
+       gui->lock_window("MWindow::load_filenames 0");
 
 if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        undo->update_undo_before();
@@ -1492,14 +1746,10 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 
                                if(load_mode != LOADMODE_RESOURCESONLY)
                                {
-SET_TRACE
                                        RecordLabels *labels = edl->session->label_cells ?
                                                new RecordLabels(new_file) : 0;
-SET_TRACE
                                        asset_to_edl(new_edl, new_asset, labels);
-SET_TRACE
                                        new_edls.append(new_edl);
-SET_TRACE
                                        new_asset->Garbage::remove_user();
                                        delete labels;
                                        new_asset = 0;
@@ -1802,10 +2052,6 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                                                show_plugin(plugin);
                                        }
                                }
-                               else
-                               {
-                                       plugin->show = 0;
-                               }
 
                                plugin = (Plugin*)plugin->next;
                        }
@@ -1819,8 +2065,11 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
            ( load_mode == LOADMODE_REPLACE ||
              load_mode == LOADMODE_REPLACE_CONCATENATE ) ) {
                select_asset(0, 0);
+               edl->session->proxy_scale = 1;
+               edl->session->proxy_use_scaler = 0;
+               edl->session->proxy_auto_scale = 0;
                edl->local_session->preview_start = 0;
-               edl->local_session->preview_end = edl->tracks->total_playable_length();
+               edl->local_session->preview_end = 0;
                edl->local_session->loop_playback = 0;
                edl->local_session->set_selectionstart(0);
                edl->local_session->set_selectionend(0);
@@ -1829,6 +2078,29 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
                goto_start();
        }
 
+       if( ( edl->session->proxy_auto_scale && edl->session->proxy_scale != 1 ) &&
+           ( load_mode != LOADMODE_REPLACE && load_mode != LOADMODE_REPLACE_CONCATENATE ) ) {
+               ArrayList<Indexable *> orig_idxbls;
+               for( int i=0; i<new_assets.size(); ++i )
+                       orig_idxbls.append(new_assets.get(i));
+               for( int i=0; i<new_edls.size(); ++i ) {
+                       EDL *new_edl = new_edls[i];
+                       for( Track *track=new_edl->tracks->first; track; track=track->next ) {
+                               if( track->data_type != TRACK_VIDEO ) continue;
+                               for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+                                       Indexable *idxbl = (Indexable *)edit->asset;
+                                       if( !idxbl ) continue;
+                                       if( !idxbl->have_video() ) continue;
+                                       if( edit->channel != 0 ) continue; // first layer only
+                                       orig_idxbls.append(edit->asset);
+                               }
+                       }
+               }
+               gui->unlock_window(); // to update progress bar
+               render_proxy(orig_idxbls);
+               gui->lock_window("MWindow::load_filenames");
+       }
+
 // 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__);
@@ -1873,8 +2145,35 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
        return 0;
 }
 
+void MWindow::render_proxy(ArrayList<Indexable *> &new_idxbls)
+{
+       Asset *format_asset = new Asset;
+       format_asset->format = FILE_FFMPEG;
+       format_asset->load_defaults(defaults, "PROXY_", 1, 1, 0, 0, 0);
+       ProxyRender proxy_render(this, format_asset);
+       int new_scale = edl->session->proxy_scale;
+       int use_scaler = edl->session->proxy_use_scaler;
+
+       for( int i=0; i<new_idxbls.size(); ++i ) {
+               Indexable *orig = new_idxbls.get(i);
+               Asset *proxy = proxy_render.add_original(orig, new_scale);
+               if( !proxy ) continue;
+               FileSystem fs;
+               int exists = fs.get_size(proxy->path) > 0 ? 1 : 0;
+               int got_it = exists && // if proxy exists, and is newer than orig
+                   fs.get_date(proxy->path) > fs.get_date(orig->path) ? 1 : 0;
+               if( got_it ) continue;
+               proxy_render.add_needed(orig, proxy);
+       }
 
-
+// render needed proxies
+       int result = proxy_render.create_needed_proxies(new_scale);
+       if( !result ) {
+               add_proxy(use_scaler,
+                       &proxy_render.orig_idxbls, &proxy_render.orig_proxies);
+       }
+       format_asset->remove_user();
+}
 
 void MWindow::test_plugins(EDL *new_edl, char *path)
 {
@@ -1987,7 +2286,6 @@ void MWindow::create_objects(int want_gui,
        int want_new,
        char *config_path)
 {
-       FileSystem fs;
        const int debug = 0;
        if(debug) PRINT_TRACE
 
@@ -2011,7 +2309,7 @@ void MWindow::create_objects(int want_gui,
        if(debug) PRINT_TRACE
        init_ladspa_plugins(this, preferences);
        if(debug) PRINT_TRACE
-       init_plugin_tips(*plugindb);
+       init_plugin_tips(*plugindb, cin_lang);
        if(splash_window)
                splash_window->operation->update(_("Initializing GUI"));
        if(debug) PRINT_TRACE
@@ -2455,10 +2753,7 @@ void MWindow::sync_parameters(int change_type)
        }
        else
        {
-               cwindow->playback_engine->que->send_command(CURRENT_FRAME,
-                                                       change_type,
-                                                       edl,
-                                                       1);
+               cwindow->refresh_frame(change_type);
        }
 }
 
@@ -2568,12 +2863,11 @@ SET_TRACE
 SET_TRACE
 
 //printf("MWindow::show_plugin 1\n");
-       if(!done)
-       {
-               if(!plugin->track)
-               {
-                       printf("MWindow::show_plugin track not defined.\n");
-               }
+       if( !done && !plugin->track ) {
+               printf("MWindow::show_plugin track not defined.\n");
+               done = 1;
+       }
+       if( !done ) {
                PluginServer *server = scan_plugindb(plugin->title,
                        plugin->track->data_type);
 
@@ -2952,7 +3246,7 @@ void MWindow::update_project(int load_mode)
        const int debug = 0;
 
        if(debug) PRINT_TRACE
-       restart_brender();
+       init_brender();
        edl->tracks->update_y_pixels(theme);
 
        if(debug) PRINT_TRACE
@@ -2974,8 +3268,8 @@ void MWindow::update_project(int load_mode)
        if(debug) PRINT_TRACE
 
 // Close all the vwindows
-       if(load_mode == LOADMODE_REPLACE ||
-               load_mode == LOADMODE_REPLACE_CONCATENATE) {
+       if( load_mode == LOADMODE_REPLACE ||
+           load_mode == LOADMODE_REPLACE_CONCATENATE ) {
                if(debug) PRINT_TRACE
                int first_vwindow = 0;
                if(session->show_vwindow) first_vwindow = 1;
@@ -2993,13 +3287,24 @@ void MWindow::update_project(int load_mode)
                        vwindow->close_window();
                }
                if(debug) PRINT_TRACE
+               select_zwindow(0);
+               close_mixers();
+
+               for( int i=0; i<edl->mixers.size(); ++i ) {
+                       Mixer *mixer = edl->mixers[i];
+                       ZWindow *zwindow = get_mixer(mixer);
+                       zwindow->set_title(mixer->title);
+                       zwindow->start();
+               }
        }
-       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();
+       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();
+                       }
                }
        }
 
@@ -3009,15 +3314,13 @@ void MWindow::update_project(int load_mode)
        cwindow->gui->unlock_window();
 
        if(debug) PRINT_TRACE
-       cwindow->playback_engine->que->send_command(CURRENT_FRAME,
-               CHANGE_ALL,
-               edl,
-               1);
+       cwindow->refresh_frame(CHANGE_ALL);
 
        awindow->gui->async_update_assets();
        if(debug) PRINT_TRACE
 
        gui->lock_window("MWindow::update_project");
+       gui->update_mixers(0, 0);
        gui->flush();
        if(debug) PRINT_TRACE
 }
@@ -3154,25 +3457,25 @@ void MWindow::reset_caches()
        wave_cache->remove_all();
        audio_cache->remove_all();
        video_cache->remove_all();
-       if( cwindow->playback_engine && cwindow->playback_engine->audio_cache )
-               cwindow->playback_engine->audio_cache->remove_all();
-       if( cwindow->playback_engine && cwindow->playback_engine->video_cache )
-               cwindow->playback_engine->video_cache->remove_all();
-
+       if( cwindow->playback_engine ) {
+               if( cwindow->playback_engine->audio_cache )
+                       cwindow->playback_engine->audio_cache->remove_all();
+               if( cwindow->playback_engine->video_cache )
+                       cwindow->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)
+               if( !vwindow->playback_engine ) continue;
+               if( vwindow->playback_engine->audio_cache )
                        vwindow->playback_engine->audio_cache->remove_all();
-               if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
+               if( vwindow->playback_engine->video_cache )
                        vwindow->playback_engine->video_cache->remove_all();
        }
 }
 
 void MWindow::remove_asset_from_caches(Asset *asset)
 {
-       gui->resource_thread->get_video_source(0);
-       gui->resource_thread->get_audio_source(0);
        frame_cache->remove_asset(asset);
        wave_cache->remove_asset(asset);
        audio_cache->delete_entry(asset);
@@ -3184,9 +3487,10 @@ void MWindow::remove_asset_from_caches(Asset *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)
+               if( !vwindow->playback_engine ) continue;
+               if( vwindow->playback_engine->audio_cache )
                        vwindow->playback_engine->audio_cache->delete_entry(asset);
-               if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
+               if( vwindow->playback_engine->video_cache )
                        vwindow->playback_engine->video_cache->delete_entry(asset);
        }
 }
@@ -3314,7 +3618,8 @@ void MWindow::dump_exe(FILE *fp)
        char mtime[256];
        strftime(mtime, sizeof(mtime), "%F %T", tm);
        fprintf(fp,"mtime: %s\n", mtime);
-
+#if 0
+// people hit ctl-c waiting for this
        int fd = open(proc_path,O_RDONLY+O_NONBLOCK);
        if( fd < 0 ) { fprintf(fp,"open: %m\n"); return; }
        uint8_t *bfr = 0;
@@ -3339,6 +3644,7 @@ void MWindow::dump_exe(FILE *fp)
        for( int i=0; i<20; ++i ) fprintf(fp, "%02x", digest[i]);
        if( ret < 0 ) fprintf(fp, " (ret %d)", ret);
        if( pos < st.st_size ) fprintf(fp, " (pos %jd)", pos);
+#endif
        fprintf(fp, "\n");
 }
 
@@ -3351,7 +3657,7 @@ void MWindow::trap_hook(FILE *fp, void *vp)
        mwindow->dump_edl(fp);
        fprintf(fp, "\nUNDO:\n");
        mwindow->dump_undo(fp);
-       fprintf(fp, "\nEXE:\n");
+       fprintf(fp, "\nEXE: %s\n", AboutPrefs::build_timestamp);
        mwindow->dump_exe(fp);
 }
 
@@ -3617,7 +3923,8 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
        int result = file->open_file(preferences, asset, 1, 0);
        if( !result && delete_tracks > 0 )
                undo->update_undo_before();
-       if( !result && asset->video_data && asset->get_video_layers() > 0 ) {
+       int video_layers = asset->get_video_layers();
+       if( !result && asset->video_data && vstream < video_layers ) {
                // try to get asset up to date, may fail
                file->select_video_stream(asset, vstream);
                // either way use what was/is there.
@@ -3673,7 +3980,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
        if( !result && asset->audio_data && asset->channels > 0 ) {
                session->sample_rate = asset->get_sample_rate();
                int64_t channel_mask = 0;
-               int astrm = !asset->video_data ? -1 :
+               int astrm = !asset->video_data || vstream >= video_layers ? -1 :
                        file->get_audio_for_video(vstream, astream, channel_mask);
                if( astrm >= 0 ) file->select_audio_stream(asset, astrm);
                if( astrm < 0 || !channel_mask ) channel_mask = (1<<asset->channels)-1;
@@ -3787,4 +4094,19 @@ PanAuto* MWindow::get_pan_auto(PatchGUI *patch)
        return (PanAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current);
 }
 
+PatchGUI *MWindow::get_patchgui(Track *track)
+{
+       PatchGUI *patchgui = 0;
+       TimelinePane **panes = gui->pane;
+        for( int i=0; i<TOTAL_PANES && !patchgui; ++i ) {
+                if( !panes[i] ) continue;
+                PatchBay *patchbay = panes[i]->patchbay;
+                if( !patchbay ) continue;
+                for( int j=0; j<patchbay->patches.total && !patchgui; ++j ) {
+                        if( patchbay->patches.values[j]->track == track )
+                                patchgui = patchbay->patches.values[j];
+                }
+        }
+        return patchgui;
+}