prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / edits.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "aedit.h"
23 #include "asset.h"
24 #include "assets.h"
25 #include "automation.h"
26 #include "bcsignals.h"
27 #include "cache.h"
28 #include "clip.h"
29 #include "edit.h"
30 #include "edits.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "file.h"
34 #include "filexml.h"
35 #include "filesystem.h"
36 #include "localsession.h"
37 #include "nestededls.h"
38 #include "plugin.h"
39 #include "strategies.inc"
40 #include "track.h"
41 #include "transition.h"
42 #include "transportque.inc"
43
44 #include <string.h>
45
46 Edits::Edits(EDL *edl, Track *track)
47  : List<Edit>()
48 {
49         this->edl = edl;
50         this->track = track;
51 }
52
53 Edits::~Edits()
54 {
55 }
56
57
58 void Edits::equivalent_output(Edits *edits, int64_t *result)
59 {
60 // For the case of plugin sets, a new plugin set may be created with
61 // plugins only starting after 0.  We only want to restart brender at
62 // the first plugin in this case.
63         for(Edit *current = first, *that_current = edits->first; 
64                 current || that_current; 
65                 current = NEXT,
66                 that_current = that_current->next)
67         {
68 //printf("Edits::equivalent_output 1 %d\n", *result);
69                 if(!current && that_current)
70                 {
71                         int64_t position1 = (last ? last->startproject + last->length : 0);
72                         int64_t position2 = that_current->startproject;
73                         if(*result < 0 || *result > MIN(position1, position2))
74                                 *result = MIN(position1, position2);
75                         break;
76                 }
77                 else
78                 if(current && !that_current)
79                 {
80                         int64_t position1 = (edits->last ? edits->last->startproject + edits->last->length : 0);
81                         int64_t position2 = current->startproject;
82                         if(*result < 0 || *result > MIN(position1, position2))
83                                 *result = MIN(position1, position2);
84                         break;
85                 }
86                 else
87                 {
88 //printf("Edits::equivalent_output 2 %d\n", *result);
89                         current->equivalent_output(that_current, result);
90 //printf("Edits::equivalent_output 3 %d\n", *result);
91                 }
92         }
93 }
94
95 void Edits::copy_from(Edits *edits)
96 {
97         while(last) delete last;
98         for(Edit *current = edits->first; current; current = NEXT)
99         {
100                 Edit *new_edit = append(create_edit());
101                 new_edit->copy_from(current);
102         }
103 }
104
105
106 Edits& Edits::operator=(Edits& edits)
107 {
108 printf("Edits::operator= 1\n");
109         copy_from(&edits);
110         return *this;
111 }
112
113
114 void Edits::insert_asset(Asset *asset,
115         EDL *nested_edl,
116         int64_t length,
117         int64_t position,
118         int track_number)
119 {
120         Edit *new_edit = insert_new_edit(position);
121
122         new_edit->nested_edl = nested_edl;
123         new_edit->asset = asset;
124         new_edit->startsource = 0;
125         new_edit->startproject = position;
126         new_edit->length = length;
127
128         if(nested_edl)
129         {
130                 if(track->data_type == TRACK_AUDIO)
131                         new_edit->channel = track_number % nested_edl->session->audio_channels;
132                 else
133                         new_edit->channel = 0;
134         }
135
136         if(asset && !nested_edl)
137         {
138                 if(asset->audio_data)
139                         new_edit->channel = track_number % asset->channels;
140                 else
141                 if(asset->video_data)
142                         new_edit->channel = track_number % asset->layers;
143         }
144
145 //printf("Edits::insert_asset %d %d\n", new_edit->channel, new_edit->length);
146         for(Edit *current = new_edit->next; current; current = NEXT)
147         {
148                 current->startproject += length;
149         }
150 }
151
152 void Edits::insert_edits(Edits *source_edits, 
153         int64_t position,
154         int64_t min_length,
155         int edit_autos)
156 {
157         //int64_t clipboard_end = position + min_length;
158 // Length pasted so far
159         int64_t source_len = 0;
160
161 // Fill region between end of edit table and beginning of pasted segment
162 // with silence.  Can't call from insert_new_edit because it's recursive.
163         if(position > length())
164         {
165                 paste_silence(length(), position);
166         }
167
168
169         for(Edit *source_edit = source_edits->first;
170                 source_edit;
171                 source_edit = source_edit->next)
172         {
173                 EDL *dest_nested_edl = 0;
174                 if(source_edit->nested_edl)
175                         dest_nested_edl = edl->nested_edls->get_copy(source_edit->nested_edl);
176
177 // Update Assets
178                 Asset *dest_asset = 0;
179                 if(source_edit->asset)
180                         dest_asset = edl->assets->update(source_edit->asset);
181 // Open destination area
182                 Edit *dest_edit = insert_new_edit(position + source_edit->startproject);
183
184                 dest_edit->copy_from(source_edit);
185                 dest_edit->asset = dest_asset;
186                 dest_edit->nested_edl = dest_nested_edl;
187                 dest_edit->startproject = position + source_edit->startproject;
188
189
190
191 // Shift keyframes in source edit to their position in the
192 // destination edit for plugin case
193                 if(edit_autos) dest_edit->shift_keyframes(position);
194
195
196
197 // Shift following edits and keyframes in following edits by length
198 // in current source edit.
199                 for(Edit *future_edit = dest_edit->next;
200                         future_edit;
201                         future_edit = future_edit->next)
202                 {
203                         future_edit->startproject += dest_edit->length;
204                         future_edit->shift_keyframes(dest_edit->length);
205                 }
206                 
207                 source_len += source_edit->length;
208         }
209
210
211
212
213 // Fill remaining clipboard length with silence
214         if(source_len < min_length)
215         {
216 //printf("Edits::insert_edits %d\n", __LINE__);
217                 paste_silence(position + source_len, position + min_length);
218         }
219 }
220
221
222 // Native units
223 // Can't paste silence in here because it's used by paste_silence.
224 Edit* Edits::insert_new_edit(int64_t position)
225 {
226         Edit *current = 0;
227 //printf("Edits::insert_new_edit 1\n");
228         current = split_edit(position);
229         if(current) current = PREVIOUS;
230
231 //printf("Edits::insert_new_edit 1\n");
232         Edit *new_edit = create_edit();
233 //printf("Edits::insert_new_edit 1\n");
234         insert_after(current, new_edit);
235         new_edit->startproject = position;
236 //printf("Edits::insert_new_edit 2\n");
237         return new_edit;
238 }
239
240
241 Edit* Edits::split_edit(int64_t position)
242 {
243 // Get edit containing position
244         Edit *edit = editof(position, PLAY_FORWARD, 0);
245         if(!edit) return 0;
246         return split_edit(edit, position);
247 }
248
249 Edit* Edits::split_edit(Edit *edit, int64_t position)
250 {
251 // Split would have created a 0 length
252 //      if(edit->startproject == position) return edit;
253 // Create anyway so the return value comes before position
254
255         Edit *new_edit = create_edit();
256         insert_after(edit, new_edit);
257         new_edit->copy_from(edit);
258         new_edit->length = new_edit->startproject + new_edit->length - position;
259         edit->length = position - edit->startproject;
260         new_edit->startproject = edit->startproject + edit->length;
261         new_edit->startsource += edit->length;
262
263
264 // Decide what to do with the transition
265         if(edit->length && edit->transition)
266         {
267                 delete new_edit->transition;
268                 new_edit->transition = 0;
269         }
270
271         if(edit->transition && edit->transition->length > edit->length) 
272                 edit->transition->length = edit->length;
273         if(new_edit->transition && new_edit->transition->length > new_edit->length)
274                 new_edit->transition->length = new_edit->length;
275         return new_edit;
276 }
277
278 int Edits::save(FileXML *xml, const char *output_path)
279 {
280         copy(0, length(), xml, output_path);
281         return 0;
282 }
283
284 void Edits::resample(double old_rate, double new_rate)
285 {
286         for(Edit *current = first; current; current = NEXT)
287         {
288                 current->startproject = Units::to_int64((double)current->startproject / 
289                         old_rate * 
290                         new_rate);
291                 if(PREVIOUS) PREVIOUS->length = current->startproject - PREVIOUS->startproject;
292                 current->startsource = Units::to_int64((double)current->startsource /
293                         old_rate *
294                         new_rate);
295                 if(!NEXT) current->length = Units::to_int64((double)current->length /
296                         old_rate *
297                         new_rate);
298                 if(current->transition)
299                 {
300                         current->transition->length = Units::to_int64(
301                                 (double)current->transition->length /
302                                 old_rate *
303                                 new_rate);
304                 }
305                 current->resample(old_rate, new_rate);
306         }
307 }
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 int Edits::optimize()
323 {
324         int result = 1;
325         Edit *current;
326
327
328 //printf("Edits::optimize %d\n", __LINE__);
329 // Sort edits by starting point
330         while(result)
331         {
332                 result = 0;
333                 
334                 for(current = first; current; current = NEXT)
335                 {
336                         Edit *next_edit = NEXT;
337                         
338                         if(next_edit && next_edit->startproject < current->startproject)
339                         {
340                                 swap(next_edit, current);
341                                 result = 1;
342                         }
343                 }
344         }
345
346 // Insert silence between edits which aren't consecutive
347         for(current = last; current; current = current->previous)
348         {
349                 if(current->previous)
350                 {
351                         Edit *previous_edit = current->previous;
352                         if(current->startproject - 
353                                 previous_edit->startproject -
354                                 previous_edit->length > 0)
355                         {
356                                 Edit *new_edit = create_edit();
357                                 insert_before(current, new_edit);
358                                 new_edit->startproject = previous_edit->startproject + previous_edit->length;
359                                 new_edit->length = current->startproject - 
360                                         previous_edit->startproject -
361                                         previous_edit->length;
362                         }
363                 }
364                 else
365                 if(current->startproject > 0)
366                 {
367                         Edit *new_edit = create_edit();
368                         insert_before(current, new_edit);
369                         new_edit->length = current->startproject;
370                 }
371         }
372
373         result = 1;
374         while(result)
375         {
376                 result = 0;
377
378
379 // delete 0 length edits
380                 for(current = first; 
381                         current && !result; )
382                 {
383                         if(current->length == 0)
384                         {
385                                 Edit* next = current->next;
386                                 delete current;
387                                 result = 1;
388                                 current = next;
389                         }
390                         else
391                                 current = current->next;
392                 }
393
394 //printf("Edits::optimize %d result=%d\n", __LINE__, result);
395 // merge same files or transitions
396                 if(track->data_type != TRACK_SUBTITLE )
397                 for(current = first; 
398                         current && current->next && !result; )
399                 {
400                         Edit *next_edit = current->next;
401
402 // printf("Edits::optimize %d %lld=%lld %d=%d %p=%p %p=%p\n", 
403 // __LINE__,
404 // current->startsource + current->length,
405 // next_edit->startsource,
406 // current->channel,
407 // next_edit->channel,
408 // current->asset,
409 // next_edit->asset,
410 // current->nested_edl,
411 // next_edit->nested_edl);
412
413
414                         if(
415 // both edits are silence & not a plugin
416                                 (current->silence() && next_edit->silence() && !current->is_plugin) ||
417                                 (current->startsource + current->length == next_edit->startsource &&
418 // source channels are identical
419                         current->channel == next_edit->channel &&
420 // assets are identical
421                                 current->asset == next_edit->asset && 
422                         current->nested_edl == next_edit->nested_edl))
423                         {
424 //printf("Edits::optimize %d\n", __LINE__);
425                         current->length += next_edit->length;
426                         remove(next_edit);
427                         result = 1;
428                 }
429
430                 current = current->next;
431                 }
432
433 // delete last edit of 0 length or silence
434                 if(track->data_type != TRACK_SUBTITLE )
435                 if(last && last->silence())
436                 {
437                         delete last;
438                         result = 1;
439                 }
440         }
441
442 //track->dump();
443         return 0;
444 }
445
446
447 // ===================================== file operations
448
449 int Edits::load(FileXML *file, int track_offset)
450 {
451         int64_t startproject = 0;
452
453         while( !file->read_tag() ) {
454 //printf("Edits::load 1 %s\n", file->tag.get_title());
455                 if(!strcmp(file->tag.get_title(), "EDIT"))
456                 {
457                         load_edit(file, startproject, track_offset);
458                 }
459                 else if(!strcmp(file->tag.get_title(), "/EDITS"))
460                         break;
461         }
462
463 //track->dump();
464         optimize();
465         return 0;
466 }
467
468 int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
469 {
470         Edit* current = append_new_edit();
471         current->load_properties(file, startproject);
472         startproject += current->length;
473
474         while( !file->read_tag() ) {
475                 if(file->tag.title_is("NESTED_EDL"))
476                 {
477                         char path[BCTEXTLEN];
478                         path[0] = 0;
479                         file->tag.get_property("SRC", path);
480 //printf("Edits::load_edit %d path=%s\n", __LINE__, path);
481                         if(path[0] != 0)
482                         {
483                                 current->nested_edl = edl->nested_edls->get(path);
484                         }
485 // printf("Edits::load_edit %d nested_edl->path=%s\n", 
486 // __LINE__, 
487 // current->nested_edl->path);
488                 }
489                 else if(file->tag.title_is("FILE"))
490                 {
491                         char filename[BCTEXTLEN];
492                         filename[0] = 0;
493                         file->tag.get_property("SRC", filename);
494 // Extend path
495                         if(filename[0] != 0)
496                         {
497                                 char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
498                                 FileSystem fs;
499                                 fs.set_current_dir("");
500                                 fs.extract_dir(directory, filename);
501                                 if(!strlen(directory))
502                                 {
503                                         fs.extract_dir(edl_directory, file->filename);
504                                         fs.join_names(directory, edl_directory, filename);
505                                         strcpy(filename, directory);
506                                 }
507                                 current->asset = edl->assets->get_asset(filename);
508                         }
509                         else
510                         {
511                                 current->asset = 0;
512                         }
513 //printf("Edits::load_edit 5\n");
514                 }
515                 else if(file->tag.title_is("TRANSITION"))
516                 {
517                         current->transition = new Transition(edl, current, "",
518                                 track->to_units(edl->session->default_transition_length, 1));
519                                 current->transition->load_xml(file);
520                 }
521                 else if(file->tag.title_is("/EDIT"))
522                         break;
523         }
524
525 //printf("Edits::load_edit %d\n", __LINE__);
526 //track->dump();
527 //printf("Edits::load_edit %d\n", __LINE__);
528         return 0;
529 }
530
531 // ============================================= accounting
532
533 int64_t Edits::length()
534 {
535         return last ? last->startproject + last->length : 0;
536 }
537
538
539
540 Edit* Edits::editof(int64_t position, int direction, int use_nudge)
541 {
542         Edit *current = 0;
543         if(use_nudge && track) position += track->nudge;
544
545         if(direction == PLAY_FORWARD)
546         {
547                 for(current = last; current; current = PREVIOUS)
548                 {
549                         if(current->startproject <= position && current->startproject + current->length > position)
550                                 return current;
551                 }
552         }
553         else
554         if(direction == PLAY_REVERSE)
555         {
556                 for(current = first; current; current = NEXT)
557                 {
558                         if(current->startproject < position && current->startproject + current->length >= position)
559                                 return current;
560                 }
561         }
562
563         return 0;     // return 0 on failure
564 }
565
566 Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
567 {
568         Edit *current;
569         if(track && use_nudge) position += track->nudge;
570
571 // Get the current edit
572         for(current = first; current; current = NEXT)
573         {
574                 if(current->startproject <= position && 
575                         current->startproject + current->length > position)
576                         break;
577         }
578
579 // Get the edit's asset
580 // TODO: descend into nested EDLs
581         if(current)
582         {
583                 if(!current->asset)
584                         current = 0;
585         }
586
587         return current;     // return 0 on failure
588 }
589
590 // ================================================ editing
591
592
593
594 int Edits::copy(int64_t start, int64_t end, FileXML *file, const char *output_path)
595 {
596         Edit *current_edit;
597
598         file->tag.set_title("EDITS");
599         file->append_tag();
600         file->append_newline();
601
602         for(current_edit = first; current_edit; current_edit = current_edit->next)
603         {
604                 current_edit->copy(start, end, file, output_path);
605         }
606
607         file->tag.set_title("/EDITS");
608         file->append_tag();
609         file->append_newline();
610         return 0;
611 }
612
613
614
615 void Edits::clear(int64_t start, int64_t end)
616 {
617         Edit* edit1 = editof(start, PLAY_FORWARD, 0);
618         Edit* edit2 = editof(end, PLAY_FORWARD, 0);
619         Edit* current_edit;
620
621         if(end == start) return;        // nothing selected
622         if(!edit1 && !edit2) return;       // nothing selected
623
624
625         if(!edit2)
626         {                // edit2 beyond end of track
627                 edit2 = last;
628                 end = this->length();
629         }
630
631         if(edit1 != edit2)
632         {
633 // in different edits
634
635 //printf("Edits::clear 3.5 %d %d %d %d\n", edit1->startproject, edit1->length, edit2->startproject, edit2->length);
636                 edit1->length = start - edit1->startproject;
637                 edit2->length -= end - edit2->startproject;
638                 edit2->startsource += end - edit2->startproject;
639                 edit2->startproject += end - edit2->startproject;
640
641 // delete
642                 for(current_edit = edit1->next; current_edit && current_edit != edit2;)
643                 {
644                         Edit* next = current_edit->next;
645                         remove(current_edit);
646                         current_edit = next;
647                 }
648 // shift
649                 for(current_edit = edit2; current_edit; current_edit = current_edit->next)
650                 {
651                         current_edit->startproject -= end - start;
652                 }
653         }
654         else
655         {
656 // in same edit. paste_edit depends on this
657 // create a new edit
658                 current_edit = split_edit(start);
659
660                 current_edit->length -= end - start;
661                 current_edit->startsource += end - start;
662
663 // shift
664                 for(current_edit = current_edit->next; 
665                         current_edit; 
666                         current_edit = current_edit->next)
667                 {            
668                         current_edit->startproject -= end - start;
669                 }
670         }
671
672         optimize();
673 }
674
675 // Used by edit handle and plugin handle movement but plugin handle movement
676 // can only effect other plugins.
677 void Edits::clear_recursive(int64_t start, 
678         int64_t end, 
679         int edit_edits,
680         int edit_labels, 
681         int edit_plugins,
682         int edit_autos,
683         Edits *trim_edits)
684 {
685 //printf("Edits::clear_recursive 1\n");
686         track->clear(start, 
687                 end, 
688                 edit_edits,
689                 edit_labels,
690                 edit_plugins,
691                 edit_autos,
692                 0,
693                 trim_edits);
694 }
695
696
697 int Edits::clear_handle(double start, 
698         double end, 
699         int edit_plugins, 
700         int edit_autos,
701         double &distance)
702 {
703         Edit *current_edit;
704
705         distance = 0.0; // if nothing is found, distance is 0!
706         for(current_edit = first; 
707                 current_edit && current_edit->next; 
708                 current_edit = current_edit->next)
709         {
710
711
712
713                 if(current_edit->asset && 
714                         current_edit->next->asset)
715                 {
716
717                         if(current_edit->asset->equivalent(*current_edit->next->asset,
718                                 0,
719                                 0))
720                         {
721
722 // Got two consecutive edits in same source
723                                 if(edl->equivalent(track->from_units(current_edit->next->startproject), 
724                                         start))
725                                 {
726 // handle selected
727                                         int length = -current_edit->length;
728                                         current_edit->length = current_edit->next->startsource - current_edit->startsource;
729                                         length += current_edit->length;
730
731 // Lengthen automation
732                                         if(edit_autos)
733                                                 track->automation->paste_silence(current_edit->next->startproject, 
734                                                         current_edit->next->startproject + length);
735
736 // Lengthen effects
737                                         if(edit_plugins)
738                                                 track->shift_effects(current_edit->next->startproject, 
739                                                         length,
740                                                         edit_autos);
741
742                                         for(current_edit = current_edit->next; current_edit; current_edit = current_edit->next)
743                                         {
744                                                 current_edit->startproject += length;
745                                         }
746
747                                         distance = track->from_units(length);
748                                         optimize();
749                                         break;
750                                 }
751                         }
752                 }
753         }
754
755         return 0;
756 }
757
758 int Edits::modify_handles(double oldposition, 
759         double newposition, 
760         int currentend,
761         int edit_mode, 
762         int edit_edits,
763         int edit_labels,
764         int edit_plugins,
765         int edit_autos,
766         Edits *trim_edits)
767 {
768         int result = 0;
769         Edit *current_edit;
770
771 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
772         if(currentend == 0)
773         {
774 // left handle
775                 for(current_edit = first; current_edit && !result;)
776                 {
777                         if(edl->equivalent(track->from_units(current_edit->startproject), 
778                                 oldposition))
779                         {
780 // edit matches selection
781 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
782                                 oldposition = track->from_units(current_edit->startproject);
783                                 result = 1;
784
785                                 if(newposition >= oldposition)
786                                 {
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),
792                                                 edit_edits,
793                                                 edit_labels,
794                                                 edit_plugins,
795                                                 edit_autos,
796                                                 trim_edits);
797                                 }
798                                 else
799                                 {
800 //printf("Edits::modify_handle 2 %s\n", track->title);
801 // move start of edit out
802                                         current_edit->shift_start_out(edit_mode, 
803                                                 track->to_units(newposition, 0), 
804                                                 track->to_units(oldposition, 0),
805                                                 edit_edits,
806                                                 edit_labels,
807                                                 edit_plugins,
808                                                 edit_autos,
809                                                 trim_edits);
810                                 }
811                         }
812
813                         if(!result) current_edit = current_edit->next;
814                 }
815         }
816         else
817         {
818 // right handle selected
819                 for(current_edit = first; current_edit && !result;)
820                 {
821                         if(edl->equivalent(track->from_units(current_edit->startproject) + 
822                                 track->from_units(current_edit->length), oldposition))
823                         {
824                 oldposition = track->from_units(current_edit->startproject) + 
825                                         track->from_units(current_edit->length);
826                                 result = 1;
827
828 //printf("Edits::modify_handle 3\n");
829                                 if(newposition <= oldposition)
830                                 {     
831 // shift end of edit in
832 //printf("Edits::modify_handle 4\n");
833                                         current_edit->shift_end_in(edit_mode, 
834                                                 track->to_units(newposition, 0), 
835                                                 track->to_units(oldposition, 0),
836                                                 edit_edits,
837                                                 edit_labels,
838                                                 edit_plugins,
839                                                 edit_autos,
840                                                 trim_edits);
841 //printf("Edits::modify_handle 5\n");
842                                 }
843                                 else
844                                 {     
845 // move end of edit out
846 //printf("Edits::modify_handle 6\n");
847                                         current_edit->shift_end_out(edit_mode, 
848                                                 track->to_units(newposition, 0), 
849                                                 track->to_units(oldposition, 0),
850                                                 edit_edits,
851                                                 edit_labels,
852                                                 edit_plugins,
853                                                 edit_autos,
854                                                 trim_edits);
855 //printf("Edits::modify_handle 7\n");
856                                 }
857                         }
858
859                         if(!result) current_edit = current_edit->next;
860 //printf("Edits::modify_handle 8\n");
861                 }
862         }
863
864         optimize();
865         return 0;
866 }
867
868
869 // Used by other editing commands so don't optimize
870 Edit* Edits::paste_silence(int64_t start, int64_t end)
871 {
872         Edit *new_edit = insert_new_edit(start);
873         new_edit->length = end - start;
874         for(Edit *current = new_edit->next; current; current = NEXT)
875         {
876                 current->startproject += end - start;
877         }
878         return new_edit;
879 }
880                                      
881 Edit* Edits::shift(int64_t position, int64_t difference)
882 {
883         Edit *new_edit = split_edit(position);
884
885         for(Edit *current = first; 
886                 current; 
887                 current = NEXT)
888         {
889                 if(current->startproject >= position)
890                 {
891                         current->shift(difference);
892                 }
893         }
894         return new_edit;
895 }
896
897
898 void Edits::shift_keyframes_recursive(int64_t position, int64_t length)
899 {
900         track->shift_keyframes(position, length);
901 }
902
903 void Edits::shift_effects_recursive(int64_t position, int64_t length, int edit_autos)
904 {
905         track->shift_effects(position, length, edit_autos);
906 }
907