Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / edits.C
blob88b29ea8cb0b36ad2684c453164dd2cb9904af6e
1 #include "aedit.h"
2 #include "asset.h"
3 #include "assets.h"
4 #include "automation.h"
5 #include "cache.h"
6 #include "clip.h"
7 #include "edit.h"
8 #include "edits.h"
9 #include "edl.h"
10 #include "edlsession.h"
11 #include "file.h"
12 #include "filexml.h"
13 #include "filesystem.h"
14 #include "localsession.h"
15 #include "plugin.h"
16 #include "strategies.inc"
17 #include "track.h"
18 #include "transition.h"
19 #include "transportque.inc"
21 #include <string.h>
23 Edits::Edits(EDL *edl, Track *track, Edit *default_edit)
24  : List<Edit>()
26         this->edl = edl;
27         this->track = track;
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);
35         loaded_length = 0;
38 Edits::~Edits()
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; 
50                 current = NEXT,
51                 that_current = that_current->next)
52         {
53 //printf("Edits::equivalent_output 1 %d\n", *result);
54                 if(!current && that_current)
55                 {
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);
60                         break;
61                 }
62                 else
63                 if(current && !that_current)
64                 {
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);
69                         break;
70                 }
71                 else
72                 {
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);
76                 }
77         }
80 void Edits::copy_from(Edits *edits)
82         while(last) delete last;
83         for(Edit *current = edits->first; current; current = NEXT)
84         {
85                 Edit *new_edit = append(create_edit());
86                 new_edit->copy_from(current);
87         }
88         loaded_length = edits->loaded_length;
92 Edits& Edits::operator=(Edits& edits)
94 printf("Edits::operator= 1\n");
95         copy_from(&edits);
96         return *this;
100 void Edits::insert_asset(Asset_GC asset,
101         int64_t length,
102         int64_t position,
103         int track_number)
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;
114         else
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)
120         {
121                 current->startproject += length;
122         }
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;
133                 source_edit;
134                 source_edit = source_edit->next)
135         {
136 // Update Assets
137                 Asset_GC 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)
154                 {
155                         dest_edit->length -= (total_length - source_edits->loaded_length);
156                 }
158 // Shift following edits and keyframes in following edits by length
159 // in current source edit.
160                 for(Edit *future_edit = dest_edit->next;
161                         future_edit;
162                         future_edit = future_edit->next)
163                 {
164                         future_edit->startproject += dest_edit->length;
165                         future_edit->shift_keyframes(dest_edit->length);
166                 }
168 // Fill clipboard length with silence
169                 if(!source_edit->next && 
170                         dest_edit->startproject + dest_edit->length < clipboard_end)
171                 {
172                         paste_silence(dest_edit->startproject + dest_edit->length,
173                                 clipboard_end);
174                 }
175         }
179 // Native units
180 // Can't paste silence in here because it's used by paste_silence.
181 Edit* Edits::insert_new_edit(int64_t position)
183         Edit *current = 0;
184 //printf("Edits::insert_new_edit 1\n");
185         Edit *new_edit;
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!
190                 new_edit = current;
191         else      // we need to insert 
192         {
193                 current = PREVIOUS;
194                 new_edit = create_edit();
195                 insert_after(current, new_edit);
196         }
197 //printf("Edits::insert_new_edit 1\n");
198         new_edit->startproject = position;
199 //printf("Edits::insert_new_edit 2\n");
200         return new_edit;
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)
211                 {
212                         edit = last; // we do not need any edit to extend past the last one
213                 } else
214                 if (!last || length() < position)
215                 {
217                         // Even when track is completely empty or split is beyond last edit, return correct edit
218                         Edit *empty = create_edit();
219                         if (last)
220                                 empty->startproject = length(); // end of last edit
221                         else
222                                 empty->startproject = 0; // empty track
223                         empty->length = position - empty->startproject;
224                         insert_after(last, empty);
225                         edit = empty;
226                 } else
227                 {  // now we are now surely in situation where we have a) broken edit list or b) negative position... report error!
228                         printf("ERROR!\n");       
229                         printf("Trying to insert edit at position, but failed: %lli\n", position);
230                         printf("Dump is here:\n");
231                         track->dump();
232                         return 0;
233                 }       
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!
241         {
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)
250                 {
251                         delete new_edit->transition;
252                         new_edit->transition = 0;
253                 }
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;
259         } else
260                 new_edit->length = 0;
261         new_edit->startproject = position;
262         return new_edit;
265 int Edits::save(FileXML *xml, char *output_path)
267         copy(0, length(), xml, output_path);
268         return 0;
271 void Edits::resample(double old_rate, double new_rate)
273         for(Edit *current = first; current; current = NEXT)
274         {
275                 current->startproject = Units::to_int64((double)current->startproject / 
276                         old_rate * 
277                         new_rate);
278                 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
279                 current->startsource = Units::to_int64((double)current->startsource /
280                         old_rate *
281                         new_rate);
282                 if(!NEXT) current->length = Units::to_int64((double)current->length /
283                         old_rate *
284                         new_rate);
285                 if(current->transition)
286                 {
287                         current->transition->length = Units::to_int64(
288                                 (double)current->transition->length /
289                                 old_rate *
290                                 new_rate);
291                 }
292                 current->resample(old_rate, new_rate);
293         }
309 int Edits::optimize()
311         int result = 1;
312         Edit *current;
314 //return 0;
315 // Sort edits by starting point
316         while(result)
317         {
318                 result = 0;
319                 
320                 for(current = first; current; current = NEXT)
321                 {
322                         Edit *next_edit = NEXT;
323                         
324                         if(next_edit && next_edit->startproject < current->startproject)
325                         {
326                                 swap(next_edit, current);
327                                 result = 1;
328                         }
329                 }
330         }
332 // Insert silence between edits which aren't consecutive
333         for(current = last; current; current = current->previous)
334         {
335                 if(current->previous)
336                 {
337                         Edit *previous_edit = current->previous;
338                         if(current->startproject - 
339                                 previous_edit->startproject -
340                                 previous_edit->length > 0)
341                         {
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;
348                         }
349                 }
350                 else
351                 if(current->startproject > 0)
352                 {
353                         Edit *new_edit = create_edit();
354                         insert_before(current, new_edit);
355                         new_edit->length = current->startproject;
356                 }
357         }
359         result = 1;
360         while(result)
361         {
362                 result = 0;
365 // delete 0 length edits
366                 for(current = first; 
367                         current != last && !result; )
368                 {
369                         if(current->length == 0)
370                         {
371                                 Edit* next = current->next;
372                                 // Be smart with transitions!
373                                 if (next && current->transition && !next->transition)
374                                 {
375                                         next->transition = current->transition;
376                                         next->transition->edit = next;
377                                         current->transition = 0;
378                                 }
379                                 delete current;
380                                 result = 1;
381                                 current = next;
382                         }
383                         else
384                                 current = current->next;
385                 }
387 // merge same files or transitions
388                 for(current = first; 
389                         current && current->next && !result; )
390                 {
391 // assets identical
392                         Edit *next_edit = current->next;
393                 if(current->asset == next_edit->asset && 
394                         (!current->asset ||
395                                         (current->startsource + current->length == next_edit->startsource &&
396                                 current->channel == next_edit->channel)
397                                 )
398                         )
399                 {       
400 // source positions are consecutive
401                         current->length += next_edit->length;
402                         remove(next_edit);
403                         result = 1;
404                 }
406                 current = (Plugin*)current->next;
407                 }
409 // delete last edit of 0 length or silence
410         }
411         if (!last || !last->silence())
412         {
413 // No last empty edit available... create one
414                 Edit *empty_edit = create_edit();
415                 if (!last) 
416                         empty_edit->startproject = 0;
417                 else
418                         empty_edit->startproject = last->startproject + last->length;
419                 empty_edit->length = LAST_VIRTUAL_LENGTH;
420                 insert_after(last, empty_edit);
421         } else
422         {
423                 last->length = LAST_VIRTUAL_LENGTH;
424         }
426 //track->dump();
427         return 0;
449 // ===================================== file operations
451 int Edits::load(FileXML *file, int track_offset)
453         int result = 0;
454         int64_t startproject = 0;
455         while (last) 
456                 delete last;
457         do{
458                 result = file->read_tag();
460 //printf("Edits::load 1 %s\n", file->tag.get_title());
461                 if(!result)
462                 {
463                         if(!strcmp(file->tag.get_title(), "EDIT"))
464                         {
465                                 load_edit(file, startproject, track_offset);
466                         }
467                         else
468                         if(!strcmp(file->tag.get_title(), "/EDITS"))
469                         {
470                                 result = 1;
471                         }
472                 }
473         }while(!result);
475         if (last)
476                 loaded_length = last->startproject + last->length;
477         else 
478                 loaded_length = 0;
479 //track->dump();
480         optimize();
483 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
485         Edit* current;
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;
495         int result = 0;
496 //printf("Edits::load_edit 1\n");
498         do{
499 //printf("Edits::load_edit 2\n");
500                 result = file->read_tag();
501 //printf("Edits::load_edit 3 %s\n", file->tag.get_title());
503                 if(!result)
504                 {
505                         if(file->tag.title_is("FILE"))
506                         {
507                                 char filename[1024];
508                                 sprintf(filename, SILENCE);
509                                 file->tag.get_property("SRC", filename);
510 // Extend path
511 //printf("Edits::load_edit 4 %s\n", filename);
512                                 if(strcmp(filename, SILENCE))
513                                 {
514                                         char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
515                                         FileSystem fs;
516                                         fs.set_current_dir("");
517                                         fs.extract_dir(directory, filename);
518                                         if(!strlen(directory))
519                                         {
520                                                 fs.extract_dir(edl_directory, file->filename);
521                                                 fs.join_names(directory, edl_directory, filename);
522                                                 strcpy(filename, directory);
523                                         }
524                                         current->asset = edl->assets->get_asset(filename);
525                                 }
526                                 else
527                                 {
528                                         current->asset = edl->assets->get_asset(SILENCE);
529                                 }
530 //printf("Edits::load_edit 5\n");
531                         }
532                         else
533                         if(file->tag.title_is("TRANSITION"))
534                         {
535                                 current->transition = new Transition(edl,
536                                         current, 
537                                         "",
538                                         track->to_units(edl->session->default_transition_length, 1));
539                                 current->transition->load_xml(file);
540                         }
541                         else
542                         if(file->tag.title_is(SILENCE))
543                         {
544 //printf("Edits::load_edit 6\n");
545                                 current->asset = edl->assets->get_asset(SILENCE);
546 //printf("Edits::load_edit 7\n");
547                         }
548                         else
549                         if(file->tag.title_is("/EDIT"))
550                         {
551                                 result = 1;
552                         }
553                 }
554 //printf("Edits::load_edit 8\n");
555         }while(!result);
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);
560         return 0;
563 // ============================================= accounting
565 int64_t Edits::length()
567         if(last) 
568                 return last->startproject + last->length;
569         else 
570                 return 0;
573 Edit* Edits::editof(int64_t position, int direction, int use_nudge)
575         Edit *current = 0;
576         if(use_nudge && track) position += track->nudge;
578         if(direction == PLAY_FORWARD)
579         {
580                 for(current = last; current; current = PREVIOUS)
581                 {
582                         if(current->startproject <= position && current->startproject + current->length > position)
583                                 return current;
584                 }
585         }
586         else
587         if(direction == PLAY_REVERSE)
588         {
589                 for(current = first; current; current = NEXT)
590                 {
591                         if(current->startproject < position && current->startproject + current->length >= position)
592                                 return current;
593                 }
594         }
596         return 0;     // return 0 on failure
599 Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
601         Edit *current;
602         if(track && use_nudge) position += track->nudge;
604 // Get the current edit
605         for(current = first; current; current = NEXT)
606         {
607                 if(current->startproject <= position && 
608                         current->startproject + current->length > position)
609                         break;
610         }
612 // Get the edit's asset
613         if(current)
614         {
615                 if(!current->asset)
616                         current = 0;
617         }
619         return current;     // return 0 on failure
622 // ================================================ editing
626 int Edits::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
628         Edit *current_edit;
630         file->tag.set_title("EDITS");
631         file->append_tag();
632         file->append_newline();
634         for(current_edit = first; current_edit; current_edit = current_edit->next)
635         {
636                 current_edit->copy(start, end, file, output_path);
637         }
639         file->tag.set_title("/EDITS");
640         file->append_tag();
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);
650         Edit* current_edit;
652         if(end == start) return;        // nothing selected
653         if(!edit1 && !edit2) return;       // nothing selected
656         if(!edit2)
657         {                // edit2 beyond end of track
658                 edit2 = last;
659                 end = this->length();
660         }
662         if(edit1 != edit2)
663         {
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;
672 // delete
673                 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
674                 {
675                         Edit* next = current_edit->next;
676                         remove(current_edit);
677                         current_edit = next;
678                 }
679 // shift
680                 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
681                 {
682                         current_edit->startproject -= end - start;
683                 }
684         }
685         else
686         {
687 // in same edit. paste_edit depends on this
688 // create a new edit
689                 current_edit = split_edit(start);
691                 current_edit->length -= end - start;
692                 current_edit->startsource += end - start;
694 // shift
695                 for(current_edit = current_edit->next; 
696                         current_edit; 
697                         current_edit = current_edit->next)
698                 {            
699                         current_edit->startproject -= end - start;
700                 }
701         }
703         optimize();
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, 
709         int64_t end, 
710         int edit_edits,
711         int edit_labels, 
712         int edit_plugins,
713         Edits *trim_edits)
715 //printf("Edits::clear_recursive 1\n");
716         track->clear(start, 
717                 end, 
718                 edit_edits,
719                 edit_labels,
720                 edit_plugins,
721                 0,
722                 trim_edits);
726 int Edits::clear_handle(double start, 
727         double end, 
728         int edit_plugins, 
729         double &distance)
731         Edit *current_edit;
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)
737         {
741                 if(current_edit->asset && 
742                         current_edit->next->asset)
743                 {
745                         if(current_edit->asset->equivalent(*current_edit->next->asset,
746                                 0,
747                                 0))
748                         {
750 // Got two consecutive edits in same source
751                                 if(edl->equivalent(track->from_units(current_edit->next->startproject), 
752                                         start))
753                                 {
754 // handle selected
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);
763 // Lengthen effects
764                                         if(edit_plugins)
765                                                 track->shift_effects(current_edit->next->startproject, 
766                                                         length,
767                                                         0);
769                                         for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
770                                         {
771                                                 current_edit->startproject += length;
772                                         }
774                                         distance = track->from_units(length);
775                                         optimize();
776                                         break;
777                                 }
778                         }
779                 }
780         }
782         return 0;
785 int Edits::modify_handles(double oldposition, 
786         double newposition, 
787         int currentend,
788         int edit_mode, 
789         int edit_edits,
790         int edit_labels,
791         int edit_plugins,
792         Edits *trim_edits)
794         int result = 0;
795         Edit *current_edit;
797 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
798         if(currentend == 0)
799         {
800 // left handle
801                 for(current_edit = first; current_edit && !result;)
802                 {
803                         if(edl->equivalent(track->from_units(current_edit->startproject), 
804                                 oldposition))
805                         {
806 // edit matches selection
807 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
808                                 oldposition = track->from_units(current_edit->startproject);
809                                 result = 1;
811                                 if(newposition >= oldposition)
812                                 {
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),
818                                                 edit_edits,
819                                                 edit_labels,
820                                                 edit_plugins,
821                                                 trim_edits);
822                                 }
823                                 else
824                                 {
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),
830                                                 edit_edits,
831                                                 edit_labels,
832                                                 edit_plugins,
833                                                 trim_edits);
834                                 }
835                         }
837                         if(!result) current_edit = current_edit->next;
838                 }
839         }
840         else
841         {
842 // right handle selected
843                 for(current_edit = first; current_edit && !result;)
844                 {
845                         if(edl->equivalent(track->from_units(current_edit->startproject) + 
846                                 track->from_units(current_edit->length), oldposition))
847                         {
848                 oldposition = track->from_units(current_edit->startproject) + 
849                                         track->from_units(current_edit->length);
850                                 result = 1;
852 //printf("Edits::modify_handle 3\n");
853                                 if(newposition <= oldposition)
854                                 {     
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),
860                                                 edit_edits,
861                                                 edit_labels,
862                                                 edit_plugins,
863                                                 trim_edits);
864 //printf("Edits::modify_handle 5\n");
865                                 }
866                                 else
867                                 {     
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),
873                                                 edit_edits,
874                                                 edit_labels,
875                                                 edit_plugins,
876                                                 trim_edits);
877 //printf("Edits::modify_handle 7\n");
878                                 }
879                         }
881                         if(!result) current_edit = current_edit->next;
882 //printf("Edits::modify_handle 8\n");
883                 }
884         }
886         optimize();
887         return 0;
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;
907         } else
908         { // we are in fact creating a new edit
909                 new_edit = insert_new_edit(start);
910                 new_edit->length = end - start;
911         }
912         for(Edit *current = new_edit->next; current; current = NEXT)
913         {
914                 current->startproject += end - start;
915         }
916         return;
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)
926         {
927                 current->startproject += end - start;
928         }
929         return new_edit;
931                                      
932 Edit* Edits::shift(int64_t position, int64_t difference)
934         Edit *new_edit = split_edit(position);
936         for(Edit *current = first; 
937                 current; 
938                 current = NEXT)
939         {
940                 if(current->startproject >= position)
941                 {
942                         current->shift(difference);
943                 }
944         }
945         return new_edit;
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);
960 //      Local Variables:
961 //      mode: C++
962 //      c-file-style: "linux"
963 //      End: