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 void Tracks::shuffle_edits(double start, double end)
125 // This doesn't affect automation or effects
126 // Labels follow the first track.
128 for(Track *current_track = first;
130 current_track = current_track->next)
132 if(current_track->record)
134 current_track->shuffle_edits(start, end, first_track);
141 void Tracks::reverse_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->reverse_edits(start, end, first_track);
158 void Tracks::align_edits(double start, double end)
160 // This doesn't affect automation or effects
161 ArrayList<double> times;
163 for(Track *current_track = first;
165 current_track = current_track->next)
167 if(current_track->record)
169 current_track->align_edits(start, end, ×);
174 void Tracks::set_edit_length(double start, double end, double length)
177 for(Track *current_track = first;
179 current_track = current_track->next)
181 if(current_track->record)
183 #define USE_FLOATING_LENGTHS
185 #ifdef USE_FLOATING_LENGTHS
188 // The first edit anchors the length offsets.
189 // Round edits up & down so they end where they would if they all had floating point lengths.
190 //int first_edit = 1;
191 int64_t start_units = current_track->to_units(start, 0);
192 int64_t end_units = current_track->to_units(end, 0);
193 // Total time of edits accumulated, in track units
194 int64_t total_units = 0;
195 // Number of length offsets added so far
196 int total_lengths = 0;
198 for(Edit *current_edit = current_track->edits->last;
200 current_edit = current_edit->previous)
202 if(current_edit->startproject >= start_units &&
203 current_edit->startproject + current_edit->length <= end_units)
205 // Calculate true length based on number of length offsets & total time
206 double end_time = (1 + total_lengths) * length;
207 int64_t length_units = current_track->to_units(end_time, 0) -
209 if(length_units < 1) length_units = 1;
210 //printf("Tracks::set_edit_length %d %f %f\n", __LINE__,
211 // end_time, current_track->from_units(total_units));
212 total_units += length_units;
214 // Go in using the edit handle interface
215 int64_t starting_length = current_edit->length;
217 if(length_units < current_edit->length)
219 current_edit->shift_end_in(MOVE_ALL_EDITS,
220 current_edit->startproject + length_units,
221 current_edit->startproject + current_edit->length,
223 edl->session->labels_follow_edits,
224 edl->session->plugins_follow_edits,
225 edl->session->autos_follow_edits,
230 current_edit->shift_end_out(MOVE_ALL_EDITS,
231 current_edit->startproject + length_units,
232 current_edit->startproject + current_edit->length,
234 edl->session->labels_follow_edits,
235 edl->session->plugins_follow_edits,
236 edl->session->autos_follow_edits,
240 int64_t ending_length = current_edit->length;
242 if(edl->session->labels_follow_edits && first_track)
244 // printf("Tracks::set_edit_length %d %f %f\n",
246 // current_track->from_units(current_edit->startproject + starting_length),
247 // current_track->from_units(current_edit->startproject + ending_length));
248 edl->labels->modify_handles(
249 current_track->from_units(current_edit->startproject + starting_length),
250 current_track->from_units(current_edit->startproject + ending_length),
264 #else // USE_FLOATING_LENGTHS
266 // The first edit anchors the length offsets.
267 // The idea was to round edits up & down so they end where they should
268 // if they all had floating point lengths. It's easier just to make sure the framerate
269 // is divisible by the required length.
270 // int first_edit = 1;
271 int64_t start_units = current_track->to_units(start, 0);
272 int64_t end_units = current_track->to_units(end, 0);
273 int64_t length_units = current_track->to_units(length, 1);
274 // Starting time of the length offsets in seconds
275 // double start_time = 0;
276 // Number of length offsets added so far
277 // int total_lengths = 0;
279 for(Edit *current_edit = current_track->edits->last;
281 current_edit = current_edit->previous)
283 if(current_edit->startproject >= start_units &&
284 current_edit->startproject + current_edit->length <= end_units)
286 // Calculate starting time of length offsets
289 // start_time = current_track->from_units(current_edit->startproject);
292 // Calculate true length based on number of length offsets
293 // double end_time = start_time + (1 + total_lengths) * length;
294 // int64_t length_units = current_track->to_units(end_time, 0) -
295 // current_edit->startproject;
296 // if(length_units < 1) length_units = 1;
298 // Go in using the edit handle interface
299 int64_t starting_length = current_edit->length;
301 if(length_units < current_edit->length)
303 current_edit->shift_end_in(MOVE_ALL_EDITS,
304 current_edit->startproject + length_units,
305 current_edit->startproject + current_edit->length,
307 edl->session->labels_follow_edits,
308 edl->session->plugins_follow_edits,
309 edl->session->autos_follow_edits,
314 current_edit->shift_end_out(MOVE_ALL_EDITS,
315 current_edit->startproject + length_units,
316 current_edit->startproject + current_edit->length,
318 edl->session->labels_follow_edits,
319 edl->session->plugins_follow_edits,
320 edl->session->autos_follow_edits,
324 int64_t ending_length = current_edit->length;
326 if(edl->session->labels_follow_edits && first_track)
328 // printf("Tracks::set_edit_length %d %f %f\n",
330 // current_track->from_units(current_edit->startproject + starting_length),
331 // current_track->from_units(current_edit->startproject + ending_length));
332 edl->labels->modify_handles(
333 current_track->from_units(current_edit->startproject + starting_length),
334 current_track->from_units(current_edit->startproject + ending_length),
345 #endif // !USE_FLOATING_LENGTHS
352 void Tracks::set_transition_length(double start, double end, double length)
354 for(Track *current_track = first;
356 current_track = current_track->next)
358 if(current_track->record)
360 int64_t start_units = current_track->to_units(start, 0);
361 int64_t end_units = current_track->to_units(end, 0);
363 for(Edit *current_edit = current_track->edits->first;
365 current_edit = current_edit->next)
367 if(current_edit->startproject >= start_units &&
368 current_edit->startproject < end_units &&
369 current_edit->transition)
371 current_edit->transition->length =
372 current_track->to_units(length, 1);
373 if( current_edit == current_track->edits->last &&
374 current_edit->silence() ) {
375 current_edit->length = current_edit->transition->length;
383 void Tracks::set_transition_length(Transition *transition, double length)
385 // Must verify existence of transition
387 if(!transition) return;
388 for(Track *current_track = first;
389 current_track && !done;
390 current_track = current_track->next)
392 for(Edit *current_edit = current_track->edits->first;
393 current_edit && !done;
394 current_edit = current_edit->next)
396 if(current_edit->transition == transition)
398 transition->length = current_track->to_units(length, 1);
399 if( current_edit == current_track->edits->last &&
400 current_edit->silence() ) {
401 current_edit->length = current_edit->transition->length;
409 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
412 for( Track *track=first; track; track=track->next ) {
413 if( !track->record || track->data_type != track_type ) continue;
414 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
415 if( !edit->is_selected ) continue;
416 edit->insert_transition(title);
421 clear_selected_edits();
425 for( Track *track=first; track; track=track->next ) {
426 if( !track->record || track->data_type != track_type ) continue;
427 int64_t start_units = track->to_units(start, 0);
428 int64_t end_units = track->to_units(end, 0);
429 if( start_units == end_units ) {
430 for( Edit *edit = track->edits->first; edit; edit = edit->next) {
431 int64_t edit_start = edit->startproject;
432 int64_t edit_end = edit_start + edit->length;
433 if( edit_start > start_units ) continue;
434 if( start_units == track->edits->length() ) {
435 double length = edl->session->default_transition_length;
436 int64_t units = track->to_units(length, 1);
437 edit = track->edits->
438 create_silence(start_units, start_units+units);
440 else if( start_units >= edit_end ) continue;
441 edit->insert_transition(title);
445 for( Edit *edit=track->edits->first; edit; edit=edit->next) {
446 int64_t edit_start = edit->startproject;
447 if( !edit_start ) continue;
448 if( edit_start >= start_units && edit_start < end_units ) {
449 edit->insert_transition(title);
456 void Tracks::set_automation_mode(double selectionstart,
460 Track* current_track;
462 for(current_track = first; current_track; current_track = current_track->next)
464 if(current_track->record)
466 current_track->set_automation_mode(selectionstart,
473 int Tracks::clear_default_keyframe()
475 for(Track *current = first; current; current = NEXT)
478 current->clear_automation(0, 0, 0, 1);
483 int Tracks::clear_handle(double start,
485 double &longest_distance,
490 Track* current_track;
493 for(current_track = first; current_track; current_track = current_track->next)
495 if(current_track->record)
497 current_track->clear_handle(start,
503 if(distance > longest_distance) longest_distance = distance;
510 int Tracks::copy_automation(double selectionstart,
516 // called by MWindow::copy_automation for copying automation alone
517 Track* current_track;
519 file->tag.set_title("AUTO_CLIPBOARD");
520 file->tag.set_property("LENGTH", selectionend - selectionstart);
521 file->tag.set_property("FRAMERATE", edl->session->frame_rate);
522 file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
524 file->append_newline();
525 file->append_newline();
527 for(current_track = first;
529 current_track = current_track->next)
531 if(current_track->record)
533 current_track->copy_automation(selectionstart,
541 file->tag.set_title("/AUTO_CLIPBOARD");
543 file->append_newline();
544 file->terminate_string();
548 // int Tracks::copy_default_keyframe(FileXML *file)
550 // copy_automation(0, 0, file, 1, 0);
554 int Tracks::delete_tracks()
556 int total_deleted = 0;
562 Track *next_track = 0;
563 for (Track* current = first; current && done; current = next_track)
565 next_track = current->next;
568 delete_track(current);
576 return total_deleted;
579 void Tracks::move_edits(ArrayList<Edit*> *edits,
582 int edit_labels, // Ignored
583 int edit_plugins, // Ignored
584 int edit_autos, // Ignored
587 //printf("Tracks::move_edits 1\n");
588 for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
590 if(dest_track->record)
592 // Need a local copy of the source edit since the original source edit may
593 // change in the editing operation.
594 Edit *source_edit = 0;
595 Track *source_track = 0;
599 if(dest_track->data_type == TRACK_AUDIO)
601 int current_aedit = 0;
603 while(current_aedit < edits->total &&
604 edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
607 if(current_aedit < edits->total)
609 source_edit = edits->values[current_aedit];
610 source_track = source_edit->track;
611 edits->remove_number(current_aedit);
615 if(dest_track->data_type == TRACK_VIDEO)
617 int current_vedit = 0;
618 while(current_vedit < edits->total &&
619 edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
622 if(current_vedit < edits->total)
624 source_edit = edits->values[current_vedit];
625 source_track = source_edit->track;
626 edits->remove_number(current_vedit);
630 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
633 int64_t position_i = source_track->to_units(position, 0);
634 // Source edit changes
635 int64_t source_length = source_edit->length;
636 int64_t source_startproject = source_edit->startproject;
640 // This works like this: CUT edit, INSERT edit at final position, keyframes also follow
641 // FIXME: there should be a GUI way to tell whenever user also wants to move autos or not
642 // this is all screwed up
643 // inserts defaults/bogus everywhere
647 AutoConf temp_autoconf;
649 temp_autoconf.set_all(1);
651 source_track->automation->copy(source_edit->startproject,
652 source_edit->startproject + source_edit->length,
656 temp.terminate_string();
658 // Insert new keyframes
659 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
660 source_track->automation->clear(source_edit->startproject,
661 source_edit->startproject + source_edit->length,
664 int64_t position_a = position_i;
665 if (dest_track == source_track)
667 if (position_a > source_edit->startproject)
668 position_a -= source_length;
671 dest_track->automation->paste_silence(position_a,
672 position_a + source_length);
673 while(!temp.read_tag())
674 dest_track->automation->paste(position_a,
675 source_length, 1.0, &temp, 0, 1,
679 Edit *dest_edit = dest_track->edits->shift(position_i,
681 Edit *result = dest_track->edits->insert_before(dest_edit,
682 dest_track->edits->create_edit());
683 result->copy_from(source_edit);
684 result->startproject = position_i;
685 result->length = source_length;
688 source_track->edits->clear(source_edit->startproject,
689 source_edit->startproject + source_length);
692 //this is outline for future thinking how it is supposed to be done trough C&P mechanisms
694 source_track->cut(source_edit->startproject,
695 source_edit->startproject + source_edit->length,
698 temp.terminate_string();
700 dest_track->paste_silence(position_a,
701 position_a + source_length,
703 while(!temp.read_tag())
704 dest_track->paste(position_a, // MISSING PIECE OF FUNCTIONALITY
715 // ONLY edit is moved, all other edits stay where they are
717 // Copy edit to temp, delete the edit, insert the edit
718 Edit *temp_edit = dest_track->edits->create_edit();
719 temp_edit->copy_from(source_edit);
720 // we call the edits directly since we do not want to move keyframes or anything else
721 source_track->edits->clear(source_startproject,
722 source_startproject + source_length);
723 source_track->edits->paste_silence(source_startproject,
724 source_startproject + source_length);
726 dest_track->edits->clear(position_i,
727 position_i + source_length);
728 Edit *dest_edit = dest_track->edits->shift(position_i, source_length);
729 Edit *result = dest_track->edits->insert_before(dest_edit,
730 dest_track->edits->create_edit());
731 result->copy_from(temp_edit);
732 result->startproject = position_i;
733 result->length = source_length;
736 source_track->optimize();
737 dest_track->optimize();
743 void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)
745 Track *source_track = plugin->track;
747 // Create a new plugin set
748 double start = track->from_units(position);
749 double length = track->from_units(plugin->length);
751 result = track->insert_effect("", &plugin->shared_location, 0, 0,
752 start, length, plugin->plugin_type);
753 result->copy_from(plugin);
754 result->shift(position - plugin->startproject);
756 // Clear new plugin from old set
757 plugin->plugin_set->clear(plugin->startproject,
758 plugin->startproject + plugin->length,
759 edl->session->autos_follow_edits);
761 source_track->optimize();
764 void Tracks::move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position)
766 // src/dest track must be the same
767 // replace plugin in source plugin_set with silence
768 PluginSet *src_plugin_set = plugin->plugin_set;
769 Plugin *silent = new Plugin(edl, src_plugin_set, "");
770 silent->startproject = plugin->startproject;
771 silent->length = plugin->length;
772 src_plugin_set->insert_after(plugin, silent);
773 src_plugin_set->remove_pointer(plugin);
774 // truncate previous plugin
775 Plugin *dest = (Plugin *)plugin_set->editof(position, PLAY_FORWARD, 0);
776 // add plugin after dest
777 plugin_set->insert_after(dest, plugin);
779 dest->length = position - dest->startproject;
780 if( dest->length < 0 ) dest->length = 0;
782 // update plugin position
783 plugin->startproject = position;
784 plugin->plugin_set = plugin_set;
785 plugin->edits = plugin_set;
786 src_plugin_set->track->optimize();
789 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
791 Track *output_track, *first_output_track, *input_track;
792 int i, data_type = TRACK_AUDIO;
797 for(i = 0; i < 2; i++)
799 // Get first output track
800 for(output_track = first;
802 output_track = output_track->next)
803 if(output_track->data_type == data_type &&
804 output_track->record) break;
806 first_output_track = output_track;
808 // Get first input track
809 for(input_track = first;
811 input_track = input_track->next)
813 if(input_track->data_type == data_type &&
815 !input_track->record) break;
819 if(output_track && input_track)
821 // Transfer input track to end of output track one at a time
824 output_start = output_track->get_length();
825 output_track->insert_track(input_track,
832 // Get next source and destination
833 for(input_track = input_track->next;
835 input_track = input_track->next)
838 if(input_track->data_type == data_type &&
839 !input_track->record &&
840 input_track->play) break;
843 for(output_track = output_track->next;
845 output_track = output_track->next)
847 if(output_track->data_type == data_type &&
848 output_track->record) break;
853 output_track = first_output_track;
859 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
865 int Tracks::delete_all_tracks()
867 while(last) delete last;
872 void Tracks::change_modules(int old_location, int new_location, int do_swap)
874 for(Track* current = first ; current; current = current->next)
876 current->change_modules(old_location, new_location, do_swap);
880 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
882 for(Track* current = first ; current; current = current->next)
884 current->change_plugins(old_location, new_location, do_swap);
890 // =========================================== EDL editing
893 int Tracks::copy(double start,
897 const char *output_path)
900 if(start == end && !all) return 1;
908 if(current->record || all)
910 current->copy(start, end, file,output_path);
919 int Tracks::move_track_up(Track *track)
921 Track *next_track = track->previous;
922 if(!next_track) next_track = last;
924 change_modules(number_of(track), number_of(next_track), 1);
926 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
928 // for(Track *current = first; current && count < 5; current = NEXT, count++)
929 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
930 // printf("Tracks::move_track_up 2\n");
932 swap(track, next_track);
935 // for(Track *current = first; current && count < 5; current = NEXT, count++)
936 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
937 // printf("Tracks::move_track_up 3\n");
942 int Tracks::move_track_down(Track *track)
944 Track *next_track = track->next;
945 if(!next_track) next_track = first;
947 change_modules(number_of(track), number_of(next_track), 1);
948 swap(track, next_track);
953 int Tracks::move_tracks_up()
955 Track *track, *next_track;
962 next_track = track->next;
968 change_modules(number_of(track->previous), number_of(track), 1);
970 swap(track->previous, track);
979 int Tracks::move_tracks_down()
981 Track *track, *previous_track;
986 track = previous_track)
988 previous_track = track->previous;
994 change_modules(number_of(track), number_of(track->next), 1);
996 swap(track, track->next);
1007 void Tracks::paste_audio_transition(PluginServer *server)
1009 for(Track *current = first; current; current = NEXT)
1011 if(current->data_type == TRACK_AUDIO &&
1014 int64_t position = current->to_units(
1015 edl->local_session->get_selectionstart(), 0);
1016 Edit *current_edit = current->edits->editof(position,
1019 if( !current_edit && position == current->edits->length() ) {
1020 double length = edl->session->default_transition_length;
1021 int64_t units = current->to_units(length, 1);
1022 current_edit = current->edits->create_silence(position, position+units);
1026 paste_transition(server, current_edit);
1032 void Tracks::paste_automation(double selectionstart,
1038 Track* current_track = 0;
1039 Track* current_atrack = 0;
1040 Track* current_vtrack = 0;
1041 Track* dst_track = 0;
1045 double frame_rate = edl->session->frame_rate;
1046 int64_t sample_rate = edl->session->sample_rate;
1047 char string[BCTEXTLEN];
1052 result = file->read_tag();
1054 !file->tag.title_is("AUTO_CLIPBOARD"));
1058 length = file->tag.get_property("LENGTH", 0);
1059 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
1060 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
1065 result = file->read_tag();
1069 if(file->tag.title_is("/AUTO_CLIPBOARD"))
1074 if(file->tag.title_is("TRACK"))
1076 file->tag.get_property("TYPE", string);
1077 if(!strcmp(string, "AUDIO"))
1079 src_type = TRACK_AUDIO;
1083 src_type = TRACK_VIDEO;
1086 // paste to any media type
1089 if(!current_track) current_track = first;
1090 while(current_track && !current_track->record)
1091 current_track = current_track->next;
1092 dst_track = current_track;
1095 if(!strcmp(string, "AUDIO"))
1097 // Get next audio track
1099 current_atrack = first;
1101 current_atrack = current_atrack->next;
1103 while(current_atrack &&
1104 (current_atrack->data_type != TRACK_AUDIO ||
1105 !current_atrack->record))
1106 current_atrack = current_atrack->next;
1107 dst_track = current_atrack;
1111 // Get next video track
1113 current_vtrack = first;
1115 current_vtrack = current_vtrack->next;
1117 while(current_vtrack &&
1118 (current_vtrack->data_type != TRACK_VIDEO ||
1119 !current_vtrack->record))
1120 current_vtrack = current_vtrack->next;
1122 dst_track = current_vtrack;
1127 double frame_rate2 = frame_rate;
1128 double sample_rate2 = sample_rate;
1130 if(src_type != dst_track->data_type)
1132 frame_rate2 = sample_rate;
1133 sample_rate2 = frame_rate;
1136 dst_track->paste_automation(selectionstart,
1150 // int Tracks::paste_default_keyframe(FileXML *file)
1152 // paste_automation(0, file, 1, 0);
1156 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1158 dest_edit->insert_transition(server->title);
1161 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1163 for(Track *current = first; current; current = NEXT)
1165 if(current->data_type == TRACK_VIDEO &&
1168 int64_t position = current->to_units(
1169 edl->local_session->get_selectionstart(), 0);
1170 Edit *current_edit = current->edits->editof(position,
1173 if( !current_edit && position == current->edits->length() ) {
1174 double length = edl->session->default_transition_length;
1175 int64_t units = current->to_units(length, 1);
1176 current_edit = current->edits->create_silence(position, position+units);
1180 paste_transition(server, current_edit);
1182 if(first_track) break;
1188 int Tracks::paste_silence(double start,
1193 Track* current_track;
1195 for(current_track = first;
1197 current_track = current_track->next)
1199 if(current_track->record)
1201 current_track->paste_silence(start,
1212 int Tracks::select_auto(int cursor_x, int cursor_y)
1215 for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1219 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1223 for(Track* current = first; current && !result; current = NEXT)
1225 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1230 int Tracks::modify_edithandles(double &oldposition,
1231 double &newposition,
1240 for(current = first; current; current = NEXT)
1244 current->modify_edithandles(oldposition,
1256 int Tracks::modify_pluginhandles(double &oldposition,
1257 double &newposition,
1266 for(current = first; current; current = NEXT)
1270 current->modify_pluginhandles(oldposition,
1284 int Tracks::purge_asset(Asset *asset)
1286 Track *current_track;
1289 for(current_track = first; current_track; current_track = current_track->next)
1291 result += current_track->purge_asset(asset);
1296 int Tracks::asset_used(Asset *asset)
1298 Track *current_track;
1301 for(current_track = first; current_track; current_track = current_track->next)
1303 result += current_track->asset_used(asset);
1308 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1310 Track *current_track;
1312 for(current_track = first;
1314 current_track = current_track->next)
1316 if((current_track->record || ignore_record) &&
1317 current_track->data_type == TRACK_VIDEO)
1319 current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);