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::clear(double start, double end, int clear_plugins, int edit_autos)
54 for(current_track = first;
56 current_track = current_track->next)
58 if(current_track->record)
60 current_track->clear(start,
64 clear_plugins, // edit_plugins
73 void Tracks::clear_automation(double selectionstart, double selectionend)
77 for(current_track = first; current_track; current_track = current_track->next)
79 if(current_track->record)
81 current_track->clear_automation(selectionstart,
89 void Tracks::clear_transitions(double start, double end)
91 for(Track *current_track = first;
93 current_track = current_track->next)
95 if(current_track->record)
97 int64_t start_units = current_track->to_units(start, 0);
98 int64_t end_units = current_track->to_units(end, 0);
100 for(Edit *current_edit = current_track->edits->first;
102 current_edit = current_edit->next)
104 if(current_edit->startproject >= start_units &&
105 current_edit->startproject < end_units &&
106 current_edit->transition)
108 current_edit->detach_transition();
115 void Tracks::shuffle_edits(double start, double end)
117 // This doesn't affect automation or effects
118 // Labels follow the first track.
120 for(Track *current_track = first;
122 current_track = current_track->next)
124 if(current_track->record)
126 current_track->shuffle_edits(start, end, first_track);
133 void Tracks::reverse_edits(double start, double end)
135 // This doesn't affect automation or effects
136 // Labels follow the first track.
138 for(Track *current_track = first;
140 current_track = current_track->next)
142 if(current_track->record)
144 current_track->reverse_edits(start, end, first_track);
150 void Tracks::align_edits(double start, double end)
152 // This doesn't affect automation or effects
153 ArrayList<double> times;
155 for(Track *current_track = first;
157 current_track = current_track->next)
159 if(current_track->record)
161 current_track->align_edits(start, end, ×);
166 void Tracks::set_edit_length(double start, double end, double length)
169 for(Track *current_track = first;
171 current_track = current_track->next)
173 if(current_track->record)
175 #define USE_FLOATING_LENGTHS
177 #ifdef USE_FLOATING_LENGTHS
180 // The first edit anchors the length offsets.
181 // Round edits up & down so they end where they would if they all had floating point lengths.
182 //int first_edit = 1;
183 int64_t start_units = current_track->to_units(start, 0);
184 int64_t end_units = current_track->to_units(end, 0);
185 // Total time of edits accumulated, in track units
186 int64_t total_units = 0;
187 // Number of length offsets added so far
188 int total_lengths = 0;
190 for(Edit *current_edit = current_track->edits->last;
192 current_edit = current_edit->previous)
194 if(current_edit->startproject >= start_units &&
195 current_edit->startproject + current_edit->length <= end_units)
197 // Calculate true length based on number of length offsets & total time
198 double end_time = (1 + total_lengths) * length;
199 int64_t length_units = current_track->to_units(end_time, 0) -
201 if(length_units < 1) length_units = 1;
202 printf("Tracks::set_edit_length %d %f %f\n", __LINE__, end_time, current_track->from_units(total_units));
203 total_units += length_units;
205 // Go in using the edit handle interface
206 int64_t starting_length = current_edit->length;
208 if(length_units < current_edit->length)
210 current_edit->shift_end_in(MOVE_ALL_EDITS,
211 current_edit->startproject + length_units,
212 current_edit->startproject + current_edit->length,
214 edl->session->labels_follow_edits,
215 edl->session->plugins_follow_edits,
216 edl->session->autos_follow_edits,
221 current_edit->shift_end_out(MOVE_ALL_EDITS,
222 current_edit->startproject + length_units,
223 current_edit->startproject + current_edit->length,
225 edl->session->labels_follow_edits,
226 edl->session->plugins_follow_edits,
227 edl->session->autos_follow_edits,
231 int64_t ending_length = current_edit->length;
233 if(edl->session->labels_follow_edits && first_track)
235 // printf("Tracks::set_edit_length %d %f %f\n",
237 // current_track->from_units(current_edit->startproject + starting_length),
238 // current_track->from_units(current_edit->startproject + ending_length));
239 edl->labels->modify_handles(
240 current_track->from_units(current_edit->startproject + starting_length),
241 current_track->from_units(current_edit->startproject + ending_length),
255 #else // USE_FLOATING_LENGTHS
257 // The first edit anchors the length offsets.
258 // The idea was to round edits up & down so they end where they should
259 // if they all had floating point lengths. It's easier just to make sure the framerate
260 // is divisible by the required length.
261 // int first_edit = 1;
262 int64_t start_units = current_track->to_units(start, 0);
263 int64_t end_units = current_track->to_units(end, 0);
264 int64_t length_units = current_track->to_units(length, 1);
265 // Starting time of the length offsets in seconds
266 // double start_time = 0;
267 // Number of length offsets added so far
268 // int total_lengths = 0;
270 for(Edit *current_edit = current_track->edits->last;
272 current_edit = current_edit->previous)
274 if(current_edit->startproject >= start_units &&
275 current_edit->startproject + current_edit->length <= end_units)
277 // Calculate starting time of length offsets
280 // start_time = current_track->from_units(current_edit->startproject);
283 // Calculate true length based on number of length offsets
284 // double end_time = start_time + (1 + total_lengths) * length;
285 // int64_t length_units = current_track->to_units(end_time, 0) -
286 // current_edit->startproject;
287 // if(length_units < 1) length_units = 1;
289 // Go in using the edit handle interface
290 int64_t starting_length = current_edit->length;
292 if(length_units < current_edit->length)
294 current_edit->shift_end_in(MOVE_ALL_EDITS,
295 current_edit->startproject + length_units,
296 current_edit->startproject + current_edit->length,
298 edl->session->labels_follow_edits,
299 edl->session->plugins_follow_edits,
300 edl->session->autos_follow_edits,
305 current_edit->shift_end_out(MOVE_ALL_EDITS,
306 current_edit->startproject + length_units,
307 current_edit->startproject + current_edit->length,
309 edl->session->labels_follow_edits,
310 edl->session->plugins_follow_edits,
311 edl->session->autos_follow_edits,
315 int64_t ending_length = current_edit->length;
317 if(edl->session->labels_follow_edits && first_track)
319 // printf("Tracks::set_edit_length %d %f %f\n",
321 // current_track->from_units(current_edit->startproject + starting_length),
322 // current_track->from_units(current_edit->startproject + ending_length));
323 edl->labels->modify_handles(
324 current_track->from_units(current_edit->startproject + starting_length),
325 current_track->from_units(current_edit->startproject + ending_length),
336 #endif // !USE_FLOATING_LENGTHS
343 void Tracks::set_transition_length(double start, double end, double length)
345 for(Track *current_track = first;
347 current_track = current_track->next)
349 if(current_track->record)
351 int64_t start_units = current_track->to_units(start, 0);
352 int64_t end_units = current_track->to_units(end, 0);
354 for(Edit *current_edit = current_track->edits->first;
356 current_edit = current_edit->next)
358 if(current_edit->startproject >= start_units &&
359 current_edit->startproject < end_units &&
360 current_edit->transition)
362 current_edit->transition->length =
363 current_track->to_units(length, 1);
364 if( current_edit == current_track->edits->last &&
365 current_edit->silence() ) {
366 current_edit->length = current_edit->transition->length;
374 void Tracks::set_transition_length(Transition *transition, double length)
376 // Must verify existence of transition
378 if(!transition) return;
379 for(Track *current_track = first;
380 current_track && !done;
381 current_track = current_track->next)
383 for(Edit *current_edit = current_track->edits->first;
384 current_edit && !done;
385 current_edit = current_edit->next)
387 if(current_edit->transition == transition)
389 transition->length = current_track->to_units(length, 1);
390 if( current_edit == current_track->edits->last &&
391 current_edit->silence() ) {
392 current_edit->length = current_edit->transition->length;
400 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
402 for(Track *current_track = first;
404 current_track = current_track->next)
406 if(current_track->record && current_track->data_type == track_type)
408 int64_t start_units = current_track->to_units(start, 0);
409 int64_t end_units = current_track->to_units(end, 0);
410 if( start_units == end_units ) {
411 for( Edit *current_edit = current_track->edits->first;
412 current_edit; current_edit = current_edit->next) {
413 int64_t edit_start = current_edit->startproject;
414 int64_t edit_end = edit_start + current_edit->length;
415 if( edit_start > start_units ) continue;
416 if( start_units == current_track->edits->length() ) {
417 double length = edl->session->default_transition_length;
418 int64_t units = current_track->to_units(length, 1);
419 current_edit = current_track->edits->
420 create_silence(start_units, start_units+units);
422 else if( start_units >= edit_end ) continue;
423 current_edit->insert_transition(title);
427 for( Edit *current_edit = current_track->edits->first;
428 current_edit; current_edit = current_edit->next) {
429 int64_t edit_start = current_edit->startproject;
430 if( !edit_start ) continue;
431 if( edit_start >= start_units && edit_start < end_units ) {
432 current_edit->insert_transition(title);
440 void Tracks::set_automation_mode(double selectionstart,
444 Track* current_track;
446 for(current_track = first; current_track; current_track = current_track->next)
448 if(current_track->record)
450 current_track->set_automation_mode(selectionstart,
457 int Tracks::clear_default_keyframe()
459 for(Track *current = first; current; current = NEXT)
462 current->clear_automation(0, 0, 0, 1);
467 int Tracks::clear_handle(double start,
469 double &longest_distance,
474 Track* current_track;
477 for(current_track = first; current_track; current_track = current_track->next)
479 if(current_track->record)
481 current_track->clear_handle(start,
487 if(distance > longest_distance) longest_distance = distance;
494 int Tracks::copy_automation(double selectionstart,
500 // called by MWindow::copy_automation for copying automation alone
501 Track* current_track;
503 file->tag.set_title("AUTO_CLIPBOARD");
504 file->tag.set_property("LENGTH", selectionend - selectionstart);
505 file->tag.set_property("FRAMERATE", edl->session->frame_rate);
506 file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
508 file->append_newline();
509 file->append_newline();
511 for(current_track = first;
513 current_track = current_track->next)
515 if(current_track->record)
517 current_track->copy_automation(selectionstart,
525 file->tag.set_title("/AUTO_CLIPBOARD");
527 file->append_newline();
528 file->terminate_string();
532 // int Tracks::copy_default_keyframe(FileXML *file)
534 // copy_automation(0, 0, file, 1, 0);
538 int Tracks::delete_tracks()
540 int total_deleted = 0;
546 Track *next_track = 0;
547 for (Track* current = first; current && done; current = next_track)
549 next_track = current->next;
552 delete_track(current);
560 return total_deleted;
563 void Tracks::move_edits(ArrayList<Edit*> *edits,
566 int edit_labels, // Ignored
567 int edit_plugins, // Ignored
568 int edit_autos, // Ignored
571 //printf("Tracks::move_edits 1\n");
572 for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
574 if(dest_track->record)
576 // Need a local copy of the source edit since the original source edit may
577 // change in the editing operation.
578 Edit *source_edit = 0;
579 Track *source_track = 0;
583 if(dest_track->data_type == TRACK_AUDIO)
585 int current_aedit = 0;
587 while(current_aedit < edits->total &&
588 edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
591 if(current_aedit < edits->total)
593 source_edit = edits->values[current_aedit];
594 source_track = source_edit->track;
595 edits->remove_number(current_aedit);
599 if(dest_track->data_type == TRACK_VIDEO)
601 int current_vedit = 0;
602 while(current_vedit < edits->total &&
603 edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
606 if(current_vedit < edits->total)
608 source_edit = edits->values[current_vedit];
609 source_track = source_edit->track;
610 edits->remove_number(current_vedit);
614 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
617 int64_t position_i = source_track->to_units(position, 0);
618 // Source edit changes
619 int64_t source_length = source_edit->length;
620 int64_t source_startproject = source_edit->startproject;
624 // This works like this: CUT edit, INSERT edit at final position, keyframes also follow
625 // FIXME: there should be a GUI way to tell whenever user also wants to move autos or not
626 // this is all screwed up
627 // inserts defaults/bogus everywhere
631 AutoConf temp_autoconf;
633 temp_autoconf.set_all(1);
635 source_track->automation->copy(source_edit->startproject,
636 source_edit->startproject + source_edit->length,
640 temp.terminate_string();
642 // Insert new keyframes
643 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
644 source_track->automation->clear(source_edit->startproject,
645 source_edit->startproject + source_edit->length,
648 int64_t position_a = position_i;
649 if (dest_track == source_track)
651 if (position_a > source_edit->startproject)
652 position_a -= source_length;
655 dest_track->automation->paste_silence(position_a,
656 position_a + source_length);
657 while(!temp.read_tag())
658 dest_track->automation->paste(position_a,
659 source_length, 1.0, &temp, 0, 1,
663 Edit *dest_edit = dest_track->edits->shift(position_i,
665 Edit *result = dest_track->edits->insert_before(dest_edit,
666 dest_track->edits->create_edit());
667 result->copy_from(source_edit);
668 result->startproject = position_i;
669 result->length = source_length;
672 source_track->edits->clear(source_edit->startproject,
673 source_edit->startproject + source_length);
676 //this is outline for future thinking how it is supposed to be done trough C&P mechanisms
678 source_track->cut(source_edit->startproject,
679 source_edit->startproject + source_edit->length,
682 temp.terminate_string();
684 dest_track->paste_silence(position_a,
685 position_a + source_length,
687 while(!temp.read_tag())
688 dest_track->paste(position_a, // MISSING PIECE OF FUNCTIONALITY
699 // ONLY edit is moved, all other edits stay where they are
701 // Copy edit to temp, delete the edit, insert the edit
702 Edit *temp_edit = dest_track->edits->create_edit();
703 temp_edit->copy_from(source_edit);
704 // we call the edits directly since we do not want to move keyframes or anything else
705 source_track->edits->clear(source_startproject,
706 source_startproject + source_length);
707 source_track->edits->paste_silence(source_startproject,
708 source_startproject + source_length);
710 dest_track->edits->clear(position_i,
711 position_i + source_length);
712 Edit *dest_edit = dest_track->edits->shift(position_i, source_length);
713 Edit *result = dest_track->edits->insert_before(dest_edit,
714 dest_track->edits->create_edit());
715 result->copy_from(temp_edit);
716 result->startproject = position_i;
717 result->length = source_length;
720 source_track->optimize();
721 dest_track->optimize();
727 void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)
729 Track *source_track = plugin->track;
731 // Create a new plugin set
732 double start = track->from_units(position);
733 double length = track->from_units(plugin->length);
735 result = track->insert_effect("", &plugin->shared_location, 0, 0,
736 start, length, plugin->plugin_type);
737 result->copy_from(plugin);
738 result->shift(position - plugin->startproject);
740 // Clear new plugin from old set
741 plugin->plugin_set->clear(plugin->startproject,
742 plugin->startproject + plugin->length,
743 edl->session->autos_follow_edits);
745 source_track->optimize();
748 void Tracks::move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position)
750 // src/dest track must be the same
751 // replace plugin in source plugin_set with silence
752 PluginSet *src_plugin_set = plugin->plugin_set;
753 Plugin *silent = new Plugin(edl, src_plugin_set, "");
754 silent->startproject = plugin->startproject;
755 silent->length = plugin->length;
756 src_plugin_set->insert_after(plugin, silent);
757 src_plugin_set->remove_pointer(plugin);
758 // truncate previous plugin
759 Plugin *dest = (Plugin *)plugin_set->editof(position, PLAY_FORWARD, 0);
760 // add plugin after dest
761 plugin_set->insert_after(dest, plugin);
763 dest->length = position - dest->startproject;
764 if( dest->length < 0 ) dest->length = 0;
766 // update plugin position
767 plugin->startproject = position;
768 plugin->plugin_set = plugin_set;
769 plugin->edits = plugin_set;
770 src_plugin_set->track->optimize();
773 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
775 Track *output_track, *first_output_track, *input_track;
776 int i, data_type = TRACK_AUDIO;
781 for(i = 0; i < 2; i++)
783 // Get first output track
784 for(output_track = first;
786 output_track = output_track->next)
787 if(output_track->data_type == data_type &&
788 output_track->record) break;
790 first_output_track = output_track;
792 // Get first input track
793 for(input_track = first;
795 input_track = input_track->next)
797 if(input_track->data_type == data_type &&
799 !input_track->record) break;
803 if(output_track && input_track)
805 // Transfer input track to end of output track one at a time
808 output_start = output_track->get_length();
809 output_track->insert_track(input_track,
816 // Get next source and destination
817 for(input_track = input_track->next;
819 input_track = input_track->next)
822 if(input_track->data_type == data_type &&
823 !input_track->record &&
824 input_track->play) break;
827 for(output_track = output_track->next;
829 output_track = output_track->next)
831 if(output_track->data_type == data_type &&
832 output_track->record) break;
837 output_track = first_output_track;
843 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
849 int Tracks::delete_all_tracks()
851 while(last) delete last;
856 void Tracks::change_modules(int old_location, int new_location, int do_swap)
858 for(Track* current = first ; current; current = current->next)
860 current->change_modules(old_location, new_location, do_swap);
864 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
866 for(Track* current = first ; current; current = current->next)
868 current->change_plugins(old_location, new_location, do_swap);
874 // =========================================== EDL editing
877 int Tracks::copy(double start,
881 const char *output_path)
884 if(start == end && !all) return 1;
892 if(current->record || all)
894 current->copy(start, end, file,output_path);
903 int Tracks::move_track_up(Track *track)
905 Track *next_track = track->previous;
906 if(!next_track) next_track = last;
908 change_modules(number_of(track), number_of(next_track), 1);
910 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
912 // for(Track *current = first; current && count < 5; current = NEXT, count++)
913 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
914 // printf("Tracks::move_track_up 2\n");
916 swap(track, next_track);
919 // for(Track *current = first; current && count < 5; current = NEXT, count++)
920 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
921 // printf("Tracks::move_track_up 3\n");
926 int Tracks::move_track_down(Track *track)
928 Track *next_track = track->next;
929 if(!next_track) next_track = first;
931 change_modules(number_of(track), number_of(next_track), 1);
932 swap(track, next_track);
937 int Tracks::move_tracks_up()
939 Track *track, *next_track;
946 next_track = track->next;
952 change_modules(number_of(track->previous), number_of(track), 1);
954 swap(track->previous, track);
963 int Tracks::move_tracks_down()
965 Track *track, *previous_track;
970 track = previous_track)
972 previous_track = track->previous;
978 change_modules(number_of(track), number_of(track->next), 1);
980 swap(track, track->next);
991 void Tracks::paste_audio_transition(PluginServer *server)
993 for(Track *current = first; current; current = NEXT)
995 if(current->data_type == TRACK_AUDIO &&
998 int64_t position = current->to_units(
999 edl->local_session->get_selectionstart(), 0);
1000 Edit *current_edit = current->edits->editof(position,
1003 if( !current_edit && position == current->edits->length() ) {
1004 double length = edl->session->default_transition_length;
1005 int64_t units = current->to_units(length, 1);
1006 current_edit = current->edits->create_silence(position, position+units);
1010 paste_transition(server, current_edit);
1016 void Tracks::paste_automation(double selectionstart,
1022 Track* current_track = 0;
1023 Track* current_atrack = 0;
1024 Track* current_vtrack = 0;
1025 Track* dst_track = 0;
1029 double frame_rate = edl->session->frame_rate;
1030 int64_t sample_rate = edl->session->sample_rate;
1031 char string[BCTEXTLEN];
1036 result = file->read_tag();
1038 !file->tag.title_is("AUTO_CLIPBOARD"));
1042 length = file->tag.get_property("LENGTH", 0);
1043 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
1044 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
1049 result = file->read_tag();
1053 if(file->tag.title_is("/AUTO_CLIPBOARD"))
1058 if(file->tag.title_is("TRACK"))
1060 file->tag.get_property("TYPE", string);
1061 if(!strcmp(string, "AUDIO"))
1063 src_type = TRACK_AUDIO;
1067 src_type = TRACK_VIDEO;
1070 // paste to any media type
1073 if(!current_track) current_track = first;
1074 while(current_track && !current_track->record)
1075 current_track = current_track->next;
1076 dst_track = current_track;
1079 if(!strcmp(string, "AUDIO"))
1081 // Get next audio track
1083 current_atrack = first;
1085 current_atrack = current_atrack->next;
1087 while(current_atrack &&
1088 (current_atrack->data_type != TRACK_AUDIO ||
1089 !current_atrack->record))
1090 current_atrack = current_atrack->next;
1091 dst_track = current_atrack;
1095 // Get next video track
1097 current_vtrack = first;
1099 current_vtrack = current_vtrack->next;
1101 while(current_vtrack &&
1102 (current_vtrack->data_type != TRACK_VIDEO ||
1103 !current_vtrack->record))
1104 current_vtrack = current_vtrack->next;
1106 dst_track = current_vtrack;
1111 double frame_rate2 = frame_rate;
1112 double sample_rate2 = sample_rate;
1114 if(src_type != dst_track->data_type)
1116 frame_rate2 = sample_rate;
1117 sample_rate2 = frame_rate;
1120 dst_track->paste_automation(selectionstart,
1134 // int Tracks::paste_default_keyframe(FileXML *file)
1136 // paste_automation(0, file, 1, 0);
1140 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1142 dest_edit->insert_transition(server->title);
1145 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1147 for(Track *current = first; current; current = NEXT)
1149 if(current->data_type == TRACK_VIDEO &&
1152 int64_t position = current->to_units(
1153 edl->local_session->get_selectionstart(), 0);
1154 Edit *current_edit = current->edits->editof(position,
1157 if( !current_edit && position == current->edits->length() ) {
1158 double length = edl->session->default_transition_length;
1159 int64_t units = current->to_units(length, 1);
1160 current_edit = current->edits->create_silence(position, position+units);
1164 paste_transition(server, current_edit);
1166 if(first_track) break;
1172 int Tracks::paste_silence(double start,
1177 Track* current_track;
1179 for(current_track = first;
1181 current_track = current_track->next)
1183 if(current_track->record)
1185 current_track->paste_silence(start,
1196 int Tracks::select_auto(int cursor_x, int cursor_y)
1199 for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1203 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1207 for(Track* current = first; current && !result; current = NEXT)
1209 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1214 int Tracks::modify_edithandles(double &oldposition,
1215 double &newposition,
1224 for(current = first; current; current = NEXT)
1228 current->modify_edithandles(oldposition,
1240 int Tracks::modify_pluginhandles(double &oldposition,
1241 double &newposition,
1250 for(current = first; current; current = NEXT)
1254 current->modify_pluginhandles(oldposition,
1268 int Tracks::purge_asset(Asset *asset)
1270 Track *current_track;
1273 for(current_track = first; current_track; current_track = current_track->next)
1275 result += current_track->purge_asset(asset);
1280 int Tracks::asset_used(Asset *asset)
1282 Track *current_track;
1285 for(current_track = first; current_track; current_track = current_track->next)
1287 result += current_track->asset_used(asset);
1292 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1294 Track *current_track;
1296 for(current_track = first;
1298 current_track = current_track->next)
1300 if((current_track->record || ignore_record) &&
1301 current_track->data_type == TRACK_VIDEO)
1303 current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);