4 #include "automation.h"
10 #include "edlsession.h"
13 #include "filesystem.h"
14 #include "localsession.h"
16 #include "strategies.inc"
18 #include "transition.h"
19 #include "transportque.inc"
23 Edits::Edits(EDL *edl, Track *track, Edit *default_edit)
29 List<Edit>::List<Edit>();
30 default_edit->edl = edl;
31 default_edit->track = track;
32 default_edit->startproject = 0;
33 default_edit->length = LAST_VIRTUAL_LENGTH;
34 insert_after(0, default_edit);
43 void Edits::equivalent_output(Edits *edits, int64_t *result)
45 // For the case of plugin sets, a new plugin set may be created with
46 // plugins only starting after 0. We only want to restart brender at
47 // the first plugin in this case.
48 for(Edit *current = first, *that_current = edits->first;
49 current || that_current;
51 that_current = that_current->next)
53 //printf("Edits::equivalent_output 1 %d\n", *result);
54 if(!current && that_current)
56 int64_t position1 = length();
57 int64_t position2 = that_current->startproject;
58 if(*result < 0 || *result > MIN(position1, position2))
59 *result = MIN(position1, position2);
63 if(current && !that_current)
65 int64_t position1 = edits->length();
66 int64_t position2 = current->startproject;
67 if(*result < 0 || *result > MIN(position1, position2))
68 *result = MIN(position1, position2);
73 //printf("Edits::equivalent_output 2 %d\n", *result);
74 current->equivalent_output(that_current, result);
75 //printf("Edits::equivalent_output 3 %d\n", *result);
80 void Edits::copy_from(Edits *edits)
82 while(last) delete last;
83 for(Edit *current = edits->first; current; current = NEXT)
85 Edit *new_edit = append(create_edit());
86 new_edit->copy_from(current);
88 loaded_length = edits->loaded_length;
92 Edits& Edits::operator=(Edits& edits)
94 printf("Edits::operator= 1\n");
100 void Edits::insert_asset(Asset *asset,
105 Edit *new_edit = insert_new_edit(position);
107 new_edit->asset = asset;
108 new_edit->startsource = 0;
109 new_edit->startproject = position;
110 new_edit->length = length;
112 if(asset->audio_data)
113 new_edit->channel = track_number % asset->channels;
115 if(asset->video_data)
116 new_edit->channel = track_number % asset->layers;
118 //printf("Edits::insert_asset %d %d\n", new_edit->channel, new_edit->length);
119 for(Edit *current = new_edit->next; current; current = NEXT)
121 current->startproject += length;
125 void Edits::insert_edits(Edits *source_edits, int64_t position)
127 int64_t clipboard_length =
128 track->to_units(source_edits->edl->local_session->clipboard_length, 1);
129 int64_t clipboard_end = position + clipboard_length;
131 int64_t total_length = 0;
132 for(Edit *source_edit = source_edits->first;
134 source_edit = source_edit->next)
137 Asset *dest_asset = edl->assets->update(source_edit->asset);
138 // Open destination area
139 Edit *dest_edit = insert_new_edit(position + source_edit->startproject);
141 dest_edit->copy_from(source_edit);
142 dest_edit->asset = dest_asset;
143 dest_edit->startproject = position + source_edit->startproject;
147 // Shift keyframes in source edit to their position in the
148 // destination edit for plugin case
149 dest_edit->shift_keyframes(position);
152 total_length += dest_edit->length;
153 if (source_edits->loaded_length && total_length > source_edits->loaded_length)
155 dest_edit->length -= (total_length - source_edits->loaded_length);
158 // Shift following edits and keyframes in following edits by length
159 // in current source edit.
160 for(Edit *future_edit = dest_edit->next;
162 future_edit = future_edit->next)
164 future_edit->startproject += dest_edit->length;
165 future_edit->shift_keyframes(dest_edit->length);
168 // Fill clipboard length with silence
169 if(!source_edit->next &&
170 dest_edit->startproject + dest_edit->length < clipboard_end)
172 paste_silence(dest_edit->startproject + dest_edit->length,
180 // Can't paste silence in here because it's used by paste_silence.
181 Edit* Edits::insert_new_edit(int64_t position)
184 //printf("Edits::insert_new_edit 1\n");
186 current = split_edit(position);
188 //printf("Edits::insert_new_edit 1\n");
189 if (current->length == 0) // when creating a split we got 0-length edit, just use it!
191 else // we need to insert
194 new_edit = create_edit();
195 insert_after(current, new_edit);
197 //printf("Edits::insert_new_edit 1\n");
198 new_edit->startproject = position;
199 //printf("Edits::insert_new_edit 2\n");
204 Edit* Edits::split_edit(int64_t position)
206 // Get edit containing position
207 Edit *edit = editof(position, PLAY_FORWARD, 0);
208 // No edit found, make one - except when we are at zero position!
209 if(!edit && position != 0)
210 if (length() == position)
212 edit = last; // we do not need any edit to extend past the last one
214 if (!last || length() < position)
217 // Even when track is completely empty or split is beyond last edit, return correct edit
218 Edit *empty = create_edit();
220 empty->startproject = length(); // end of last edit
222 empty->startproject = 0; // empty track
223 empty->length = position - empty->startproject;
224 insert_after(last, empty);
227 { // now we are now surely in situation where we have a) broken edit list or b) negative position... report error!
229 printf("Trying to insert edit at position, but failed: %lli\n", position);
230 printf("Dump is here:\n");
234 // Split would have created a 0 length
235 // if(edit->startproject == position) return edit;
236 // Create anyway so the return value comes before position
238 Edit *new_edit = create_edit();
239 insert_after(edit, new_edit);
240 if (edit) // if we have actually split the edit, do the funky stuff!
242 new_edit->copy_from(edit);
243 new_edit->length = new_edit->startproject + new_edit->length - position;
244 edit->length = position - edit->startproject;
245 new_edit->startsource += edit->length;
248 // Decide what to do with the transition
249 if(edit->length && edit->transition)
251 delete new_edit->transition;
252 new_edit->transition = 0;
255 if(edit->transition && edit->transition->length > edit->length)
256 edit->transition->length = edit->length;
257 if(new_edit->transition && new_edit->transition->length > new_edit->length)
258 new_edit->transition->length = new_edit->length;
260 new_edit->length = 0;
261 new_edit->startproject = position;
265 int Edits::save(FileXML *xml, char *output_path)
267 copy(0, length(), xml, output_path);
271 void Edits::resample(double old_rate, double new_rate)
273 for(Edit *current = first; current; current = NEXT)
275 current->startproject = Units::to_int64((double)current->startproject /
278 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
279 current->startsource = Units::to_int64((double)current->startsource /
282 if(!NEXT) current->length = Units::to_int64((double)current->length /
285 if(current->transition)
287 current->transition->length = Units::to_int64(
288 (double)current->transition->length /
292 current->resample(old_rate, new_rate);
309 int Edits::optimize()
315 // Sort edits by starting point
320 for(current = first; current; current = NEXT)
322 Edit *next_edit = NEXT;
324 if(next_edit && next_edit->startproject < current->startproject)
326 swap(next_edit, current);
332 // Insert silence between edits which aren't consecutive
333 for(current = last; current; current = current->previous)
335 if(current->previous)
337 Edit *previous_edit = current->previous;
338 if(current->startproject -
339 previous_edit->startproject -
340 previous_edit->length > 0)
342 Edit *new_edit = create_edit();
343 insert_before(current, new_edit);
344 new_edit->startproject = previous_edit->startproject + previous_edit->length;
345 new_edit->length = current->startproject -
346 previous_edit->startproject -
347 previous_edit->length;
351 if(current->startproject > 0)
353 Edit *new_edit = create_edit();
354 insert_before(current, new_edit);
355 new_edit->length = current->startproject;
365 // delete 0 length edits
367 current != last && !result; )
369 if(current->length == 0)
371 Edit* next = current->next;
372 // Be smart with transitions!
373 if (next && current->transition && !next->transition)
375 next->transition = current->transition;
376 next->transition->edit = next;
377 current->transition = 0;
384 current = current->next;
387 // merge same files or transitions
389 current && current->next && !result; )
392 Edit *next_edit = current->next;
393 if(current->asset == next_edit->asset &&
395 (current->startsource + current->length == next_edit->startsource &&
396 current->channel == next_edit->channel)
400 // source positions are consecutive
401 current->length += next_edit->length;
406 current = (Plugin*)current->next;
409 // delete last edit of 0 length or silence
411 if (!last || !last->silence())
413 // No last empty edit available... create one
414 Edit *empty_edit = create_edit();
416 empty_edit->startproject = 0;
418 empty_edit->startproject = last->startproject + last->length;
419 empty_edit->length = LAST_VIRTUAL_LENGTH;
420 insert_after(last, empty_edit);
423 last->length = LAST_VIRTUAL_LENGTH;
449 // ===================================== file operations
451 int Edits::load(FileXML *file, int track_offset)
454 int64_t startproject = 0;
458 result = file->read_tag();
460 //printf("Edits::load 1 %s\n", file->tag.get_title());
463 if(!strcmp(file->tag.get_title(), "EDIT"))
465 load_edit(file, startproject, track_offset);
468 if(!strcmp(file->tag.get_title(), "/EDITS"))
476 loaded_length = last->startproject + last->length;
483 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
487 //printf("Edits::load_edit 1 %d\n", total());
488 current = append_new_edit();
489 //printf("Edits::load_edit 2 %d\n", total());
491 current->load_properties(file, startproject);
493 startproject += current->length;
496 //printf("Edits::load_edit 1\n");
499 //printf("Edits::load_edit 2\n");
500 result = file->read_tag();
501 //printf("Edits::load_edit 3 %s\n", file->tag.get_title());
505 if(file->tag.title_is("FILE"))
508 sprintf(filename, SILENCE);
509 file->tag.get_property("SRC", filename);
511 //printf("Edits::load_edit 4 %s\n", filename);
512 if(strcmp(filename, SILENCE))
514 char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
516 fs.set_current_dir("");
517 fs.extract_dir(directory, filename);
518 if(!strlen(directory))
520 fs.extract_dir(edl_directory, file->filename);
521 fs.join_names(directory, edl_directory, filename);
522 strcpy(filename, directory);
524 current->asset = edl->assets->get_asset(filename);
528 current->asset = edl->assets->get_asset(SILENCE);
530 //printf("Edits::load_edit 5\n");
533 if(file->tag.title_is("TRANSITION"))
535 current->transition = new Transition(edl,
538 track->to_units(edl->session->default_transition_length, 1));
539 current->transition->load_xml(file);
542 if(file->tag.title_is(SILENCE))
544 //printf("Edits::load_edit 6\n");
545 current->asset = edl->assets->get_asset(SILENCE);
546 //printf("Edits::load_edit 7\n");
549 if(file->tag.title_is("/EDIT"))
554 //printf("Edits::load_edit 8\n");
557 //printf("Edits::load_edit 5\n");
558 // in case of incomplete edit tag
559 if(!current->asset) current->asset = edl->assets->get_asset(SILENCE);
563 // ============================================= accounting
565 int64_t Edits::length()
568 return last->startproject + last->length;
573 Edit* Edits::editof(int64_t position, int direction, int use_nudge)
576 if(use_nudge && track) position += track->nudge;
578 if(direction == PLAY_FORWARD)
580 for(current = last; current; current = PREVIOUS)
582 if(current->startproject <= position && current->startproject + current->length > position)
587 if(direction == PLAY_REVERSE)
589 for(current = first; current; current = NEXT)
591 if(current->startproject < position && current->startproject + current->length >= position)
596 return 0; // return 0 on failure
599 Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
602 if(track && use_nudge) position += track->nudge;
604 // Get the current edit
605 for(current = first; current; current = NEXT)
607 if(current->startproject <= position &&
608 current->startproject + current->length > position)
612 // Get the edit's asset
619 return current; // return 0 on failure
622 // ================================================ editing
626 int Edits::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
630 file->tag.set_title("EDITS");
632 file->append_newline();
634 for(current_edit = first; current_edit; current_edit = current_edit->next)
636 current_edit->copy(start, end, file, output_path);
639 file->tag.set_title("/EDITS");
641 file->append_newline();
646 void Edits::clear(int64_t start, int64_t end)
648 Edit* edit1 = editof(start, PLAY_FORWARD, 0);
649 Edit* edit2 = editof(end, PLAY_FORWARD, 0);
652 if(end == start) return; // nothing selected
653 if(!edit1 && !edit2) return; // nothing selected
657 { // edit2 beyond end of track
659 end = this->length();
664 // in different edits
666 //printf("Edits::clear 3.5 %d %d %d %d\n", edit1->startproject, edit1->length, edit2->startproject, edit2->length);
667 edit1->length = start - edit1->startproject;
668 edit2->length -= end - edit2->startproject;
669 edit2->startsource += end - edit2->startproject;
670 edit2->startproject += end - edit2->startproject;
673 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
675 Edit* next = current_edit->next;
676 remove(current_edit);
680 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
682 current_edit->startproject -= end - start;
687 // in same edit. paste_edit depends on this
689 current_edit = split_edit(start);
691 current_edit->length -= end - start;
692 current_edit->startsource += end - start;
695 for(current_edit = current_edit->next;
697 current_edit = current_edit->next)
699 current_edit->startproject -= end - start;
706 // Used by edit handle and plugin handle movement but plugin handle movement
707 // can only effect other plugins.
708 void Edits::clear_recursive(int64_t start,
715 //printf("Edits::clear_recursive 1\n");
726 int Edits::clear_handle(double start,
733 distance = 0.0; // if nothing is found, distance is 0!
734 for(current_edit = first;
735 current_edit && current_edit->next;
736 current_edit = current_edit->next)
741 if(current_edit->asset &&
742 current_edit->next->asset)
745 if(current_edit->asset->equivalent(*current_edit->next->asset,
750 // Got two consecutive edits in same source
751 if(edl->equivalent(track->from_units(current_edit->next->startproject),
755 int length = -current_edit->length;
756 current_edit->length = current_edit->next->startsource - current_edit->startsource;
757 length += current_edit->length;
759 // Lengthen automation
760 track->automation->paste_silence(current_edit->next->startproject,
761 current_edit->next->startproject + length);
765 track->shift_effects(current_edit->next->startproject,
769 for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
771 current_edit->startproject += length;
774 distance = track->from_units(length);
785 int Edits::modify_handles(double oldposition,
797 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
801 for(current_edit = first; current_edit && !result;)
803 if(edl->equivalent(track->from_units(current_edit->startproject),
806 // edit matches selection
807 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
808 oldposition = track->from_units(current_edit->startproject);
811 if(newposition >= oldposition)
813 //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition);
814 // shift start of edit in
815 current_edit->shift_start_in(edit_mode,
816 track->to_units(newposition, 0),
817 track->to_units(oldposition, 0),
825 //printf("Edits::modify_handle 2 %s\n", track->title);
826 // move start of edit out
827 current_edit->shift_start_out(edit_mode,
828 track->to_units(newposition, 0),
829 track->to_units(oldposition, 0),
837 if(!result) current_edit = current_edit->next;
842 // right handle selected
843 for(current_edit = first; current_edit && !result;)
845 if(edl->equivalent(track->from_units(current_edit->startproject) +
846 track->from_units(current_edit->length), oldposition))
848 oldposition = track->from_units(current_edit->startproject) +
849 track->from_units(current_edit->length);
852 //printf("Edits::modify_handle 3\n");
853 if(newposition <= oldposition)
855 // shift end of edit in
856 //printf("Edits::modify_handle 4\n");
857 current_edit->shift_end_in(edit_mode,
858 track->to_units(newposition, 0),
859 track->to_units(oldposition, 0),
864 //printf("Edits::modify_handle 5\n");
868 // move end of edit out
869 //printf("Edits::modify_handle 6\n");
870 current_edit->shift_end_out(edit_mode,
871 track->to_units(newposition, 0),
872 track->to_units(oldposition, 0),
877 //printf("Edits::modify_handle 7\n");
881 if(!result) current_edit = current_edit->next;
882 //printf("Edits::modify_handle 8\n");
891 // Paste silence should not return anything - since pasting silence to an empty track should produce no edits
892 // If we need rutine to create new edit by pushing others forward, write new rutine and call it properly
893 // This are two distinctive functions
894 // This rutine leaves edits in optimized state!
895 void Edits::paste_silence(int64_t start, int64_t end)
897 // paste silence does not do anything if
898 // a) paste silence is on empty track
899 // b) paste silence is after last edit
900 // in both cases editof returns NULL
901 Edit *new_edit = editof(start, PLAY_FORWARD, 0);
902 if (!new_edit) return;
904 if (!new_edit->asset)
905 { // in this case we extend already existing edit
906 new_edit->length += end - start;
908 { // we are in fact creating a new edit
909 new_edit = insert_new_edit(start);
910 new_edit->length = end - start;
912 for(Edit *current = new_edit->next; current; current = NEXT)
914 current->startproject += end - start;
919 // Used by other editing commands so don't optimize
920 // This is separate from paste_silence, since it has to wrok also on empty tracks/beyond end of track
921 Edit *Edits::create_and_insert_edit(int64_t start, int64_t end)
923 Edit *new_edit = insert_new_edit(start);
924 new_edit->length = end - start;
925 for(Edit *current = new_edit->next; current; current = NEXT)
927 current->startproject += end - start;
932 Edit* Edits::shift(int64_t position, int64_t difference)
934 Edit *new_edit = split_edit(position);
936 for(Edit *current = first;
940 if(current->startproject >= position)
942 current->shift(difference);
949 void Edits::shift_keyframes_recursive(int64_t position, int64_t length)
951 track->shift_keyframes(position, length, 0);
954 void Edits::shift_effects_recursive(int64_t position, int64_t length)
956 track->shift_effects(position, length, 0);