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)
35 void Edits::equivalent_output(Edits *edits, int64_t *result)
37 // For the case of plugin sets, a new plugin set may be created with
38 // plugins only starting after 0. We only want to restart brender at
39 // the first plugin in this case.
40 for(Edit *current = first, *that_current = edits->first;
41 current || that_current;
43 that_current = that_current->next)
45 //printf("Edits::equivalent_output 1 %d\n", *result);
46 if(!current && that_current)
48 int64_t position1 = (last ? last->startproject + last->length : 0);
49 int64_t position2 = that_current->startproject;
50 if(*result < 0 || *result > MIN(position1, position2))
51 *result = MIN(position1, position2);
55 if(current && !that_current)
57 int64_t position1 = (edits->last ? edits->last->startproject + edits->last->length : 0);
58 int64_t position2 = current->startproject;
59 if(*result < 0 || *result > MIN(position1, position2))
60 *result = MIN(position1, position2);
65 //printf("Edits::equivalent_output 2 %d\n", *result);
66 current->equivalent_output(that_current, result);
67 //printf("Edits::equivalent_output 3 %d\n", *result);
72 void Edits::copy_from(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);
83 Edits& Edits::operator=(Edits& edits)
85 printf("Edits::operator= 1\n");
91 void Edits::insert_asset(Asset *asset,
96 Edit *new_edit = insert_new_edit(position);
98 new_edit->asset = asset;
99 new_edit->startsource = 0;
100 new_edit->startproject = position;
101 new_edit->length = length;
103 if(asset->audio_data)
104 new_edit->channel = track_number % asset->channels;
106 if(asset->video_data)
107 new_edit->channel = track_number % asset->layers;
109 //printf("Edits::insert_asset %d %d\n", new_edit->channel, new_edit->length);
110 for(Edit *current = new_edit->next; current; current = NEXT)
112 current->startproject += length;
116 void Edits::insert_edits(Edits *source_edits, int64_t position)
118 int64_t clipboard_length =
119 track->to_units(source_edits->edl->local_session->clipboard_length, 1);
120 int64_t clipboard_end = position + clipboard_length;
123 // Fill region between end of edit table and beginning of pasted segment
124 // with silence. Can't call from insert_new_edit because it's recursive.
125 if(position > length())
127 paste_silence(length(), position);
131 for(Edit *source_edit = source_edits->first;
133 source_edit = source_edit->next)
136 Asset *dest_asset = edl->assets->update(source_edit->asset);
137 // Open destination area
138 Edit *dest_edit = insert_new_edit(position + source_edit->startproject);
140 dest_edit->copy_from(source_edit);
141 dest_edit->asset = dest_asset;
142 dest_edit->startproject = position + source_edit->startproject;
146 // Shift keyframes in source edit to their position in the
147 // destination edit for plugin case
148 dest_edit->shift_keyframes(position);
152 // Shift following edits and keyframes in following edits by length
153 // in current source edit.
154 for(Edit *future_edit = dest_edit->next;
156 future_edit = future_edit->next)
158 future_edit->startproject += dest_edit->length;
159 future_edit->shift_keyframes(dest_edit->length);
162 // Fill clipboard length with silence
163 if(!source_edit->next &&
164 dest_edit->startproject + dest_edit->length < clipboard_end)
166 paste_silence(dest_edit->startproject + dest_edit->length,
174 // Can't paste silence in here because it's used by paste_silence.
175 Edit* Edits::insert_new_edit(int64_t position)
178 //printf("Edits::insert_new_edit 1\n");
179 current = split_edit(position);
181 // FIXME: This check can go out now... since split_edit always returns an edit!
182 if(current) current = PREVIOUS;
184 //printf("Edits::insert_new_edit 1\n");
185 Edit *new_edit = create_edit();
186 //printf("Edits::insert_new_edit 1\n");
187 insert_after(current, new_edit);
188 new_edit->startproject = position;
189 //printf("Edits::insert_new_edit 2\n");
194 Edit* Edits::split_edit(int64_t position)
196 // Get edit containing position
197 Edit *edit = editof(position, PLAY_FORWARD, 0);
201 if (!last || last->startproject + last->length <= position)
203 // Even when track is completely empty or split is beyond last edit, return correct edit
204 Edit *empty = create_edit();
206 empty->startproject = last->startproject + last->length; // end of last edit
208 empty->startproject = 0; // empty track
209 empty->length = position - empty->startproject;
210 insert_after(last, empty);
213 { // now we are now surely in situation where we have a) broken edit list or b) negative position... report error!
215 printf("Trying to insert edit at position, but failed: %lli\n", position);
216 printf("Dump is here:\n");
220 // Split would have created a 0 length
221 // if(edit->startproject == position) return edit;
222 // Create anyway so the return value comes before position
224 Edit *new_edit = create_edit();
225 insert_after(edit, new_edit);
226 new_edit->copy_from(edit);
227 new_edit->length = new_edit->startproject + new_edit->length - position;
228 edit->length = position - edit->startproject;
229 new_edit->startproject = edit->startproject + edit->length;
230 new_edit->startsource += edit->length;
233 // Decide what to do with the transition
234 if(edit->length && edit->transition)
236 delete new_edit->transition;
237 new_edit->transition = 0;
240 if(edit->transition && edit->transition->length > edit->length)
241 edit->transition->length = edit->length;
242 if(new_edit->transition && new_edit->transition->length > new_edit->length)
243 new_edit->transition->length = new_edit->length;
247 int Edits::save(FileXML *xml, char *output_path)
249 copy(0, length(), xml, output_path);
253 void Edits::resample(double old_rate, double new_rate)
255 for(Edit *current = first; current; current = NEXT)
257 current->startproject = Units::to_int64((double)current->startproject /
260 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
261 current->startsource = Units::to_int64((double)current->startsource /
264 if(!NEXT) current->length = Units::to_int64((double)current->length /
267 if(current->transition)
269 current->transition->length = Units::to_int64(
270 (double)current->transition->length /
274 current->resample(old_rate, new_rate);
291 int Edits::optimize()
297 // Sort edits by starting point
302 for(current = first; current; current = NEXT)
304 Edit *next_edit = NEXT;
306 if(next_edit && next_edit->startproject < current->startproject)
308 swap(next_edit, current);
314 // Insert silence between edits which aren't consecutive
315 for(current = last; current; current = current->previous)
317 if(current->previous)
319 Edit *previous_edit = current->previous;
320 if(current->startproject -
321 previous_edit->startproject -
322 previous_edit->length > 0)
324 Edit *new_edit = create_edit();
325 insert_before(current, new_edit);
326 new_edit->startproject = previous_edit->startproject + previous_edit->length;
327 new_edit->length = current->startproject -
328 previous_edit->startproject -
329 previous_edit->length;
333 if(current->startproject > 0)
335 Edit *new_edit = create_edit();
336 insert_before(current, new_edit);
337 new_edit->length = current->startproject;
347 // delete 0 length edits
349 current && !result; )
351 if(current->length == 0)
353 Edit* next = current->next;
359 current = current->next;
362 // merge same files or transitions
364 current && current->next && !result; )
367 Edit *next_edit = current->next;
368 if(current->asset == next_edit->asset &&
370 (current->startsource + current->length == next_edit->startsource &&
371 current->channel == next_edit->channel)
375 // source positions are consecutive
376 current->length += next_edit->length;
381 current = (Plugin*)current->next;
384 // delete last edit of 0 length or silence
417 // ===================================== file operations
419 int Edits::load(FileXML *file, int track_offset)
422 int64_t startproject = 0;
425 result = file->read_tag();
427 //printf("Edits::load 1 %s\n", file->tag.get_title());
430 if(!strcmp(file->tag.get_title(), "EDIT"))
432 load_edit(file, startproject, track_offset);
435 if(!strcmp(file->tag.get_title(), "/EDITS"))
446 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
450 //printf("Edits::load_edit 1 %d\n", total());
451 current = append_new_edit();
452 //printf("Edits::load_edit 2 %d\n", total());
454 current->load_properties(file, startproject);
456 startproject += current->length;
459 //printf("Edits::load_edit 1\n");
462 //printf("Edits::load_edit 2\n");
463 result = file->read_tag();
464 //printf("Edits::load_edit 3 %s\n", file->tag.get_title());
468 if(file->tag.title_is("FILE"))
471 sprintf(filename, SILENCE);
472 file->tag.get_property("SRC", filename);
474 //printf("Edits::load_edit 4 %s\n", filename);
475 if(strcmp(filename, SILENCE))
477 char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
479 fs.set_current_dir("");
480 fs.extract_dir(directory, filename);
481 if(!strlen(directory))
483 fs.extract_dir(edl_directory, file->filename);
484 fs.join_names(directory, edl_directory, filename);
485 strcpy(filename, directory);
487 current->asset = edl->assets->get_asset(filename);
491 current->asset = edl->assets->get_asset(SILENCE);
493 //printf("Edits::load_edit 5\n");
496 if(file->tag.title_is("TRANSITION"))
498 current->transition = new Transition(edl,
501 track->to_units(edl->session->default_transition_length, 1));
502 current->transition->load_xml(file);
505 if(file->tag.title_is(SILENCE))
507 //printf("Edits::load_edit 6\n");
508 current->asset = edl->assets->get_asset(SILENCE);
509 //printf("Edits::load_edit 7\n");
512 if(file->tag.title_is("/EDIT"))
517 //printf("Edits::load_edit 8\n");
520 //printf("Edits::load_edit 5\n");
521 // in case of incomplete edit tag
522 if(!current->asset) current->asset = edl->assets->get_asset(SILENCE);
526 // ============================================= accounting
528 int64_t Edits::length()
531 return last->startproject + last->length;
536 // int64_t Edits::total_length()
538 // int64_t total = 0;
540 // for(current = first; current; current = NEXT)
542 // total += current->length;
547 Edit* Edits::editof(int64_t position, int direction, int use_nudge)
550 if(use_nudge && track) position += track->nudge;
552 if(direction == PLAY_FORWARD)
554 for(current = last; current; current = PREVIOUS)
556 if(current->startproject <= position && current->startproject + current->length > position)
561 if(direction == PLAY_REVERSE)
563 for(current = first; current; current = NEXT)
565 if(current->startproject < position && current->startproject + current->length >= position)
570 return 0; // return 0 on failure
573 Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
576 if(track && use_nudge) position += track->nudge;
578 // Get the current edit
579 for(current = first; current; current = NEXT)
581 if(current->startproject <= position &&
582 current->startproject + current->length > position)
586 // Get the edit's asset
593 return current; // return 0 on failure
596 // ================================================ editing
600 int Edits::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
604 file->tag.set_title("EDITS");
606 file->append_newline();
608 for(current_edit = first; current_edit; current_edit = current_edit->next)
610 current_edit->copy(start, end, file, output_path);
613 file->tag.set_title("/EDITS");
615 file->append_newline();
620 void Edits::clear(int64_t start, int64_t end)
622 Edit* edit1 = editof(start, PLAY_FORWARD, 0);
623 Edit* edit2 = editof(end, PLAY_FORWARD, 0);
626 if(end == start) return; // nothing selected
627 if(!edit1 && !edit2) return; // nothing selected
631 { // edit2 beyond end of track
633 end = this->length();
638 // in different edits
640 //printf("Edits::clear 3.5 %d %d %d %d\n", edit1->startproject, edit1->length, edit2->startproject, edit2->length);
641 edit1->length = start - edit1->startproject;
642 edit2->length -= end - edit2->startproject;
643 edit2->startsource += end - edit2->startproject;
644 edit2->startproject += end - edit2->startproject;
647 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
649 Edit* next = current_edit->next;
650 remove(current_edit);
654 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
656 current_edit->startproject -= end - start;
661 // in same edit. paste_edit depends on this
663 current_edit = split_edit(start);
665 current_edit->length -= end - start;
666 current_edit->startsource += end - start;
669 for(current_edit = current_edit->next;
671 current_edit = current_edit->next)
673 current_edit->startproject -= end - start;
680 // Used by edit handle and plugin handle movement but plugin handle movement
681 // can only effect other plugins.
682 void Edits::clear_recursive(int64_t start,
689 //printf("Edits::clear_recursive 1\n");
700 int Edits::clear_handle(double start,
707 distance = 0.0; // if nothing is found, distance is 0!
708 for(current_edit = first;
709 current_edit && current_edit->next;
710 current_edit = current_edit->next)
715 if(current_edit->asset &&
716 current_edit->next->asset)
719 if(current_edit->asset->equivalent(*current_edit->next->asset,
724 // Got two consecutive edits in same source
725 if(edl->equivalent(track->from_units(current_edit->next->startproject),
729 int length = -current_edit->length;
730 current_edit->length = current_edit->next->startsource - current_edit->startsource;
731 length += current_edit->length;
733 // Lengthen automation
734 track->automation->paste_silence(current_edit->next->startproject,
735 current_edit->next->startproject + length);
739 track->shift_effects(current_edit->next->startproject,
743 for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
745 current_edit->startproject += length;
748 distance = track->from_units(length);
759 int Edits::modify_handles(double oldposition,
771 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
775 for(current_edit = first; current_edit && !result;)
777 if(edl->equivalent(track->from_units(current_edit->startproject),
780 // edit matches selection
781 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
782 oldposition = track->from_units(current_edit->startproject);
785 if(newposition >= oldposition)
787 //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition);
788 // shift start of edit in
789 current_edit->shift_start_in(edit_mode,
790 track->to_units(newposition, 0),
791 track->to_units(oldposition, 0),
799 //printf("Edits::modify_handle 2 %s\n", track->title);
800 // move start of edit out
801 current_edit->shift_start_out(edit_mode,
802 track->to_units(newposition, 0),
803 track->to_units(oldposition, 0),
811 if(!result) current_edit = current_edit->next;
816 // right handle selected
817 for(current_edit = first; current_edit && !result;)
819 if(edl->equivalent(track->from_units(current_edit->startproject) +
820 track->from_units(current_edit->length), oldposition))
822 oldposition = track->from_units(current_edit->startproject) +
823 track->from_units(current_edit->length);
826 //printf("Edits::modify_handle 3\n");
827 if(newposition <= oldposition)
829 // shift end of edit in
830 //printf("Edits::modify_handle 4\n");
831 current_edit->shift_end_in(edit_mode,
832 track->to_units(newposition, 0),
833 track->to_units(oldposition, 0),
838 //printf("Edits::modify_handle 5\n");
842 // move end of edit out
843 //printf("Edits::modify_handle 6\n");
844 current_edit->shift_end_out(edit_mode,
845 track->to_units(newposition, 0),
846 track->to_units(oldposition, 0),
851 //printf("Edits::modify_handle 7\n");
855 if(!result) current_edit = current_edit->next;
856 //printf("Edits::modify_handle 8\n");
865 // Paste silence should not return anything - since pasting silence to an empty track should produce no edits
866 // If we need rutine to create new edit by pushing others forward, write new rutine and call it properly
867 // This are two distinctive functions
868 // This rutine leaves edits in optimized state!
869 void Edits::paste_silence(int64_t start, int64_t end)
871 // paste silence does not do anything if
872 // a) paste silence is on empty track
873 // b) paste silence is after last edit
874 // in both cases editof returns NULL
875 Edit *new_edit = editof(start, PLAY_FORWARD, 0);
876 if (!new_edit) return;
878 if (!new_edit->asset)
879 { // in this case we extend already existing edit
880 new_edit->length += end - start;
882 { // we are in fact creating a new edit
883 new_edit = insert_new_edit(start);
884 new_edit->length = end - start;
886 for(Edit *current = new_edit->next; current; current = NEXT)
888 current->startproject += end - start;
893 // Used by other editing commands so don't optimize
894 // This is separate from paste_silence, since it has to wrok also on empty tracks/beyond end of track
895 Edit *Edits::create_and_insert_edit(int64_t start, int64_t end)
897 Edit *new_edit = insert_new_edit(start);
898 new_edit->length = end - start;
899 for(Edit *current = new_edit->next; current; current = NEXT)
901 current->startproject += end - start;
906 Edit* Edits::shift(int64_t position, int64_t difference)
908 Edit *new_edit = split_edit(position);
910 for(Edit *current = first;
914 if(current->startproject >= position)
916 current->shift(difference);
923 void Edits::shift_keyframes_recursive(int64_t position, int64_t length)
925 track->shift_keyframes(position, length, 0);
928 void Edits::shift_effects_recursive(int64_t position, int64_t length)
930 track->shift_effects(position, length, 0);