X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fmwindow.C;h=2e590c668f376c244c2d46fd6af4f7693962888c;hp=adb7a87aaa868e746eb879ab5bda531c2fa6a459;hb=08284a3a20b2cc8606dd90c3c147e2c31d301a61;hpb=50a589b1decdd353a984d8a710e064ebaf8b4f7b diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index adb7a87a..2e590c66 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -18,15 +18,19 @@ * */ +#include "aboutprefs.h" #include "asset.h" #include "assets.h" +#include "atrack.h" #include "audioalsa.h" +#include "autos.h" #include "awindowgui.h" #include "awindow.h" #include "batchrender.h" #include "bcdisplayinfo.h" #include "bcsignals.h" #include "bctimer.h" +#include "bctrace.h" #include "bdcreate.h" #include "brender.h" #include "cache.h" @@ -34,8 +38,10 @@ #include "channeldb.h" #include "channelinfo.h" #include "clip.h" +#include "clipedls.h" #include "bccmodels.h" #include "commercials.h" +#include "confirmsave.h" #include "cplayback.h" #include "ctimebar.h" #include "cwindowgui.h" @@ -52,11 +58,13 @@ #include "file.h" #include "filesystem.h" #include "filexml.h" +#include "floatautos.h" #include "framecache.h" #include "gwindow.h" #include "gwindowgui.h" #include "keyframegui.h" #include "indexfile.h" +#include "intautos.h" #include "interlacemodes.h" #include "language.h" #include "levelwindowgui.h" @@ -74,8 +82,8 @@ #include "mutex.h" #include "mwindowgui.h" #include "mwindow.h" -#include "nestededls.h" #include "new.h" +#include "panautos.h" #include "patchbay.h" #include "playback3d.h" #include "playbackengine.h" @@ -83,6 +91,7 @@ #include "pluginserver.h" #include "pluginset.h" #include "preferences.h" +#include "proxy.h" #include "record.h" #include "recordmonitor.h" #include "recordlabel.h" @@ -97,6 +106,7 @@ #include "theme.h" #include "threadloader.h" #include "timebar.h" +#include "timelinepane.h" #include "tipwindow.h" #include "trackcanvas.h" #include "track.h" @@ -106,6 +116,8 @@ #include "transition.h" #include "transportque.h" #include "vframe.h" +#include "vtrack.h" +#include "versioninfo.h" #include "videodevice.inc" #include "videowindow.h" #include "vplayback.h" @@ -114,16 +126,24 @@ #include "wavecache.h" #include "wwindow.h" #include "zoombar.h" +#include "zwindow.h" +#include "zwindowgui.h" #include "exportedl.h" #include "defaultformats.h" #include "ntsczones.h" -#include -#include +#include +#include +#include #include #include +#include #include +#include +#include +#include +#include extern "C" @@ -154,6 +174,7 @@ extern "C" } +extern long cin_timezone; ArrayList* MWindow::plugindb = 0; Commercials* MWindow::commercials = 0; @@ -162,9 +183,11 @@ Commercials* MWindow::commercials = 0; MWindow::MWindow() : Thread(1, 0, 0) { + run_lock = new Mutex("MWindow::run_lock"); 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"); @@ -185,9 +208,10 @@ MWindow::MWindow() mainindexes = 0; mainprogress = 0; brender = 0; + brender_active = 0; + strcpy(cin_lang,"en"); channeldb_buz = new ChannelDB; channeldb_v4l2jpeg = new ChannelDB; - //file_server = 0; plugin_guis = 0; dead_plugins = 0; keyframe_threads = 0; @@ -207,29 +231,31 @@ MWindow::MWindow() restart_status = 0; screens = 1; in_destructor = 0; + speed_edl = 0; + proxy_beep = 0; } // Need to delete brender temporary here. MWindow::~MWindow() { + run_lock->lock("MWindow::~MWindow"); in_destructor = 1; - stop_playback(1); - stop_brender(); //printf("MWindow::~MWindow %d\n", __LINE__); - gui->stop_drawing(); gui->remote_control->deactivate(); gui->record->stop(); +#ifdef HAVE_DVB gui->channel_info->stop(); - brender_lock->lock("MWindow::quit"); - delete brender; brender = 0; - brender_lock->unlock(); +#endif + delete proxy_beep; delete create_bd; create_bd = 0; delete create_dvd; create_dvd = 0; delete batch_render; batch_render = 0; + delete render; render = 0; commit_commercial(); if( commercials && !commercials->remove_user() ) commercials = 0; - + close_mixers(); + if( speed_edl ) { speed_edl->remove_user(); speed_edl = 0; } // Save defaults for open plugins plugin_gui_lock->lock("MWindow::~MWindow"); for(int i = 0; i < plugin_guis->size(); i++) { @@ -255,6 +281,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(); @@ -275,25 +302,26 @@ 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(); colormodels.remove_all_objects(); - delete gui; gui = 0; - delete render; render = 0; 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; - //delete file_server; file_server = 0; // reusable + delete gui; gui = 0; delete mainindexes; mainindexes = 0; delete mainprogress; mainprogress = 0; delete audio_cache; audio_cache = 0; // delete the cache after the assets @@ -310,7 +338,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; @@ -319,6 +346,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(); @@ -327,23 +355,13 @@ MWindow::~MWindow() interlace_asset_fixmethods.remove_all_objects(); sighandler->terminate(); delete sighandler; + delete run_lock; } -void MWindow::quit(int unlock) +void MWindow::quit() { - stop_playback(1); - if(unlock) gui->unlock_window(); - - brender_lock->lock("MWindow::quit"); - delete brender; brender = 0; - brender_lock->unlock(); - - interrupt_indexes(); - clean_indexes(); - save_defaults(); gui->set_done(0); - if(unlock) gui->lock_window("MWindow::quit"); } void MWindow::init_error() @@ -361,7 +379,7 @@ void MWindow::create_defaults_path(char *string, const char *config_file) // set the .bcast path FileSystem fs; - sprintf(string, "%s", BCASTDIR); + sprintf(string, "%s/", File::get_config_path()); fs.complete_path(string); if(!fs.is_dir(string)) fs.create_dir(string); @@ -371,43 +389,46 @@ void MWindow::create_defaults_path(char *string, const char *config_file) } const char *MWindow::default_std() { - int fd, i, l = 0; - char buf[BCTEXTLEN]; - char *p; + char buf[BCTEXTLEN], *p = 0; - if((fd = open(TIMEZONE_NAME, O_RDONLY)) >= 0) - { - l = read(fd, buf, BCTEXTLEN); + int fd = open(TIMEZONE_NAME, O_RDONLY); + if( fd >= 0 ) { + int l = read(fd, buf, sizeof(buf)-1); close(fd); - if(l > 0) - { + if( l > 0 ) { + if( buf[l-1] == '\n' ) --l; buf[l] = 0; - if(buf[l - 1] == '\n') - buf[--l] = 0; + p = buf; } - p = buf; } - if(l < 1) - { - if((l = readlink(LOCALTIME_LINK, buf, BCTEXTLEN)) > 0) - { + if( !p ) { + int l = readlink(LOCALTIME_LINK, buf, sizeof(buf)-1); + if( l > 0 ) { buf[l] = 0; - if( (p=strstr(buf, ZONEINFO_STR)) != 0 ) - { - p += strlen(ZONEINFO_STR); - l = strlen(p); - } - else - l = 0; + if( !(p=strstr(buf, ZONEINFO_STR)) != 0 ) return "PAL"; + p += strlen(ZONEINFO_STR); } } - if(l) - { - for(i = 0; ntsc_zones[i]; i++) - if(strcmp(ntsc_zones[i], p) == 0) - return "NTSC"; + + if( p ) { + for( int i=0; ntsc_zones[i]; ++i ) { + if( !strcmp(ntsc_zones[i], p) ) + return "NTSC"; + } } - return "PAL"; + + p = getenv("TZ"); + if( p ) { + for( int i=0; ntsc_zones[i]; ++i ) { + if( !strcmp(ntsc_zones[i], p) ) + return "NTSC"; + } + } + +// cin_timezone: Seconds west of UTC. 240sec/deg + double tz_deg = -cin_timezone / 240.; +// from Honolulu = -10, to New York = -5, 15deg/hr lat -150..-75 + return tz_deg >= -10*15 && tz_deg <= -5*15 ? "NTSC" : "PAL"; } void MWindow::fill_preset_defaults(const char *preset, EDLSession *session) @@ -416,7 +437,7 @@ void MWindow::fill_preset_defaults(const char *preset, EDLSession *session) for(fpr = &format_presets[0]; fpr->name; fpr++) { - if(strcmp(fpr->name, preset) == 0) + if(strcmp(_(fpr->name), preset) == 0) { session->audio_channels = fpr->audio_channels; session->audio_tracks = fpr->audio_tracks; @@ -439,7 +460,7 @@ const char *MWindow::get_preset_name(int index) { if(index < 0 || index >= (int)MAX_NUM_PRESETS) return "Error"; - return format_presets[index].name; + return _(format_presets[index].name); } @@ -452,10 +473,44 @@ void MWindow::init_defaults(BC_Hash* &defaults, char *config_path) else create_defaults_path(path, CONFIG_FILE); + delete defaults; defaults = new BC_Hash(path); defaults->load(); } + +void MWindow::check_language() +{ + char curr_lang[BCTEXTLEN]; curr_lang[0] = 0; + const char *env_lang = getenv("LANGUAGE"); + if( !env_lang ) env_lang = getenv("LC_ALL"); + if( !env_lang ) env_lang = getenv("LANG"); + if( !env_lang ) { + snprintf(curr_lang, sizeof(curr_lang), "%s_%s-%s", + BC_Resources::language, BC_Resources::region, BC_Resources::encoding); + env_lang = curr_lang; + } + char last_lang[BCTEXTLEN]; last_lang[0] = 0; + defaults->get("LAST_LANG",last_lang); + if( strcmp(env_lang,last_lang)) { + printf("lang changed from '%s' to '%s'\n", last_lang, env_lang); + defaults->update("LAST_LANG",env_lang); + char plugin_path[BCTEXTLEN]; + create_defaults_path(plugin_path, PLUGIN_FILE); + ::remove(plugin_path); + char ladspa_path[BCTEXTLEN]; + create_defaults_path(ladspa_path, LADSPA_FILE); + ::remove(ladspa_path); + defaults->save(); + } + if( strlen(env_lang) > 1 && + ( env_lang[2] == 0 || env_lang[2] == '_' || env_lang[2] == '.' ) ) { + cin_lang[0] = env_lang[0]; cin_lang[1] = env_lang[1]; cin_lang[2] = 0; + } + else + strcpy(cin_lang, "en"); +} + 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; @@ -509,6 +564,9 @@ int MWindow::load_plugin_index(MWindow *mwindow, const char *index_path, const c case PLUGIN_TYPE_FFMPEG: { server = new_ffmpeg_server(mwindow, path); break; } + case PLUGIN_TYPE_LV2: { + server = new_lv2_server(mwindow, path); + break; } } if( !server ) continue; plugins.append(server); @@ -577,6 +635,7 @@ int MWindow::init_plugins(MWindow *mwindow, Preferences *preferences) fprintf(fp, "%s\n", plugin_path); init_plugin_index(mwindow, preferences, fp, plugin_path); init_ffmpeg_index(mwindow, preferences, fp); + init_lv2_index(mwindow, preferences, fp); fclose(fp); return load_plugin_index(mwindow, index_path, plugin_path); } @@ -586,8 +645,7 @@ 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"); + strncpy(ladspa_path, File::get_ladspa_path(), sizeof(ladspa_path)); path = ladspa_path; } for( int len=0; *path; path+=len ) { @@ -595,6 +653,7 @@ int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences) len = !cp ? strlen(path) : cp-path; char index_path[BCTEXTLEN], plugin_path[BCTEXTLEN]; memcpy(plugin_path, path, len); plugin_path[len] = 0; + if( cp ) ++len; char *plugin_dir = FileSystem::basepath(plugin_path); strcpy(plugin_path, plugin_dir); delete [] plugin_dir; create_defaults_path(index_path, LADSPA_FILE); @@ -623,25 +682,6 @@ void MWindow::init_plugin_index(MWindow *mwindow, Preferences *preferences, 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); - fprintf(fp, "%s\n", plugin_dir); - init_plugin_index(mwindow, preferences, fp, plugin_path); - fclose(fp); - return 0; -} - void MWindow::scan_plugin_index(MWindow *mwindow, Preferences *preferences, FILE *fp, const char *plug_dir, const char *plug_path, int &idx) { @@ -692,6 +732,64 @@ void MWindow::add_plugins(ArrayList &plugins) plugins.remove_all(); } +void MWindow::init_plugin_tips(ArrayList &plugins, const char *lang) +{ + const char *dat_path = File::get_cindat_path(); + char msg_path[BCTEXTLEN]; + FILE *fp = 0; + if( BC_Resources::language[0] ) { + snprintf(msg_path, sizeof(msg_path), "%s/info/plugins.%s", + dat_path, lang); + fp = fopen(msg_path, "r"); + } + if( !fp ) { + snprintf(msg_path, sizeof(msg_path), "%s/info/plugins.txt", + dat_path); + fp = fopen(msg_path, "r"); + } + if( !fp ) return; + char text[BCTEXTLEN]; + char *tp = text, *ep = tp + sizeof(text)-1; + char title[BCTEXTLEN]; + title[0] = 0; + int no = 0; + for(;;) { + ++no; int done = 1; + char line[BCTEXTLEN], *cp = line; + if( fgets(line,sizeof(line)-1,fp) ) { + if( *cp == '#' ) continue; + done = *cp == ' ' || *cp == '\t' ? 0 : -1; + } + if( done ) { + if( tp > text && *--tp == '\n' ) *tp = 0; + if( title[0] ) { + int idx = plugins.size(); + while( --idx>=0 && strcmp(plugins[idx]->title, title) ); + if( idx >= 0 ) { + delete [] plugins[idx]->tip; + plugins[idx]->tip = cstrdup(text); + } + title[0] = 0; + } + if( done > 0 ) break; + tp = text; *tp = 0; + char *dp = strchr(cp, ':'); + if( !dp ) { + printf("plugin tips: error on line %d\n", no); + continue; + } + char *bp = title; + while( cp < dp ) *bp++ = *cp++; + *bp = 0; + ++cp; + } + + while( *cp == ' ' || *cp == '\t' ) ++cp; + for( ; tpremove_all_objects(); @@ -761,6 +859,20 @@ PluginServer* MWindow::scan_plugindb(char *title, return 0; } +// repair session files with xlated plugin titles +void MWindow::fix_plugin_title(char *title) +{ + for(int i = 0; i < plugindb->total; i++) { + PluginServer *server = plugindb->get(i); + if( !server->title ) continue; + const char *server_title = server->title; + if( !bstrcasecmp(title, _(server_title)) ) { + strcpy(title, server_title); + return; + } + } +} + int MWindow::plugin_exists(const char *plugin_path, ArrayList &plugins) { for( int i=0; iload_defaults(defaults); + const char *lv2_path = getenv("LV2_PATH"); + if( lv2_path && strcmp(lv2_path, preferences->lv2_path) ) { + strncpy(preferences->lv2_path, lv2_path, sizeof(preferences->lv2_path)); + remove_plugin_index(); + } + else if( !lv2_path && preferences->lv2_path[0] ) { + File::setenv_path("LV2_PATH",preferences->lv2_path, 0); + } session = new MainSession(this); session->load_defaults(defaults); // set x11_host, screens, window_config screens = session->set_default_x11_host(); - BC_Signals::set_trap_path("/tmp/cinelerra_%d.dmp"); BC_Signals::set_trap_hook(trap_hook, this); BC_Signals::set_catch_segv(preferences->trap_sigsegv); BC_Signals::set_catch_intr(preferences->trap_sigintr); + if( preferences->trap_sigsegv || preferences->trap_sigintr ) { + BC_Trace::enable_locks(); + } + else { + BC_Trace::disable_locks(); + } + 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() @@ -879,6 +1015,7 @@ void MWindow::init_gwindow() void MWindow::init_tipwindow() { + TipWindow::load_tips(cin_lang); if( !twindow ) twindow = new TipWindow(this); twindow->start(); @@ -892,6 +1029,11 @@ void MWindow::show_warning(int *do_warning, const char *text) wwindow->show_warning(do_warning, text); } +int MWindow::wait_warning() +{ + return wwindow->wait_result(); +} + void MWindow::init_theme() { Timer timer; @@ -908,12 +1050,13 @@ void MWindow::init_theme() fprintf(stderr, _("MWindow::init_theme: prefered theme %s not found.\n"), preferences->theme); - if( !theme_plugin && strcasecmp(preferences->theme, DEFAULT_THEME) ) { + const char *default_theme = DEFAULT_THEME; + if( !theme_plugin && strcasecmp(preferences->theme, default_theme) ) { fprintf(stderr, _("MWindow::init_theme: trying default theme %s\n"), - DEFAULT_THEME); + default_theme); for(int i = 0; i < plugindb->total && !theme_plugin; i++) { if( plugindb->get(i)->theme && - !strcasecmp(DEFAULT_THEME, plugindb->get(i)->title) ) + !strcasecmp(default_theme, plugindb->get(i)->title) ) theme_plugin = plugindb->get(i); } } @@ -943,8 +1086,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()); } @@ -960,6 +1103,7 @@ void MWindow::init_edl() edl->create_objects(); fill_preset_defaults(default_standard, edl->session); edl->load_defaults(defaults); + edl->session->brender_start = edl->session->brender_end = 0; edl->create_default_tracks(); edl->tracks->update_y_pixels(theme); } @@ -997,6 +1141,308 @@ 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 && iidx < 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); + 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, int loop_play) +{ + zwindows_lock->lock("MWindow::queue_mixers"); + for( int vidx=0; vidxidx < 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, loop_play); + } + zwindows_lock->unlock(); +} + +void MWindow::refresh_mixers(int dir) +{ + int command = dir >= 0 ? CURRENT_FRAME : LAST_FRAME; + queue_mixers(edl,command,0,0,1,0,0); +} + +void MWindow::stop_mixers() +{ + for( int vidx=0; vidxidx < 0 ) continue; + zwindow->issue_command(STOP, 0, 0, 0, 0, 0); + } +} + +void MWindow::close_mixers(int destroy) +{ + zwindows_lock->lock("MWindow::close_mixers"); + for( int i=zwindows.size(); --i>=0; ) { + ZWindow *zwindow = zwindows[i]; + if( zwindow->idx < 0 ) continue; + zwindow->destroy = destroy; + 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; iidx < 0 ) continue; + zwindow->close_window(); + } +} + +ZWindow *MWindow::create_mixer(Indexable *indexable) +{ + ArrayList new_assets; + new_assets.append(indexable); + Track *track = edl->tracks->last; + load_assets(&new_assets, 0, LOADMODE_NEW_TRACKS, 0, 0, 0, 0, 0, 0); + track = !track ? edl->tracks->first : track->next; + Mixer *mixer = 0; + ZWindow *zwindow = get_mixer(mixer); + while( track ) { + track->play = track->record = 0; + if( track->data_type == TRACK_VIDEO ) { + sprintf(track->title, _("Mixer %d"), zwindow->idx); + } + mixer->mixer_ids.append(track->get_mixer_id()); + track = track->next; + } + if( indexable->is_asset ) { + char *path = indexable->path; + char *tp = strrchr(path, '/'); + if( !tp ) tp = path; else ++tp; + zwindow->set_title(tp); + } + else { + char *title = ((EDL*)indexable)->local_session->clip_title; + zwindow->set_title(title); + } + return zwindow; +} + +void MWindow::create_mixers() +{ + if( !session->drag_assets->size() && + !session->drag_clips->size() ) return; + undo->update_undo_before(); + + select_zwindow(0); + ArrayListnew_mixers; + + for( int i=0; idrag_assets->size(); ++i ) { + Indexable *indexable = session->drag_assets->get(i); + if( !indexable->have_video() ) continue; + ZWindow *zwindow = create_mixer(indexable); + new_mixers.append(zwindow); + } + for( int i=0; idrag_clips->size(); ++i ) { + Indexable *indexable = (Indexable*)session->drag_clips->get(i); + if( !indexable->have_video() ) continue; + ZWindow *zwindow = create_mixer(indexable); + new_mixers.append(zwindow); + } + + tile_mixers(); + for( int i=0; istart(); + + refresh_mixers(); + save_backup(); + undo->update_undo_after(_("create mixers"), LOAD_ALL); + restart_brender(); + gui->update(1, 2, 1, 1, 1, 1, 0); + sync_parameters(CHANGE_ALL); +} + +void MWindow::open_mixers() +{ + for( int i=0; imixers.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; iidx < 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; iidx < 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; iidx < 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); @@ -1047,21 +1493,21 @@ void MWindow::init_menus() interlace_asset_fixmethods.append(new InterlacefixmethodItem(string, x)); // Interlacing Modes - ILACEASSETMODELISTADD(BC_ILACE_MODE_UNDETECTED); // Not included in the list for the project options. + ILACEASSETMODELISTADD(ILACE_MODE_UNDETECTED); // Not included in the list for the project options. - ILACEASSETMODELISTADD(BC_ILACE_MODE_TOP_FIRST); - ILACEPROJECTMODELISTADD(BC_ILACE_MODE_TOP_FIRST); + ILACEASSETMODELISTADD(ILACE_MODE_TOP_FIRST); + ILACEPROJECTMODELISTADD(ILACE_MODE_TOP_FIRST); - ILACEASSETMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST); - ILACEPROJECTMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST); + ILACEASSETMODELISTADD(ILACE_MODE_BOTTOM_FIRST); + ILACEPROJECTMODELISTADD(ILACE_MODE_BOTTOM_FIRST); - ILACEASSETMODELISTADD(BC_ILACE_MODE_NOTINTERLACED); - ILACEPROJECTMODELISTADD(BC_ILACE_MODE_NOTINTERLACED); + ILACEASSETMODELISTADD(ILACE_MODE_NOTINTERLACED); + ILACEPROJECTMODELISTADD(ILACE_MODE_NOTINTERLACED); // Interlacing Fixing Methods - ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_NONE); - ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_UPONE); - ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_DOWNONE); + ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_NONE); + ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_UPONE); + ILACEFIXMETHODLISTADD(ILACE_FIXMETHOD_DOWNONE); } void MWindow::init_indexes() @@ -1082,7 +1528,7 @@ void MWindow::init_gui() void MWindow::init_signals() { sighandler = new SigHandler; - sighandler->initialize(); + sighandler->initialize("/tmp/cinelerra_%d.dmp"); ENABLE_BUFFER } @@ -1118,25 +1564,30 @@ void MWindow::init_brender() session->brender_end = 0; brender_lock->unlock(); } - if(brender) brender->restart(edl); + brender_active = 0; + stop_brender(); } void MWindow::restart_brender() { //printf("MWindow::restart_brender 1\n"); - if(brender) brender->restart(edl); + if( !brender_active || !preferences->use_brender ) return; + if( !brender ) return; + brender->restart(edl); } void MWindow::stop_brender() { - if(brender) brender->stop(); + if( !brender ) return; +// cannot be holding mwindow->gui display lock + brender->stop(); } int MWindow::brender_available(int position) { int result = 0; brender_lock->lock("MWindow::brender_available 1"); - if(brender) + if(brender && brender_active) { if(brender->map_valid) { @@ -1155,47 +1606,77 @@ int MWindow::brender_available(int position) return result; } -void MWindow::set_brender_start() +void MWindow::set_brender_active(int v, int update) { - edl->session->brender_start = edl->local_session->get_selectionstart(1); - restart_brender(); - gui->draw_overlays(1); + if( !preferences->use_brender ) v = 0; + brender_active = v; + gui->mainmenu->brender_active->set_checked(v); + if( v != 0 ) { + edl->session->brender_start = edl->local_session->get_selectionstart(1); + edl->session->brender_end = edl->local_session->get_selectionend(1); + + if(EQUIV(edl->session->brender_end, edl->session->brender_start)) { + edl->session->brender_end = edl->tracks->total_video_length(); + } + restart_brender(); + } + else { + edl->session->brender_start = edl->session->brender_end = 0; + gui->unlock_window(); + stop_brender(); + gui->lock_window("MWindow::set_brender_active"); + } + if( update ) { + gui->update_timebar(0); + gui->draw_overlays(1); + } } - int MWindow::has_commercials() { +#ifdef HAVE_COMMERCIAL return theme->use_commercials; +#else + return 0; +#endif } void MWindow::init_commercials() { +#ifdef HAVE_COMMERCIAL if( !commercials ) { commercials = new Commercials(this); commercial_active = 0; } else commercials->add_user(); +#endif } void MWindow::commit_commercial() { +#ifdef HAVE_COMMERCIAL if( !commercial_active ) return; commercial_active = 0; if( !commercials ) return; commercials->commitDb(); +#endif } void MWindow::undo_commercial() { +#ifdef HAVE_COMMERCIAL if( !commercial_active ) return; commercial_active = 0; if( !commercials ) return; commercials->undoDb(); +#endif } int MWindow::put_commercial() { + int result = 0; +#ifdef HAVE_COMMERCIAL double start = edl->local_session->get_selectionstart(); double end = edl->local_session->get_selectionend(); if( start >= end ) return 0; @@ -1203,7 +1684,6 @@ int MWindow::put_commercial() const char *errmsg = 0; int count = 0; Tracks *tracks = edl->tracks; - int result = 0; //check it for(Track *track=tracks->first; track && !errmsg; track=track->next) { if( track->data_type != TRACK_VIDEO ) continue; @@ -1256,27 +1736,37 @@ int MWindow::put_commercial() undo_commercial(); result = 1; } +#endif return result; } void MWindow::stop_playback(int wait) { - int locked = gui->get_window_lock(); - if( locked ) gui->unlock_window(); + gui->stop_drawing(); - cwindow->playback_engine->que->send_command(STOP, - CHANGE_NONE, - 0, - 0); - cwindow->playback_engine->interrupt_playback(wait); + cwindow->stop_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); + vwindow->stop_playback(wait); } - if( locked ) gui->lock_window("MWindow::stop_playback"); + for(int i = 0; i < zwindows.size(); i++) { + ZWindow *zwindow = zwindows[i]; + if( zwindow->idx < 0 ) continue; + zwindow->stop_playback(wait); + } +} + +void MWindow::stop_transport() +{ + gui->stop_transport(gui->get_window_lock() ? "MWindow::stop_transport" : 0); +} + +void MWindow::beep(double freq, double secs, double gain) +{ + if( !proxy_beep ) proxy_beep = new ProxyBeep(this); + proxy_beep->tone(freq, secs, gain); } int MWindow::load_filenames(ArrayList *filenames, @@ -1294,7 +1784,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(); @@ -1304,8 +1796,8 @@ 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->size(); i++) - { + + for( int i=0; isize(); ++i ) { // Get type of file File *new_file = new File; Asset *new_asset = new Asset(filenames->get(i)); @@ -1324,224 +1816,210 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); if(debug) printf("MWindow::load_filenames %d\n", __LINE__); result = 1; - switch(ftype) - { + switch( ftype ) { // Convert media file to EDL - case FILE_OK: + case FILE_OK: // Warn about odd image dimensions - if(new_asset->video_data && - ((new_asset->width % 2) || - (new_asset->height % 2))) - { - char string[BCTEXTLEN]; - 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); - MainError::show_error(string); - } - - if(new_asset->program >= 0 && - 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."), - new_asset->path, new_asset->program, - edl->session->program_no, new_asset->program); - MainError::show_error(string); - } + if( new_asset->video_data && + ((new_asset->width % 2) || (new_asset->height % 2)) ) { + char string[BCTEXTLEN]; + 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); + MainError::show_error(string); + } + if( new_asset->program >= 0 && + 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."), + new_asset->path, new_asset->program, + edl->session->program_no, new_asset->program); + MainError::show_error(string); + } - 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; - } - else - { - new_assets.append(new_asset); - new_asset = 0; - } + if( load_mode != LOADMODE_RESOURCESONLY ) { + RecordLabels *labels = edl->session->label_cells ? + new RecordLabels(new_file) : 0; + asset_to_edl(new_edl, new_asset, labels); + new_edls.append(new_edl); + new_edl->add_user(); + delete labels; + } + else { + new_assets.append(new_asset); + new_asset->add_user(); + } // Set filename to nothing for assets since save EDL would overwrite them. - if(load_mode == LOADMODE_REPLACE || - load_mode == LOADMODE_REPLACE_CONCATENATE) - { - set_filename(""); + if( load_mode == LOADMODE_REPLACE || + load_mode == LOADMODE_REPLACE_CONCATENATE ) { + set_filename(""); // Reset timeline position - for(int i = 0; i < TOTAL_PANES; i++) - { - new_edl->local_session->view_start[i] = 0; - new_edl->local_session->track_start[i] = 0; - } + for( int i=0; ilocal_session->view_start[i] = 0; + new_edl->local_session->track_start[i] = 0; } + } - result = 0; - break; + result = 0; + break; // File not found - case FILE_NOT_FOUND: - sprintf(string, _("Failed to open %s"), new_asset->path); - gui->show_message(string, theme->message_error); - break; + case FILE_NOT_FOUND: + sprintf(string, _("Failed to open %s"), new_asset->path); + gui->show_message(string, theme->message_error); + gui->update_default_message(); + break; // Unknown format - case FILE_UNRECOGNIZED_CODEC: - { + case FILE_UNRECOGNIZED_CODEC: { // Test index file - IndexFile indexfile(this, new_asset); - result = indexfile.open_index(); - if(!result) - { - indexfile.close_index(); - } + { IndexFile indexfile(this, new_asset); + if( !(result = indexfile.open_index()) ) + indexfile.close_index(); } // Test existing EDLs - if(result) - { - for(int j = 0; j < new_edls.total + 1; j++) - { - Asset *old_asset; - if(j == new_edls.total) - { - old_asset = edl->assets->get_asset(new_asset->path); - if( old_asset ) - { - *new_asset = *old_asset; - result = 0; - } - } - else - { - old_asset = new_edls[j]->assets->get_asset(new_asset->path); - if( old_asset ) - { - *new_asset = *old_asset; - result = 0; - } - } - } + for( int j=0; result && jassets->get_asset(new_asset->path); + if( old_asset ) { + new_asset->copy_from(old_asset,1); + result = 0; + } + } + if( result ) { + Asset *old_asset = edl->assets->get_asset(new_asset->path); + if( old_asset ) { + new_asset->copy_from(old_asset,1); + result = 0; } + } // Prompt user - if(result) - { - char string[BCTEXTLEN]; - FileSystem fs; - fs.extract_name(string, new_asset->path); - - strcat(string, _("'s format couldn't be determined.")); - new_asset->audio_data = 1; - new_asset->format = FILE_PCM; - new_asset->channels = defaults->get("AUDIO_CHANNELS", 2); - new_asset->sample_rate = defaults->get("SAMPLE_RATE", 44100); - new_asset->bits = defaults->get("AUDIO_BITS", 16); - new_asset->byte_order = defaults->get("BYTE_ORDER", 1); - new_asset->signed_ = defaults->get("SIGNED_", 1); - new_asset->header = defaults->get("HEADER", 0); - - FileFormat fwindow(this); - fwindow.create_objects(new_asset, string); - result = fwindow.run_window(); - - - defaults->update("AUDIO_CHANNELS", new_asset->channels); - defaults->update("SAMPLE_RATE", new_asset->sample_rate); - defaults->update("AUDIO_BITS", new_asset->bits); - defaults->update("BYTE_ORDER", new_asset->byte_order); - defaults->update("SIGNED_", new_asset->signed_); - defaults->update("HEADER", new_asset->header); - save_defaults(); - } + if( result ) { + char string[BCTEXTLEN]; + FileSystem fs; + fs.extract_name(string, new_asset->path); + + strcat(string, _("'s format couldn't be determined.")); + new_asset->audio_data = 1; + new_asset->format = FILE_PCM; + new_asset->channels = defaults->get("AUDIO_CHANNELS", 2); + new_asset->sample_rate = defaults->get("SAMPLE_RATE", 44100); + new_asset->bits = defaults->get("AUDIO_BITS", 16); + new_asset->byte_order = defaults->get("BYTE_ORDER", 1); + new_asset->signed_ = defaults->get("SIGNED_", 1); + new_asset->header = defaults->get("HEADER", 0); + + FileFormat fwindow(this); + fwindow.create_objects(new_asset, string); + result = fwindow.run_window(); + + defaults->update("AUDIO_CHANNELS", new_asset->channels); + defaults->update("SAMPLE_RATE", new_asset->sample_rate); + defaults->update("AUDIO_BITS", new_asset->bits); + defaults->update("BYTE_ORDER", new_asset->byte_order); + defaults->update("SIGNED_", new_asset->signed_); + defaults->update("HEADER", new_asset->header); + save_defaults(); + } // Append to list - if(!result) - { + if( !result ) { // Recalculate length - delete new_file; - new_file = new File; - result = new_file->open_file(preferences, new_asset, 1, 0); + delete new_file; + new_file = new File; + result = new_file->open_file(preferences, new_asset, 1, 0); - if(load_mode != LOADMODE_RESOURCESONLY) - { - RecordLabels *labels = edl->session->label_cells ? - new RecordLabels(new_file) : 0; - asset_to_edl(new_edl, new_asset, labels); - new_edls.append(new_edl); - new_asset->Garbage::remove_user(); - delete labels; - new_asset = 0; - } - else - { - new_assets.append(new_asset); - new_asset = 0; - } + if( load_mode != LOADMODE_RESOURCESONLY ) { + RecordLabels *labels = edl->session->label_cells ? + new RecordLabels(new_file) : 0; + asset_to_edl(new_edl, new_asset, labels); + new_edls.append(new_edl); + new_edl->add_user(); + delete labels; } - else - { - result = 1; + else { + new_assets.append(new_asset); + new_asset->add_user(); } - break; } + else { + result = 1; + } + break; } - case FILE_IS_XML: - { - FileXML xml_file; + case FILE_IS_XML: { + FileXML xml_file; if(debug) printf("MWindow::load_filenames %d\n", __LINE__); - xml_file.read_from_file(filenames->get(i)); + xml_file.read_from_file(filenames->get(i)); if(debug) printf("MWindow::load_filenames %d\n", __LINE__); - - if(load_mode == LOADMODE_NESTED) - { + const char *cin_version = 0; + while( !xml_file.read_tag() ) { + if( xml_file.tag.title_is("EDL") ) { + cin_version = xml_file.tag.get_property("VERSION"); + break; + } + } + xml_file.rewind(); + if( !cin_version ) { + eprintf(_("XML file %s\n not from cinelerra."),filenames->get(i)); + char string[BCTEXTLEN]; + sprintf(string,_("Unknown %s"), filenames->get(i)); + gui->show_message(string); + result = 1; + break; + } + if( strcmp(cin_version, CINELERRA_VERSION) ) { + char string[BCTEXTLEN]; + snprintf(string, sizeof(string), + _("Warning: XML from cinelerra version %s\n" + "Session data may be incompatible."), cin_version); + show_warning(&preferences->warn_version, string); + } + if( load_mode == LOADMODE_NESTED ) { // Load temporary EDL for nesting. - EDL *nested_edl = new EDL; - nested_edl->create_objects(); - nested_edl->set_path(filenames->get(i)); - nested_edl->load_xml(&xml_file, LOAD_ALL); + EDL *nested_edl = new EDL; + nested_edl->create_objects(); + 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); - nested_edl->Garbage::remove_user(); - } - else - { + new_edl->create_nested(nested_edl); + new_edl->set_path(filenames->get(i)); + nested_edl->Garbage::remove_user(); + } + else { // Load EDL for pasting - new_edl->load_xml(&xml_file, LOAD_ALL); + new_edl->load_xml(&xml_file, LOAD_ALL); if(debug) printf("MWindow::load_filenames %d\n", __LINE__); - test_plugins(new_edl, filenames->get(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->get(i)); - strcpy(new_edl->local_session->clip_title, - filenames->get(i)); - if(update_filename) - set_filename(new_edl->local_session->clip_title); - } + if( load_mode == LOADMODE_REPLACE || + load_mode == LOADMODE_REPLACE_CONCATENATE ) { + strcpy(session->filename, filenames->get(i)); + strcpy(new_edl->local_session->clip_title, + filenames->get(i)); + if(update_filename) + set_filename(new_edl->local_session->clip_title); + } + else if( load_mode == LOADMODE_RESOURCESONLY ) { + 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); } - - new_edls.append(new_edl); - result = 0; - break; } + + new_edls.append(new_edl); + new_edl->add_user(); + result = 0; + break; } } -// edls are in new_edls - if( result && new_edl ) new_edl->Garbage::remove_user(); -// assets are copied - if( new_asset ) new_asset->Garbage::remove_user(); + new_edl->Garbage::remove_user(); + new_asset->Garbage::remove_user(); // Store for testing index new_files.append(new_file); @@ -1550,12 +2028,10 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); if(debug) printf("MWindow::load_filenames %d\n", __LINE__); - if(!result) gui->statusbar->default_message(); - - - - - + if(!result) { + gui->reset_default_message(); + gui->default_message(); + } if(debug) printf("MWindow::load_filenames %d\n", __LINE__); @@ -1578,10 +2054,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); edl->session->autos_follow_edits); } - paste_edls(&new_edls, - load_mode, - 0, - -1, + paste_edls(&new_edls, load_mode, 0, -1, edl->session->labels_follow_edits, edl->session->plugins_follow_edits, edl->session->autos_follow_edits, @@ -1595,46 +2068,33 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); // Add new assets to EDL and schedule assets for index building. int got_indexes = 0; - for(int i = 0; i < new_edls.size(); i++) - { + for( int i=0; inested_edls->size(); j++) - { - mainindexes->add_next_asset(0, - new_edl->nested_edls->get(j)); + for( int j=0; jnested_edls.size(); ++j ) { + mainindexes->add_next_asset(0, new_edl->nested_edls[j]); + edl->nested_edls.update_index(new_edl->nested_edls[j]); got_indexes = 1; - edl->nested_edls->update_index(new_edl->nested_edls->get(j)); } } if(debug) printf("MWindow::load_filenames %d\n", __LINE__); - if(new_assets.size()) - { - for(int i = 0; i < new_assets.size(); 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[j]; - if(!strcmp(new_file->asset->path, - new_asset->path)) - { - got_it = 1; - break; - } + for( int i=0; iasset->path, new_asset->path) ) { + got_it = 1; + break; } - - mainindexes->add_next_asset(got_it ? new_file : 0, new_asset); - got_indexes = 1; - edl->assets->update(new_asset); - } - + mainindexes->add_next_asset(got_it ? new_file : 0, new_asset); + edl->assets->update(new_asset); + got_indexes = 1; } if(debug) printf("MWindow::load_filenames %d\n", __LINE__); @@ -1662,10 +2122,6 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); show_plugin(plugin); } } - else - { - plugin->show = 0; - } plugin = (Plugin*)plugin->next; } @@ -1675,19 +2131,54 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); } // if just opening one new resource in replace mode - if( load_mode == LOADMODE_REPLACE && new_edls.size() == 1 && - ftype != FILE_IS_XML ) - { + if( ftype != FILE_IS_XML && + ( load_mode == LOADMODE_REPLACE || + load_mode == LOADMODE_REPLACE_CONCATENATE ) ) { select_asset(0, 0); + edl->session->proxy_scale = 1; + edl->session->proxy_disabled_scale = 1; + edl->session->proxy_use_scaler = 0; + edl->session->proxy_auto_scale = 0; + edl->session->proxy_beep = 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); + set_brender_active(0, 0); fit_selection(); goto_start(); } + if( ( edl->session->proxy_auto_scale && edl->session->proxy_scale != 1 ) && + ( load_mode != LOADMODE_REPLACE && load_mode != LOADMODE_REPLACE_CONCATENATE ) ) { + ArrayList orig_idxbls; + for( int i=0; itracks->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 + int ret = render_proxy(orig_idxbls); + gui->lock_window("MWindow::load_filenames"); + if( ret >= 0 && edl->session->proxy_beep ) { + if( ret > 0 ) + beep(2000., 1.5, 0.5); + else + beep(4000., 0.25, 0.5); + } + } + // 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__); @@ -1732,113 +2223,273 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); return 0; } +int MWindow::render_proxy(ArrayList &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; ipath) > 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(); + return !result ? proxy_render.needed_proxies.size() : -1; +} + +int MWindow::enable_proxy() +{ + int ret = 0; + if( edl->session->proxy_scale == 1 && + edl->session->proxy_disabled_scale != 1 ) { + int new_scale = edl->session->proxy_disabled_scale; + edl->session->proxy_disabled_scale = 1; + Asset *asset = new Asset; + asset->format = FILE_FFMPEG; + asset->load_defaults(defaults, "PROXY_", 1, 1, 0, 0, 0); + ret = to_proxy(asset, new_scale); + asset->remove_user(); + if( ret > 0 ) + beep(2000., 1.5, 0.5); + } + return 1; +} + +int MWindow::disable_proxy() +{ + if( edl->session->proxy_scale != 1 && + edl->session->proxy_disabled_scale == 1 ) { + edl->session->proxy_disabled_scale = edl->session->proxy_scale; + Asset *asset = new Asset; + asset->format = FILE_FFMPEG; + asset->load_defaults(defaults, "PROXY_", 1, 1, 0, 0, 0); + to_proxy(asset, 1); + asset->remove_user(); + } + return 1; +} + +int MWindow::to_proxy(Asset *asset, int new_scale) +{ + ArrayList orig_idxbls; + ArrayList proxy_assets; + + edl->Garbage::add_user(); + save_backup(); + undo->update_undo_before(_("proxy"), this); + ProxyRender proxy_render(this, asset); + +// revert project to original size from current size +// remove all session proxy assets at the at the current proxy_scale + int proxy_scale = edl->session->proxy_scale; + int proxy_use_scaler = edl->session->proxy_use_scaler; + + if( proxy_scale > 1 ) { + Asset *orig_asset = edl->assets->first; + for( ; orig_asset; orig_asset=orig_asset->next ) { + char new_path[BCTEXTLEN]; + proxy_render.to_proxy_path(new_path, orig_asset, proxy_scale); +// test if proxy asset was already added to proxy_assets + int got_it = 0; + for( int i = 0; !got_it && ipath, new_path); + if( got_it ) continue; + Asset *proxy_asset = edl->assets->get_asset(new_path); + if( !proxy_asset ) continue; +// add pointer to existing EDL asset if it exists +// EDL won't delete it unless it's the same pointer. + proxy_assets.append(proxy_asset); + proxy_asset->add_user(); + orig_idxbls.append(orig_asset); + orig_asset->add_user(); + } + for( int i=0,n=edl->nested_edls.size(); inested_edls[i]; + char new_path[BCTEXTLEN]; + if( !ProxyRender::from_proxy_path(new_path, orig_nested, proxy_scale) ) + continue; + proxy_render.to_proxy_path(new_path, orig_nested, proxy_scale); +// test if proxy asset was already added to proxy_assets + int got_it = 0; + for( int i = 0; !got_it && ipath, new_path); + if( got_it ) continue; + Asset *proxy_nested = edl->assets->get_asset(new_path); + if( !proxy_nested ) continue; +// add pointer to existing EDL asset if it exists +// EDL won't delete it unless it's the same pointer. + proxy_assets.append(proxy_nested); + proxy_nested->add_user(); + orig_idxbls.append(orig_nested); + orig_nested->add_user(); + } + +// convert from the proxy assets to the original assets + edl->set_proxy(1, 0, &proxy_assets, &orig_idxbls); + +// remove the references + for( int i=0; iwidth = proxy->actual_width; + proxy->height = proxy->actual_height; + proxy->remove_user(); + edl->assets->remove_pointer(proxy); + proxy->remove_user(); + } + proxy_assets.remove_all(); + for( int i = 0; i < orig_idxbls.size(); i++ ) + orig_idxbls[i]->remove_user(); + orig_idxbls.remove_all(); + } + + ArrayList confirm_paths; // test for new files + confirm_paths.set_array_delete(); + +// convert to new size if not original size + if( new_scale != 1 ) { + FileSystem fs; + Asset *orig = edl->assets->first; + for( ; orig; orig=orig->next ) { + Asset *proxy = proxy_render.add_original(orig, new_scale); + if( !proxy ) continue; + 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 ) { + if( exists ) // prompt user to overwrite + confirm_paths.append(cstrdup(proxy->path)); + proxy_render.add_needed(orig, proxy); + } + } + for( int i=0,n=edl->nested_edls.size(); inested_edls[i]; + Asset *proxy = proxy_render.add_original(orig_nested, new_scale); + if( !proxy ) continue; + int exists = fs.get_size(proxy->path) > 0 ? 1 : 0; + int got_it = exists && // if proxy exists, and is newer than orig_nested + fs.get_date(proxy->path) > fs.get_date(orig_nested->path) ? 1 : 0; + if( !got_it ) { + if( exists ) // prompt user to overwrite + confirm_paths.append(cstrdup(proxy->path)); + proxy_render.add_needed(orig_nested, proxy); + } + } + } + + int result = 0; +// test for existing files + if( confirm_paths.size() ) { + result = ConfirmSave::test_files(this, &confirm_paths); + confirm_paths.remove_all_objects(); + } + + if( !result ) + result = proxy_render.create_needed_proxies(new_scale); + + if( !result ) // resize project + edl->set_proxy(new_scale, proxy_use_scaler, + &proxy_render.orig_idxbls, &proxy_render.orig_proxies); + undo->update_undo_after(_("proxy"), LOAD_ALL); + edl->Garbage::remove_user(); + restart_brender(); + + gui->lock_window("MWindow::to_proxy"); + update_project(LOADMODE_REPLACE); + gui->unlock_window(); + return !result ? proxy_render.needed_proxies.size() : -1; +} void MWindow::test_plugins(EDL *new_edl, char *path) { char string[BCTEXTLEN]; -// Do a check weather plugins exist - for(Track *track = new_edl->tracks->first; track; track = track->next) - { - for(int k = 0; k < track->plugin_set.total; k++) - { +// Do a check whether plugins exist + for( Track *track=new_edl->tracks->first; track; track=track->next ) { + for( int k=0; kplugin_set.total; ++k ) { PluginSet *plugin_set = track->plugin_set[k]; - for(Plugin *plugin = (Plugin*)plugin_set->first; - plugin; - plugin = (Plugin*)plugin->next) - { - if(plugin->plugin_type == PLUGIN_STANDALONE) - { + for( Plugin *plugin = (Plugin*)plugin_set->first; + plugin; plugin = (Plugin*)plugin->next ) { + if( plugin->plugin_type != PLUGIN_STANDALONE ) continue; // ok we need to find it in plugindb - int plugin_found = 0; - - for(int j = 0; j < plugindb->size(); j++) - { - PluginServer *server = plugindb->get(j); - if(server->title && - !strcasecmp(server->title, plugin->title) && - ((track->data_type == TRACK_AUDIO && server->audio) || - (track->data_type == TRACK_VIDEO && server->video)) && - (!server->transition)) - plugin_found = 1; - } - - if (!plugin_found) - { - sprintf(string, + PluginServer *server = + scan_plugindb(plugin->title, track->data_type); + if( !server || server->transition ) { + sprintf(string, _("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); - } + "effect", _(plugin->title), path); + MainError::show_error(string); } } } - for(Edit *edit = (Edit*)track->edits->first; - edit; - edit = (Edit*)edit->next) - { - if (edit->transition) - { + for( Edit *edit=track->edits->first; edit; edit=edit->next ) { + if( !edit->transition ) continue; // ok we need to find transition in plugindb - - int transition_found = 0; - for(int j = 0; j < plugindb->size(); j++) - { - PluginServer *server = plugindb->get(j); - if(server->title && - !strcasecmp(server->title, edit->transition->title) && - ((track->data_type == TRACK_AUDIO && server->audio) || - (track->data_type == TRACK_VIDEO && server->video)) && - (server->transition)) - transition_found = 1; - } - - if (!transition_found) - { - sprintf(string, + PluginServer *server = + scan_plugindb(edit->transition->title, track->data_type); + if( !server || !server->transition ) { + sprintf(string, _("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); - } + "transition", _(edit->transition->title), path); + MainError::show_error(string); } } } } -void MWindow::init_shm() +void MWindow::init_shm(const char *pfn, int64_t min) { + int64_t result = 0; // Fix shared memory - FILE *fd = fopen("/proc/sys/kernel/shmmax", "w"); - if(fd) { - fprintf(fd, "0x7fffffff"); + FILE *fd = fopen(pfn, "r"); + if( fd ) { + fscanf(fd, "%jd", &result); fclose(fd); + if( result >= min ) return; } - fd = 0; - fd = fopen("/proc/sys/kernel/shmmax", "r"); - if(!fd) { - MainError::show_error("MWindow::init_shm: couldn't open /proc/sys/kernel/shmmax for reading.\n"); + fd = fopen(pfn, "w"); + if( !fd ) return; + fprintf(fd, "0x%jx", min); + fclose(fd); + + fd = fopen(pfn, "r"); + if( !fd ) { + eprintf(_("MWindow::init_shm: couldn't open %s for reading.\n"), pfn); return; } - int64_t result = 0; - fscanf(fd, _LD, &result); + fscanf(fd, "%jd", &result); fclose(fd); - fd = 0; - if(result < 0x7fffffff) { - eprintf(_("MWindow::init_shm: /proc/sys/kernel/shmmax is %p.\n" + if( result < min ) { + eprintf(_("MWindow::init_shm: %s is %p.\n" "you probably need to be root, or:\n" - "as root, run: echo 0x7fffffff > /proc/sys/kernel/shmmax\n" + "as root, run: echo 0x%jx > %s\n" "before trying to start cinelerra.\n" - "It should be at least 0x7fffffff for Cinelerra.\n"), (void *)result); + "It should be at least 0x%jx for Cinelerra.\n"), + pfn, (void *)result, min, pfn, min); } } @@ -1846,7 +2497,6 @@ void MWindow::create_objects(int want_gui, int want_new, char *config_path) { - FileSystem fs; const int debug = 0; if(debug) PRINT_TRACE @@ -1862,6 +2512,7 @@ void MWindow::create_objects(int want_gui, if(debug) PRINT_TRACE default_standard = default_std(); init_defaults(defaults, config_path); + check_language(); init_preferences(); if(splash_window) splash_window->operation->update(_("Initializing Plugins")); @@ -1869,6 +2520,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, cin_lang); if(splash_window) splash_window->operation->update(_("Initializing GUI")); if(debug) PRINT_TRACE @@ -1885,9 +2537,6 @@ void MWindow::create_objects(int want_gui, BC_Resources::init_fontconfig(string); if(debug) PRINT_TRACE -// Initialize before too much else is running -// Preferences & theme are required for building MPEG table of contents - // Default project created here init_edl(); if(debug) PRINT_TRACE @@ -1897,6 +2546,9 @@ void MWindow::create_objects(int want_gui, Timer timer; + init_awindow(); + if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); + init_compositor(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); @@ -1908,24 +2560,21 @@ void MWindow::create_objects(int want_gui, init_gui(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); - init_awindow(); - if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); - init_levelwindow(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); - if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); - init_indexes(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); init_channeldb(); - if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); + init_gwindow(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); + init_render(); if(debug) printf("MWindow::create_objects %d total_time=%d\n", __LINE__, (int)timer.get_difference()); + init_brender(); init_exportedl(); init_commercials(); @@ -2022,7 +2671,8 @@ void MWindow::create_objects(int want_gui, &MWindowGUI::keyboard_listener); hide_splash(); - init_shm(); + init_shm("/proc/sys/kernel/shmmax", 0x7fffffff); + init_shm("/proc/sys/kernel/shmmni", 0x4000); if(debug) PRINT_TRACE BC_WindowBase::get_resources()->vframe_shm = 1; @@ -2069,7 +2719,18 @@ ENABLE_BUFFER void MWindow::run() { + run_lock->lock("MWindow::run"); gui->run_window(); + stop_playback(1); + + brender_lock->lock("MWindow::run 1"); + delete brender; brender = 0; + brender_lock->unlock(); + + interrupt_indexes(); + clean_indexes(); + save_defaults(); + run_lock->unlock(); } void MWindow::show_vwindow() @@ -2136,6 +2797,14 @@ void MWindow::show_gwindow() gui->mainmenu->show_gwindow->set_checked(1); } +void MWindow::hide_gwindow() +{ + session->show_gwindow = 0; + + gwindow->gui->lock_window("MWindow::show_gwindow"); + gwindow->gui->hide_window(); + gwindow->gui->unlock_window(); +} void MWindow::show_lwindow() { @@ -2198,6 +2867,22 @@ void MWindow::set_auto_keyframes(int value, int lock_mwindow, int lock_cwindow) if(lock_cwindow) cwindow->gui->unlock_window(); } +void MWindow::set_auto_visibility(Autos *autos, int value) +{ + if( autos->type == Autos::AUTOMATION_TYPE_PLUGIN ) + edl->session->auto_conf->plugins = value; + else if( autos->autoidx >= 0 ) + edl->session->auto_conf->autos[autos->autoidx] = value; + else + return; + + gui->update(0, 1, 0, 0, 0, 0, 0); + gui->mainmenu->update_toggles(1); + gui->unlock_window(); + gwindow->gui->update_toggles(1); + gui->lock_window("MWindow::set_auto_visibility"); +} + void MWindow::set_keyframe_type(int mode) { gui->lock_window("MWindow::set_keyframe_type"); @@ -2277,10 +2962,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); } } @@ -2390,12 +3072,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); @@ -2407,8 +3088,8 @@ SET_TRACE // Needs mwindow to do GUI gui->set_mwindow(this); gui->open_plugin(0, preferences, edl, plugin); - gui->show_gui(); plugin->show = 1; + gui->show_gui(); } } plugin_gui_lock->unlock(); @@ -2439,7 +3120,7 @@ void MWindow::hide_plugin(Plugin *plugin, int lock) ptr->hide_gui(); delete_plugin(ptr); //sleep(1); -// return; + return; } } if(lock) plugin_gui_lock->unlock(); @@ -2735,38 +3416,6 @@ if(debug) printf("MWindow::asset_to_edl %d\n", __LINE__); return 0; } -int MWindow::edl_to_nested(EDL *new_edl, - EDL *nested_edl) -{ - -// Keep frame rate, sample rate, and output size unchanged. -// These parameters would revert the project if VWindow displayed an asset -// of different size than the project. - - - -// Nest all video & audio outputs - new_edl->session->video_tracks = 1; - new_edl->session->audio_tracks = nested_edl->session->audio_channels; - new_edl->create_default_tracks(); - - - - new_edl->insert_asset(0, - nested_edl, - 0, - 0, - 0); - - char string[BCTEXTLEN]; - FileSystem fs; - fs.extract_name(string, nested_edl->path); -//printf("MWindow::edl_to_nested %p %s\n", nested_edl, nested_edl->path); - - strcpy(new_edl->local_session->clip_title, string); - - return 0; -} // Reset everything after a load. void MWindow::update_project(int load_mode) @@ -2774,7 +3423,6 @@ void MWindow::update_project(int load_mode) const int debug = 0; if(debug) PRINT_TRACE - restart_brender(); edl->tracks->update_y_pixels(theme); if(debug) PRINT_TRACE @@ -2788,6 +3436,7 @@ void MWindow::update_project(int load_mode) gui->update(1, 1, 1, 1, 1, 1, 1); if(debug) PRINT_TRACE gui->unlock_window(); + init_brender(); cwindow->gui->lock_window("MWindow::update_project 1"); cwindow->update(0, 0, 1, 1, 1); @@ -2796,8 +3445,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; @@ -2814,14 +3463,29 @@ void MWindow::update_project(int load_mode) if( !vwindow->is_running() ) continue; vwindow->close_window(); } + for( int i=0; ivwindow_edls.size(); ++i ) { + VWindow *vwindow = get_viewer(1, -1); + vwindow->change_source(i); + } if(debug) PRINT_TRACE + select_zwindow(0); + close_mixers(0); + + for( int i=0; imixers.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(); + } } } @@ -2831,15 +3495,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 } @@ -2866,9 +3528,14 @@ void MWindow::rebuild_indices() index_state->index_status = INDEX_NOTTESTED; if( indexable->is_asset ) { Asset *asset = (Asset *)indexable; - if( asset->format != FILE_PCM ) + if( asset->format != FILE_PCM ) { + asset->format = FILE_UNKNOWN; asset->reset_audio(); + } asset->reset_video(); + remove_asset_from_caches(asset); +// File file; // re-probe the asset +// file.open_file(preferences, asset, 1, 0); } mainindexes->add_next_asset(0, indexable); } @@ -2879,21 +3546,23 @@ void MWindow::rebuild_indices() void MWindow::save_backup() { FileXML file; + edl->optimize(); edl->set_path(session->filename); - edl->save_xml(&file, - BACKUP_PATH, - 0, - 0); + 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); + rename(backup_path, backup_path1); + edl->save_xml(&file, backup_path); file.terminate_string(); - char path[BCTEXTLEN]; FileSystem fs; - strcpy(path, BACKUP_PATH); - fs.complete_path(path); + fs.complete_path(backup_path); - if(file.write_to_file(path)) + if(file.write_to_file(backup_path)) { char string2[256]; - sprintf(string2, _("Couldn't open %s for writing."), BACKUP_PATH); + sprintf(string2, _("Couldn't open %s for writing."), backup_path); gui->show_message(string2); } } @@ -2903,13 +3572,14 @@ void MWindow::load_backup() ArrayList path_list; path_list.set_array_delete(); char *out_path; - char string[BCTEXTLEN]; - strcpy(string, BACKUP_PATH); + char backup_path[BCTEXTLEN]; + snprintf(backup_path, sizeof(backup_path), "%s/%s", + File::get_config_path(), BACKUP_FILE); FileSystem fs; - fs.complete_path(string); + fs.complete_path(backup_path); - path_list.append(out_path = new char[strlen(string) + 1]); - strcpy(out_path, string); + path_list.append(out_path = new char[strlen(backup_path) + 1]); + strcpy(out_path, backup_path); load_filenames(&path_list, LOADMODE_REPLACE, 0); edl->local_session->clip_title[0] = 0; @@ -2920,6 +3590,29 @@ void MWindow::load_backup() save_backup(); } + +void MWindow::save_undo_data() +{ + char perpetual_path[BCTEXTLEN]; + snprintf(perpetual_path, sizeof(perpetual_path), "%s/%s", + File::get_config_path(), PERPETUAL_FILE); + FILE *fp = fopen(perpetual_path,"w"); + if( !fp ) return; + undo->save(fp); + fclose(fp); +} + +void MWindow::load_undo_data() +{ + 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); + fclose(fp); +} + static inline int gcd(int m, int n) { int r; @@ -2932,6 +3625,9 @@ int MWindow::create_aspect_ratio(float &w, float &h, int width, int height) { w = 1; h = 1; if(!width || !height) return 1; + if( width == 720 && (height == 480 || height == 576) ) { + w = 4; h = 3; return 0; // for NTSC and PAL + } double ar = (double)width / height; // square-ish pixels if( EQUIV(ar, 1.0000) ) return 0; @@ -2969,25 +3665,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); @@ -2999,9 +3695,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); } } @@ -3010,8 +3707,8 @@ void MWindow::remove_asset_from_caches(Asset *asset) void MWindow::remove_assets_from_project(int push_undo, int redraw, ArrayList *drag_assets, ArrayList *drag_clips) { - for(int i = 0; i < session->drag_assets->total; i++) { - Indexable *indexable = session->drag_assets->get(i); + 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); } @@ -3028,11 +3725,11 @@ void MWindow::remove_assets_from_project(int push_undo, int redraw, } } - for(int i = 0; i < session->drag_assets->size(); i++) { + 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(session->drag_assets->get(i) == vwindow->get_source()) { + 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(); @@ -3040,29 +3737,22 @@ void MWindow::remove_assets_from_project(int push_undo, int redraw, } } - for(int i = 0; i < session->drag_assets->size(); i++) { - Indexable *indexable = session->drag_assets->get(i); + 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); if(push_undo) undo->update_undo_before(); if(drag_assets) edl->remove_from_project(drag_assets); - if(drag_clips) edl->remove_from_project(session->drag_clips); + if(drag_clips) edl->remove_from_project(drag_clips); if(redraw) save_backup(); if(push_undo) undo->update_undo_after(_("remove assets"), LOAD_ALL); - if(redraw) - { + if(redraw) { restart_brender(); gui->lock_window("MWindow::remove_assets_from_project 3"); - gui->update(1, - 1, - 1, - 1, - 0, - 1, - 0); + gui->update(1, 1, 1, 1, 0, 1, 0); gui->unlock_window(); // Removes from playback here @@ -3119,39 +3809,64 @@ void MWindow::dump_undo(FILE *fp) void MWindow::dump_exe(FILE *fp) { - char proc_path[BCTEXTLEN], exe_path[BCTEXTLEN]; - sprintf(proc_path, "/proc/%d/exe", (int)getpid()); - int len = readlink(proc_path, exe_path, sizeof(exe_path)); - if( len < 0 ) { fprintf(fp,"readlink: %m\n"); return; } - exe_path[len] = 0; + char proc_path[BCTEXTLEN], exe_path[BCTEXTLEN]; + sprintf(proc_path, "/proc/%d/exe", (int)getpid()); + + int ret = -1, n = 100; + for( int len; (len=readlink(proc_path, exe_path, sizeof(exe_path)))>0; --n ) { + exe_path[len] = 0; strcpy(proc_path, exe_path); + ret = 0; + } + if( n < 0 || ret < 0 ) { fprintf(fp,"readlink: %m\n"); return; } + struct stat st; - if( stat(exe_path,&st) ) { fprintf(fp,"stat: %m\n"); return; } - fprintf(fp, "path: %s = %9jd bytes\n",exe_path,st.st_size); - int fd = open(exe_path,O_RDONLY); + if( stat(proc_path,&st) ) { fprintf(fp,"stat: %m\n"); return; } + fprintf(fp, "path: %s = %9jd bytes\n",proc_path,st.st_size); + struct tm *tm = localtime(&st.st_mtime); + 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 buf[65536]; SHA1 sha1; - while( (len=read(fd,buf,sizeof(buf))) > 0 ) { - sha1.addBytes(buf, len); + uint8_t *bfr = 0; + int64_t bfrsz = 0; + int64_t pagsz = sysconf(_SC_PAGE_SIZE); + int64_t maxsz = 1024*pagsz; + int64_t size = st.st_size, pos = 0; + SHA1 sha1; + while( (bfrsz = size-pos) > 0 ) { + if( bfrsz > maxsz ) bfrsz = maxsz; + bfr = (uint8_t *)mmap(NULL, bfrsz, PROT_READ, + MAP_PRIVATE+MAP_NORESERVE+MAP_POPULATE, fd, pos); + if( bfr == MAP_FAILED ) break; + sha1.addBytes(bfr, bfrsz); + munmap(bfr, bfrsz); + pos += bfrsz; } close(fd); + ret = pos < size ? EIO : 0; fprintf(fp, "SHA1: "); uint8_t digest[20]; sha1.computeHash(digest); 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"); } - void MWindow::trap_hook(FILE *fp, void *vp) { MWindow *mwindow = (MWindow *)vp; - fprintf(fp, "\nEXE:\n"); - mwindow->dump_exe(fp); - fprintf(fp, "\nPLUGINS:\n"); - mwindow->dump_plugins(fp); +// fprintf(fp, "\nPLUGINS:\n"); +// mwindow->dump_plugins(fp); fprintf(fp, "\nEDL:\n"); mwindow->dump_edl(fp); fprintf(fp, "\nUNDO:\n"); mwindow->dump_undo(fp); + fprintf(fp, "\nEXE: %s\n", AboutPrefs::build_timestamp); + mwindow->dump_exe(fp); } @@ -3213,6 +3928,7 @@ int MWindow::run_script(FileXML *script) int MWindow::interrupt_indexes() { + mainprogress->cancelled = 1; mainindexes->interrupt_build(); return 0; } @@ -3410,10 +4126,13 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra EDLSession *session = edl->session; double old_framerate = session->frame_rate; double old_samplerate = session->sample_rate; + int old_auto_keyframes = session->auto_keyframes; + session->auto_keyframes = 0; int result = file->open_file(preferences, asset, 1, 0); if( !result && delete_tracks > 0 ) undo->update_undo_before(); - if( !result && 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. @@ -3452,7 +4171,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra next_edit = edit->next; if( edit->channel != vstream || !edit->asset || !edit->asset->is_asset || - *asset != *edit->asset ) + !asset->equivalent(*edit->asset,1,1,edl) ) delete edit; } } @@ -3463,32 +4182,24 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra else if( delete_tracks ) edl->tracks->delete_track(track); } + edl->retrack(); edl->resample(old_framerate, session->frame_rate, TRACK_VIDEO); } - if( !result && asset->channels > 0 ) { + if( !result && asset->audio_data && asset->channels > 0 ) { session->sample_rate = asset->get_sample_rate(); int64_t channel_mask = 0; - int astrm = file->get_audio_for_video(vstream, astream, channel_mask); + 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<channels)-1; int channels = 0; for( uint64_t mask=channel_mask; mask!=0; mask>>=1 ) channels += mask & 1; + if( channels < 1 ) channels = 1; if( channels > 6 ) channels = 6; session->audio_tracks = session->audio_channels = channels; - switch( channels ) { - case 6: - session->achannel_positions[0] = 90; - session->achannel_positions[1] = 150; - session->achannel_positions[2] = 30; - session->achannel_positions[3] = 210; - session->achannel_positions[4] = 330; - session->achannel_positions[5] = 270; - break; - case 2: - session->achannel_positions[0] = 180; - session->achannel_positions[1] = 0; - break; - } + + int *achannel_positions = preferences->channel_positions[session->audio_channels-1]; + memcpy(&session->achannel_positions, achannel_positions, sizeof(session->achannel_positions)); remap_audio(MWindow::AUDIO_1_TO_1); if( delete_tracks ) { @@ -3501,7 +4212,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra next_edit = edit->next; if( !((1<channel) & channel_mask) || !edit->asset || !edit->asset->is_asset || - *asset != *edit->asset ) + !asset->equivalent(*edit->asset,1,1,edl) ) delete edit; } if( !track->edits->first ) @@ -3512,6 +4223,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra edl->resample(old_samplerate, session->sample_rate, TRACK_AUDIO); } delete file; + session->auto_keyframes = old_auto_keyframes; if( !result && delete_tracks > 0 ) { save_backup(); undo->update_undo_after(_("select asset"), LOAD_ALL); @@ -3523,12 +4235,14 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra int MWindow::select_asset(int vtrack, int delete_tracks) { Track *track = edl->tracks->get(vtrack, TRACK_VIDEO); + if( !track ) + track = edl->tracks->get(vtrack, TRACK_AUDIO); if( !track ) return 1; Edit *edit = track->edits->first; if( !edit ) return 1; Asset *asset = edit->asset; if( !asset || !asset->is_asset ) return 1; - return select_asset(asset, edit->channel, -1, delete_tracks); + return select_asset(asset, edit->channel, 0, delete_tracks); } void MWindow::dump_plugindb(FILE *fp) @@ -3538,3 +4252,49 @@ void MWindow::dump_plugindb(FILE *fp) plugindb->get(i)->dump(fp); } +FloatAuto* MWindow::get_float_auto(PatchGUI *patch,int idx) +{ + Auto *current = 0; + double unit_position = edl->local_session->get_selectionstart(1); + unit_position = patch->track->to_units(unit_position, 0); + + FloatAutos *ptr = (FloatAutos*)patch->track->automation->autos[idx]; + return (FloatAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current); +} + +IntAuto* MWindow::get_int_auto(PatchGUI *patch,int idx) +{ + Auto *current = 0; + double unit_position = edl->local_session->get_selectionstart(1); + unit_position = patch->track->to_units(unit_position, 0); + + IntAutos *ptr = (IntAutos*)patch->track->automation->autos[idx]; + return (IntAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current); +} + +PanAuto* MWindow::get_pan_auto(PatchGUI *patch) +{ + Auto *current = 0; + double unit_position = edl->local_session->get_selectionstart(1); + unit_position = patch->track->to_units(unit_position, 0); + + PanAutos *ptr = (PanAutos*)patch->track->automation->autos[AUTOMATION_PAN]; + 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; ipatchbay; + if( !patchbay ) continue; + for( int j=0; jpatches.total && !patchgui; ++j ) { + if( patchbay->patches.values[j]->track == track ) + patchgui = patchbay->patches.values[j]; + } + } + return patchgui; +} +