*
*/
+#include "aboutprefs.h"
#include "asset.h"
#include "assets.h"
#include "atrack.h"
#include "awindow.h"
#include "batchrender.h"
#include "bcdisplayinfo.h"
+#include "bcprogressbox.h"
#include "bcsignals.h"
#include "bctimer.h"
#include "bctrace.h"
#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"
#include "mutex.h"
#include "mwindowgui.h"
#include "mwindow.h"
-#include "nestededls.h"
#include "new.h"
#include "panautos.h"
#include "patchbay.h"
#include "pluginserver.h"
#include "pluginset.h"
#include "preferences.h"
+#include "proxy.h"
#include "record.h"
#include "recordmonitor.h"
#include "recordlabel.h"
#include "removefile.h"
#include "render.h"
#include "resourcethread.h"
+#include "savefile.inc"
#include "samplescroll.h"
#include "sha1.h"
#include "sighandler.h"
#include "theme.h"
#include "threadloader.h"
#include "timebar.h"
+#include "timelinepane.h"
#include "tipwindow.h"
#include "trackcanvas.h"
#include "track.h"
#include "wavecache.h"
#include "wwindow.h"
#include "zoombar.h"
+#include "zwindow.h"
+#include "zwindowgui.h"
#include "exportedl.h"
#include "defaultformats.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
+#include <sys/file.h>
#include <limits.h>
#include <errno.h>
}
+extern long cin_timezone;
ArrayList<PluginServer*>* MWindow::plugindb = 0;
Commercials* MWindow::commercials = 0;
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");
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;
restart_status = 0;
screens = 1;
in_destructor = 0;
+ speed_edl = 0;
+ proxy_beep = 0;
}
run_lock->lock("MWindow::~MWindow");
in_destructor = 1;
//printf("MWindow::~MWindow %d\n", __LINE__);
- gui->stop_drawing();
gui->remote_control->deactivate();
gui->record->stop();
#ifdef HAVE_DVB
gui->channel_info->stop();
#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++) {
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();
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();
delete gwindow; gwindow = 0;
delete cwindow; cwindow = 0;
delete gui; gui = 0;
- //delete file_server; file_server = 0; // reusable
delete mainindexes; mainindexes = 0;
delete mainprogress; mainprogress = 0;
delete audio_cache; audio_cache = 0; // delete the cache after the assets
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;
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();
}
}
-//__timezone: Seconds west of UTC. 240sec/deg
- double tz_deg = -__timezone / 240.;
+// 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";
}
else
create_defaults_path(path, CONFIG_FILE);
+ delete defaults;
defaults = new BC_Hash(path);
defaults->load();
}
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",
+ snprintf(curr_lang, sizeof(curr_lang), "%s_%s-%s",
BC_Resources::language, BC_Resources::region, BC_Resources::encoding);
env_lang = curr_lang;
}
::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)
delete [] base_path;
}
-int MWindow::load_plugin_index(MWindow *mwindow, const char *index_path, const char *plugin_dir)
+int MWindow::load_plugin_index(MWindow *mwindow, FILE *fp, const char *plugin_dir)
{
-// load index
- FILE *fp = fopen(index_path, "r");
if( !fp ) return -1;
-
+// load index
+ fseek(fp, 0, SEEK_SET);
int ret = 0;
char index_line[BCTEXTLEN];
int index_version = -1, len = strlen(plugin_dir);
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);
ret = 1; continue;
}
}
- fclose(fp);
if( !ret )
ret = check_plugin_index(plugins, plugin_dir, ".");
create_defaults_path(index_path, PLUGIN_FILE);
char *plugin_dir = FileSystem::basepath(preferences->plugin_dir);
strcpy(plugin_path, plugin_dir); delete [] plugin_dir;
- if( !load_plugin_index(mwindow, index_path, plugin_path) ) return 1;
- printf("init plugin index: %s\n", plugin_path);
- FILE *fp = fopen(index_path,"w");
+ FILE *fp = fopen(index_path,"a+");
if( !fp ) {
fprintf(stderr,_("MWindow::init_plugins: "
- "can't create plugin index: %s\n"), index_path);
- return 1;
+ "can't open plugin index: %s\n"), index_path);
+ return -1;
+ }
+ int fd = fileno(fp), ret = -1;
+ if( !flock(fd, LOCK_EX) ) {
+ fseek(fp, 0, SEEK_SET);
+ ret = load_plugin_index(mwindow, fp, plugin_path);
+ }
+ if( ret > 0 ) {
+ ftruncate(fd, 0);
+ fseek(fp, 0, SEEK_SET);
+ printf("init plugin index: %s\n", plugin_path);
+ fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
+ 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);
+ fseek(fp, 0, SEEK_SET);
+ ret = load_plugin_index(mwindow, fp, plugin_path);
+ }
+ if( ret ) {
+ fprintf(stderr,_("MWindow::init_plugins: "
+ "can't %s plugin index: %s\n"),
+ ret>0 ? _("create") : _("lock"), index_path);
}
- fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
- fprintf(fp, "%s\n", plugin_path);
- init_plugin_index(mwindow, preferences, fp, plugin_path);
- init_ffmpeg_index(mwindow, preferences, fp);
fclose(fp);
- return load_plugin_index(mwindow, index_path, plugin_path);
+ return ret;
}
int MWindow::init_ladspa_plugins(MWindow *mwindow, Preferences *preferences)
for( char *bp=plugin_path; *bp!=0; ++bp )
*cp++ = *bp=='/' ? '_' : *bp;
*cp = 0;
- if( !load_plugin_index(mwindow, index_path, plugin_path) ) continue;
- if( init_ladspa_index(mwindow, preferences, index_path, plugin_path) ) continue;
- load_plugin_index(mwindow, index_path, plugin_path);
+ FILE *fp = fopen(index_path,"a+");
+ if( !fp ) {
+ fprintf(stderr,_("MWindow::init_ladspa_plugins: "
+ "can't open ladspa plugin index: %s\n"), index_path);
+ continue;
+ }
+ int fd = fileno(fp), ret = -1;
+ if( !flock(fd, LOCK_EX) ) {
+ fseek(fp, 0, SEEK_SET);
+ ret = load_plugin_index(mwindow, fp, plugin_path);
+ }
+ if( ret > 0 ) {
+ ftruncate(fd, 0);
+ fseek(fp, 0, SEEK_SET);
+ init_ladspa_index(mwindow, preferences, fp, plugin_path);
+ fseek(fp, 0, SEEK_SET);
+ ret = load_plugin_index(mwindow, fp, plugin_path);
+ }
+ if( ret ) {
+ fprintf(stderr,_("MWindow::init_ladspa_plugins: "
+ "can't %s ladspa plugin index: %s\n"),
+ ret>0 ? _("create") : _("lock"), index_path);
+ }
+ fclose(fp);
}
return 1;
}
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)
{
plugins.remove_all();
}
+void MWindow::init_plugin_tips(ArrayList<PluginServer*> &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( ; tp<ep && (*tp=*cp)!=0; ++tp,++cp );
+ }
+ fclose(fp);
+}
+
void MWindow::delete_plugins()
{
plugindb->remove_all_objects();
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<PluginServer*> &plugins)
{
for( int i=0; i<plugins.size(); ++i )
return !plugindb ? 0 : plugin_exists(plugin_path, *plugindb);
}
+void MWindow::remove_plugin_index()
+{
+ char index_path[BCTEXTLEN];
+ MWindow::create_defaults_path(index_path, PLUGIN_FILE);
+ ::remove(index_path);
+}
+
void MWindow::init_preferences()
{
preferences = new Preferences;
preferences->load_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
}
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()
void MWindow::init_tipwindow()
{
+ TipWindow::load_tips(cin_lang);
if( !twindow )
twindow = new TipWindow(this);
twindow->start();
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);
}
}
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());
}
return vwindow;
}
+ZWindow *MWindow::get_mixer(Mixer *&mixer)
+{
+ zwindows_lock->lock("MWindow::get_mixer");
+ if( !mixer ) mixer = edl->mixers.new_mixer();
+ ZWindow *zwindow = 0;
+ for( int i=0; !zwindow && i<zwindows.size(); ++i )
+ if( zwindows[i]->idx < 0 ) zwindow = zwindows[i];
+ if( !zwindow )
+ zwindows.append(zwindow = new ZWindow(this));
+ zwindow->idx = mixer->idx;
+ zwindows_lock->unlock();
+ return zwindow;
+}
+
+void MWindow::del_mixer(ZWindow *zwindow)
+{
+ zwindows_lock->lock("MWindow::del_mixer 0");
+ edl->mixers.del_mixer(zwindow->idx);
+ 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; vidx<zwindows.size(); ++vidx ) {
+ ZWindow *zwindow = zwindows[vidx];
+ if( zwindow->idx < 0 ) continue;
+ Mixer *mixer = edl->mixers.get_mixer(zwindow->idx);
+ if( !mixer || !mixer->mixer_ids.size() ) continue;
+ int k = -1;
+ for( Track *track = edl->tracks->first; k<0 && track!=0; track=track->next ) {
+ if( track->data_type != TRACK_VIDEO ) continue;
+ int mixer_id = track->get_mixer_id();
+ k = mixer->mixer_ids.size();
+ while( --k >= 0 && mixer_id != mixer->mixer_ids[k] );
+ }
+ if( k < 0 ) continue;
+ EDL *mixer_edl = new EDL(this->edl);
+ mixer_edl->create_objects();
+ mixer_edl->copy_all(edl);
+ mixer_edl->remove_vwindow_edls();
+ for( Track *track = mixer_edl->tracks->first; track!=0; track=track->next ) {
+ k = mixer->mixer_ids.size();
+ while( --k >= 0 && track->get_mixer_id() != mixer->mixer_ids[k] );
+ if( k >= 0 ) {
+ track->record = 1;
+ track->play = track->data_type == TRACK_VIDEO ? 1 : 0;
+ }
+ else
+ track->record = track->play = 0;
+ }
+ zwindow->change_source(mixer_edl);
+ zwindow->issue_command(command,
+ wait_tracking, use_inout, update_refresh, toggle_audio, 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; vidx<zwindows.size(); ++vidx ) {
+ ZWindow *zwindow = zwindows[vidx];
+ if( zwindow->idx < 0 ) continue;
+ zwindow->issue_command(STOP, 0, 0, 0, 0, 0);
+ }
+}
+
+void MWindow::close_mixers(int destroy)
+{
+ ArrayList<ZWindow*> closed;
+ 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();
+ closed.append(zwindow);
+ }
+ zwindows_lock->unlock();
+ for( int i=0; i<closed.size(); ++i ) {
+ ZWindow *zwindow = closed[i];
+ zwindow->join();
+ }
+}
+
+ZWindow *MWindow::create_mixer(Indexable *indexable)
+{
+ ArrayList<Indexable*> 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);
+ ArrayList<ZWindow *>new_mixers;
+
+ for( int i=0; i<session->drag_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; i<session->drag_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; i<new_mixers.size(); ++i )
+ new_mixers[i]->start();
+
+ 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; i<edl->mixers.size(); ++i ) {
+ Mixer *mixer = edl->mixers[i];
+ ZWindow *zwindow = get_mixer(mixer);
+ zwindow->set_title(mixer->title);
+ zwindow->start();
+ }
+ refresh_mixers();
+}
+
+int MWindow::select_zwindow(ZWindow *zwindow)
+{
+ int ret = 0, n = zwindows.number_of(zwindow);
+ if( session->selected_zwindow != n ) {
+ session->selected_zwindow = n;
+ for( int i=0; i<zwindows.size(); ++i ) {
+ ZWindow *zwindow = zwindows[i];
+ if( zwindow->idx < 0 ) continue;
+ ZWindowGUI *zgui = zwindow->zgui;
+ zgui->lock_window("MWindow::select_zwindow 0");
+ zwindow->highlighted = i == n ? 1 : 0;
+ if( zgui->draw_overlays() )
+ zgui->canvas->get_canvas()->flash(1);
+ zgui->unlock_window();
+ }
+ ret = 1;
+ gui->lock_window("MWindow::select_window 1");
+ gui->update_mixers(0, -1);
+ gui->unlock_window();
+ }
+ return ret;
+}
+
+void MWindow::tile_mixers()
+{
+ int nz = 0;
+ for( int i=0; i<zwindows.size(); ++i ) {
+ ZWindow *zwindow = zwindows[i];
+ if( zwindow->idx < 0 ) continue;
+ ++nz;
+ }
+ if( !nz ) return;
+ int zn = ceil(sqrt(nz));
+ int x1 = 1 + gui->get_x(), x2 = cwindow->gui->get_x();
+ int y1 = 1, y2 = gui->get_y();
+ int rw = gui->get_root_w(0), rh = gui->get_root_h(0);
+ if( x1 < 0 ) x1 = 0;
+ if( y1 < 0 ) y1 = 0;
+ if( x2 > rw ) x2 = rw;
+ if( y2 > rh ) y2 = rh;
+ int dx = x2 - x1, dy = y2 - y1;
+ int zw = dx / zn;
+ int lt = BC_DisplayInfo::get_left_border();
+ int top = BC_DisplayInfo::get_top_border();
+ int bw = lt + BC_DisplayInfo::get_right_border(); // borders
+ int bh = top + BC_DisplayInfo::get_bottom_border();
+ int zx = 0, zy = 0; // window origins
+ int mw = 10+10, mh = 10+10; // canvas margins
+ int rsz = 0, n = 0, dz = 0;
+ int ow = edl->session->output_w, oh = edl->session->output_h;
+ for( int i=0; i<zwindows.size(); ++i ) {
+ ZWindow *zwindow = zwindows[i];
+ if( zwindow->idx < 0 ) continue;
+ int ww = zw - bw, hh = (ww - mw) * oh / ow + mh, zh = hh + bh;
+ if( rsz < hh ) rsz = hh;
+ int xx = zx + x1, yy = zy + y1;
+ int mx = x2 - zw, my = y2 - zh;
+ if( xx > mx ) xx = mx;
+ if( yy > my ) yy = my;
+ xx += lt + dz; yy += top + dz;
+ zwindow->reposition(xx,yy, ww,hh);
+ if( zwindow->running() ) {
+ ZWindowGUI *gui = (ZWindowGUI *)zwindow->get_gui();
+ gui->lock_window("MWindow::tile_mixers");
+ gui->BC_WindowBase::reposition_window(xx,yy, ww,hh);
+ gui->unlock_window();
+ }
+ if( ++n >= zn ) {
+ n = 0; rsz += bh;
+ if( (zy += rsz) > (dy - rsz) ) dz += 10;
+ rsz = 0;
+ zx = 0;
+ }
+ else
+ zx += zw;
+ }
+}
+
void MWindow::init_cache()
{
audio_cache = new CICache(preferences);
void MWindow::init_gui()
{
gui = new MWindowGUI(this);
- gui->lock_window("MWindow::init_gui");
gui->create_objects();
- gui->unlock_window();
gui->load_defaults(defaults);
}
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)
{
return result;
}
-void MWindow::set_brender_range()
+void MWindow::set_brender_active(int v, int update)
{
- edl->session->brender_start = edl->local_session->get_selectionstart(1);
- edl->session->brender_end = edl->local_session->get_selectionend(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();
+ 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);
}
-
- restart_brender();
- 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;
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;
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<char*> *filenames,
// 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();
// 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; i<filenames->size(); ++i ) {
// Get type of file
File *new_file = new File;
Asset *new_asset = new Asset(filenames->get(i));
char string[BCTEXTLEN];
new_edl->create_objects();
- new_edl->copy_session(edl);
+ new_edl->copy_session(edl, -1);
new_file->set_program(edl->session->program_no);
sprintf(string, _("Loading %s"), new_asset->path);
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; i<TOTAL_PANES; ++i ) {
+ new_edl->local_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
- for(int j = 0; result && j <= new_edls.total; j++) {
- Asset *old_asset = j < new_edls.total ?
- new_edls[j]->assets->get_asset(new_asset->path) :
- edl->assets->get_asset(new_asset->path);
- if( old_asset ) {
- *new_asset = *old_asset;
- result = 0;
- }
+ for( int j=0; result && j<new_edls.total; ++j ) {
+ Asset *old_asset = new_edls[j]->assets->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__);
- 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;
+ 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;
}
- 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)
- {
+ }
+ 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);
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__);
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,
// 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; i<new_edls.size(); ++i ) {
EDL *new_edl = new_edls[i];
- for(int j = 0; j < new_edl->nested_edls->size(); j++)
- {
- mainindexes->add_next_asset(0,
- new_edl->nested_edls->get(j));
+ for( int j=0; j<new_edl->nested_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; 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;
}
-
- 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__);
show_plugin(plugin);
}
}
- else
- {
- plugin->show = 0;
- }
plugin = (Plugin*)plugin->next;
}
( 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 = -1;
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<Indexable *> orig_idxbls;
+ for( int i=0; i<new_assets.size(); ++i )
+ orig_idxbls.append(new_assets.get(i));
+ for( int i=0; i<new_edls.size(); ++i ) {
+ EDL *new_edl = new_edls[i];
+ for( Track *track=new_edl->tracks->first; track; track=track->next ) {
+ if( track->data_type != TRACK_VIDEO ) continue;
+ for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+ Indexable *idxbl = (Indexable *)edit->asset;
+ if( !idxbl ) continue;
+ if( !idxbl->have_video() ) continue;
+ if( edit->channel != 0 ) continue; // first layer only
+ orig_idxbls.append(edit->asset);
+ }
+ }
+ }
+ gui->unlock_window(); // to update progress bar
+ 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__);
return 0;
}
+int MWindow::render_proxy(ArrayList<Indexable *> &new_idxbls)
+{
+ Asset *format_asset = new Asset;
+ format_asset->format = FILE_FFMPEG;
+ format_asset->load_defaults(defaults, "PROXY_", 1, 1, 0, 0, 0);
+ ProxyRender proxy_render(this, format_asset);
+ int new_scale = edl->session->proxy_scale;
+ int use_scaler = edl->session->proxy_use_scaler;
+
+ for( int i=0; i<new_idxbls.size(); ++i ) {
+ Indexable *orig = new_idxbls.get(i);
+ Asset *proxy = proxy_render.add_original(orig, new_scale);
+ if( !proxy ) continue;
+ FileSystem fs;
+ int exists = fs.get_size(proxy->path) > 0 ? 1 : 0;
+ int got_it = exists && // if proxy exists, and is newer than orig
+ fs.get_date(proxy->path) > fs.get_date(orig->path) ? 1 : 0;
+ if( got_it ) continue;
+ proxy_render.add_needed(orig, proxy);
+ }
+
+// render needed proxies
+ int result = proxy_render.create_needed_proxies(new_scale);
+ if( !result ) {
+ add_proxy(use_scaler,
+ &proxy_render.orig_idxbls, &proxy_render.orig_proxies);
+ }
+ format_asset->remove_user();
+ 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;
+ int new_use_scaler = edl->session->proxy_use_scaler;
+ 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, new_use_scaler);
+ 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 ) {
+ int new_scale = 1;
+ int new_use_scaler = edl->session->proxy_use_scaler;
+ 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, new_scale, new_use_scaler);
+ asset->remove_user();
+ }
+ return 1;
+}
+
+int MWindow::to_proxy(Asset *asset, int new_scale, int new_use_scaler)
+{
+ ArrayList<Indexable*> orig_idxbls;
+ ArrayList<Indexable*> 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;
+
+ 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 && i<proxy_assets.size(); ++i )
+ got_it = !strcmp(proxy_assets[i]->path, 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(); i<n; ++i ) {
+ EDL *orig_nested = edl->nested_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 && i<proxy_assets.size(); ++i )
+ got_it = !strcmp(proxy_assets[i]->path, 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; i<proxy_assets.size(); ++i ) {
+ Asset *proxy = (Asset *) proxy_assets[i];
+ proxy->width = 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<char *> 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(); i<n; ++i ) {
+ EDL *orig_nested = edl->nested_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, new_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; k<track->plugin_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, "%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);
}
}
int want_new,
char *config_path)
{
- FileSystem fs;
const int debug = 0;
if(debug) PRINT_TRACE
check_language();
init_preferences();
if(splash_window)
- splash_window->operation->update(_("Initializing Plugins"));
+ splash_window->update_status(_("Initializing Plugins"));
init_plugins(this, preferences);
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"));
+ splash_window->update_status(_("Initializing GUI"));
if(debug) PRINT_TRACE
init_theme();
init_error();
if(splash_window)
- splash_window->operation->update(_("Initializing Fonts"));
+ splash_window->update_status(_("Initializing Fonts"));
char string[BCTEXTLEN];
strcpy(string, preferences->plugin_dir);
strcat(string, "/" FONT_SEARCHPATH);
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
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());
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();
&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;
}
else
{
- cwindow->playback_engine->que->send_command(CURRENT_FRAME,
- change_type,
- edl,
- 1);
+ cwindow->refresh_frame(change_type);
}
}
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);
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)
const int debug = 0;
if(debug) PRINT_TRACE
- restart_brender();
edl->tracks->update_y_pixels(theme);
if(debug) PRINT_TRACE
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);
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;
if( !vwindow->is_running() ) continue;
vwindow->close_window();
}
+ for( int i=0; i<edl->vwindow_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; i<edl->mixers.size(); ++i ) {
+ Mixer *mixer = edl->mixers[i];
+ ZWindow *zwindow = get_mixer(mixer);
+ zwindow->set_title(mixer->title);
+ zwindow->start();
+ }
}
- else if(vwindows.size()) {
- VWindow *vwindow = vwindows[DEFAULT_VWINDOW];
- if( vwindow->is_running() ) {
- vwindow->gui->lock_window("MWindow::update_project");
- vwindow->update(1);
- vwindow->gui->unlock_window();
+ else {
+ if(vwindows.size()) {
+ VWindow *vwindow = vwindows[DEFAULT_VWINDOW];
+ if( vwindow->is_running() ) {
+ vwindow->gui->lock_window("MWindow::update_project");
+ vwindow->update(1);
+ vwindow->gui->unlock_window();
+ }
}
}
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
}
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);
}
FileXML file;
edl->optimize();
edl->set_path(session->filename);
- char backup_path[BCTEXTLEN];
+ char backup_path[BCTEXTLEN], backup_path1[BCTEXTLEN];
snprintf(backup_path, sizeof(backup_path), "%s/%s",
File::get_config_path(), BACKUP_FILE);
- edl->save_xml(&file, backup_path, 0, 0);
+ 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();
FileSystem fs;
fs.complete_path(backup_path);
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);
+}
+
+
+int MWindow::copy_target(const char *path, const char *target)
+{
+ int ifd = ::open(path, O_RDONLY);
+ if( ifd < 0 ) {
+ eprintf("Cannot open asset: %s", path);
+ return 1;
+ }
+ int ret = 0;
+ int ofd = ::open(target, O_CREAT+O_TRUNC+O_WRONLY, 0777);
+ if( ofd >= 0 ) {
+ struct stat st;
+ int64_t total_bytes = !fstat(ifd, &st) ? st.st_size : 0;
+ char progress_title[BCTEXTLEN];
+ sprintf(progress_title, _("Copying: %s\n"), target);
+ BC_ProgressBox progress(-1, -1, progress_title, total_bytes);
+
+ int64_t count = 0, len = -1;
+ int bfrsz = 0x100000;
+ uint8_t *bfr = new uint8_t[bfrsz];
+ while( (len=::read(ifd, bfr, bfrsz)) > 0 ) {
+ if( len != ::write(ofd, bfr, len) ) {
+ eprintf("Error writing: %s", target);
+ break;
+ }
+ if( progress.is_cancelled() ) {
+ ret = 1;
+ break;
+ }
+ progress.update(count += len, 1);
+ }
+ delete [] bfr;
+ ::close(ofd);
+
+ progress.stop_progress();
+ if( len < 0 ) {
+ eprintf("Error reading: %s", path);
+ ret = 1;
+ }
+ }
+ else
+ eprintf("Cannot create asset target: %s", target);
+ ::close(ifd);
+ return ret;
+}
+
+int MWindow::link_target(const char *real_path, const char *link_path, int relative)
+{
+ char target[BCTEXTLEN];
+ if( relative ) {
+ const char *bp = real_path, *cp = bp;
+ const char *lp = link_path, *np = lp;
+ char *tp = target, *ep = tp+sizeof(target)-1, lch;
+ while( *lp && *bp && (lch=*lp++) == *bp++ ) {
+ if( lch == '/' ) { np = lp; cp = bp; }
+ }
+ while( tp<ep && *np ) {
+ if( *np++ != '/' ) continue;
+ *tp++ = '.'; *tp++ = '.'; *tp++ = '/';
+ }
+ while( tp<ep && *cp ) *tp++ = *cp++;
+ *tp = 0;
+ }
+ else
+ strcpy(target, real_path);
+ if( symlink(target, link_path) ) {
+ eprintf("Cannot create symlink: %s", link_path);
+ return 1;
+ }
+ return 0;
+}
+
+void MWindow::save_project(const char *dir, int save_mode, int overwrite, int reload)
+{
+ char dir_path[BCTEXTLEN];
+ strcpy(dir_path, dir);
+ FileSystem fs;
+ fs.complete_path(dir_path);
+
+ struct stat st;
+ if( !stat(dir_path, &st) ) {
+ if( !S_ISDIR(st.st_mode) ) {
+ eprintf("Path exists and is not a directory\n%s", dir_path);
+ return;
+ }
+ }
+ else {
+ if( mkdir(dir_path, S_IRWXU | S_IRWXG | S_IRWXO) ) {
+ eprintf("Cannot create directory\n%s", dir_path);
+ return;
+ }
+ }
+ char *real_dir = realpath(dir_path, 0);
+ strcpy(dir_path, real_dir);
+ free(real_dir);
+
+ EDL *save_edl = new EDL;
+ save_edl->create_objects();
+ save_edl->copy_all(edl);
+
+ char progress_title[BCTEXTLEN];
+ sprintf(progress_title, _("Saving to %s:\n"), dir);
+ int total_assets = save_edl->assets->total();
+ MainProgressBar *progress = mainprogress->start_progress(progress_title, total_assets);
+ int ret = 0;
+ Asset *current = save_edl->assets->first;
+ for( int i=0; !ret && current; ++i, current=NEXT ) {
+ char *path = current->path;
+ if( ::stat(path, &st) ) {
+ eprintf("Asset not found: %s", path);
+ continue;
+ }
+ char *real_path = realpath(path, 0);
+ const char *cp = strrchr(path, '/'), *bp = !cp ? path : cp+1;
+ char link_path[BCTEXTLEN];
+ snprintf(link_path, sizeof(link_path), "%s/%s", dir_path, bp);
+ int skip = 0;
+ if( strcmp(real_path, link_path) ) {
+ if( !::lstat(link_path, &st) ) {
+ if( overwrite )
+ ::remove(link_path);
+ else
+ skip = 1;
+ }
+ }
+ else {
+ eprintf("copy/link to self, skippped: %s", path);
+ skip = 1;
+ }
+ if( !skip ) {
+ if( save_mode == SAVE_PROJECT_COPY ) {
+ if( copy_target(real_path, link_path) )
+ ret = 1;
+ }
+ else {
+ link_target(real_path, link_path,
+ save_mode == SAVE_PROJECT_RELLINK ? 1 : 0);
+ }
+ }
+ free(real_path);
+ strcpy(path, link_path);
+
+ if( progress->is_cancelled() ) break;
+ progress->update(i);
+ }
+
+ progress->stop_progress();
+ delete progress;
+
+ char *cp = strrchr(dir_path,'/');
+ char *bp = cp ? cp+1 : dir_path;
+ char filename[BCTEXTLEN];
+ snprintf(filename, sizeof(filename), "%s/%s.xml", dir_path, bp);
+ save_edl->set_path(filename);
+ FileXML file;
+ save_edl->save_xml(&file, filename);
+ file.terminate_string();
+
+ if( !file.write_to_file(filename) ) {
+ char string[BCTEXTLEN];
+ sprintf(string, _("\"%s\" %dC written"), filename, (int)strlen(file.string()));
+ gui->lock_window("SaveProject::run 2");
+ gui->show_message(string);
+ gui->unlock_window();
+ gui->mainmenu->add_load(filename);
+ }
+ else
+ eprintf(_("Couldn't open %s."), filename);
+
+ save_edl->remove_user();
+
+ if( reload ) {
+ gui->lock_window("MWindow::save_project");
+ ArrayList<char*> filenames;
+ filenames.append(filename);
+ load_filenames(&filenames, LOADMODE_REPLACE);
+ gui->unlock_window();
+ }
+}
+
+
static inline int gcd(int m, int n)
{
int r;
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);
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);
}
}
void MWindow::remove_assets_from_project(int push_undo, int redraw,
ArrayList<Indexable*> *drag_assets, ArrayList<EDL*> *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);
}
}
}
- 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();
}
}
- 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
char mtime[256];
strftime(mtime, sizeof(mtime), "%F %T", tm);
fprintf(fp,"mtime: %s\n", mtime);
-
+#if 0
+// people hit ctl-c waiting for this
int fd = open(proc_path,O_RDONLY+O_NONBLOCK);
if( fd < 0 ) { fprintf(fp,"open: %m\n"); return; }
uint8_t *bfr = 0;
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");
}
mwindow->dump_edl(fp);
fprintf(fp, "\nUNDO:\n");
mwindow->dump_undo(fp);
- fprintf(fp, "\nEXE:\n");
+ fprintf(fp, "\nEXE: %s\n", AboutPrefs::build_timestamp);
mwindow->dump_exe(fp);
}
int result = file->open_file(preferences, asset, 1, 0);
if( !result && delete_tracks > 0 )
undo->update_undo_before();
- if( !result && asset->video_data && asset->get_video_layers() > 0 ) {
+ int video_layers = asset->get_video_layers();
+ if( !result && asset->video_data && vstream < video_layers ) {
// try to get asset up to date, may fail
file->select_video_stream(asset, vstream);
// either way use what was/is there.
else if( delete_tracks )
edl->tracks->delete_track(track);
}
+ edl->retrack();
edl->resample(old_framerate, session->frame_rate, TRACK_VIDEO);
}
if( !result && asset->audio_data && asset->channels > 0 ) {
session->sample_rate = asset->get_sample_rate();
int64_t channel_mask = 0;
- int astrm = !asset->video_data ? -1 :
+ int astrm = !asset->video_data || vstream >= video_layers ? -1 :
file->get_audio_for_video(vstream, astream, channel_mask);
if( astrm >= 0 ) file->select_audio_stream(asset, astrm);
if( astrm < 0 || !channel_mask ) channel_mask = (1<<asset->channels)-1;
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;
- case 1:
- session->achannel_positions[1] = 90;
- break;
- default: {
- if( !channels ) break;
- double t = 0, dt = 360./channels;
- for( int i=channels; --i>=0; t+=dt )
- session->achannel_positions[i] = int(t+0.5);
- 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 ) {
return (PanAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current);
}
+PatchGUI *MWindow::get_patchgui(Track *track)
+{
+ PatchGUI *patchgui = 0;
+ TimelinePane **panes = gui->pane;
+ for( int i=0; i<TOTAL_PANES && !patchgui; ++i ) {
+ if( !panes[i] ) continue;
+ PatchBay *patchbay = panes[i]->patchbay;
+ if( !patchbay ) continue;
+ for( int j=0; j<patchbay->patches.total && !patchgui; ++j ) {
+ if( patchbay->patches.values[j]->track == track )
+ patchgui = patchbay->patches.values[j];
+ }
+ }
+ return patchgui;
+}