3 #include "automation.h"
9 #include "edlsession.h"
12 #include "filesystem.h"
13 #include "localsession.h"
15 #include "strategies.inc"
17 #include "transition.h"
18 #include "transportque.inc"
22 Edits::Edits(EDL *edl, Track *track)
34 void Edits::equivalent_output(Edits *edits, int64_t *result)
36 // For the case of plugin sets, a new plugin set may be created with
37 // plugins only starting after 0. We only want to restart brender at
38 // the first plugin in this case.
39 for(Edit *current = first, *that_current = edits->first;
40 current || that_current;
42 that_current = that_current->next)
44 //printf("Edits::equivalent_output 1 %d\n", *result);
45 if(!current && that_current)
47 int64_t position1 = (last ? last->startproject + last->length : 0);
48 int64_t position2 = that_current->startproject;
49 if(*result < 0 || *result > MIN(position1, position2))
50 *result = MIN(position1, position2);
54 if(current && !that_current)
56 int64_t position1 = (edits->last ? edits->last->startproject + edits->last->length : 0);
57 int64_t position2 = current->startproject;
58 if(*result < 0 || *result > MIN(position1, position2))
59 *result = MIN(position1, position2);
64 //printf("Edits::equivalent_output 2 %d\n", *result);
65 current->equivalent_output(that_current, result);
66 //printf("Edits::equivalent_output 3 %d\n", *result);
72 Edits& Edits::operator=(Edits& edits)
74 while(last) delete last;
75 for(Edit *current = edits.first; current; current = NEXT)
77 Edit *new_edit = append(create_edit());
78 new_edit->copy_from(current);
84 void Edits::insert_asset(Asset *asset,
89 Edit *new_edit = insert_new_edit(position);
91 new_edit->asset = asset;
92 new_edit->startsource = 0;
93 new_edit->startproject = position;
94 new_edit->length = length;
97 new_edit->channel = track_number % asset->channels;
100 new_edit->channel = track_number % asset->layers;
102 //printf("Edits::insert_asset %d %d\n", new_edit->channel, new_edit->length);
103 for(Edit *current = new_edit->next; current; current = NEXT)
105 current->startproject += length;
109 void Edits::insert_edits(Edits *source_edits, int64_t position)
111 int64_t clipboard_length =
112 track->to_units(source_edits->edl->local_session->clipboard_length, 1);
113 int64_t clipboard_end = position + clipboard_length;
116 // Fill region between end of edit table and beginning of pasted segment
117 // with silence. Can't call from insert_new_edit because it's recursive.
118 if(position > length())
120 paste_silence(length(), position);
124 for(Edit *source_edit = source_edits->first;
126 source_edit = source_edit->next)
129 Asset *dest_asset = edl->assets->update(source_edit->asset);
130 // Open destination area
131 Edit *dest_edit = insert_new_edit(position + source_edit->startproject);
133 dest_edit->copy_from(source_edit);
134 dest_edit->asset = dest_asset;
135 dest_edit->startproject = position + source_edit->startproject;
139 // Shift keyframes in source edit to their position in the
140 // destination edit for plugin case
141 dest_edit->shift_keyframes(position);
145 // Shift following edits and keyframes in following edits by length
146 // in current source edit.
147 for(Edit *future_edit = dest_edit->next;
149 future_edit = future_edit->next)
151 future_edit->startproject += dest_edit->length;
152 future_edit->shift_keyframes(dest_edit->length);
155 // Fill clipboard length with silence
156 if(!source_edit->next &&
157 dest_edit->startproject + dest_edit->length < clipboard_end)
159 paste_silence(dest_edit->startproject + dest_edit->length,
167 // Can't paste silence in here because it's used by paste_silence.
168 Edit* Edits::insert_new_edit(int64_t position)
171 //printf("Edits::insert_new_edit 1\n");
172 current = split_edit(position);
173 if(current) current = PREVIOUS;
175 //printf("Edits::insert_new_edit 1\n");
176 Edit *new_edit = create_edit();
177 //printf("Edits::insert_new_edit 1\n");
178 insert_after(current, new_edit);
179 new_edit->startproject = position;
180 //printf("Edits::insert_new_edit 2\n");
185 Edit* Edits::split_edit(int64_t position)
187 // Get edit containing position
188 Edit *edit = editof(position, PLAY_FORWARD);
195 // Split would have created a 0 length
196 // if(edit->startproject == position) return edit;
197 // Create anyway so the return value comes before position
199 Edit *new_edit = create_edit();
200 insert_after(edit, new_edit);
201 new_edit->copy_from(edit);
202 new_edit->length = new_edit->startproject + new_edit->length - position;
203 edit->length = position - edit->startproject;
204 new_edit->startproject = edit->startproject + edit->length;
205 new_edit->startsource += edit->length;
208 // Decide what to do with the transition
209 if(edit->length && edit->transition)
211 delete new_edit->transition;
212 new_edit->transition = 0;
215 if(edit->transition && edit->transition->length > edit->length)
216 edit->transition->length = edit->length;
217 if(new_edit->transition && new_edit->transition->length > new_edit->length)
218 new_edit->transition->length = new_edit->length;
222 int Edits::save(FileXML *xml, char *output_path)
224 copy(0, length(), xml, output_path);
228 void Edits::resample(double old_rate, double new_rate)
230 for(Edit *current = first; current; current = NEXT)
232 current->startproject = Units::to_int64((double)current->startproject /
235 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
236 current->startsource = Units::to_int64((double)current->startsource /
239 if(!NEXT) current->length = Units::to_int64((double)current->length /
242 current->resample(old_rate, new_rate);
259 int Edits::optimize()
265 // Sort edits by starting point
270 for(current = first; current; current = NEXT)
272 Edit *next_edit = NEXT;
274 if(next_edit && next_edit->startproject < current->startproject)
276 swap(next_edit, current);
282 // Insert silence between edits which aren't consecutive
283 for(current = last; current; current = current->previous)
285 if(current->previous)
287 Edit *previous_edit = current->previous;
288 if(current->startproject -
289 previous_edit->startproject -
290 previous_edit->length > 0)
292 Edit *new_edit = create_edit();
293 insert_before(current, new_edit);
294 new_edit->startproject = previous_edit->startproject + previous_edit->length;
295 new_edit->length = current->startproject -
296 previous_edit->startproject -
297 previous_edit->length;
301 if(current->startproject > 0)
303 Edit *new_edit = create_edit();
304 insert_before(current, new_edit);
305 new_edit->length = current->startproject;
315 // delete 0 length edits
317 current && !result; )
319 if(current->length == 0)
321 Edit* next = current->next;
327 current = current->next;
330 // merge same files or transitions
332 current && current->next && !result; )
335 Edit *next_edit = current->next;
336 if(current->asset == next_edit->asset &&
338 (current->startsource + current->length == next_edit->startsource &&
339 current->channel == next_edit->channel)
343 // source positions are consecutive
344 current->length += next_edit->length;
349 current = (Plugin*)current->next;
352 // delete last edit of 0 length or silence
385 // ===================================== file operations
387 int Edits::load(FileXML *file, int track_offset)
390 int64_t startproject = 0;
393 result = file->read_tag();
395 //printf("Edits::load 1 %s\n", file->tag.get_title());
398 if(!strcmp(file->tag.get_title(), "EDIT"))
400 load_edit(file, startproject, track_offset);
403 if(!strcmp(file->tag.get_title(), "/EDITS"))
414 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
418 //printf("Edits::load_edit 1 %d\n", total());
419 current = append_new_edit();
420 //printf("Edits::load_edit 2 %d\n", total());
422 current->load_properties(file, startproject);
424 startproject += current->length;
427 //printf("Edits::load_edit 1\n");
430 //printf("Edits::load_edit 2\n");
431 result = file->read_tag();
432 //printf("Edits::load_edit 3 %s\n", file->tag.get_title());
436 if(file->tag.title_is("FILE"))
439 sprintf(filename, SILENCE);
440 file->tag.get_property("SRC", filename);
442 //printf("Edits::load_edit 4 %s\n", filename);
443 if(strcmp(filename, SILENCE))
445 char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
447 fs.set_current_dir("");
448 fs.extract_dir(directory, filename);
449 if(!strlen(directory))
451 fs.extract_dir(edl_directory, file->filename);
452 fs.join_names(directory, edl_directory, filename);
453 strcpy(filename, directory);
455 current->asset = edl->assets->get_asset(filename);
459 current->asset = edl->assets->get_asset(SILENCE);
461 //printf("Edits::load_edit 5\n");
464 if(file->tag.title_is("TRANSITION"))
466 current->transition = new Transition(edl,
469 track->to_units(edl->session->default_transition_length, 1));
470 current->transition->load_xml(file);
473 if(file->tag.title_is(SILENCE))
475 //printf("Edits::load_edit 6\n");
476 current->asset = edl->assets->get_asset(SILENCE);
477 //printf("Edits::load_edit 7\n");
480 if(file->tag.title_is("/EDIT"))
485 //printf("Edits::load_edit 8\n");
488 //printf("Edits::load_edit 5\n");
489 // in case of incomplete edit tag
490 if(!current->asset) current->asset = edl->assets->get_asset(SILENCE);
494 // ============================================= accounting
496 int64_t Edits::length()
499 return last->startproject + last->length;
504 // int64_t Edits::total_length()
506 // int64_t total = 0;
508 // for(current = first; current; current = NEXT)
510 // total += current->length;
515 Edit* Edits::editof(int64_t position, int direction)
519 if(direction == PLAY_FORWARD)
521 for(current = last; current; current = PREVIOUS)
523 if(current->startproject <= position && current->startproject + current->length > position)
528 if(direction == PLAY_REVERSE)
530 for(current = first; current; current = NEXT)
532 if(current->startproject < position && current->startproject + current->length >= position)
537 return 0; // return 0 on failure
540 Edit* Edits::get_playable_edit(int64_t position)
544 // Get the current edit
545 for(current = first; current; current = NEXT)
547 if(current->startproject <= position &&
548 current->startproject + current->length > position)
552 // Get the edit's asset
559 return current; // return 0 on failure
562 // ================================================ editing
566 int Edits::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
570 file->tag.set_title("EDITS");
572 file->append_newline();
574 for(current_edit = first; current_edit; current_edit = current_edit->next)
576 current_edit->copy(start, end, file, output_path);
579 file->tag.set_title("/EDITS");
581 file->append_newline();
586 void Edits::clear(int64_t start, int64_t end)
588 Edit* edit1 = editof(start, PLAY_FORWARD);
589 Edit* edit2 = editof(end, PLAY_FORWARD);
592 if(end == start) return; // nothing selected
593 if(!edit1 && !edit2) return; // nothing selected
597 { // edit2 beyond end of track
599 end = this->length();
604 // in different edits
606 //printf("Edits::clear 3.5 %d %d %d %d\n", edit1->startproject, edit1->length, edit2->startproject, edit2->length);
607 edit1->length = start - edit1->startproject;
608 edit2->length -= end - edit2->startproject;
609 edit2->startsource += end - edit2->startproject;
610 edit2->startproject += end - edit2->startproject;
613 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
615 Edit* next = current_edit->next;
616 remove(current_edit);
620 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
622 current_edit->startproject -= end - start;
627 // in same edit. paste_edit depends on this
629 current_edit = split_edit(start);
631 current_edit->length -= end - start;
632 current_edit->startsource += end - start;
635 for(current_edit = current_edit->next;
637 current_edit = current_edit->next)
639 current_edit->startproject -= end - start;
646 // Used by edit handle and plugin handle movement but plugin handle movement
647 // can only effect other plugins.
648 void Edits::clear_recursive(int64_t start,
654 //printf("Edits::clear_recursive 1\n");
664 int Edits::clear_handle(double start,
672 for(current_edit = first;
673 current_edit && current_edit->next;
674 current_edit = current_edit->next)
679 if(current_edit->asset &&
680 current_edit->next->asset)
683 if(current_edit->asset->equivalent(*current_edit->next->asset,
688 // Got two consecutive edits in same source
689 if(edl->equivalent(track->from_units(current_edit->next->startproject),
693 int length = -current_edit->length;
694 current_edit->length = current_edit->next->startsource - current_edit->startsource;
695 length += current_edit->length;
697 // Lengthen automation
698 track->automation->paste_silence(current_edit->next->startproject,
699 current_edit->next->startproject + length);
703 track->shift_effects(current_edit->next->startproject,
707 for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
709 current_edit->startproject += length;
712 distance = track->from_units(length);
723 int Edits::modify_handles(double oldposition,
734 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
738 for(current_edit = first; current_edit && !result;)
740 //printf("Edits::modify_handles 2 %f %f\n",
741 //track->from_units(current_edit->startproject),
743 if(edl->equivalent(track->from_units(current_edit->startproject),
746 // edit matches selection
747 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
748 oldposition = track->from_units(current_edit->startproject);
751 if(newposition >= oldposition)
753 //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition);
754 // shift start of edit in
755 current_edit->shift_start_in(edit_mode,
756 track->to_units(newposition, 0),
757 track->to_units(oldposition, 0),
764 //printf("Edits::modify_handle 2 %s\n", track->title);
765 // move start of edit out
766 current_edit->shift_start_out(edit_mode,
767 track->to_units(newposition, 0),
768 track->to_units(oldposition, 0),
775 if(!result) current_edit = current_edit->next;
780 // right handle selected
781 for(current_edit = first; current_edit && !result;)
783 //printf("Edits::modify_handle 1 %s\n", track->title);
784 if(edl->equivalent(track->from_units(current_edit->startproject) +
785 track->from_units(current_edit->length), oldposition))
787 //printf("Edits::modify_handle 2\n");
788 oldposition = track->from_units(current_edit->startproject) +
789 track->from_units(current_edit->length);
792 //printf("Edits::modify_handle 3\n");
793 if(newposition <= oldposition)
794 { // shift end of edit in
795 //printf("Edits::modify_handle 4\n");
796 current_edit->shift_end_in(edit_mode,
797 track->to_units(newposition, 0),
798 track->to_units(oldposition, 0),
802 //printf("Edits::modify_handle 5\n");
805 { // move end of edit out
806 //printf("Edits::modify_handle 6\n");
807 current_edit->shift_end_out(edit_mode,
808 track->to_units(newposition, 0),
809 track->to_units(oldposition, 0),
813 //printf("Edits::modify_handle 7\n");
817 if(!result) current_edit = current_edit->next;
818 //printf("Edits::modify_handle 8\n");
827 // Used by other editing commands so don't optimize
828 Edit* Edits::paste_silence(int64_t start, int64_t end)
830 Edit *new_edit = insert_new_edit(start);
831 new_edit->length = end - start;
832 for(Edit *current = new_edit->next; current; current = NEXT)
834 current->startproject += end - start;
839 Edit* Edits::shift(int64_t position, int64_t difference)
841 Edit *new_edit = split_edit(position);
843 for(Edit *current = first;
847 if(current->startproject >= position)
849 current->shift(difference);
856 void Edits::shift_keyframes_recursive(int64_t position, int64_t length)
858 track->shift_keyframes(position, length, 0);
861 void Edits::shift_effects_recursive(int64_t position, int64_t length)
863 track->shift_effects(position, length, 0);