add haupauge-1657 dual usb capture support, add deinterlace to recordmonitor, asset...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindow.C
index a99d30982ba1e837ba052ca7c6dafedea4533574..39c996433da4473abcbfeea39961dcfe64d6dc64 100644 (file)
@@ -27,6 +27,7 @@
 #include "awindowgui.h"
 #include "awindow.h"
 #include "batchrender.h"
+#include "bccmodels.h"
 #include "bcdisplayinfo.h"
 #include "bcprogressbox.h"
 #include "bcsignals.h"
@@ -40,9 +41,9 @@
 #include "channelinfo.h"
 #include "clip.h"
 #include "clipedls.h"
-#include "bccmodels.h"
 #include "commercials.h"
 #include "confirmsave.h"
+#include "convert.h"
 #include "cplayback.h"
 #include "ctimebar.h"
 #include "cwindowgui.h"
@@ -179,7 +180,6 @@ extern "C"
 
 }
 
-
 extern long cin_timezone;
 
 ArrayList<PluginServer*>* MWindow::plugindb = 0;
@@ -225,6 +225,7 @@ MWindow::MWindow()
        create_bd = 0;
        create_dvd = 0;
        batch_render = 0;
+       convert_render = 0;
        render = 0;
        edl = 0;
        gui = 0;
@@ -265,6 +266,7 @@ MWindow::~MWindow()
        delete create_dvd;      create_dvd = 0;
        delete shuttle;         shuttle = 0;
        delete batch_render;    batch_render = 0;
+       delete convert_render;  convert_render = 0;
        delete render;          render = 0;
        delete mixers_align;    mixers_align = 0;
        commit_commercial();
@@ -1309,7 +1311,7 @@ void MWindow::stop_mixers()
        }
 }
 
-void MWindow::close_mixers(int destroy)
+void MWindow::close_mixers(int result)
 {
        ArrayList<ZWindow*> closed;
        zwindows_lock->lock("MWindow::close_mixers");
@@ -1317,10 +1319,9 @@ void MWindow::close_mixers(int destroy)
                ZWindow *zwindow = zwindows[i];
                if( zwindow->idx < 0 ) continue;
                zwindow->idx = -1;
-               zwindow->destroy = destroy;
                ZWindowGUI *zgui = zwindow->zgui;
                zgui->lock_window("MWindow::select_zwindow 0");
-               zgui->set_done(0);
+               zgui->set_done(result);
                zgui->unlock_window();
                closed.append(zwindow);
        }
@@ -1453,7 +1454,7 @@ void MWindow::tile_mixers()
        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 mw = xS(10+10), mh = yS(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 ) {
@@ -1465,7 +1466,7 @@ void MWindow::tile_mixers()
                int mx = x2 - zw, my = y2 - zh;
                if( xx > mx ) xx = mx;
                if( yy > my ) yy = my;
-               xx += lt + dz;  yy += top + dz;
+               xx += lt + xS(dz);  yy += top + yS(dz);
                zwindow->reposition(xx,yy, ww,hh);
                if( zwindow->running() ) {
                        ZWindowGUI *gui = (ZWindowGUI *)zwindow->get_gui();
@@ -2635,7 +2636,7 @@ void MWindow::create_objects(int want_gui,
 
        if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference());
 
-       plugin_guis = new ArrayList<PluginServer*>;
+       plugin_guis = new PluginGUIs(this);
        dead_plugins = new ArrayList<PluginServer*>;
        keyframe_threads = new ArrayList<KeyFrameThread*>;
 
@@ -3171,9 +3172,6 @@ void MWindow::show_keyframe_gui(Plugin *plugin)
 }
 
 
-
-
-
 void MWindow::show_plugin(Plugin *plugin)
 {
        int done = 0;
@@ -3223,6 +3221,8 @@ SET_TRACE
                }
        }
        plugin_gui_lock->unlock();
+// update show/gui_id
+       sync_parameters(CHANGE_PARAMS);
 //printf("MWindow::show_plugin %d\n", __LINE__);
 SET_TRACE
 //sleep(1);
@@ -3254,6 +3254,8 @@ void MWindow::hide_plugin(Plugin *plugin, int lock)
                }
        }
        if(lock) plugin_gui_lock->unlock();
+// update show/gui_id
+       sync_parameters(CHANGE_PARAMS);
 }
 
 void MWindow::delete_plugin(PluginServer *plugin)
@@ -3429,7 +3431,6 @@ void MWindow::update_plugin_guis(int do_keyframe_guis)
                                }
 
                                if(!got_it) plugin->show = 0;
-
                                plugin = (Plugin*)plugin->next;
                        }
                }
@@ -3443,50 +3444,85 @@ void MWindow::update_plugin_guis(int do_keyframe_guis)
        if(do_keyframe_guis) update_keyframe_guis();
 }
 
-int MWindow::plugin_gui_open(Plugin *plugin)
+void MWindow::stop_plugin_guis()
 {
-       int result = 0;
-       plugin_gui_lock->lock("MWindow::plugin_gui_open");
-       for(int i = 0; i < plugin_guis->total; i++)
-       {
-               if(plugin_guis->get(i)->plugin->identical_location(plugin))
-               {
-                       result = 1;
-                       break;
+// Send new configuration to plugin GUI's
+       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();
                }
        }
+       plugin_gui_lock->unlock(); 
+}
+
+int MWindow::plugin_gui_open(Plugin *plugin)
+{
+       int gui_id = plugin->gui_id;
+       if( gui_id < 0 ) return 0;
+       plugin_gui_lock->lock("MWindow::plugin_gui_open");
+       PluginServer *plugin_server = plugin_guis->gui_server(gui_id);
+       int result = plugin_server ? 1 : 0;
        plugin_gui_lock->unlock();
        return result;
 }
 
+
 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->get(i)->plugin->identical_location(plugin))
-               {
-                       plugin_guis->get(i)->render_gui(data);
-                       break;
-               }
-       }
+       int gui_id = plugin->gui_id;
+       if( gui_id < 0 ) return;
+       plugin_gui_lock->lock("MWindow::render_plugin_gui 0");
+       PluginServer *plugin_server = plugin_guis->gui_server(gui_id);
+       if( plugin_server )
+               plugin_server->render_gui(data);
        plugin_gui_lock->unlock();
 }
 
 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->get(i)->plugin->identical_location(plugin))
-               {
-                       plugin_guis->get(i)->render_gui(data, size);
-                       break;
-               }
-       }
+       int gui_id = plugin->gui_id;
+       if( gui_id < 0 ) return;
+       plugin_gui_lock->lock("MWindow::render_plugin_gui 1");
+       PluginServer *plugin_server = plugin_guis->gui_server(gui_id);
+       if( plugin_server )
+               plugin_server->render_gui(data, size);
        plugin_gui_lock->unlock();
 }
 
+void MWindow::reset_plugin_gui_frames(Plugin *plugin)
+{
+       int gui_id = plugin->gui_id;
+       if( gui_id < 0 ) return;
+       plugin_gui_lock->lock("MWindow::reset_plugin_gui_frames");
+       PluginServer *plugin_server = plugin_guis->gui_server(gui_id);
+       if( plugin_server )
+               plugin_server->reset_plugin_gui_frames();
+       plugin_gui_lock->unlock();
+}
+
+void MWindow::render_plugin_gui_frames(PluginClientFrames *frames, Plugin *plugin)
+{
+       int gui_id = plugin->gui_id;
+       if( gui_id < 0 ) return;
+       plugin_gui_lock->lock("MWindow::render_plugin_gui_frames");
+       PluginServer *plugin_server = plugin_guis->gui_server(gui_id);
+       if( plugin_server )
+               plugin_server->render_plugin_gui_frames(frames);
+       plugin_gui_lock->unlock();
+}
+
+double MWindow::get_tracking_position()
+{
+       return edl->local_session->get_selectionstart(1);
+}
+
+int MWindow::get_tracking_direction()
+{
+       return cwindow->playback_engine->get_direction();
+}
 
 void MWindow::update_plugin_states()
 {
@@ -3671,6 +3707,7 @@ void MWindow::update_project(int load_mode)
                        zwindow->set_title(mixer->title);
                        zwindow->start();
                }
+               cwindow->gui->canvas->set_zoom(edl, 0);
        }
        update_vwindow();
 
@@ -3680,6 +3717,7 @@ void MWindow::update_project(int load_mode)
        Track *track = cwindow->calculate_affected_track();
        cwindow->mask_track_id = track ? track->get_id() : -1;
        cwindow->gui->tool_panel->raise_tool();
+       cwindow->gui->update_canvas(0);
        cwindow->gui->unlock_window();
 
        if(debug) PRINT_TRACE
@@ -3694,6 +3732,145 @@ void MWindow::update_project(int load_mode)
        if(debug) PRINT_TRACE
 }
 
+void MWindow::stack_push(EDL *new_edl)
+{
+// needs gui lock
+       gui->lock_window("MWindow::stack_push");
+       if( stack.size() < 9 ) {
+               undo_before();
+               StackItem &item = stack.append();
+               item.edl = edl;
+               item.new_edl = new_edl;
+               item.undo = undo;
+               edl = new_edl;
+               edl->add_user();
+               strcpy(session->filename, edl->path);
+               undo = new MainUndo(this);
+               gui->stack_button->update();
+               update_project(LOADMODE_REPLACE);
+       }
+       gui->unlock_window();
+}
+
+void MWindow::stack_pop()
+{
+       if( !stack.size() ) return;
+// writes on config_path/backup%d.xml
+       save_backup();
+// already have gui lock
+       forget_nested_edl(edl);
+       StackItem &item = stack.last();
+// session edl replaced, overwrite and save clip data
+       if( item.new_edl != edl )
+               item.new_edl->overwrite_clip(edl);
+       edl->remove_user();
+       edl = item.edl;
+       delete undo;
+       undo = item.undo;
+       stack.remove();
+       strcpy(session->filename, edl->path);
+       update_project(LOADMODE_REPLACE);
+       undo_after(_("open edl"), LOAD_ALL);
+       gui->stack_button->update();
+}
+
+void MWindow::forget_nested_edl(EDL *nested)
+{
+       frame_cache->remove_item(nested);
+       wave_cache->remove_item(nested);
+       if( gui->render_engine &&
+           gui->render_engine_id == nested->id ) {
+               delete gui->render_engine;
+               gui->render_engine = 0;
+       }
+       if( gui->resource_thread->render_engine_id == nested->id ) {
+               gui->resource_thread->render_engine_id = -1;
+               delete gui->resource_thread->render_engine;
+               gui->resource_thread->render_engine = 0;
+       }
+}
+
+void MWindow::clip_to_media()
+{
+       if( edl->session->proxy_scale != 1 ) {
+               eprintf("Nesting not allowed when proxy scale != 1");
+               return;
+       }
+       undo_before();
+       int clips_total = session->drag_clips->total;
+       for( int i=0; i<clips_total; ++i ) {
+               EDL *clip = session->drag_clips->values[i];
+               time_t dt;      time(&dt);
+               struct tm dtm;  localtime_r(&dt, &dtm);
+               char path[BCTEXTLEN], *cp = path, *ep = cp+sizeof(path)-1;
+// path_basename = "Nested_<date>-<time>_<basename>"
+               cp += snprintf(cp, ep-cp, _("Nested_%02d%02d%02d-%02d%02d%02d_"),
+                       dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
+                       dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
+               char *bp = strrchr(clip->local_session->clip_title, '/');
+               bp = bp ? bp+1 : clip->local_session->clip_title;
+               cp += snprintf(cp, ep-cp, "%s", bp);
+               EDL *nested = edl->new_nested_edl(clip, path);
+               edl->clips.remove(clip);
+               clip->remove_user();
+               mainindexes->add_next_asset(0, nested);
+       }
+       undo_after(_("clip2media"), LOAD_ALL);
+       mainindexes->start_build();
+       awindow->gui->async_update_assets();
+}
+
+void MWindow::media_to_clip()
+{
+       undo_before();
+       int assets_total = session->drag_assets->total;
+       for( int i=0; i<assets_total; ++i ) {
+               Indexable *idxbl = session->drag_assets->values[i];
+               if( idxbl->is_asset ) {
+                       eprintf(_("media is not EDL:\n%s"), idxbl->path);
+                       continue;
+               }
+               char clip_title[BCSTRLEN];
+               int name_ok = 0;
+               while( !name_ok ) {
+                       name_ok = 1;
+                       sprintf(clip_title, _("Clip %d"), session->clip_number++);
+                       for( int i=0; name_ok && i<edl->clips.size(); ++i ) {
+                               char *title = edl->clips[i]->local_session->clip_title;
+                               if( !strcasecmp(clip_title, title) ) name_ok = 0;
+                       }
+               }
+               EDL *nested = (EDL *)idxbl;
+               EDL *clip = edl->add_clip(nested);
+               strcpy(clip->local_session->clip_title, clip_title);
+               snprintf(clip->local_session->clip_notes,
+                       sizeof(clip->local_session->clip_notes),
+                       _("From: %s"), nested->path);
+       }
+       undo_after(_("media2clip"), LOAD_ALL);
+       awindow->gui->async_update_assets();
+}
+
+void MWindow::update_preferences(Preferences *prefs)
+{
+       if( prefs != preferences )
+               preferences->copy_from(prefs);
+       if( cwindow->playback_engine )
+               cwindow->playback_engine->preferences->copy_from(prefs);
+       for(int i = 0; i < vwindows.size(); i++) {
+               VWindow *vwindow = vwindows[i];
+               if( !vwindow->is_running() ) continue;
+               if( vwindow->playback_engine )
+                       vwindow->playback_engine->preferences->copy_from(prefs);
+       }
+       for(int i = 0; i < zwindows.size(); i++) {
+               ZWindow *zwindow = zwindows[i];
+               if( !zwindow->is_running() ) continue;
+               if( zwindow->zgui->playback_engine )
+                       zwindow->zgui->playback_engine->preferences->copy_from(prefs);
+       }
+}
+
 void MWindow::update_vwindow()
 {
        for( int i=0; i<vwindows.size(); ++i ) {
@@ -3724,8 +3901,9 @@ void MWindow::rebuild_indices()
 //printf("MWindow::rebuild_indices 1 %s\n", indexable->path);
                remove_indexfile(indexable);
 // Schedule index build
-               IndexState *index_state = indexable->index_state;
-               index_state->index_status = INDEX_NOTTESTED;
+               indexable->index_state->remove_user();
+               indexable->index_state = new IndexState;
+               IndexFile::delete_index_files(preferences, indexable);
                if( indexable->is_asset ) {
                        Asset *asset = (Asset *)indexable;
                        if( asset->format != FILE_PCM ) {
@@ -3739,28 +3917,36 @@ void MWindow::rebuild_indices()
                }
                mainindexes->add_next_asset(0, indexable);
        }
+// still in render engine
+       sync_parameters(CHANGE_ALL);
+       awindow->gui->async_update_assets();
        mainindexes->start_build();
 }
 
 
+void MWindow::get_backup_path(char *path, int len)
+{
+       char *cp = path, *ep = cp + len-1;
+       cp += snprintf(cp, ep-cp, "%s/", File::get_config_path());
+       int idx = stack.size();
+       cp += snprintf(cp, ep-cp, idx ? BACKUPn_FILE : BACKUP_FILE, idx);
+}
+
 void MWindow::save_backup()
 {
        FileXML file;
        edl->optimize();
        edl->set_path(session->filename);
+
        char backup_path[BCTEXTLEN], backup_path1[BCTEXTLEN];
-       snprintf(backup_path, sizeof(backup_path), "%s/%s",
-               File::get_config_path(), BACKUP_FILE);
-       snprintf(backup_path1, sizeof(backup_path1), "%s/%s",
-               File::get_config_path(), BACKUP_FILE1);
+       get_backup_path(backup_path, sizeof(backup_path));
        rename(backup_path, backup_path1);
        edl->save_xml(&file, backup_path);
        file.terminate_string();
        FileSystem fs;
        fs.complete_path(backup_path);
 
-       if(file.write_to_file(backup_path))
-       {
+       if(file.write_to_file(backup_path)) {
                char string2[256];
                sprintf(string2, _("Couldn't open %s for writing."), backup_path);
                gui->show_message(string2);
@@ -3773,8 +3959,7 @@ void MWindow::load_backup()
        path_list.set_array_delete();
        char *out_path;
        char backup_path[BCTEXTLEN];
-       snprintf(backup_path, sizeof(backup_path), "%s/%s",
-               File::get_config_path(), BACKUP_FILE);
+       get_backup_path(backup_path, sizeof(backup_path));
        FileSystem fs;
        fs.complete_path(backup_path);
 
@@ -4084,47 +4269,60 @@ void MWindow::remove_asset_from_caches(Asset *asset)
                if( vwindow->playback_engine->video_cache )
                        vwindow->playback_engine->video_cache->delete_entry(asset);
        }
+       for(int i = 0; i < zwindows.size(); i++) {
+               ZWindow *zwindow = zwindows[i];
+               if( !zwindow->is_running() ) continue;
+               if( zwindow->zgui->playback_engine->audio_cache )
+                       zwindow->zgui->playback_engine->audio_cache->delete_entry(asset);
+               if( zwindow->zgui->playback_engine->video_cache )
+                       zwindow->zgui->playback_engine->video_cache->delete_entry(asset);
+       }
 }
 
-
-void MWindow::remove_assets_from_project(int push_undo, int redraw,
+void MWindow::remove_assets_from_project(int push_undo, int redraw, int delete_indexes,
                ArrayList<Indexable*> *drag_assets, ArrayList<EDL*> *drag_clips)
 {
        awindow->gui->close_view_popup();
 
-       for(int i = 0; i < drag_assets->total; i++) {
-               Indexable *indexable = drag_assets->get(i);
-               if(indexable->is_asset) remove_asset_from_caches((Asset*)indexable);
-       }
-
 // Remove from VWindow.
-       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();
+       if( drag_clips ) {
+               for(int i = 0; i < drag_clips->total; i++) {
+                       for(int j = 0; j < vwindows.size(); j++) {
+                               VWindow *vwindow = vwindows[j];
+                               if( !vwindow->is_running() ) continue;
+                               if(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 < drag_assets->size(); i++) {
-               for(int j = 0; j < vwindows.size(); j++) {
-                       VWindow *vwindow = vwindows[j];
-                       if( !vwindow->is_running() ) continue;
-                       if(drag_assets->get(i) == vwindow->get_source()) {
-                               vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
-                               vwindow->delete_source(1, 1);
-                               vwindow->gui->unlock_window();
+       if( drag_assets ) {
+               for(int i = 0; i < drag_assets->size(); i++) {
+                       for(int j = 0; j < vwindows.size(); j++) {
+                               VWindow *vwindow = vwindows[j];
+                               if( !vwindow->is_running() ) continue;
+                               if(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 < drag_assets->size(); i++) {
-               Indexable *indexable = drag_assets->get(i);
-               remove_indexfile(indexable);
+               for(int i = 0; i < drag_assets->total; i++) {
+                       Indexable *indexable = drag_assets->get(i);
+                       if(indexable->is_asset) remove_asset_from_caches((Asset*)indexable);
+               }
+
+               if( delete_indexes ) {
+                       for(int i = 0; i < drag_assets->size(); i++) {
+                               Indexable *indexable = drag_assets->get(i);
+                               remove_indexfile(indexable);
+                       }
+               }
        }
 
 //printf("MWindow::rebuild_indices 1 %s\n", indexable->path);
@@ -4149,10 +4347,8 @@ void MWindow::remove_assets_from_project(int push_undo, int redraw,
 
 void MWindow::remove_assets_from_disk()
 {
-       remove_assets_from_project(1,
-               1,
-               session->drag_assets,
-               session->drag_clips);
+       remove_assets_from_project(1, 1, 1,
+               session->drag_assets, session->drag_clips);
 
 // Remove from disk
        for(int i = 0; i < session->drag_assets->total; i++)