r914: Fix a long outstanding bug regarding dragndroping
[cinelerra_cv/mob.git] / cinelerra / edits.C
blob9618c7edc3088d71aa69a9fb1fbda1b9d54b5022
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->track = track;
31         default_edit->startproject = 0;
32         default_edit->length = LAST_VIRTUAL_LENGTH;
33         insert_after(0, default_edit);
34         loaded_length = 0;
37 Edits::~Edits()
42 void Edits::equivalent_output(Edits *edits, int64_t *result)
44 // For the case of plugin sets, a new plugin set may be created with
45 // plugins only starting after 0.  We only want to restart brender at
46 // the first plugin in this case.
47         for(Edit *current = first, *that_current = edits->first; 
48                 current || that_current; 
49                 current = NEXT,
50                 that_current = that_current->next)
51         {
52 //printf("Edits::equivalent_output 1 %d\n", *result);
53                 if(!current && that_current)
54                 {
55                         int64_t position1 = length();
56                         int64_t position2 = that_current->startproject;
57                         if(*result < 0 || *result > MIN(position1, position2))
58                                 *result = MIN(position1, position2);
59                         break;
60                 }
61                 else
62                 if(current && !that_current)
63                 {
64                         int64_t position1 = edits->length();
65                         int64_t position2 = current->startproject;
66                         if(*result < 0 || *result > MIN(position1, position2))
67                                 *result = MIN(position1, position2);
68                         break;
69                 }
70                 else
71                 {
72 //printf("Edits::equivalent_output 2 %d\n", *result);
73                         current->equivalent_output(that_current, result);
74 //printf("Edits::equivalent_output 3 %d\n", *result);
75                 }
76         }
79 void Edits::copy_from(Edits *edits)
81         while(last) delete last;
82         for(Edit *current = edits->first; current; current = NEXT)
83         {
84                 Edit *new_edit = append(create_edit());
85                 new_edit->copy_from(current);
86         }
87         loaded_length = edits->loaded_length;
91 Edits& Edits::operator=(Edits& edits)
93 printf("Edits::operator= 1\n");
94         copy_from(&edits);
95         return *this;
99 void Edits::insert_asset(Asset *asset,
100         int64_t length,
101         int64_t position,
102         int track_number)
104         Edit *new_edit = insert_new_edit(position);
106         new_edit->asset = asset;
107         new_edit->startsource = 0;
108         new_edit->startproject = position;
109         new_edit->length = length;
111         if(asset->audio_data)
112                 new_edit->channel = track_number % asset->channels;
113         else
114         if(asset->video_data)
115                 new_edit->channel = track_number % asset->layers;
117 //printf("Edits::insert_asset %d %d\n", new_edit->channel, new_edit->length);
118         for(Edit *current = new_edit->next; current; current = NEXT)
119         {
120                 current->startproject += length;
121         }
124 void Edits::insert_edits(Edits *source_edits, int64_t position)
126         int64_t clipboard_length = 
127                 track->to_units(source_edits->edl->local_session->clipboard_length, 1);
128         int64_t clipboard_end = position + clipboard_length;
130         int64_t total_length = 0;
131         for(Edit *source_edit = source_edits->first;
132                 source_edit;
133                 source_edit = source_edit->next)
134         {
135 // Update Assets
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);
151                 total_length += dest_edit->length;
152                 if (source_edits->loaded_length && total_length > source_edits->loaded_length)
153                 {
154                         dest_edit->length -= (total_length - source_edits->loaded_length);
155                 }
157 // Shift following edits and keyframes in following edits by length
158 // in current source edit.
159                 for(Edit *future_edit = dest_edit->next;
160                         future_edit;
161                         future_edit = future_edit->next)
162                 {
163                         future_edit->startproject += dest_edit->length;
164                         future_edit->shift_keyframes(dest_edit->length);
165                 }
167 // Fill clipboard length with silence
168                 if(!source_edit->next && 
169                         dest_edit->startproject + dest_edit->length < clipboard_end)
170                 {
171                         paste_silence(dest_edit->startproject + dest_edit->length,
172                                 clipboard_end);
173                 }
174         }
178 // Native units
179 // Can't paste silence in here because it's used by paste_silence.
180 Edit* Edits::insert_new_edit(int64_t position)
182         Edit *current = 0;
183 //printf("Edits::insert_new_edit 1\n");
184         Edit *new_edit;
185         current = split_edit(position);
187 //printf("Edits::insert_new_edit 1\n");
188         if (current->length == 0) // when creating a split we got 0-length edit, just use it!
189                 new_edit = current;
190         else      // we need to insert 
191         {
192                 current = PREVIOUS;
193                 new_edit = create_edit();
194                 insert_after(current, new_edit);
195         }
196 //printf("Edits::insert_new_edit 1\n");
197         new_edit->startproject = position;
198 //printf("Edits::insert_new_edit 2\n");
199         return new_edit;
203 Edit* Edits::split_edit(int64_t position)
205 // Get edit containing position
206         Edit *edit = editof(position, PLAY_FORWARD, 0);
207 // No edit found, make one - except when we are at zero position!
208         if(!edit && position != 0)
209                 if (length() == position)
210                 {
211                         edit = last; // we do not need any edit to extend past the last one
212                 } else
213                 if (!last || length() < position)
214                 {
216                         // Even when track is completely empty or split is beyond last edit, return correct edit
217                         Edit *empty = create_edit();
218                         if (last)
219                                 empty->startproject = length(); // end of last edit
220                         else
221                                 empty->startproject = 0; // empty track
222                         empty->length = position - empty->startproject;
223                         insert_after(last, empty);
224                         edit = empty;
225                 } else
226                 {  // now we are now surely in situation where we have a) broken edit list or b) negative position... report error!
227                         printf("ERROR!\n");       
228                         printf("Trying to insert edit at position, but failed: %lli\n", position);
229                         printf("Dump is here:\n");
230                         track->dump();
231                         return 0;
232                 }       
233 // Split would have created a 0 length
234 //      if(edit->startproject == position) return edit;
235 // Create anyway so the return value comes before position
237         Edit *new_edit = create_edit();
238         insert_after(edit, new_edit);
239         if (edit)  // if we have actually split the edit, do the funky stuff!
240         {
241                 new_edit->copy_from(edit);
242                 new_edit->length = new_edit->startproject + new_edit->length - position;
243                 edit->length = position - edit->startproject;
244                 new_edit->startsource += edit->length;
247 // Decide what to do with the transition
248                 if(edit->length && edit->transition)
249                 {
250                         delete new_edit->transition;
251                         new_edit->transition = 0;
252                 }
254                 if(edit->transition && edit->transition->length > edit->length) 
255                         edit->transition->length = edit->length;
256                 if(new_edit->transition && new_edit->transition->length > new_edit->length)
257                         new_edit->transition->length = new_edit->length;
258         } else
259                 new_edit->length = 0;
260         new_edit->startproject = position;
261         return new_edit;
264 int Edits::save(FileXML *xml, char *output_path)
266         copy(0, length(), xml, output_path);
267         return 0;
270 void Edits::resample(double old_rate, double new_rate)
272         for(Edit *current = first; current; current = NEXT)
273         {
274                 current->startproject = Units::to_int64((double)current->startproject / 
275                         old_rate * 
276                         new_rate);
277                 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
278                 current->startsource = Units::to_int64((double)current->startsource /
279                         old_rate *
280                         new_rate);
281                 if(!NEXT) current->length = Units::to_int64((double)current->length /
282                         old_rate *
283                         new_rate);
284                 if(current->transition)
285                 {
286                         current->transition->length = Units::to_int64(
287                                 (double)current->transition->length /
288                                 old_rate *
289                                 new_rate);
290                 }
291                 current->resample(old_rate, new_rate);
292         }
308 int Edits::optimize()
310         int result = 1;
311         Edit *current;
313 //return 0;
314 // Sort edits by starting point
315         while(result)
316         {
317                 result = 0;
318                 
319                 for(current = first; current; current = NEXT)
320                 {
321                         Edit *next_edit = NEXT;
322                         
323                         if(next_edit && next_edit->startproject < current->startproject)
324                         {
325                                 swap(next_edit, current);
326                                 result = 1;
327                         }
328                 }
329         }
331 // Insert silence between edits which aren't consecutive
332         for(current = last; current; current = current->previous)
333         {
334                 if(current->previous)
335                 {
336                         Edit *previous_edit = current->previous;
337                         if(current->startproject - 
338                                 previous_edit->startproject -
339                                 previous_edit->length > 0)
340                         {
341                                 Edit *new_edit = create_edit();
342                                 insert_before(current, new_edit);
343                                 new_edit->startproject = previous_edit->startproject + previous_edit->length;
344                                 new_edit->length = current->startproject - 
345                                         previous_edit->startproject -
346                                         previous_edit->length;
347                         }
348                 }
349                 else
350                 if(current->startproject > 0)
351                 {
352                         Edit *new_edit = create_edit();
353                         insert_before(current, new_edit);
354                         new_edit->length = current->startproject;
355                 }
356         }
358         result = 1;
359         while(result)
360         {
361                 result = 0;
364 // delete 0 length edits
365                 for(current = first; 
366                         current != last && !result; )
367                 {
368                         if(current->length == 0)
369                         {
370                                 Edit* next = current->next;
371                                 // Be smart with transitions!
372                                 if (next && current->transition && !next->transition)
373                                 {
374                                         next->transition = current->transition;
375                                         next->transition->edit = next;
376                                         current->transition = 0;
377                                 }
378                                 delete current;
379                                 result = 1;
380                                 current = next;
381                         }
382                         else
383                                 current = current->next;
384                 }
386 // merge same files or transitions
387                 for(current = first; 
388                         current && current->next && !result; )
389                 {
390 // assets identical
391                         Edit *next_edit = current->next;
392                 if(current->asset == next_edit->asset && 
393                         (!current->asset ||
394                                         (current->startsource + current->length == next_edit->startsource &&
395                                 current->channel == next_edit->channel)
396                                 )
397                         )
398                 {       
399 // source positions are consecutive
400                         current->length += next_edit->length;
401                         remove(next_edit);
402                         result = 1;
403                 }
405                 current = (Plugin*)current->next;
406                 }
408 // delete last edit of 0 length or silence
409         }
410         if (!last || !last->silence())
411         {
412 // No last empty edit available... create one
413                 Edit *empty_edit = create_edit();
414                 if (!last) 
415                         empty_edit->startproject = 0;
416                 else
417                         empty_edit->startproject = last->startproject + last->length;
418                 empty_edit->length = LAST_VIRTUAL_LENGTH;
419                 insert_after(last, empty_edit);
420         } else
421         {
422                 last->length = LAST_VIRTUAL_LENGTH;
423         }
425 //track->dump();
426         return 0;
448 // ===================================== file operations
450 int Edits::load(FileXML *file, int track_offset)
452         int result = 0;
453         int64_t startproject = 0;
454         while (last) 
455                 delete last;
456         do{
457                 result = file->read_tag();
459 //printf("Edits::load 1 %s\n", file->tag.get_title());
460                 if(!result)
461                 {
462                         if(!strcmp(file->tag.get_title(), "EDIT"))
463                         {
464                                 load_edit(file, startproject, track_offset);
465                         }
466                         else
467                         if(!strcmp(file->tag.get_title(), "/EDITS"))
468                         {
469                                 result = 1;
470                         }
471                 }
472         }while(!result);
474         if (last)
475                 loaded_length = last->startproject + last->length;
476         else 
477                 loaded_length = 0;
478 //track->dump();
479         optimize();
482 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
484         Edit* current;
486 //printf("Edits::load_edit 1 %d\n", total());
487         current = append_new_edit();
488 //printf("Edits::load_edit 2 %d\n", total());
490         current->load_properties(file, startproject);
492         startproject += current->length;
494         int result = 0;
495 //printf("Edits::load_edit 1\n");
497         do{
498 //printf("Edits::load_edit 2\n");
499                 result = file->read_tag();
500 //printf("Edits::load_edit 3 %s\n", file->tag.get_title());
502                 if(!result)
503                 {
504                         if(file->tag.title_is("FILE"))
505                         {
506                                 char filename[1024];
507                                 sprintf(filename, SILENCE);
508                                 file->tag.get_property("SRC", filename);
509 // Extend path
510 //printf("Edits::load_edit 4 %s\n", filename);
511                                 if(strcmp(filename, SILENCE))
512                                 {
513                                         char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
514                                         FileSystem fs;
515                                         fs.set_current_dir("");
516                                         fs.extract_dir(directory, filename);
517                                         if(!strlen(directory))
518                                         {
519                                                 fs.extract_dir(edl_directory, file->filename);
520                                                 fs.join_names(directory, edl_directory, filename);
521                                                 strcpy(filename, directory);
522                                         }
523                                         current->asset = edl->assets->get_asset(filename);
524                                 }
525                                 else
526                                 {
527                                         current->asset = edl->assets->get_asset(SILENCE);
528                                 }
529 //printf("Edits::load_edit 5\n");
530                         }
531                         else
532                         if(file->tag.title_is("TRANSITION"))
533                         {
534                                 current->transition = new Transition(edl,
535                                         current, 
536                                         "",
537                                         track->to_units(edl->session->default_transition_length, 1));
538                                 current->transition->load_xml(file);
539                         }
540                         else
541                         if(file->tag.title_is(SILENCE))
542                         {
543 //printf("Edits::load_edit 6\n");
544                                 current->asset = edl->assets->get_asset(SILENCE);
545 //printf("Edits::load_edit 7\n");
546                         }
547                         else
548                         if(file->tag.title_is("/EDIT"))
549                         {
550                                 result = 1;
551                         }
552                 }
553 //printf("Edits::load_edit 8\n");
554         }while(!result);
556 //printf("Edits::load_edit 5\n");
557 // in case of incomplete edit tag
558         if(!current->asset) current->asset = edl->assets->get_asset(SILENCE);
559         return 0;
562 // ============================================= accounting
564 int64_t Edits::length()
566         if(last) 
567                 return last->startproject + last->length;
568         else 
569                 return 0;
572 Edit* Edits::editof(int64_t position, int direction, int use_nudge)
574         Edit *current = 0;
575         if(use_nudge && track) position += track->nudge;
577         if(direction == PLAY_FORWARD)
578         {
579                 for(current = last; current; current = PREVIOUS)
580                 {
581                         if(current->startproject <= position && current->startproject + current->length > position)
582                                 return current;
583                 }
584         }
585         else
586         if(direction == PLAY_REVERSE)
587         {
588                 for(current = first; current; current = NEXT)
589                 {
590                         if(current->startproject < position && current->startproject + current->length >= position)
591                                 return current;
592                 }
593         }
595         return 0;     // return 0 on failure
598 Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
600         Edit *current;
601         if(track && use_nudge) position += track->nudge;
603 // Get the current edit
604         for(current = first; current; current = NEXT)
605         {
606                 if(current->startproject <= position && 
607                         current->startproject + current->length > position)
608                         break;
609         }
611 // Get the edit's asset
612         if(current)
613         {
614                 if(!current->asset)
615                         current = 0;
616         }
618         return current;     // return 0 on failure
621 // ================================================ editing
625 int Edits::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
627         Edit *current_edit;
629         file->tag.set_title("EDITS");
630         file->append_tag();
631         file->append_newline();
633         for(current_edit = first; current_edit; current_edit = current_edit->next)
634         {
635                 current_edit->copy(start, end, file, output_path);
636         }
638         file->tag.set_title("/EDITS");
639         file->append_tag();
640         file->append_newline();
645 void Edits::clear(int64_t start, int64_t end)
647         Edit* edit1 = editof(start, PLAY_FORWARD, 0);
648         Edit* edit2 = editof(end, PLAY_FORWARD, 0);
649         Edit* current_edit;
651         if(end == start) return;        // nothing selected
652         if(!edit1 && !edit2) return;       // nothing selected
655         if(!edit2)
656         {                // edit2 beyond end of track
657                 edit2 = last;
658                 end = this->length();
659         }
661         if(edit1 != edit2)
662         {
663 // in different edits
665 //printf("Edits::clear 3.5 %d %d %d %d\n", edit1->startproject, edit1->length, edit2->startproject, edit2->length);
666                 edit1->length = start - edit1->startproject;
667                 edit2->length -= end - edit2->startproject;
668                 edit2->startsource += end - edit2->startproject;
669                 edit2->startproject += end - edit2->startproject;
671 // delete
672                 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
673                 {
674                         Edit* next = current_edit->next;
675                         remove(current_edit);
676                         current_edit = next;
677                 }
678 // shift
679                 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
680                 {
681                         current_edit->startproject -= end - start;
682                 }
683         }
684         else
685         {
686 // in same edit. paste_edit depends on this
687 // create a new edit
688                 current_edit = split_edit(start);
690                 current_edit->length -= end - start;
691                 current_edit->startsource += end - start;
693 // shift
694                 for(current_edit = current_edit->next; 
695                         current_edit; 
696                         current_edit = current_edit->next)
697                 {            
698                         current_edit->startproject -= end - start;
699                 }
700         }
702         optimize();
705 // Used by edit handle and plugin handle movement but plugin handle movement
706 // can only effect other plugins.
707 void Edits::clear_recursive(int64_t start, 
708         int64_t end, 
709         int edit_edits,
710         int edit_labels, 
711         int edit_plugins,
712         Edits *trim_edits)
714 //printf("Edits::clear_recursive 1\n");
715         track->clear(start, 
716                 end, 
717                 edit_edits,
718                 edit_labels,
719                 edit_plugins,
720                 0,
721                 trim_edits);
725 int Edits::clear_handle(double start, 
726         double end, 
727         int edit_plugins, 
728         double &distance)
730         Edit *current_edit;
732         distance = 0.0; // if nothing is found, distance is 0!
733         for(current_edit = first; 
734                 current_edit && current_edit->next; 
735                 current_edit = current_edit->next)
736         {
740                 if(current_edit->asset && 
741                         current_edit->next->asset)
742                 {
744                         if(current_edit->asset->equivalent(*current_edit->next->asset,
745                                 0,
746                                 0))
747                         {
749 // Got two consecutive edits in same source
750                                 if(edl->equivalent(track->from_units(current_edit->next->startproject), 
751                                         start))
752                                 {
753 // handle selected
754                                         int length = -current_edit->length;
755                                         current_edit->length = current_edit->next->startsource - current_edit->startsource;
756                                         length += current_edit->length;
758 // Lengthen automation
759                                         track->automation->paste_silence(current_edit->next->startproject, 
760                                                 current_edit->next->startproject + length);
762 // Lengthen effects
763                                         if(edit_plugins)
764                                                 track->shift_effects(current_edit->next->startproject, 
765                                                         length,
766                                                         0);
768                                         for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
769                                         {
770                                                 current_edit->startproject += length;
771                                         }
773                                         distance = track->from_units(length);
774                                         optimize();
775                                         break;
776                                 }
777                         }
778                 }
779         }
781         return 0;
784 int Edits::modify_handles(double oldposition, 
785         double newposition, 
786         int currentend,
787         int edit_mode, 
788         int edit_edits,
789         int edit_labels,
790         int edit_plugins,
791         Edits *trim_edits)
793         int result = 0;
794         Edit *current_edit;
796 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
797         if(currentend == 0)
798         {
799 // left handle
800                 for(current_edit = first; current_edit && !result;)
801                 {
802                         if(edl->equivalent(track->from_units(current_edit->startproject), 
803                                 oldposition))
804                         {
805 // edit matches selection
806 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
807                                 oldposition = track->from_units(current_edit->startproject);
808                                 result = 1;
810                                 if(newposition >= oldposition)
811                                 {
812 //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition);
813 // shift start of edit in
814                                         current_edit->shift_start_in(edit_mode, 
815                                                 track->to_units(newposition, 0), 
816                                                 track->to_units(oldposition, 0),
817                                                 edit_edits,
818                                                 edit_labels,
819                                                 edit_plugins,
820                                                 trim_edits);
821                                 }
822                                 else
823                                 {
824 //printf("Edits::modify_handle 2 %s\n", track->title);
825 // move start of edit out
826                                         current_edit->shift_start_out(edit_mode, 
827                                                 track->to_units(newposition, 0), 
828                                                 track->to_units(oldposition, 0),
829                                                 edit_edits,
830                                                 edit_labels,
831                                                 edit_plugins,
832                                                 trim_edits);
833                                 }
834                         }
836                         if(!result) current_edit = current_edit->next;
837                 }
838         }
839         else
840         {
841 // right handle selected
842                 for(current_edit = first; current_edit && !result;)
843                 {
844                         if(edl->equivalent(track->from_units(current_edit->startproject) + 
845                                 track->from_units(current_edit->length), oldposition))
846                         {
847                 oldposition = track->from_units(current_edit->startproject) + 
848                                         track->from_units(current_edit->length);
849                                 result = 1;
851 //printf("Edits::modify_handle 3\n");
852                                 if(newposition <= oldposition)
853                                 {     
854 // shift end of edit in
855 //printf("Edits::modify_handle 4\n");
856                                         current_edit->shift_end_in(edit_mode, 
857                                                 track->to_units(newposition, 0), 
858                                                 track->to_units(oldposition, 0),
859                                                 edit_edits,
860                                                 edit_labels,
861                                                 edit_plugins,
862                                                 trim_edits);
863 //printf("Edits::modify_handle 5\n");
864                                 }
865                                 else
866                                 {     
867 // move end of edit out
868 //printf("Edits::modify_handle 6\n");
869                                         current_edit->shift_end_out(edit_mode, 
870                                                 track->to_units(newposition, 0), 
871                                                 track->to_units(oldposition, 0),
872                                                 edit_edits,
873                                                 edit_labels,
874                                                 edit_plugins,
875                                                 trim_edits);
876 //printf("Edits::modify_handle 7\n");
877                                 }
878                         }
880                         if(!result) current_edit = current_edit->next;
881 //printf("Edits::modify_handle 8\n");
882                 }
883         }
885         optimize();
886         return 0;
890 // Paste silence should not return anything - since pasting silence to an empty track should produce no edits
891 // If we need rutine to create new edit by pushing others forward, write new rutine and call it properly
892 // This are two distinctive functions
893 // This rutine leaves edits in optimized state!
894 void Edits::paste_silence(int64_t start, int64_t end)
896         // paste silence does not do anything if 
897         // a) paste silence is on empty track
898         // b) paste silence is after last edit
899         // in both cases editof returns NULL
900         Edit *new_edit = editof(start, PLAY_FORWARD, 0);
901         if (!new_edit) return;
903         if (!new_edit->asset)
904         { // in this case we extend already existing edit
905                 new_edit->length += end - start;
906         } else
907         { // we are in fact creating a new edit
908                 new_edit = insert_new_edit(start);
909                 new_edit->length = end - start;
910         }
911         for(Edit *current = new_edit->next; current; current = NEXT)
912         {
913                 current->startproject += end - start;
914         }
915         return;
918 // Used by other editing commands so don't optimize
919 // This is separate from paste_silence, since it has to wrok also on empty tracks/beyond end of track
920 Edit *Edits::create_and_insert_edit(int64_t start, int64_t end)
922         Edit *new_edit = insert_new_edit(start);
923         new_edit->length = end - start;
924         for(Edit *current = new_edit->next; current; current = NEXT)
925         {
926                 current->startproject += end - start;
927         }
928         return new_edit;
930                                      
931 Edit* Edits::shift(int64_t position, int64_t difference)
933         Edit *new_edit = split_edit(position);
935         for(Edit *current = first; 
936                 current; 
937                 current = NEXT)
938         {
939                 if(current->startproject >= position)
940                 {
941                         current->shift(difference);
942                 }
943         }
944         return new_edit;
948 void Edits::shift_keyframes_recursive(int64_t position, int64_t length)
950         track->shift_keyframes(position, length, 0);
953 void Edits::shift_effects_recursive(int64_t position, int64_t length)
955         track->shift_effects(position, length, 0);