+void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
+{
+ int got_indexes = 0;
+ for( int i=0; i<new_edl->nested_edls.size(); ++i ) {
+ EDL *nested_edl = new_edl->nested_edls[i];
+ mainindexes->add_indexable(nested_edl);
+ edl->nested_edls.update_index(nested_edl);
+ got_indexes = 1;
+ }
+ for( Asset *asset=new_edl->assets->first; asset; asset=asset->next ) {
+ mainindexes->add_indexable(asset);
+ edl->assets->update(asset);
+ got_indexes = 1;
+ }
+// Start examining next batch of index files
+ if( got_indexes )
+ mainindexes->start_build();
+
+// needs gui lock
+ gui->lock_window("MWindow::stack_push");
+ if( stack.size() < 9 ) {
+ save_backup();
+ hide_plugins();
+ undo_before();
+ StackItem &item = stack.append();
+ item.edl = edl;
+ item.new_edl = new_edl;
+ item.undo = undo;
+ item.idxbl = idxbl;
+ item.mtime = 0;
+ if( idxbl && idxbl->is_asset ) {
+ struct stat st;
+ Asset *asset = (Asset *)idxbl;
+ if( asset->format == FILE_REF &&
+ !stat(asset->path, &st) )
+ item.mtime = st.st_mtime;
+ }
+ 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();
+ show_plugins();
+}
+
+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);
+ edl->remove_user();
+ edl = item.edl;
+ delete undo;
+ undo = item.undo;
+ Indexable *idxbl = item.idxbl;
+ int64_t mtime = item.mtime;
+ stack.remove();
+ if( idxbl ) {
+ gui->unlock_window();
+ remove_from_caches(idxbl);
+ remove_indexfile(idxbl);
+ mainindexes->add_indexable(idxbl);
+ mainindexes->start_build();
+ awindow->gui->async_update_assets();
+ gui->lock_window("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;
+ Asset *asset = (Asset *)idxbl;
+ if( asset->format == FILE_REF && !stat(asset->path, &st) &&
+ item.mtime == st.st_mtime ) {
+ char text[BCTEXTLEN];
+ snprintf(text, sizeof(text),
+ _("Warning: Asset not updated: %s"), asset->path);
+ show_warning(&preferences->warn_stack, text);
+ }
+ }
+}
+
+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 ) {
+ 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_indexable(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();
+}
+
+int MWindow::create_ref(Asset *asset, EDL *ref)
+{
+ asset->format = FILE_REF;
+ double secs = ref->tracks->total_length();
+ int audio_channels = ref->session->audio_channels;
+ asset->audio_data = audio_channels > 0 ? 1 : 0;
+ asset->channels = audio_channels;
+ asset->sample_rate = ref->session->sample_rate;
+ asset->audio_length = audio_channels > 0 && secs > 0 ?
+ secs * asset->sample_rate : 0;
+ strcpy(asset->acodec, _("reference"));
+
+ int video_layers = ref->session->video_channels;
+ asset->video_data = video_layers > 0 ? 1 : 0;
+ asset->layers = video_layers > 0 ? 1 : 0;
+ asset->actual_width = ref->session->output_w;
+ asset->actual_height = ref->session->output_h;
+ asset->width = asset->actual_width;
+ asset->height = asset->actual_height;
+ asset->frame_rate = ref->session->frame_rate;
+ asset->video_length = video_layers > 0 && secs > 0 ?
+ secs * asset->frame_rate : 0;
+ strcpy(asset->vcodec, _("reference"));
+ return 0;
+}
+
+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);
+ }
+}
+