3 * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "automation.h"
25 #include "bcsignals.h"
29 #include "edlsession.h"
34 #include "localsession.h"
37 #include "mainsession.h"
38 #include "pluginserver.h"
39 #include "pluginset.h"
42 #include "trackcanvas.h"
44 #include "trackscroll.h"
45 #include "transition.h"
46 #include "transportque.h"
50 int Tracks::blade(double position)
52 for( Track *track=first; track!=0; track=track->next ) {
53 if( !track->record ) continue;
54 track->blade(position);
59 int Tracks::clear(double start, double end, int clear_plugins, int edit_autos)
63 for(current_track = first;
65 current_track = current_track->next)
67 if(current_track->record)
69 current_track->clear(start,
73 clear_plugins, // edit_plugins
82 void Tracks::clear_automation(double selectionstart, double selectionend)
86 for(current_track = first; current_track; current_track = current_track->next)
88 if(current_track->record)
90 current_track->clear_automation(selectionstart,
98 void Tracks::clear_transitions(double start, double end)
100 for(Track *current_track = first;
102 current_track = current_track->next)
104 if(current_track->record)
106 int64_t start_units = current_track->to_units(start, 0);
107 int64_t end_units = current_track->to_units(end, 0);
109 for(Edit *current_edit = current_track->edits->first;
111 current_edit = current_edit->next)
113 if(current_edit->startproject >= start_units &&
114 current_edit->startproject < end_units &&
115 current_edit->transition)
117 current_edit->detach_transition();
124 void Tracks::shuffle_edits(double start, double end)
126 // This doesn't affect automation or effects
127 // Labels follow the first track.
129 for(Track *current_track = first;
131 current_track = current_track->next)
133 if(current_track->record)
135 current_track->shuffle_edits(start, end, first_track);
142 void Tracks::reverse_edits(double start, double end)
144 // This doesn't affect automation or effects
145 // Labels follow the first track.
147 for(Track *current_track = first;
149 current_track = current_track->next)
151 if(current_track->record)
153 current_track->reverse_edits(start, end, first_track);
159 void Tracks::align_edits(double start, double end)
161 // This doesn't affect automation or effects
162 ArrayList<double> times;
164 for(Track *current_track = first;
166 current_track = current_track->next)
168 if(current_track->record)
170 current_track->align_edits(start, end, ×);
175 void Tracks::set_edit_length(double start, double end, double length)
178 for(Track *current_track = first;
180 current_track = current_track->next)
182 if(current_track->record)
184 #define USE_FLOATING_LENGTHS
186 #ifdef USE_FLOATING_LENGTHS
189 // The first edit anchors the length offsets.
190 // Round edits up & down so they end where they would if they all had floating point lengths.
191 //int first_edit = 1;
192 int64_t start_units = current_track->to_units(start, 0);
193 int64_t end_units = current_track->to_units(end, 0);
194 // Total time of edits accumulated, in track units
195 int64_t total_units = 0;
196 // Number of length offsets added so far
197 int total_lengths = 0;
199 for(Edit *current_edit = current_track->edits->last;
201 current_edit = current_edit->previous)
203 if(current_edit->startproject >= start_units &&
204 current_edit->startproject + current_edit->length <= end_units)
206 // Calculate true length based on number of length offsets & total time
207 double end_time = (1 + total_lengths) * length;
208 int64_t length_units = current_track->to_units(end_time, 0) -
210 if(length_units < 1) length_units = 1;
211 //printf("Tracks::set_edit_length %d %f %f\n", __LINE__,
212 // end_time, current_track->from_units(total_units));
213 total_units += length_units;
215 // Go in using the edit handle interface
216 int64_t starting_length = current_edit->length;
218 if(length_units < current_edit->length)
220 current_edit->shift_end_in(MOVE_ALL_EDITS,
221 current_edit->startproject + length_units,
222 current_edit->startproject + current_edit->length,
224 edl->session->labels_follow_edits,
225 edl->session->plugins_follow_edits,
226 edl->session->autos_follow_edits,
231 current_edit->shift_end_out(MOVE_ALL_EDITS,
232 current_edit->startproject + length_units,
233 current_edit->startproject + current_edit->length,
235 edl->session->labels_follow_edits,
236 edl->session->plugins_follow_edits,
237 edl->session->autos_follow_edits,
241 int64_t ending_length = current_edit->length;
243 if(edl->session->labels_follow_edits && first_track)
245 // printf("Tracks::set_edit_length %d %f %f\n",
247 // current_track->from_units(current_edit->startproject + starting_length),
248 // current_track->from_units(current_edit->startproject + ending_length));
249 edl->labels->modify_handles(
250 current_track->from_units(current_edit->startproject + starting_length),
251 current_track->from_units(current_edit->startproject + ending_length),
265 #else // USE_FLOATING_LENGTHS
267 // The first edit anchors the length offsets.
268 // The idea was to round edits up & down so they end where they should
269 // if they all had floating point lengths. It's easier just to make sure the framerate
270 // is divisible by the required length.
271 // int first_edit = 1;
272 int64_t start_units = current_track->to_units(start, 0);
273 int64_t end_units = current_track->to_units(end, 0);
274 int64_t length_units = current_track->to_units(length, 1);
275 // Starting time of the length offsets in seconds
276 // double start_time = 0;
277 // Number of length offsets added so far
278 // int total_lengths = 0;
280 for(Edit *current_edit = current_track->edits->last;
282 current_edit = current_edit->previous)
284 if(current_edit->startproject >= start_units &&
285 current_edit->startproject + current_edit->length <= end_units)
287 // Calculate starting time of length offsets
290 // start_time = current_track->from_units(current_edit->startproject);
293 // Calculate true length based on number of length offsets
294 // double end_time = start_time + (1 + total_lengths) * length;
295 // int64_t length_units = current_track->to_units(end_time, 0) -
296 // current_edit->startproject;
297 // if(length_units < 1) length_units = 1;
299 // Go in using the edit handle interface
300 int64_t starting_length = current_edit->length;
302 if(length_units < current_edit->length)
304 current_edit->shift_end_in(MOVE_ALL_EDITS,
305 current_edit->startproject + length_units,
306 current_edit->startproject + current_edit->length,
308 edl->session->labels_follow_edits,
309 edl->session->plugins_follow_edits,
310 edl->session->autos_follow_edits,
315 current_edit->shift_end_out(MOVE_ALL_EDITS,
316 current_edit->startproject + length_units,
317 current_edit->startproject + current_edit->length,
319 edl->session->labels_follow_edits,
320 edl->session->plugins_follow_edits,
321 edl->session->autos_follow_edits,
325 int64_t ending_length = current_edit->length;
327 if(edl->session->labels_follow_edits && first_track)
329 // printf("Tracks::set_edit_length %d %f %f\n",
331 // current_track->from_units(current_edit->startproject + starting_length),
332 // current_track->from_units(current_edit->startproject + ending_length));
333 edl->labels->modify_handles(
334 current_track->from_units(current_edit->startproject + starting_length),
335 current_track->from_units(current_edit->startproject + ending_length),
346 #endif // !USE_FLOATING_LENGTHS
353 void Tracks::set_transition_length(double start, double end, double length)
355 for(Track *current_track = first;
357 current_track = current_track->next)
359 if(current_track->record)
361 int64_t start_units = current_track->to_units(start, 0);
362 int64_t end_units = current_track->to_units(end, 0);
364 for(Edit *current_edit = current_track->edits->first;
366 current_edit = current_edit->next)
368 if(current_edit->startproject >= start_units &&
369 current_edit->startproject < end_units &&
370 current_edit->transition)
372 current_edit->transition->length =
373 current_track->to_units(length, 1);
374 if( current_edit == current_track->edits->last &&
375 current_edit->silence() ) {
376 current_edit->length = current_edit->transition->length;
384 void Tracks::set_transition_length(Transition *transition, double length)
386 // Must verify existence of transition
388 if(!transition) return;
389 for(Track *current_track = first;
390 current_track && !done;
391 current_track = current_track->next)
393 for(Edit *current_edit = current_track->edits->first;
394 current_edit && !done;
395 current_edit = current_edit->next)
397 if(current_edit->transition == transition)
399 transition->length = current_track->to_units(length, 1);
400 if( current_edit == current_track->edits->last &&
401 current_edit->silence() ) {
402 current_edit->length = current_edit->transition->length;
410 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
413 for( Track *track=first; track; track=track->next ) {
414 if( !track->record || track->data_type != track_type ) continue;
415 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
416 if( !edit->is_selected ) continue;
417 edit->insert_transition(title);
422 clear_selected_edits();
426 for( Track *track=first; track; track=track->next ) {
427 if( !track->record || track->data_type != track_type ) continue;
428 int64_t start_units = track->to_units(start, 0);
429 int64_t end_units = track->to_units(end, 0);
430 if( start_units == end_units ) {
431 for( Edit *edit = track->edits->first; edit; edit = edit->next) {
432 int64_t edit_start = edit->startproject;
433 int64_t edit_end = edit_start + edit->length;
434 if( edit_start > start_units ) continue;
435 if( start_units == track->edits->length() ) {
436 double length = edl->session->default_transition_length;
437 int64_t units = track->to_units(length, 1);
438 edit = track->edits->
439 create_silence(start_units, start_units+units);
441 else if( start_units >= edit_end ) continue;
442 edit->insert_transition(title);
446 for( Edit *edit=track->edits->first; edit; edit=edit->next) {
447 int64_t edit_start = edit->startproject;
448 if( !edit_start ) continue;
449 if( edit_start >= start_units && edit_start < end_units ) {
450 edit->insert_transition(title);
457 void Tracks::set_automation_mode(double selectionstart,
461 Track* current_track;
463 for(current_track = first; current_track; current_track = current_track->next)
465 if(current_track->record)
467 current_track->set_automation_mode(selectionstart,
474 int Tracks::clear_default_keyframe()
476 for(Track *current = first; current; current = NEXT)
479 current->clear_automation(0, 0, 0, 1);
484 int Tracks::clear_handle(double start,
486 double &longest_distance,
491 Track* current_track;
494 for(current_track = first; current_track; current_track = current_track->next)
496 if(current_track->record)
498 current_track->clear_handle(start,
504 if(distance > longest_distance) longest_distance = distance;
511 int Tracks::copy_automation(double selectionstart,
517 // called by MWindow::copy_automation for copying automation alone
518 Track* current_track;
520 file->tag.set_title("AUTO_CLIPBOARD");
521 file->tag.set_property("LENGTH", selectionend - selectionstart);
522 file->tag.set_property("FRAMERATE", edl->session->frame_rate);
523 file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
525 file->append_newline();
526 file->append_newline();
528 for(current_track = first;
530 current_track = current_track->next)
532 if(current_track->record)
534 current_track->copy_automation(selectionstart,
542 file->tag.set_title("/AUTO_CLIPBOARD");
544 file->append_newline();
545 file->terminate_string();
549 // int Tracks::copy_default_keyframe(FileXML *file)
551 // copy_automation(0, 0, file, 1, 0);
555 int Tracks::delete_tracks()
557 int total_deleted = 0;
563 Track *next_track = 0;
564 for (Track* current = first; current && done; current = next_track)
566 next_track = current->next;
569 delete_track(current);
577 return total_deleted;
580 void Tracks::move_edits(ArrayList<Edit*> *edits,
583 int edit_labels, // Ignored
584 int edit_plugins, // Ignored
585 int edit_autos, // Ignored
588 //printf("Tracks::move_edits 1\n");
589 for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
591 if(dest_track->record)
593 // Need a local copy of the source edit since the original source edit may
594 // change in the editing operation.
595 Edit *source_edit = 0;
596 Track *source_track = 0;
600 if(dest_track->data_type == TRACK_AUDIO)
602 int current_aedit = 0;
604 while(current_aedit < edits->total &&
605 edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
608 if(current_aedit < edits->total)
610 source_edit = edits->values[current_aedit];
611 source_track = source_edit->track;
612 edits->remove_number(current_aedit);
616 if(dest_track->data_type == TRACK_VIDEO)
618 int current_vedit = 0;
619 while(current_vedit < edits->total &&
620 edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
623 if(current_vedit < edits->total)
625 source_edit = edits->values[current_vedit];
626 source_track = source_edit->track;
627 edits->remove_number(current_vedit);
631 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
634 int64_t position_i = source_track->to_units(position, 0);
635 // Source edit changes
636 int64_t source_length = source_edit->length;
637 int64_t source_startproject = source_edit->startproject;
641 // This works like this: CUT edit, INSERT edit at final position, keyframes also follow
642 // FIXME: there should be a GUI way to tell whenever user also wants to move autos or not
643 // this is all screwed up
644 // inserts defaults/bogus everywhere
648 AutoConf temp_autoconf;
650 temp_autoconf.set_all(1);
652 source_track->automation->copy(source_edit->startproject,
653 source_edit->startproject + source_edit->length,
657 temp.terminate_string();
659 // Insert new keyframes
660 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
661 source_track->automation->clear(source_edit->startproject,
662 source_edit->startproject + source_edit->length,
665 int64_t position_a = position_i;
666 if (dest_track == source_track)
668 if (position_a > source_edit->startproject)
669 position_a -= source_length;
672 dest_track->automation->paste_silence(position_a,
673 position_a + source_length);
674 while(!temp.read_tag())
675 dest_track->automation->paste(position_a,
676 source_length, 1.0, &temp, 0, 1,
680 Edit *dest_edit = dest_track->edits->shift(position_i,
682 Edit *result = dest_track->edits->insert_before(dest_edit,
683 dest_track->edits->create_edit());
684 result->copy_from(source_edit);
685 result->startproject = position_i;
686 result->length = source_length;
689 source_track->edits->clear(source_edit->startproject,
690 source_edit->startproject + source_length);
693 //this is outline for future thinking how it is supposed to be done trough C&P mechanisms
695 source_track->cut(source_edit->startproject,
696 source_edit->startproject + source_edit->length,
699 temp.terminate_string();
701 dest_track->paste_silence(position_a,
702 position_a + source_length,
704 while(!temp.read_tag())
705 dest_track->paste(position_a, // MISSING PIECE OF FUNCTIONALITY
716 // ONLY edit is moved, all other edits stay where they are
718 // Copy edit to temp, delete the edit, insert the edit
719 Edit *temp_edit = dest_track->edits->create_edit();
720 temp_edit->copy_from(source_edit);
721 // we call the edits directly since we do not want to move keyframes or anything else
722 source_track->edits->clear(source_startproject,
723 source_startproject + source_length);
724 source_track->edits->paste_silence(source_startproject,
725 source_startproject + source_length);
727 dest_track->edits->clear(position_i,
728 position_i + source_length);
729 Edit *dest_edit = dest_track->edits->shift(position_i, source_length);
730 Edit *result = dest_track->edits->insert_before(dest_edit,
731 dest_track->edits->create_edit());
732 result->copy_from(temp_edit);
733 result->startproject = position_i;
734 result->length = source_length;
737 source_track->optimize();
738 dest_track->optimize();
744 void Tracks::move_group(EDL *group, Track *first_track, double position, int overwrite)
746 for( Track *track=first; track; track=track->next ) {
747 if( !track->record ) continue;
748 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
749 if( !edit->is_selected ) continue;
751 edit->is_selected = 0;
755 Track *src = group->tracks->first;
756 for( Track *track=first_track; track && src; track=track->next ) {
757 if( !track->record ) continue;
758 int64_t pos = track->to_units(position, 0);
759 for( Edit *edit=src->edits->first; edit; edit=edit->next ) {
760 if( edit->silence() ) continue;
761 int64_t start = pos + edit->startproject;
762 int64_t end = start + edit->length;
764 track->edits->clear(start, end);
765 Edit *dst = track->edits->insert_new_edit(start);
766 dst->copy_from(edit);
767 dst->startproject = start;
768 dst->is_selected = 1;
769 while( (dst=dst->next) != 0 )
770 dst->startproject += edit->length;
777 void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)
779 Track *source_track = plugin->track;
781 // Create a new plugin set
782 double start = track->from_units(position);
783 double length = track->from_units(plugin->length);
785 result = track->insert_effect("", &plugin->shared_location, 0, 0,
786 start, length, plugin->plugin_type);
787 result->copy_from(plugin);
788 result->shift(position - plugin->startproject);
790 // Clear new plugin from old set
791 plugin->plugin_set->clear(plugin->startproject,
792 plugin->startproject + plugin->length,
793 edl->session->autos_follow_edits);
795 source_track->optimize();
798 void Tracks::move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position)
800 // src/dest track must be the same
801 // replace plugin in source plugin_set with silence
802 PluginSet *src_plugin_set = plugin->plugin_set;
803 Plugin *silent = new Plugin(edl, src_plugin_set, "");
804 silent->startproject = plugin->startproject;
805 silent->length = plugin->length;
806 src_plugin_set->insert_after(plugin, silent);
807 src_plugin_set->remove_pointer(plugin);
808 // truncate previous plugin
809 Plugin *dest = (Plugin *)plugin_set->editof(position, PLAY_FORWARD, 0);
810 // add plugin after dest
811 plugin_set->insert_after(dest, plugin);
813 dest->length = position - dest->startproject;
814 if( dest->length < 0 ) dest->length = 0;
816 // update plugin position
817 plugin->startproject = position;
818 plugin->plugin_set = plugin_set;
819 plugin->edits = plugin_set;
820 src_plugin_set->track->optimize();
823 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
825 Track *output_track, *first_output_track, *input_track;
826 int i, data_type = TRACK_AUDIO;
831 for(i = 0; i < 2; i++)
833 // Get first output track
834 for(output_track = first;
836 output_track = output_track->next)
837 if(output_track->data_type == data_type &&
838 output_track->record) break;
840 first_output_track = output_track;
842 // Get first input track
843 for(input_track = first;
845 input_track = input_track->next)
847 if(input_track->data_type == data_type &&
849 !input_track->record) break;
853 if(output_track && input_track)
855 // Transfer input track to end of output track one at a time
858 output_start = output_track->get_length();
859 output_track->insert_track(input_track,
866 // Get next source and destination
867 for(input_track = input_track->next;
869 input_track = input_track->next)
872 if(input_track->data_type == data_type &&
873 !input_track->record &&
874 input_track->play) break;
877 for(output_track = output_track->next;
879 output_track = output_track->next)
881 if(output_track->data_type == data_type &&
882 output_track->record) break;
887 output_track = first_output_track;
893 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
899 int Tracks::delete_all_tracks()
901 while(last) delete last;
906 void Tracks::change_modules(int old_location, int new_location, int do_swap)
908 for(Track* current = first ; current; current = current->next)
910 current->change_modules(old_location, new_location, do_swap);
914 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
916 for(Track* current = first ; current; current = current->next)
918 current->change_plugins(old_location, new_location, do_swap);
924 // =========================================== EDL editing
927 int Tracks::copy(double start,
931 const char *output_path)
934 if(start == end && !all) return 1;
942 if(current->record || all)
944 current->copy(start, end, file,output_path);
953 int Tracks::move_track_up(Track *track)
955 Track *next_track = track->previous;
956 if(!next_track) next_track = last;
958 change_modules(number_of(track), number_of(next_track), 1);
960 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
962 // for(Track *current = first; current && count < 5; current = NEXT, count++)
963 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
964 // printf("Tracks::move_track_up 2\n");
966 swap(track, next_track);
969 // for(Track *current = first; current && count < 5; current = NEXT, count++)
970 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
971 // printf("Tracks::move_track_up 3\n");
976 int Tracks::move_track_down(Track *track)
978 Track *next_track = track->next;
979 if(!next_track) next_track = first;
981 change_modules(number_of(track), number_of(next_track), 1);
982 swap(track, next_track);
987 int Tracks::move_tracks_up()
989 Track *track, *next_track;
996 next_track = track->next;
1002 change_modules(number_of(track->previous), number_of(track), 1);
1004 swap(track->previous, track);
1013 int Tracks::move_tracks_down()
1015 Track *track, *previous_track;
1020 track = previous_track)
1022 previous_track = track->previous;
1028 change_modules(number_of(track), number_of(track->next), 1);
1030 swap(track, track->next);
1041 void Tracks::paste_audio_transition(PluginServer *server)
1043 for(Track *current = first; current; current = NEXT)
1045 if(current->data_type == TRACK_AUDIO &&
1048 int64_t position = current->to_units(
1049 edl->local_session->get_selectionstart(), 0);
1050 Edit *current_edit = current->edits->editof(position,
1053 if( !current_edit && position == current->edits->length() ) {
1054 double length = edl->session->default_transition_length;
1055 int64_t units = current->to_units(length, 1);
1056 current_edit = current->edits->create_silence(position, position+units);
1060 paste_transition(server, current_edit);
1066 void Tracks::paste_automation(double selectionstart,
1072 Track* current_track = 0;
1073 Track* current_atrack = 0;
1074 Track* current_vtrack = 0;
1075 Track* dst_track = 0;
1079 double frame_rate = edl->session->frame_rate;
1080 int64_t sample_rate = edl->session->sample_rate;
1081 char string[BCTEXTLEN];
1086 result = file->read_tag();
1088 !file->tag.title_is("AUTO_CLIPBOARD"));
1092 length = file->tag.get_property("LENGTH", 0);
1093 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
1094 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
1099 result = file->read_tag();
1103 if(file->tag.title_is("/AUTO_CLIPBOARD"))
1108 if(file->tag.title_is("TRACK"))
1110 file->tag.get_property("TYPE", string);
1111 if(!strcmp(string, "AUDIO"))
1113 src_type = TRACK_AUDIO;
1117 src_type = TRACK_VIDEO;
1120 // paste to any media type
1123 if(!current_track) current_track = first;
1124 while(current_track && !current_track->record)
1125 current_track = current_track->next;
1126 dst_track = current_track;
1129 if(!strcmp(string, "AUDIO"))
1131 // Get next audio track
1133 current_atrack = first;
1135 current_atrack = current_atrack->next;
1137 while(current_atrack &&
1138 (current_atrack->data_type != TRACK_AUDIO ||
1139 !current_atrack->record))
1140 current_atrack = current_atrack->next;
1141 dst_track = current_atrack;
1145 // Get next video track
1147 current_vtrack = first;
1149 current_vtrack = current_vtrack->next;
1151 while(current_vtrack &&
1152 (current_vtrack->data_type != TRACK_VIDEO ||
1153 !current_vtrack->record))
1154 current_vtrack = current_vtrack->next;
1156 dst_track = current_vtrack;
1161 double frame_rate2 = frame_rate;
1162 double sample_rate2 = sample_rate;
1164 if(src_type != dst_track->data_type)
1166 frame_rate2 = sample_rate;
1167 sample_rate2 = frame_rate;
1170 dst_track->paste_automation(selectionstart,
1184 // int Tracks::paste_default_keyframe(FileXML *file)
1186 // paste_automation(0, file, 1, 0);
1190 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1192 dest_edit->insert_transition(server->title);
1195 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1197 for(Track *current = first; current; current = NEXT)
1199 if(current->data_type == TRACK_VIDEO &&
1202 int64_t position = current->to_units(
1203 edl->local_session->get_selectionstart(), 0);
1204 Edit *current_edit = current->edits->editof(position,
1207 if( !current_edit && position == current->edits->length() ) {
1208 double length = edl->session->default_transition_length;
1209 int64_t units = current->to_units(length, 1);
1210 current_edit = current->edits->create_silence(position, position+units);
1214 paste_transition(server, current_edit);
1216 if(first_track) break;
1222 int Tracks::paste_silence(double start,
1227 Track* current_track;
1229 for(current_track = first;
1231 current_track = current_track->next)
1233 if(current_track->record)
1235 current_track->paste_silence(start,
1246 int Tracks::select_auto(int cursor_x, int cursor_y)
1249 for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1253 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1257 for(Track* current = first; current && !result; current = NEXT)
1259 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1264 int Tracks::modify_edithandles(double &oldposition,
1265 double &newposition,
1274 for(current = first; current; current = NEXT)
1278 current->modify_edithandles(oldposition,
1290 int Tracks::modify_pluginhandles(double &oldposition,
1291 double &newposition,
1300 for(current = first; current; current = NEXT)
1304 current->modify_pluginhandles(oldposition,
1318 int Tracks::purge_asset(Asset *asset)
1320 Track *current_track;
1323 for(current_track = first; current_track; current_track = current_track->next)
1325 result += current_track->purge_asset(asset);
1330 int Tracks::asset_used(Asset *asset)
1332 Track *current_track;
1335 for(current_track = first; current_track; current_track = current_track->next)
1337 result += current_track->asset_used(asset);
1342 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1344 Track *current_track;
1346 for(current_track = first;
1348 current_track = current_track->next)
1350 if((current_track->record || ignore_record) &&
1351 current_track->data_type == TRACK_VIDEO)
1353 current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);