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
81 void Tracks::clear_automation(double selectionstart, double selectionend)
85 for(current_track = first; current_track; current_track = current_track->next)
87 if(current_track->record)
89 current_track->clear_automation(selectionstart,
97 void Tracks::clear_transitions(double start, double end)
99 for(Track *current_track = first;
101 current_track = current_track->next)
103 if(current_track->record)
105 int64_t start_units = current_track->to_units(start, 0);
106 int64_t end_units = current_track->to_units(end, 0);
108 for(Edit *current_edit = current_track->edits->first;
110 current_edit = current_edit->next)
112 if(current_edit->startproject >= start_units &&
113 current_edit->startproject < end_units &&
114 current_edit->transition)
116 current_edit->detach_transition();
123 int Tracks::clear_hard_edges(double start, double end)
125 for( Track *track=first; track; track=track->next ) {
126 if( !track->record ) continue;
127 int64_t start_units = track->to_units(start, 0);
128 int64_t end_units = track->to_units(end, 0);
130 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
131 if( edit->startproject < start_units ) continue;
132 if( edit->startproject >= end_units ) continue;
134 if( !edit->previous ) continue;
135 edit->previous->hard_right = 0;
141 void Tracks::shuffle_edits(double start, double end)
143 // This doesn't affect automation or effects
144 // Labels follow the first track.
146 for(Track *current_track = first;
148 current_track = current_track->next)
150 if(current_track->record)
152 current_track->shuffle_edits(start, end, first_track);
159 void Tracks::reverse_edits(double start, double end)
161 // This doesn't affect automation or effects
162 // Labels follow the first track.
164 for(Track *current_track = first;
166 current_track = current_track->next)
168 if(current_track->record)
170 current_track->reverse_edits(start, end, first_track);
176 void Tracks::align_edits(double start, double end)
178 // This doesn't affect automation or effects
179 ArrayList<double> times;
181 for(Track *current_track = first;
183 current_track = current_track->next)
185 if(current_track->record)
187 current_track->align_edits(start, end, ×);
192 void Tracks::set_edit_length(double start, double end, double length)
195 for(Track *current_track = first;
197 current_track = current_track->next)
199 if(current_track->record)
201 #define USE_FLOATING_LENGTHS
203 #ifdef USE_FLOATING_LENGTHS
206 // The first edit anchors the length offsets.
207 // Round edits up & down so they end where they would if they all had floating point lengths.
208 //int first_edit = 1;
209 int64_t start_units = current_track->to_units(start, 0);
210 int64_t end_units = current_track->to_units(end, 0);
211 // Total time of edits accumulated, in track units
212 int64_t total_units = 0;
213 // Number of length offsets added so far
214 int total_lengths = 0;
216 for(Edit *current_edit = current_track->edits->last;
218 current_edit = current_edit->previous)
220 if(current_edit->startproject >= start_units &&
221 current_edit->startproject + current_edit->length <= end_units)
223 // Calculate true length based on number of length offsets & total time
224 double end_time = (1 + total_lengths) * length;
225 int64_t length_units = current_track->to_units(end_time, 0) -
227 if(length_units < 1) length_units = 1;
228 //printf("Tracks::set_edit_length %d %f %f\n", __LINE__,
229 // end_time, current_track->from_units(total_units));
230 total_units += length_units;
232 // Go in using the edit handle interface
233 int64_t starting_length = current_edit->length;
235 current_edit->shift_end(MOVE_RIPPLE,
236 current_edit->startproject + length_units,
237 current_edit->startproject + current_edit->length,
239 edl->session->autos_follow_edits,
240 edl->session->plugins_follow_edits,
243 int64_t ending_length = current_edit->length;
245 if(edl->session->labels_follow_edits && first_track)
247 // printf("Tracks::set_edit_length %d %f %f\n",
249 // current_track->from_units(current_edit->startproject + starting_length),
250 // current_track->from_units(current_edit->startproject + ending_length));
251 edl->labels->modify_handles(
252 current_track->from_units(current_edit->startproject + starting_length),
253 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 current_edit->shift_end(MOVE_RIPPLE,
303 current_edit->startproject + length_units,
304 current_edit->startproject + current_edit->length,
306 edl->session->autos_follow_edits,
307 edl->session->plugins_follow_edits,
310 int64_t ending_length = current_edit->length;
312 if(edl->session->labels_follow_edits && first_track) {
313 // printf("Tracks::set_edit_length %d %f %f\n", __LINE__,
314 // current_track->from_units(current_edit->startproject + starting_length),
315 // current_track->from_units(current_edit->startproject + ending_length));
316 edl->labels->modify_handles(
317 current_track->from_units(current_edit->startproject + starting_length),
318 current_track->from_units(current_edit->startproject + ending_length),
327 #endif // !USE_FLOATING_LENGTHS
334 void Tracks::set_transition_length(double start, double end, double length)
336 for(Track *current_track = first;
338 current_track = current_track->next)
340 if(current_track->record)
342 int64_t start_units = current_track->to_units(start, 0);
343 int64_t end_units = current_track->to_units(end, 0);
345 for(Edit *current_edit = current_track->edits->first;
347 current_edit = current_edit->next)
349 if(current_edit->startproject >= start_units &&
350 current_edit->startproject < end_units &&
351 current_edit->transition)
353 current_edit->transition->length =
354 current_track->to_units(length, 1);
355 if( current_edit == current_track->edits->last &&
356 current_edit->silence() ) {
357 current_edit->length = current_edit->transition->length;
365 void Tracks::set_transition_length(Transition *transition, double length)
367 // Must verify existence of transition
369 if(!transition) return;
370 for(Track *current_track = first;
371 current_track && !done;
372 current_track = current_track->next)
374 for(Edit *current_edit = current_track->edits->first;
375 current_edit && !done;
376 current_edit = current_edit->next)
378 if(current_edit->transition == transition)
380 transition->length = current_track->to_units(length, 1);
381 if( current_edit == current_track->edits->last &&
382 current_edit->silence() ) {
383 current_edit->length = current_edit->transition->length;
391 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
394 for( Track *track=first; track; track=track->next ) {
395 if( !track->record || track->data_type != track_type ) continue;
396 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
397 if( !edit->is_selected ) continue;
398 edit->insert_transition(title);
403 clear_selected_edits();
407 for( Track *track=first; track; track=track->next ) {
408 if( !track->record || track->data_type != track_type ) continue;
409 int64_t start_units = track->to_units(start, 0);
410 int64_t end_units = track->to_units(end, 0);
411 if( start_units == end_units ) {
412 for( Edit *edit = track->edits->first; edit; edit = edit->next) {
413 int64_t edit_start = edit->startproject;
414 int64_t edit_end = edit_start + edit->length;
415 if( edit_start > start_units ) continue;
416 if( start_units == track->edits->length() ) {
417 double length = edl->session->default_transition_length;
418 int64_t units = track->to_units(length, 1);
419 edit = track->edits->
420 create_silence(start_units, start_units+units);
422 else if( start_units >= edit_end ) continue;
423 edit->insert_transition(title);
427 for( Edit *edit=track->edits->first; edit; edit=edit->next) {
428 int64_t edit_start = edit->startproject;
429 if( !edit_start ) continue;
430 if( edit_start >= start_units && edit_start < end_units ) {
431 edit->insert_transition(title);
438 void Tracks::set_automation_mode(double selectionstart,
442 Track* current_track;
444 for(current_track = first; current_track; current_track = current_track->next)
446 if(current_track->record)
448 current_track->set_automation_mode(selectionstart,
455 int Tracks::clear_default_keyframe()
457 for(Track *current = first; current; current = NEXT)
460 current->clear_automation(0, 0, 0, 1);
465 int Tracks::clear_handle(double start,
467 double &longest_distance,
472 Track* current_track;
475 for(current_track = first; current_track; current_track = current_track->next)
477 if(current_track->record)
479 current_track->clear_handle(start,
485 if(distance > longest_distance) longest_distance = distance;
492 int Tracks::copy_automation(double selectionstart,
498 // called by MWindow::copy_automation for copying automation alone
499 Track* current_track;
501 file->tag.set_title("AUTO_CLIPBOARD");
502 file->tag.set_property("LENGTH", selectionend - selectionstart);
503 file->tag.set_property("FRAMERATE", edl->session->frame_rate);
504 file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
506 file->append_newline();
507 file->append_newline();
509 for(current_track = first;
511 current_track = current_track->next)
513 if(current_track->record)
515 current_track->copy_automation(selectionstart,
523 file->tag.set_title("/AUTO_CLIPBOARD");
525 file->append_newline();
526 file->terminate_string();
530 // int Tracks::copy_default_keyframe(FileXML *file)
532 // copy_automation(0, 0, file, 1, 0);
536 int Tracks::delete_tracks()
538 int total_deleted = 0;
544 Track *next_track = 0;
545 for (Track* current = first; current && done; current = next_track)
547 next_track = current->next;
550 delete_track(current);
558 return total_deleted;
561 void Tracks::move_edits(ArrayList<Edit*> *in_edits, Track *track, double position,
562 int edit_labels, int edit_plugins, int edit_autos, int mode)
564 // have to make a copy, optimize kills edits
565 ArrayList<Edit*> edits;
566 for( int i=0; i<in_edits->size(); ++i ) {
567 Edit *edit = in_edits->get(i);
568 Edit *new_edit = new Edit(edit->edl, edit->track);
569 new_edit->copy_from(edit);
570 edits.append(new_edit);
573 int current_aedit = 0, current_vedit = 0;
574 //printf("Tracks::move_edits 1\n");
575 for( Track *dest_track=track; dest_track; dest_track=dest_track->next ) {
576 if( !dest_track->record ) continue;
577 // Need a local copy of the source edit since the original source edit may
578 // change in the editing operation.
580 Edit *source_edit = 0;
581 Track *clip_track = 0;
582 switch( dest_track->data_type ) {
584 while( current_aedit < edits.size() ) {
585 Edit *edit = edits[current_aedit++];
586 if( edit->track->data_type == TRACK_AUDIO ) {
588 ATrack *atrack = new ATrack(dest_track->edl, 0);
589 atrack->create_objects();
596 while( current_vedit < edits.size() ) {
597 Edit *edit = edits[current_vedit++];
598 if( edit->track->data_type == TRACK_VIDEO ) {
600 VTrack *vtrack = new VTrack(dest_track->edl, 0);
601 vtrack->create_objects();
608 if( !source_edit ) continue;
610 Track *source_track = source_edit->track;
611 int64_t start = source_edit->startproject;
612 int64_t length = source_edit->length, end = start + length;
613 double source_start = source_track->from_units(start);
614 double source_end = source_track->from_units(start+length);
615 double len = source_end - source_start;
616 double dest_start = position;
617 double dest_end = dest_start + len;
619 if( edit_labels && dest_track == track ) {
621 Labels labels(0, "LABELS");
622 source_edit->edl->labels->copy(source_start, source_end, &label_xml);
623 source_edit->edl->labels->clear(source_start, source_end, mode);
624 if( !label_xml.read_tag() )
625 labels.load(&label_xml, LOAD_ALL);
626 double pos = dest_start;
627 if( mode && source_start < dest_start ) pos -= len;
628 edl->labels->insert_labels(&labels, pos, len, mode);
633 source_track->copy(COPY_TRACKS, source_start, source_end, &track_xml, "");
634 if( !track_xml.read_tag() )
635 clip_track->load(&track_xml, 0, LOAD_ALL);
637 if( !mode ) { // mute and overwrite
638 source_track->clear(start, end, 1, 0,
639 edit_plugins, edit_autos, 0);
640 source_track->edits->paste_silence(start, end);
642 source_track->shift_keyframes(start, length);
644 int n = source_track->plugin_set.size();
645 if( n > 0 ) dest_track->expand_view = 1;
646 for( int k=0; k<n; ++k )
647 source_track->plugin_set[k]->paste_silence(start, end, 1);
649 dest_track->clear(dest_start, dest_end, 1, 0,
650 edit_plugins, edit_autos, 0);
651 dest_track->insert_track(clip_track, dest_start, 0,
652 edit_plugins, edit_autos, len);
654 else { // cut and paste
655 dest_track->insert_track(clip_track, dest_start, 0,
656 edit_plugins, edit_autos, len);
657 if( source_track == dest_track && dest_start < source_start ) {
658 source_start += len; source_end += len;
660 source_track->clear(source_start, source_end, 1, 0,
661 edit_plugins, edit_autos, 0);
665 dest_track->optimize();
668 edits.remove_all_objects();
671 void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)
673 Track *source_track = plugin->track;
675 // Create a new plugin set
676 double start = track->from_units(position);
677 double length = track->from_units(plugin->length);
679 result = track->insert_effect("", &plugin->shared_location, 0, 0,
680 start, length, plugin->plugin_type);
681 result->copy_from(plugin);
682 result->shift(position - plugin->startproject);
684 // Clear new plugin from old set
685 plugin->plugin_set->clear(plugin->startproject,
686 plugin->startproject + plugin->length,
687 edl->session->autos_follow_edits);
689 source_track->optimize();
692 void Tracks::move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position)
694 // src/dest track must be the same
695 // replace plugin in source plugin_set with silence
696 PluginSet *src_plugin_set = plugin->plugin_set;
697 Plugin *silent = new Plugin(edl, src_plugin_set, "");
698 silent->startproject = plugin->startproject;
699 silent->length = plugin->length;
700 src_plugin_set->insert_after(plugin, silent);
701 src_plugin_set->remove_pointer(plugin);
702 // truncate previous plugin
703 Plugin *dest = (Plugin *)plugin_set->editof(position, PLAY_FORWARD, 0);
704 // add plugin after dest
705 plugin_set->insert_after(dest, plugin);
707 dest->length = position - dest->startproject;
708 if( dest->length < 0 ) dest->length = 0;
710 // update plugin position
711 plugin->startproject = position;
712 plugin->plugin_set = plugin_set;
713 plugin->edits = plugin_set;
714 src_plugin_set->track->optimize();
717 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
719 Track *output_track, *first_output_track, *input_track;
720 int i, data_type = TRACK_AUDIO;
725 for(i = 0; i < 2; i++)
727 // Get first output track
728 for(output_track = first;
730 output_track = output_track->next)
731 if(output_track->data_type == data_type &&
732 output_track->record) break;
734 first_output_track = output_track;
736 // Get first input track
737 for(input_track = first;
739 input_track = input_track->next)
741 if(input_track->data_type == data_type &&
743 !input_track->record) break;
747 if(output_track && input_track)
749 // Transfer input track to end of output track one at a time
752 output_start = output_track->get_length();
753 output_track->insert_track(input_track,
760 // Get next source and destination
761 for(input_track = input_track->next;
763 input_track = input_track->next)
766 if(input_track->data_type == data_type &&
767 !input_track->record &&
768 input_track->play) break;
771 for(output_track = output_track->next;
773 output_track = output_track->next)
775 if(output_track->data_type == data_type &&
776 output_track->record) break;
781 output_track = first_output_track;
787 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
793 int Tracks::delete_all_tracks()
795 while(last) delete last;
800 void Tracks::change_modules(int old_location, int new_location, int do_swap)
802 for(Track* current = first ; current; current = current->next)
804 current->change_modules(old_location, new_location, do_swap);
808 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
810 for(Track* current = first ; current; current = current->next)
812 current->change_plugins(old_location, new_location, do_swap);
818 // =========================================== EDL editing
821 int Tracks::copy(int copy_flags, double start, double end,
822 FileXML *file, const char *output_path)
824 int all = (copy_flags & COPY_ALL) ? 1 : 0;
825 // if nothing selected
826 if( start == end && !all ) return 1;
827 for( Track *track=first; track; track=track->next ) {
828 if( track->record || all )
829 track->copy(copy_flags, start, end, file, output_path);
836 int Tracks::move_track_up(Track *track)
838 Track *next_track = track->previous;
839 if(!next_track) next_track = last;
841 change_modules(number_of(track), number_of(next_track), 1);
843 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
845 // for(Track *current = first; current && count < 5; current = NEXT, count++)
846 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
847 // printf("Tracks::move_track_up 2\n");
849 swap(track, next_track);
852 // for(Track *current = first; current && count < 5; current = NEXT, count++)
853 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
854 // printf("Tracks::move_track_up 3\n");
859 int Tracks::move_track_down(Track *track)
861 Track *next_track = track->next;
862 if(!next_track) next_track = first;
864 change_modules(number_of(track), number_of(next_track), 1);
865 swap(track, next_track);
870 int Tracks::move_tracks_up()
875 Track *track = next; next = track->next;
876 if( !track->record ) continue;
877 if( track->previous ) {
878 change_modules(number_of(track->previous), number_of(track), 1);
879 swap(track->previous, track);
887 int Tracks::move_tracks_down()
892 Track *track = prev; prev = track->previous;
893 if( !track->record ) continue;
895 change_modules(number_of(track), number_of(track->next), 1);
896 swap(track, track->next);
905 void Tracks::paste_audio_transition(PluginServer *server)
907 for(Track *current = first; current; current = NEXT)
909 if(current->data_type == TRACK_AUDIO &&
912 int64_t position = current->to_units(
913 edl->local_session->get_selectionstart(), 0);
914 Edit *current_edit = current->edits->editof(position,
917 if( !current_edit && position == current->edits->length() ) {
918 double length = edl->session->default_transition_length;
919 int64_t units = current->to_units(length, 1);
920 current_edit = current->edits->create_silence(position, position+units);
924 paste_transition(server, current_edit);
930 void Tracks::paste_automation(double selectionstart,
936 Track* current_track = 0;
937 Track* current_atrack = 0;
938 Track* current_vtrack = 0;
939 Track* dst_track = 0;
943 double frame_rate = edl->session->frame_rate;
944 int64_t sample_rate = edl->session->sample_rate;
945 char string[BCTEXTLEN];
950 result = file->read_tag();
952 !file->tag.title_is("AUTO_CLIPBOARD"));
956 length = file->tag.get_property("LENGTH", 0);
957 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
958 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
963 result = file->read_tag();
967 if(file->tag.title_is("/AUTO_CLIPBOARD"))
972 if(file->tag.title_is("TRACK"))
974 file->tag.get_property("TYPE", string);
975 if(!strcmp(string, "AUDIO"))
977 src_type = TRACK_AUDIO;
981 src_type = TRACK_VIDEO;
984 // paste to any media type
987 if(!current_track) current_track = first;
988 while(current_track && !current_track->record)
989 current_track = current_track->next;
990 dst_track = current_track;
993 if(!strcmp(string, "AUDIO"))
995 // Get next audio track
997 current_atrack = first;
999 current_atrack = current_atrack->next;
1001 while(current_atrack &&
1002 (current_atrack->data_type != TRACK_AUDIO ||
1003 !current_atrack->record))
1004 current_atrack = current_atrack->next;
1005 dst_track = current_atrack;
1009 // Get next video track
1011 current_vtrack = first;
1013 current_vtrack = current_vtrack->next;
1015 while(current_vtrack &&
1016 (current_vtrack->data_type != TRACK_VIDEO ||
1017 !current_vtrack->record))
1018 current_vtrack = current_vtrack->next;
1020 dst_track = current_vtrack;
1025 double frame_rate2 = frame_rate;
1026 double sample_rate2 = sample_rate;
1028 if(src_type != dst_track->data_type)
1030 frame_rate2 = sample_rate;
1031 sample_rate2 = frame_rate;
1034 dst_track->paste_automation(selectionstart,
1048 // int Tracks::paste_default_keyframe(FileXML *file)
1050 // paste_automation(0, file, 1, 0);
1054 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1056 dest_edit->insert_transition(server->title);
1059 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1061 for(Track *current = first; current; current = NEXT)
1063 if(current->data_type == TRACK_VIDEO &&
1066 int64_t position = current->to_units(
1067 edl->local_session->get_selectionstart(), 0);
1068 Edit *current_edit = current->edits->editof(position,
1071 if( !current_edit && position == current->edits->length() ) {
1072 double length = edl->session->default_transition_length;
1073 int64_t units = current->to_units(length, 1);
1074 current_edit = current->edits->create_silence(position, position+units);
1078 paste_transition(server, current_edit);
1080 if(first_track) break;
1086 int Tracks::paste_silence(double start,
1091 Track* current_track;
1093 for(current_track = first;
1095 current_track = current_track->next)
1097 if(current_track->record)
1099 current_track->paste_silence(start,
1110 int Tracks::select_auto(int cursor_x, int cursor_y)
1113 for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1117 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1121 for(Track* current = first; current && !result; current = NEXT)
1123 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1128 int Tracks::modify_edithandles(double &oldposition, double &newposition,
1129 int currentend, int handle_mode, int edit_labels,
1130 int edit_plugins, int edit_autos, int group_id)
1132 for( Track *track=first; track; track=track->next ) {
1133 if( !track->record ) continue;
1134 track->modify_edithandles(oldposition, newposition,
1135 currentend, handle_mode, edit_labels,
1136 edit_plugins, edit_autos, group_id);
1137 // labels follow first armed track
1143 int Tracks::modify_pluginhandles(double &oldposition, double &newposition,
1144 int currentend, int handle_mode, int edit_labels,
1145 int edit_autos, Edits *trim_edits)
1147 for( Track *track=first; track; track=track->next ) {
1148 if( !track->record ) continue;
1149 track->modify_pluginhandles(oldposition, newposition,
1150 currentend, handle_mode, edit_labels,
1151 edit_autos, trim_edits);
1157 int Tracks::purge_asset(Asset *asset)
1159 Track *current_track;
1162 for(current_track = first; current_track; current_track = current_track->next)
1164 result += current_track->purge_asset(asset);
1169 int Tracks::asset_used(Asset *asset)
1171 Track *current_track;
1174 for(current_track = first; current_track; current_track = current_track->next)
1176 result += current_track->asset_used(asset);
1181 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1183 Track *current_track;
1185 for(current_track = first;
1187 current_track = current_track->next)
1189 if((current_track->record || ignore_record) &&
1190 current_track->data_type == TRACK_VIDEO)
1192 current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);