void EDL::delete_edits(ArrayList<Edit*> *edits, int collapse)
{
edits->sort(dead_edit_cmp);
- if( session->labels_follow_edits )
- delete_edit_labels(edits, collapse);
for( int i=0; i<edits->size(); ++i ) {
Edit *edit = edits->get(i);
Track *track = edit->track;
PluginSet *plugin_set = track->plugin_set[k];
plugin_set->clear(start, end, 1);
if( !collapse )
- plugin_set->paste_silence(start, end);
+ plugin_set->paste_silence(start, end, 1);
+ plugin_set->optimize();
}
}
Edit *dead_edit = edit;
edit->startproject -= length;
}
delete dead_edit;
- }
-// optimize edits only.
-// full optimize deletes pluginsets, mistargeting drag and drop
- for( Track *track=tracks->first; track; track=track->next )
track->edits->optimize();
+ }
}
class Range {
void cut_selected_edits(int collapse, int packed);
// Move edit to new position
void move_edits(ArrayList<Edit*> *edits, Track *track, double position,
-// 0 - old style (cut and insert elswhere), 1- new style - (clear and overwrite elsewere)
- int behaviour);
+ int mode); // mode: 0 - mute and overwrite, 1 - cut and paste
void paste_edits(EDL *clip, Track *first_track, double position, int overwrite,
int edit_edits, int edit_labels, int edit_autos, int edit_plugins);
void paste_clipboard(Track *first_track, double position, int overwrite,
{
if( !edits->size() ) return;
undo->update_undo_before();
+ if( edl->session->labels_follow_edits )
+ edl->delete_edit_labels(edits, collapse);
edl->delete_edits(edits, collapse);
edl->optimize();
save_backup();
void MWindow::move_edits(ArrayList<Edit*> *edits,
- Track *track,
- double position,
- int behaviour)
+ Track *track, double position, int mode)
{
undo->update_undo_before();
-
- EDL *clip = selected_edits_to_clip(0, 0, 0,
- edl->session->labels_follow_edits,
- edl->session->autos_follow_edits,
- edl->session->plugins_follow_edits);
- edl->delete_edits(edits, 0);
- paste_edits(clip, track, position, behaviour, 1,
+// lockout timebar labels update
+// labels can be deleted with tooltip repeater running
+ cwindow->gui->lock_window("Tracks::move_edits");
+ edl->tracks->move_edits(edits, track, position,
edl->session->labels_follow_edits,
- edl->session->autos_follow_edits,
- edl->session->plugins_follow_edits);
- edl->tracks->clear_selected_edits();
+ edl->session->plugins_follow_edits,
+ edl->session->autos_follow_edits, mode);
+ cwindow->gui->timebar->update(1);
+ cwindow->gui->unlock_window();
save_backup();
undo->update_undo_after(_("move edit"), LOAD_ALL);
if( plugin->startproject >= start )
plugin->startproject += edit->length;
else if( plugin->startproject+plugin->length > end )
- plugin->length += end - start;
+ plugin->length += edit->length;
Auto *default_keyframe = plugin->keyframes->default_auto;
if( default_keyframe->position >= start )
default_keyframe->position += edit->length;
int64_t keyframe_pos = pos + keyframe->position;
new_plugin->keyframes->insert_auto(keyframe_pos, keyframe);
}
+ while( (new_plugin=(Plugin *)new_plugin->next) ) {
+ KeyFrame *keyframe = (KeyFrame*)new_plugin->keyframes->first;
+ for( ; keyframe; keyframe=(KeyFrame*)keyframe->next )
+ keyframe->position += plugin->length;
+ }
}
}
}
void MWindow::move_group(EDL *group, Track *first_track, double position, int overwrite)
{
undo->update_undo_before();
+// lockout timebar labels update
+// labels can be deleted with tooltip repeater running
+ cwindow->gui->lock_window("Tracks::move_group");
ArrayList<Edit *>edits;
edl->tracks->get_selected_edits(&edits);
+ if( edl->session->labels_follow_edits )
+ edl->delete_edit_labels(&edits, 0);
edl->delete_edits(&edits, 0);
paste_edits(group, first_track, position, overwrite, 1,
edl->session->labels_follow_edits,
edl->session->autos_follow_edits,
edl->session->plugins_follow_edits);
+ cwindow->gui->timebar->update(1);
+ cwindow->gui->unlock_window();
// big debate over whether to do this, must either clear selected, or no tweaking
// edl->tracks->clear_selected_edits();
}
}
+void PluginSet::paste_silence(int64_t start, int64_t end, int edit_autos)
+{
+ Plugin *new_plugin = (Plugin *) insert_new_edit(start);
+ int64_t length = end - start;
+ new_plugin->length = length;
+ while( (new_plugin=(Plugin *)new_plugin->next) != 0 ) {
+ new_plugin->startproject += length;
+ if( !edit_autos ) continue;
+ new_plugin->keyframes->default_auto->position += length;
+ new_plugin->keyframes->paste_silence(start, end);
+ }
+}
+
void PluginSet::copy(int64_t start, int64_t end, FileXML *file)
{
file->tag.set_title("PLUGINSET");
int use_default, int active_only);
void paste_keyframes(int64_t start, int64_t length, FileXML *file,
int use_default, int active_only);
+ void paste_silence(int64_t start, int64_t end, int edit_autos);
// Return the nearest boundary of any kind in the plugin edits
int64_t plugin_change_duration(int64_t input_position,
int64_t input_length,
double track_position = track->from_units(drop_position);
track_position = mwindow->edl->align_to_frame(track_position, 0);
mwindow->move_edits(mwindow->session->drag_edits,
- track, track_position, !insertion);
+ track, track_position, insertion);
}
result = 1;
void TrackCanvas::draw_drag_handle()
{
- if(mwindow->session->current_operation == DRAG_EDITHANDLE2 ||
- mwindow->session->current_operation == DRAG_PLUGINHANDLE2)
- {
-//printf("TrackCanvas::draw_drag_handle 1 %ld %ld\n", mwindow->session->drag_sample, mwindow->edl->local_session->view_start);
- int64_t pixel1 = Units::round(mwindow->session->drag_position *
- mwindow->edl->session->sample_rate /
- mwindow->edl->local_session->zoom_sample -
- mwindow->edl->local_session->view_start[pane->number]);
-//printf("TrackCanvas::draw_drag_handle 2 %d %jd\n", pane->number, pixel1);
- set_color(!snapped ? GREEN : (snapped=0, YELLOW));
- set_inverse();
-//printf("TrackCanvas::draw_drag_handle 3\n");
- draw_line(pixel1, 0, pixel1, get_h());
- set_opaque();
-//printf("TrackCanvas::draw_drag_handle 4\n");
+ if( mwindow->session->current_operation != DRAG_EDITHANDLE2 &&
+ mwindow->session->current_operation != DRAG_PLUGINHANDLE2 ) return;
+ int64_t pixel1 = Units::round(mwindow->session->drag_position *
+ mwindow->edl->session->sample_rate /
+ mwindow->edl->local_session->zoom_sample -
+ mwindow->edl->local_session->view_start[pane->number]);
+ set_color(!snapped ? GREEN : (snapped=0, YELLOW));
+ set_inverse();
+ draw_line(pixel1, 0, pixel1, get_h());
+ set_opaque();
+
+ if( mwindow->session->current_operation != DRAG_EDITHANDLE2 ) return;
+ if( !mwindow->session->drag_edit ) return;
+ int group_id = mwindow->session->drag_edit->group_id;
+ if( !group_id ) return;
+ int drag_handle = mwindow->session->drag_handle;
+ set_color(RED);
+ set_line_width(3);
+
+ for( Track *track=mwindow->edl->tracks->first; track; track=track->next ) {
+ Edit *left = 0, *right = 0;
+ double start = DBL_MAX, end = DBL_MIN;
+ for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+ if( edit->group_id != group_id ) continue;
+ double edit_start = edit->track->from_units(edit->startproject);
+ if( edit_start < start ) { start = edit_start; left = edit; }
+ double edit_end = edit->track->from_units(edit->startproject+edit->length);
+ if( edit_end > end ) { end = edit_end; right = edit; }
+ }
+ Edit *edit = !drag_handle ? left : right;
+ if( !edit ) continue;
+ Indexable *idxbl = edit->asset;
+ if( !idxbl ) idxbl = edit->nested_edl;
+ int can_drag = idxbl ? 1 : 0;
+ if( drag_handle ) {
+ int64_t source_len = !idxbl ? -1 :
+ edit->track->data_type == TRACK_AUDIO ?
+ idxbl->get_audio_samples() :
+ edit->track->data_type == TRACK_VIDEO ?
+ idxbl->get_video_frames() : -1;
+ if( edit->startsource + edit->length >= source_len )
+ can_drag = 0;
+ }
+ else if( !edit->startsource )
+ can_drag = 0;
+ int64_t x, y, w, h;
+ edit_dimensions(edit, x, y, w, h);
+ int edge_x = !drag_handle ? x : x + w;
+ int edge_y = y + h/2, k = 10;
+ if( edge_x >= 0 && edge_x < get_w() &&
+ edge_y >= 0 && edge_y < get_h() ) {
+ if( !can_drag ) {
+ draw_line(edge_x-k,edge_y-k, edge_x+k,edge_y+k);
+ draw_line(edge_x-k,edge_y+k, edge_x+k,edge_y-k);
+ }
+ else if( !drag_handle ) {
+ draw_line(edge_x+k,edge_y-k, edge_x,edge_y);
+ draw_line(edge_x+k,edge_y+k, edge_x,edge_y);
+ }
+ else {
+ draw_line(edge_x,edge_y, edge_x-k,edge_y-k);
+ draw_line(edge_x,edge_y, edge_x-k,edge_y+k);
+ }
+ }
}
+ set_line_width(1);
}
}
}
+ if( result > 0 ) {
+ int group_id = edit_result->group_id;
+ if( group_id > 0 ) {
+ Track *track = edit_result->track;
+ Edit *left = 0, *right = 0;
+ double start = DBL_MAX, end = DBL_MIN;
+ for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+ if( edit->group_id != group_id ) continue;
+ double edit_start = edit->track->from_units(edit->startproject);
+ if( edit_start < start ) { start = edit_start; left = edit; }
+ double edit_end = edit->track->from_units(edit->startproject+edit->length);
+ if( edit_end > end ) { end = edit_end; right = edit; }
+ }
+ Edit *edit = !handle_result ? left : right;
+ if( edit != edit_result )
+ result = 0;
+ }
+ }
+
update_cursor = 1;
if( result > 0 ) {
double position = 0;
int &track_offset,
uint32_t load_flags);
void move_edits(ArrayList<Edit*> *edits, Track *track, double position,
- int edit_labels, int edit_plugins, int edit_autos, int behaviour);
+ int edit_labels, int edit_plugins, int edit_autos, int mode);
void move_group(EDL *group, Track *first_track, double position, int overwrite);
void move_effect(Plugin *plugin, Track *track, int64_t position);
void move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position);
return total_deleted;
}
-void Tracks::move_edits(ArrayList<Edit*> *edits,
- Track *track,
- double position,
- int edit_labels, // Ignored
- int edit_plugins, // Ignored
- int edit_autos, // Ignored
- int behaviour)
+void Tracks::move_edits(ArrayList<Edit*> *in_edits, Track *track, double position,
+ int edit_labels, int edit_plugins, int edit_autos, int mode)
{
+// have to make a copy, optimize kills edits
+ ArrayList<Edit*> edits;
+ for( int i=0; i<in_edits->size(); ++i ) {
+ Edit *edit = in_edits->get(i);
+ Edit *new_edit = new Edit(edit->edl, edit->track);
+ new_edit->copy_from(edit);
+ edits.append(new_edit);
+ }
+
+ int current_aedit = 0, current_vedit = 0;
//printf("Tracks::move_edits 1\n");
- for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
- {
- if(dest_track->record)
- {
+ for( Track *dest_track=track; dest_track; dest_track=dest_track->next ) {
+ if( !dest_track->record ) continue;
// Need a local copy of the source edit since the original source edit may
// change in the editing operation.
- Edit *source_edit = 0;
- Track *source_track = 0;
-
-
-// Get source track
- if(dest_track->data_type == TRACK_AUDIO)
- {
- int current_aedit = 0;
-
- while(current_aedit < edits->total &&
- edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
- current_aedit++;
-
- if(current_aedit < edits->total)
- {
- source_edit = edits->values[current_aedit];
- source_track = source_edit->track;
- edits->remove_number(current_aedit);
+// Get source edit
+ Edit *source_edit = 0;
+ Track *clip_track = 0;
+ switch( dest_track->data_type ) {
+ case TRACK_AUDIO: {
+ while( current_aedit < edits.size() ) {
+ Edit *edit = edits[current_aedit++];
+ if( edit->track->data_type == TRACK_AUDIO ) {
+ source_edit = edit;
+ ATrack *atrack = new ATrack(dest_track->edl, 0);
+ atrack->create_objects();
+ clip_track = atrack;
+ break;
}
}
- else
- if(dest_track->data_type == TRACK_VIDEO)
- {
- int current_vedit = 0;
- while(current_vedit < edits->total &&
- edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
- current_vedit++;
-
- if(current_vedit < edits->total)
- {
- source_edit = edits->values[current_vedit];
- source_track = source_edit->track;
- edits->remove_number(current_vedit);
+ break; }
+ case TRACK_VIDEO: {
+ while( current_vedit < edits.size() ) {
+ Edit *edit = edits[current_vedit++];
+ if( edit->track->data_type == TRACK_VIDEO ) {
+ source_edit = edit;
+ VTrack *vtrack = new VTrack(dest_track->edl, 0);
+ vtrack->create_objects();
+ clip_track = vtrack;
+ break;
}
}
+ break; }
+ }
+ if( !source_edit ) continue;
+
+ Track *source_track = source_edit->track;
+ int64_t start = source_edit->startproject;
+ int64_t length = source_edit->length, end = start + length;
+ double source_start = source_track->from_units(start);
+ double source_end = source_track->from_units(start+length);
+ double len = source_end - source_start;
+ double dest_start = position;
+ double dest_end = dest_start + len;
+
+ if( edit_labels && dest_track == track ) {
+ FileXML label_xml;
+ Labels labels(0, "LABELS");
+ source_edit->edl->labels->copy(source_start, source_end, &label_xml);
+ source_edit->edl->labels->clear(source_start, source_end, mode);
+ if( !label_xml.read_tag() )
+ labels.load(&label_xml, LOAD_ALL);
+ double pos = dest_start;
+ if( mode && source_start < dest_start ) pos -= len;
+ edl->labels->insert_labels(&labels, pos, len, mode);
+ edit_labels = 0;
+ }
-//printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
- if(source_edit)
- {
- int64_t position_i = source_track->to_units(position, 0);
-// Source edit changes
- int64_t source_length = source_edit->length;
- int64_t source_startproject = source_edit->startproject;
-
- if (behaviour == 0)
- {
- // This works like this: CUT edit, INSERT edit at final position, keyframes also follow
- // FIXME: there should be a GUI way to tell whenever user also wants to move autos or not
-// this is all screwed up
-// inserts defaults/bogus everywhere
-#if 0
-// Copy keyframes
- FileXML temp;
- AutoConf temp_autoconf;
-
- temp_autoconf.set_all(1);
-
- source_track->automation->copy(source_edit->startproject,
- source_edit->startproject + source_edit->length,
- &temp,
- 0,
- 0);
- temp.terminate_string();
- temp.rewind();
-// Insert new keyframes
-//printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
- source_track->automation->clear(source_edit->startproject,
- source_edit->startproject + source_edit->length,
- &temp_autoconf,
- 1);
- int64_t position_a = position_i;
- if (dest_track == source_track)
- {
- if (position_a > source_edit->startproject)
- position_a -= source_length;
- }
-
- dest_track->automation->paste_silence(position_a,
- position_a + source_length);
- while(!temp.read_tag())
- dest_track->automation->paste(position_a,
- source_length, 1.0, &temp, 0, 1,
- &temp_autoconf);
-#endif
-// Insert new edit
- Edit *dest_edit = dest_track->edits->shift(position_i,
- source_length);
- Edit *result = dest_track->edits->insert_before(dest_edit,
- dest_track->edits->create_edit());
- result->copy_from(source_edit);
- result->startproject = position_i;
- result->length = source_length;
-
-// Clear source
- source_track->edits->clear(source_edit->startproject,
- source_edit->startproject + source_length);
-
- /*
-//this is outline for future thinking how it is supposed to be done trough C&P mechanisms
- temp.reset_tag();
- source_track->cut(source_edit->startproject,
- source_edit->startproject + source_edit->length,
- &temp,
- NULL);
- temp.terminate_string();
- temp.rewind();
- dest_track->paste_silence(position_a,
- position_a + source_length,
- edit_plugins);
- while(!temp.read_tag())
- dest_track->paste(position_a, // MISSING PIECE OF FUNCTIONALITY
- source_length,
- 1.0,
- &temp,
- 0,
- &temp_autoconf);
- */
-
-
- } else
- if (behaviour == 1)
- // ONLY edit is moved, all other edits stay where they are
- {
- // Copy edit to temp, delete the edit, insert the edit
- Edit *temp_edit = dest_track->edits->create_edit();
- temp_edit->copy_from(source_edit);
- // we call the edits directly since we do not want to move keyframes or anything else
- source_track->edits->clear(source_startproject,
- source_startproject + source_length);
- source_track->edits->paste_silence(source_startproject,
- source_startproject + source_length);
-
- dest_track->edits->clear(position_i,
- position_i + source_length);
- Edit *dest_edit = dest_track->edits->shift(position_i, source_length);
- Edit *result = dest_track->edits->insert_before(dest_edit,
- dest_track->edits->create_edit());
- result->copy_from(temp_edit);
- result->startproject = position_i;
- result->length = source_length;
- delete temp_edit;
- }
- source_track->optimize();
- dest_track->optimize();
+ FileXML track_xml;
+ source_track->copy(source_start, source_end, &track_xml, "");
+ if( !track_xml.read_tag() )
+ clip_track->load(&track_xml, 0, LOAD_ALL);
+
+ if( !mode ) { // mute and overwrite
+ source_track->clear(start, end, 1, 0,
+ edit_plugins, edit_autos, 0);
+ source_track->edits->paste_silence(start, end);
+ if( edit_autos )
+ source_track->shift_keyframes(start, length);
+ if( edit_plugins ) {
+ int n = source_track->plugin_set.size();
+ if( n > 0 ) dest_track->expand_view = 1;
+ for( int k=0; k<n; ++k )
+ source_track->plugin_set[k]->paste_silence(start, end, 1);
+ }
+ dest_track->clear(dest_start, dest_end, 1, 0,
+ edit_plugins, edit_autos, 0);
+ dest_track->insert_track(clip_track, dest_start, 0,
+ edit_plugins, edit_autos, len);
+ }
+ else { // cut and paste
+ dest_track->insert_track(clip_track, dest_start, 0,
+ edit_plugins, edit_autos, len);
+ if( source_track == dest_track && dest_start < source_start ) {
+ source_start += len; source_end += len;
}
+ source_track->clear(source_start, source_end, 1, 0,
+ edit_plugins, edit_autos, 0);
}
+
+ delete clip_track;
+ dest_track->optimize();
}
+
+ edits.remove_all_objects();
}
void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)