void MWindow::add_audio_track_entry(int above, Track *dst)
{
undo_before();
- add_audio_track(above, dst);
+ Track *track = add_audio_track(above, dst);
+ track->master = 1;
save_backup();
undo_after(_("add track"), LOAD_ALL);
cwindow->refresh_frame(CHANGE_EDL);
}
-void MWindow::add_video_track_entry(Track *dst)
+void MWindow::add_video_track_entry(int above, Track *dst)
{
undo_before();
- add_video_track(1, dst);
+ Track *track = add_video_track(above, dst);
+ track->master = 1;
undo_after(_("add track"), LOAD_ALL);
restart_brender();
save_backup();
}
-void MWindow::add_subttl_track_entry(Track *dst)
+void MWindow::add_subttl_track_entry(int above, Track *dst)
{
undo_before();
- add_subttl_track(1, dst);
+ Track *track = add_subttl_track(above, dst);
+ track->master = 1;
undo_after(_("add track"), LOAD_ALL);
restart_brender();
}
-int MWindow::add_audio_track(int above, Track *dst)
+Track *MWindow::add_audio_track(int above, Track *dst)
{
- edl->tracks->add_audio_track(above, dst);
+ Track *track = edl->tracks->add_audio_track(above, dst);
edl->tracks->update_y_pixels(theme);
save_backup();
- return 0;
+ return track;
}
-int MWindow::add_video_track(int above, Track *dst)
+Track *MWindow::add_video_track(int above, Track *dst)
{
- edl->tracks->add_video_track(above, dst);
+ Track *track = edl->tracks->add_video_track(above, dst);
edl->tracks->update_y_pixels(theme);
save_backup();
- return 0;
+ return track;
}
-int MWindow::add_subttl_track(int above, Track *dst)
+Track *MWindow::add_subttl_track(int above, Track *dst)
{
- edl->tracks->add_subttl_track(above, dst);
+ Track *track = edl->tracks->add_subttl_track(above, dst);
edl->tracks->update_y_pixels(theme);
save_backup();
- return 0;
+ return track;
}
void MWindow::asset_to_all()
for( Track *current=edl->tracks->first; current; current=NEXT ) {
if( current->data_type == TRACK_VIDEO /* &&
- current->record */ ) {
+ current->is_armed() */ ) {
current->track_w = w;
current->track_h = h;
}
//printf("MWindow::insert 6 %p\n", vwindow->get_edl());
}
-void MWindow::insert_effects_canvas(double start,
- double length)
+void MWindow::insert_effects_canvas(Track *dest_track, double start, double length)
{
- Track *dest_track = session->track_highlighted;
- if( !dest_track ) return;
-
undo_before();
- for( int i=0; i<session->drag_pluginservers->total; ++i ) {
- PluginServer *plugin = session->drag_pluginservers->values[i];
- insert_effect(plugin->title, 0, dest_track,
- i == 0 ? session->pluginset_highlighted : 0,
- start, length, PLUGIN_STANDALONE);
+ ArrayList<SharedLocation> shared_locations;
+ PluginSet *pluginset = session->pluginset_highlighted;
+ int gang = edl->session->gang_tracks != GANG_NONE ? 1 : 0;
+ int data_type = dest_track->data_type;
+ int first_track = 1;
+
+ for( Track *track=dest_track; track; track=track->next ) {
+ if( gang && track->master && !first_track ) break;
+ if( track->data_type != data_type ) continue;
+ if( !track->is_armed() ) continue;
+ int module = edl->tracks->number_of(track);
+ for( int i=0; i<session->drag_pluginservers->total; ++i ) {
+ PluginServer *plugin = session->drag_pluginservers->values[i];
+ int shared = gang; // && plugin->multichannel ? 1 : 0;
+ int plugin_type = !first_track && shared ?
+ PLUGIN_SHAREDPLUGIN : PLUGIN_STANDALONE;
+ SharedLocation *shared_location = !first_track ?
+ &shared_locations[i] : &shared_locations.append();
+ insert_effect(plugin->title, shared_location, track,
+ pluginset, start, length, plugin_type);
+ if( first_track && shared ) {
+ shared_location->module = module;
+ shared_location->plugin = pluginset ?
+ track->plugin_set.number_of(pluginset) :
+ track->plugin_set.total-1 ;
+ }
+ }
+ if( !gang ) break;
+ first_track = 0;
+ pluginset = 0;
}
save_backup();
{
if( !dest_track ) return;
- undo_before();
-
double start = 0;
double length = dest_track->get_length();
edl->local_session->get_selectionstart();
}
- for( int i=0; i<session->drag_pluginservers->total; ++i ) {
- PluginServer *plugin = session->drag_pluginservers->values[i];
- insert_effect(plugin->title, 0, dest_track, 0,
- start, length, PLUGIN_STANDALONE);
- }
-
- save_backup();
- undo_after(_("insert effect"), LOAD_EDITS | LOAD_PATCHES);
- restart_brender();
- sync_parameters(CHANGE_EDL);
+ insert_effects_canvas(dest_track, start, length);
gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
}
-void MWindow::insert_effect(char *title,
- SharedLocation *shared_location,
- int data_type,
- int plugin_type,
- int single_standalone)
+void MWindow::insert_effect(char *title, SharedLocation *shared_location,
+ int data_type, int plugin_type, int single_standalone)
{
Track *current = edl->tracks->first;
SharedLocation shared_location_local;
shared_location_local.copy_from(shared_location);
int first_track = 1;
+ double start_pos = edl->local_session->get_selectionstart(1);
+ double end_pos = edl->local_session->get_selectionend(1);
for( ; current; current=NEXT ) {
- if( current->data_type == data_type &&
- current->record ) {
- insert_effect(title, &shared_location_local,
- current, 0, 0, 0, plugin_type);
-
- if( first_track ) {
- if( plugin_type == PLUGIN_STANDALONE && single_standalone ) {
- plugin_type = PLUGIN_SHAREDPLUGIN;
- shared_location_local.module = edl->tracks->number_of(current);
- shared_location_local.plugin = current->plugin_set.total - 1;
- }
- first_track = 0;
+ if( current->data_type != data_type ) continue;
+ if( !current->is_armed() ) continue;
+ double start = start_pos, end = end_pos;
+ if( plugin_type == PLUGIN_STANDALONE && start >= end ) {
+ start = 0;
+ end = current->get_length();
+ }
+ double length = end - start;
+ insert_effect(title, &shared_location_local,
+ current, 0, start, length, plugin_type);
+ if( first_track ) {
+ if( plugin_type == PLUGIN_STANDALONE && single_standalone ) {
+ plugin_type = PLUGIN_SHAREDPLUGIN;
+ shared_location_local.module = edl->tracks->number_of(current);
+ shared_location_local.plugin = current->plugin_set.total - 1;
+ start_pos = start; end_pos = end;
}
+ first_track = 0;
}
}
}
-
void MWindow::insert_effect(char *title,
- SharedLocation *shared_location,
- Track *track,
- PluginSet *plugin_set,
- double start,
- double length,
- int plugin_type)
+ SharedLocation *shared_location, Track *track, PluginSet *plugin_set,
+ double start, double length, int plugin_type)
{
KeyFrame *default_keyframe = 0;
PluginServer *server = 0;
server->save_data(default_keyframe);
}
// Insert plugin object
- track->insert_effect(title, shared_location,
- default_keyframe, plugin_set,
- start, length, plugin_type);
+ track->insert_effect(title, shared_location, default_keyframe,
+ plugin_set, start, length, plugin_type);
track->optimize();
if( plugin_type == PLUGIN_STANDALONE ) {
}
+void MWindow::swap_track_down(Track *track)
+{
+ undo_before();
+ edl->tracks->swap_track_down(track);
+ save_backup();
+ undo_after(_("swap track down"), LOAD_ALL);
+
+ restart_brender();
+ gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+ sync_parameters(CHANGE_EDL);
+ save_backup();
+}
+
+void MWindow::swap_tracks_down()
+{
+ undo_before();
+ edl->tracks->swap_tracks_down();
+ save_backup();
+ undo_after(_("swap tracks down"), LOAD_ALL);
+
+ restart_brender();
+ gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+ sync_parameters(CHANGE_EDL);
+ save_backup();
+}
+
+void MWindow::swap_track_up(Track *track)
+{
+ undo_before();
+ edl->tracks->swap_track_up(track);
+ save_backup();
+ undo_after(_("swap track up"), LOAD_ALL);
+ restart_brender();
+ gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+ sync_parameters(CHANGE_EDL);
+ save_backup();
+}
+
+void MWindow::swap_tracks_up()
+{
+ undo_before();
+ edl->tracks->swap_tracks_up();
+ save_backup();
+ undo_after(_("swap tracks up"), LOAD_ALL);
+ restart_brender();
+ gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+ sync_parameters(CHANGE_EDL);
+}
+
+
void MWindow::mute_selection()
{
double start = edl->local_session->get_selectionstart();
for( int i=0; i<new_assets->total; ++i ) {
Indexable *indexable = new_assets->get(i);
if( indexable->is_asset ) {
- remove_asset_from_caches((Asset*)indexable);
+ remove_from_caches(indexable);
}
EDL *new_edl = new EDL;
new_edl->create_objects();
need_new_tracks = 1;
for( int i=0; i<new_edls->total; ++i ) {
EDL *new_edl = new_edls->values[i];
+ int first_track = 1;
for( Track *current=new_edl->tracks->first; current; current=NEXT ) {
switch( current->data_type ) {
case TRACK_VIDEO:
default:
continue;
}
+ if( first_track ) {
+ edl->tracks->last->master = 1;
+ first_track = 0;
+ }
// re-label only if not already labeled
if( new_edl->local_session->asset2edl )
strcpy(current->title, edl->tracks->last->title);
else
// Recycle existing tracks of master EDL
if( load_mode == LOADMODE_CONCATENATE ||
- load_mode == LOADMODE_PASTE ||
- load_mode == LOADMODE_NESTED ) {
+ load_mode == LOADMODE_PASTE ) {
Track *current = first_track ? first_track : edl->tracks->first;
for( ; current; current=NEXT ) {
- if( current->record ) {
+ if( current->is_armed() ) {
destination_tracks.append(current);
}
}
// Add assets and prepare index files
for( Asset *new_asset=new_edl->assets->first;
new_asset; new_asset=new_asset->next ) {
- mainindexes->add_next_asset(0, new_asset);
+ mainindexes->add_indexable(new_asset);
}
// Capture index file status from mainindex test
edl->update_assets(new_edl);
//PRINT_TRACE
// Get starting point of insertion. Need this to paste labels.
switch( load_mode ) {
+ case LOADMODE_NOTHING:
+ continue;
case LOADMODE_REPLACE:
current_position = 0;
break;
break;
case LOADMODE_PASTE:
- case LOADMODE_NESTED:
destination_track = 0;
if( i == 0 ) {
for( int j=0; j<destination_tracks.total; ++j ) {
load_mode != LOADMODE_ASSETSONLY ) {
// Insert labels
if( edit_labels ) {
- if( load_mode == LOADMODE_PASTE || load_mode == LOADMODE_NESTED )
+ if( load_mode == LOADMODE_PASTE )
edl->labels->insert_labels(new_edl->labels,
destination_tracks.total ? paste_position[0] : 0.0,
edl_length, 1);
if( destination_track < destination_tracks.total &&
destination_tracks.values[destination_track]->data_type == new_track->data_type ) {
Track *track = destination_tracks.values[destination_track];
-
// Replace default keyframes if first EDL and new tracks were created.
// This means data copied from one track and pasted to another won't retain
// the camera position unless it's a keyframe. If it did, previous data in the
// track might get unknowingly corrupted. Ideally we would detect when differing
// default keyframes existed and create discrete keyframes for both.
int replace_default = (i == 0) && need_new_tracks;
-
+// master tracks are the first track in each new edl when new tracks are created
+ int master = track->master;
//printf("MWindow::paste_edls 1 %d\n", replace_default);
// Insert new track at current position
switch( load_mode ) {
break;
case LOADMODE_PASTE:
- case LOADMODE_NESTED:
current_position = paste_position[destination_track];
paste_position[destination_track] += new_track->get_length();
break;
//PRINT_TRACE
track->insert_track(new_track, current_position, replace_default,
edit_plugins, edit_autos, edl_length);
+ if( master ) track->master = 1;
//PRINT_TRACE
}
}
}
- if( load_mode == LOADMODE_PASTE ||
- load_mode == LOADMODE_NESTED )
+ if( load_mode == LOADMODE_PASTE )
current_position += edl_length;
}
Track *track = new_edl->tracks->first;
const char *path = edl->path;
for( ; (!path || !*path) && track; track=track->next ) {
- if( !track->record ) continue;
+ if( !track->is_armed() ) continue;
Edit *edit = track->edits->first;
if( !edit ) continue;
Indexable *indexable = edit->get_source();
time_t now; time(&now);
struct tm dtm; localtime_r(&now, &dtm);
char *cp = new_edl->local_session->clip_notes;
- int n, sz = sizeof(new_edl->local_session->clip_notes)-1;
- if( txt && *txt ) {
- n = snprintf(cp, sz, "%s", txt);
- cp += n; sz -= n;
- }
- n = snprintf(cp, sz,
+ char *ep = cp + sizeof(new_edl->local_session->clip_notes)-1;
+ if( txt && *txt )
+ cp += snprintf(cp, ep-cp, "%s", txt);
+ cp += snprintf(cp, ep-cp,
"%02d/%02d/%02d %02d:%02d:%02d, +%s\n",
dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
dtm.tm_hour, dtm.tm_min, dtm.tm_sec, duration);
- cp += n; sz -= n;
if( path && *path ) {
FileSystem fs;
char title[BCTEXTLEN];
fs.extract_name(title, path);
- n = snprintf(cp, sz, "%s", title);
- cp += n; sz -= n;
+ cp += snprintf(cp, ep-cp, "%s", title);
}
- cp[n] = 0;
sprintf(new_edl->local_session->clip_icon,
- "clip_%02d%02d%02d-%02d%02d%02d.png",
+ "clip_%02d%02d%02d-%02d%02d%02d-%d.png",
dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
- dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
+ dtm.tm_hour, dtm.tm_min, dtm.tm_sec,
+ new_edl->id);
new_edl->folder_no = AW_CLIP_FOLDER;
edl->update_assets(new_edl);
int cur_x, cur_y;
int current_track = 0;
for( Track *current=edl->tracks->first; current; current=NEXT ) {
if( current->data_type == TRACK_AUDIO &&
- current->record ) {
+ current->is_armed() ) {
Autos *pan_autos = current->automation->autos[AUTOMATION_PAN];
PanAuto *pan_auto = (PanAuto*)pan_autos->get_auto_for_editing(-1);
}
void MWindow::start_convert(Asset *format_asset, const char *suffix,
- float beep, int remove_originals)
+ float beep, int to_proxy, int remove_originals)
{
if( !convert_render )
convert_render = new ConvertRender(this);
- convert_render->set_format(format_asset, suffix);
+ convert_render->set_format(format_asset, suffix, to_proxy);
int found = convert_render->find_convertable_assets(edl);
if( convert_render->needed_idxbls.size() > 0 )
convert_render->start_convert(beep, remove_originals);
return result;
}
+void MWindow::collect_effects()
+{
+ FileXML file;
+ const char *file_string = "";
+ EDL *group = 0;
+ int ret = edl->collect_effects(group);
+ switch( ret ) {
+ case COLLECT_EFFECTS_RECORD:
+ eprintf(_("Selected edit track not armed."));
+ break;
+ case COLLECT_EFFECTS_MULTIPLE:
+ eprintf(_("More than one edit selected on a track."));
+ break;
+ case COLLECT_EFFECTS_MISSING:
+ eprintf(_("No effects under selected edit."));
+ break;
+ case COLLECT_EFFECTS_EMPTY:
+ eprintf(_("No edits selected."));
+ break;
+ case COLLECT_EFFECTS_MASTER:
+ eprintf(_("Shared effect added without master."));
+ break;
+ case 0:
+ group->save_xml(&file, "");
+ file_string = file.string();
+ group->remove_user();
+ }
+ long file_length = strlen(file_string);
+ gui->to_clipboard(file_string, file_length, BC_PRIMARY_SELECTION);
+ gui->to_clipboard(file_string, file_length, SECONDARY_SELECTION);
+}
+
+void MWindow::paste_effects()
+{
+ char *string = 0;
+ int64_t len = gui->clipboard_len(BC_PRIMARY_SELECTION);
+ if( len ) {
+ string = new char[len];
+ gui->from_clipboard(string, len, BC_PRIMARY_SELECTION);
+ }
+ if( !string || !string[0] ) {
+ eprintf(_("Error clipboard buffer empty."));
+ return;
+ }
+ FileXML file;
+ file.read_from_string(string);
+ EDL *group = new EDL();
+ group->create_objects();
+ if( !group->load_xml(&file, LOAD_ALL) ) {
+ undo_before();
+ int ret = edl->insert_effects(group);
+ switch( ret ) {
+ case INSERT_EFFECTS_RECORD:
+ eprintf(_("Selected edit track not armed."));
+ break;
+ case INSERT_EFFECTS_TYPE:
+ eprintf(_("Track type mismatched."));
+ break;
+ case INSERT_EFFECTS_MULTIPLE:
+ eprintf(_("More than one edit selected on a track."));
+ break;
+ case INSERT_EFFECTS_MISSING:
+ eprintf(_("Too few target edits to add group effects."));
+ break;
+ case INSERT_EFFECTS_EXTRA:
+ eprintf(_("Too many target edits to add group effects."));
+ break;
+ case INSERT_EFFECTS_MASTER:
+ eprintf(_("Shared effect added without master."));
+ break;
+ case 0:
+ break;
+ }
+ save_backup();
+ undo_after(_("paste effects"), LOAD_ALL);
+ restart_brender();
+ cwindow->refresh_frame(CHANGE_EDL);
+ update_plugin_guis();
+ gui->update(1, NORMAL_DRAW, 1, 0, 0, 0, 0);
+ }
+ else
+ eprintf(_("Error loading clip from clipboard buffer."));
+ delete [] string;
+ group->remove_user();
+}
+
+void MWindow::align_timecodes()
+{
+ undo_before();
+ double offset = edl->tracks->align_timecodes();
+ set_timecode_offset(offset);
+ save_backup();
+ undo_after(_("align timecodes"), LOAD_ALL);
+ restart_brender();
+ cwindow->refresh_frame(CHANGE_EDL);
+ update_plugin_guis();
+}
+
+
+int MWindow::masters_to_mixers()
+{
+ Track *master_track = edl->tracks->first;
+ while( master_track && !master_track->master )
+ master_track = master_track->next;
+ while( master_track ) { // test for track/mixer conflicts
+ int failed = 0;
+ Track *mixer_last = master_track;
+ Track *track = master_track->next;
+ for( ; track && !track->master; track=track->next )
+ mixer_last = track;
+ Track *next_track = track;
+ Mixer *master_mixer = 0;
+ for( int i=0, n=edl->mixers.size(); i<n; ++i ) {
+ if( master_track->index_in(edl->mixers[i]) >= 0 ) {
+ master_mixer = edl->mixers[i];
+ break;
+ }
+ }
+ if( master_mixer ) { // existing mixer track group
+ for( track=master_track; !failed && track; track=track->next ) {
+ if( track->index_in(master_mixer) < 0 ) {
+ eprintf("Mixer: %s missing track: %s",
+ master_mixer->title, track->title);
+ failed = 1;
+ }
+ if( track == mixer_last ) break;
+ }
+ for( int i=0, n=master_mixer->mixer_ids.size(); !failed && i<n; ++i ) {
+ int mixer_id = master_mixer->mixer_ids[i], found = 0;
+ for( track=master_track; track; track=track->next ) {
+ if( track->mixer_id == mixer_id ) {
+ found = 1;
+ break;
+ }
+ if( track == mixer_last ) break;
+ }
+ if( !found ) {
+ eprintf("Mixer: %s track missing: %s",
+ master_mixer->title, track->title);
+ failed = 1;
+ }
+ }
+ }
+ else { // create mixer
+ for( track=master_track->next; !failed && track; track=track->next ) {
+ for( int i=0, n=edl->mixers.size(); !failed && i<n; ++i ) {
+ Mixer *mixer = edl->mixers[i];
+ if( track->index_in(mixer) >= 0 ) {
+ eprintf("Track: %s already exists in mixer: %s",
+ track->title, mixer->title);
+ failed = 1;
+ break;
+ }
+ }
+ if( track == mixer_last ) break;
+ }
+ if( !failed ) { // new mixer
+ ZWindow *zwindow = get_mixer(master_mixer);
+ zwindow->set_title(master_track->title);
+ sprintf(master_track->title, _("Mixer %d"), zwindow->idx);
+ for( track=master_track; track; track=track->next ) {
+ track->play = track->armed = 0;
+ master_mixer->mixer_ids.append(track->get_mixer_id());
+ if( track == mixer_last ) break;
+ }
+ zwindow->start();
+ }
+ }
+ master_track = next_track;
+ }
+ return 0;
+}
+
+void MWindow::mix_masters()
+{
+ undo_before();
+ masters_to_mixers();
+ undo_after(_("mix masters"), LOAD_ALL);
+
+ restart_brender();
+ gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+ gui->activate_timeline();
+ cwindow->refresh_frame(CHANGE_EDL);
+ save_backup();
+}
+