afe491f39aec9176c1581358c04fe803f385e144
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / tracksedit.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
4  *
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.
9  *
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.
14  *
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
18  *
19  */
20
21 #include "assets.h"
22 #include "atrack.h"
23 #include "automation.h"
24 #include "aedits.h"
25 #include "bcsignals.h"
26 #include "edit.h"
27 #include "edits.h"
28 #include "edl.h"
29 #include "edlsession.h"
30 #include "filexml.h"
31 #include "intauto.h"
32 #include "intautos.h"
33 #include "labels.h"
34 #include "localsession.h"
35 #include "mainundo.h"
36 #include "module.h"
37 #include "mainsession.h"
38 #include "pluginserver.h"
39 #include "pluginset.h"
40 #include "plugin.h"
41 #include "timebar.h"
42 #include "trackcanvas.h"
43 #include "tracks.h"
44 #include "trackscroll.h"
45 #include "transition.h"
46 #include "transportque.h"
47 #include "vtrack.h"
48 #include <string.h>
49
50 int Tracks::blade(double position)
51 {
52         for( Track *track=first; track!=0; track=track->next ) {
53                 if( !track->record ) continue;
54                 track->blade(position);
55         }
56         return 0;
57 }
58
59 int Tracks::clear(double start, double end, int clear_plugins, int edit_autos)
60 {
61         Track *current_track;
62
63         for(current_track = first;
64                 current_track;
65                 current_track = current_track->next)
66         {
67                 if(current_track->record)
68                 {
69                         current_track->clear(start,
70                                 end,
71                                 1, // edits
72                                 1, // labels
73                                 clear_plugins, // edit_plugins
74                                 edit_autos,
75                                 0); // trim_edits
76                 }
77         }
78         return 0;
79 }
80
81 void Tracks::clear_automation(double selectionstart, double selectionend)
82 {
83         Track* current_track;
84
85         for(current_track = first; current_track; current_track = current_track->next)
86         {
87                 if(current_track->record)
88                 {
89                         current_track->clear_automation(selectionstart,
90                                 selectionend,
91                                 0,
92                                 0);
93                 }
94         }
95 }
96
97 void Tracks::clear_transitions(double start, double end)
98 {
99         for(Track *current_track = first;
100                 current_track;
101                 current_track = current_track->next)
102         {
103                 if(current_track->record)
104                 {
105                         int64_t start_units = current_track->to_units(start, 0);
106                         int64_t end_units = current_track->to_units(end, 0);
107
108                         for(Edit *current_edit = current_track->edits->first;
109                                 current_edit;
110                                 current_edit = current_edit->next)
111                         {
112                                 if(current_edit->startproject >= start_units &&
113                                         current_edit->startproject < end_units &&
114                                         current_edit->transition)
115                                 {
116                                         current_edit->detach_transition();
117                                 }
118                         }
119                 }
120         }
121 }
122
123 void Tracks::shuffle_edits(double start, double end)
124 {
125 // This doesn't affect automation or effects
126 // Labels follow the first track.
127         int first_track = 1;
128         for(Track *current_track = first;
129                 current_track;
130                 current_track = current_track->next)
131         {
132                 if(current_track->record)
133                 {
134                         current_track->shuffle_edits(start, end, first_track);
135
136                         first_track = 0;
137                 }
138         }
139 }
140
141 void Tracks::reverse_edits(double start, double end)
142 {
143 // This doesn't affect automation or effects
144 // Labels follow the first track.
145         int first_track = 1;
146         for(Track *current_track = first;
147                 current_track;
148                 current_track = current_track->next)
149         {
150                 if(current_track->record)
151                 {
152                         current_track->reverse_edits(start, end, first_track);
153
154                         first_track = 0;
155                 }
156         }
157 }
158 void Tracks::align_edits(double start, double end)
159 {
160 // This doesn't affect automation or effects
161         ArrayList<double> times;
162
163         for(Track *current_track = first;
164                 current_track;
165                 current_track = current_track->next)
166         {
167                 if(current_track->record)
168                 {
169                         current_track->align_edits(start, end, &times);
170                 }
171         }
172 }
173
174 void Tracks::set_edit_length(double start, double end, double length)
175 {
176         int first_track = 1;
177         for(Track *current_track = first;
178                 current_track;
179                 current_track = current_track->next)
180         {
181                 if(current_track->record)
182                 {
183 #define USE_FLOATING_LENGTHS
184
185 #ifdef USE_FLOATING_LENGTHS
186
187
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;
197
198                         for(Edit *current_edit = current_track->edits->last;
199                                 current_edit;
200                                 current_edit = current_edit->previous)
201                         {
202                                 if(current_edit->startproject >= start_units &&
203                                         current_edit->startproject + current_edit->length <= end_units)
204                                 {
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) -
208                                                 total_units;
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;
213
214 // Go in using the edit handle interface
215                                         int64_t starting_length = current_edit->length;
216
217                                         if(length_units < current_edit->length)
218                                         {
219                                                 current_edit->shift_end_in(MOVE_ALL_EDITS,
220                                                         current_edit->startproject + length_units,
221                                                         current_edit->startproject + current_edit->length,
222                                                         1,
223                                                         edl->session->labels_follow_edits,
224                                                         edl->session->plugins_follow_edits,
225                                                         edl->session->autos_follow_edits,
226                                                         0);
227                                         }
228                                         else
229                                         {
230                                                 current_edit->shift_end_out(MOVE_ALL_EDITS,
231                                                         current_edit->startproject + length_units,
232                                                         current_edit->startproject + current_edit->length,
233                                                         1,
234                                                         edl->session->labels_follow_edits,
235                                                         edl->session->plugins_follow_edits,
236                                                         edl->session->autos_follow_edits,
237                                                         0);
238                                         }
239
240                                         int64_t ending_length = current_edit->length;
241
242                                         if(edl->session->labels_follow_edits && first_track)
243                                         {
244 // printf("Tracks::set_edit_length %d %f %f\n",
245 // __LINE__,
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),
251                                                         1,
252                                                         MOVE_ALL_EDITS,
253                                                         1);
254                                         }
255
256
257                                         //first_edit = 0;
258                                         total_lengths++;
259                                 }
260                         }
261
262
263
264 #else // USE_FLOATING_LENGTHS
265
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;
278
279                         for(Edit *current_edit = current_track->edits->last;
280                                 current_edit;
281                                 current_edit = current_edit->previous)
282                         {
283                                 if(current_edit->startproject >= start_units &&
284                                         current_edit->startproject + current_edit->length <= end_units)
285                                 {
286 // Calculate starting time of length offsets
287 //                                      if(first_edit)
288 //                                      {
289 //                                              start_time = current_track->from_units(current_edit->startproject);
290 //                                      }
291
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;
297
298 // Go in using the edit handle interface
299                                         int64_t starting_length = current_edit->length;
300
301                                         if(length_units < current_edit->length)
302                                         {
303                                                 current_edit->shift_end_in(MOVE_ALL_EDITS,
304                                                         current_edit->startproject + length_units,
305                                                         current_edit->startproject + current_edit->length,
306                                                         1,
307                                                         edl->session->labels_follow_edits,
308                                                         edl->session->plugins_follow_edits,
309                                                         edl->session->autos_follow_edits,
310                                                         0);
311                                         }
312                                         else
313                                         {
314                                                 current_edit->shift_end_out(MOVE_ALL_EDITS,
315                                                         current_edit->startproject + length_units,
316                                                         current_edit->startproject + current_edit->length,
317                                                         1,
318                                                         edl->session->labels_follow_edits,
319                                                         edl->session->plugins_follow_edits,
320                                                         edl->session->autos_follow_edits,
321                                                         0);
322                                         }
323
324                                         int64_t ending_length = current_edit->length;
325
326                                         if(edl->session->labels_follow_edits && first_track)
327                                         {
328 // printf("Tracks::set_edit_length %d %f %f\n",
329 // __LINE__,
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),
335                                                         1,
336                                                         MOVE_ALL_EDITS,
337                                                         1);
338                                         }
339
340
341 //                                      first_edit = 0;
342 //                                      total_lengths++;
343                                 }
344                         }
345 #endif // !USE_FLOATING_LENGTHS
346
347                         first_track = 0;
348                 }
349         }
350 }
351
352 void Tracks::set_transition_length(double start, double end, double length)
353 {
354         for(Track *current_track = first;
355                 current_track;
356                 current_track = current_track->next)
357         {
358                 if(current_track->record)
359                 {
360                         int64_t start_units = current_track->to_units(start, 0);
361                         int64_t end_units = current_track->to_units(end, 0);
362
363                         for(Edit *current_edit = current_track->edits->first;
364                                 current_edit;
365                                 current_edit = current_edit->next)
366                         {
367                                 if(current_edit->startproject >= start_units &&
368                                         current_edit->startproject < end_units &&
369                                         current_edit->transition)
370                                 {
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;
376                                         }
377                                 }
378                         }
379                 }
380         }
381 }
382
383 void Tracks::set_transition_length(Transition *transition, double length)
384 {
385 // Must verify existence of transition
386         int done = 0;
387         if(!transition) return;
388         for(Track *current_track = first;
389                 current_track && !done;
390                 current_track = current_track->next)
391         {
392                 for(Edit *current_edit = current_track->edits->first;
393                         current_edit && !done;
394                         current_edit = current_edit->next)
395                 {
396                         if(current_edit->transition == transition)
397                         {
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;
402                                 }
403                                 done = 1;
404                         }
405                 }
406         }
407 }
408
409 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
410 {
411         int count = 0;
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);
417                         ++count;
418                 }
419         }
420         if( count > 0 ) {
421                 clear_selected_edits();
422                 return;
423         }
424
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);
439                                 }
440                                 else if( start_units >= edit_end ) continue;
441                                 edit->insert_transition(title);
442                         }
443                 }
444                 else {
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);
450                                 }
451                         }
452                 }
453         }
454 }
455
456 void Tracks::set_automation_mode(double selectionstart,
457         double selectionend,
458         int mode)
459 {
460         Track* current_track;
461
462         for(current_track = first; current_track; current_track = current_track->next)
463         {
464                 if(current_track->record)
465                 {
466                         current_track->set_automation_mode(selectionstart,
467                                 selectionend,
468                                 mode);
469                 }
470         }
471 }
472
473 int Tracks::clear_default_keyframe()
474 {
475         for(Track *current = first; current; current = NEXT)
476         {
477                 if(current->record)
478                         current->clear_automation(0, 0, 0, 1);
479         }
480         return 0;
481 }
482
483 int Tracks::clear_handle(double start,
484         double end,
485         double &longest_distance,
486         int clear_labels,
487         int clear_plugins,
488         int edit_autos)
489 {
490         Track* current_track;
491         double distance;
492
493         for(current_track = first; current_track; current_track = current_track->next)
494         {
495                 if(current_track->record)
496                 {
497                         current_track->clear_handle(start,
498                                 end,
499                                 clear_labels,
500                                 clear_plugins,
501                                 edit_autos,
502                                 distance);
503                         if(distance > longest_distance) longest_distance = distance;
504                 }
505         }
506
507         return 0;
508 }
509
510 int Tracks::copy_automation(double selectionstart,
511         double selectionend,
512         FileXML *file,
513         int default_only,
514         int autos_only)
515 {
516 // called by MWindow::copy_automation for copying automation alone
517         Track* current_track;
518
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);
523         file->append_tag();
524         file->append_newline();
525         file->append_newline();
526
527         for(current_track = first;
528                 current_track;
529                 current_track = current_track->next)
530         {
531                 if(current_track->record)
532                 {
533                         current_track->copy_automation(selectionstart,
534                                 selectionend,
535                                 file,
536                                 default_only,
537                                 autos_only);
538                 }
539         }
540
541         file->tag.set_title("/AUTO_CLIPBOARD");
542         file->append_tag();
543         file->append_newline();
544         file->terminate_string();
545         return 0;
546 }
547
548 // int Tracks::copy_default_keyframe(FileXML *file)
549 // {
550 //      copy_automation(0, 0, file, 1, 0);
551 //      return 0;
552 // }
553
554 int Tracks::delete_tracks()
555 {
556         int total_deleted = 0;
557         int done = 0;
558
559         while(!done)
560         {
561                 done = 1;
562                 Track *next_track = 0;
563                 for (Track* current = first; current && done; current = next_track)
564                 {
565                         next_track = current->next;
566                         if(current->record)
567                         {
568                                 delete_track(current);
569                                 current = NULL;
570                                 total_deleted++;
571                                 done = 0;
572                                 break;
573                         }
574                 }
575         }
576         return total_deleted;
577 }
578
579 void Tracks::move_edits(ArrayList<Edit*> *in_edits, Track *track, double position,
580         int edit_labels, int edit_plugins, int edit_autos, int mode)
581 {
582 // have to make a copy, optimize kills edits
583         ArrayList<Edit*> edits;
584         for( int i=0; i<in_edits->size(); ++i ) {
585                 Edit *edit = in_edits->get(i);
586                 Edit *new_edit = new Edit(edit->edl, edit->track);
587                 new_edit->copy_from(edit);
588                 edits.append(new_edit);
589         }
590
591         int current_aedit = 0, current_vedit = 0;
592 //printf("Tracks::move_edits 1\n");
593         for( Track *dest_track=track; dest_track; dest_track=dest_track->next ) {
594                 if( !dest_track->record ) continue;
595 // Need a local copy of the source edit since the original source edit may
596 // change in the editing operation.
597 // Get source edit
598                 Edit *source_edit = 0;
599                 Track *clip_track = 0;
600                 switch( dest_track->data_type ) {
601                 case TRACK_AUDIO: {
602                         while( current_aedit < edits.size() ) {
603                                 Edit *edit = edits[current_aedit++];
604                                 if( edit->track->data_type == TRACK_AUDIO ) {
605                                         source_edit = edit;
606                                         ATrack *atrack = new ATrack(dest_track->edl, 0);
607                                         atrack->create_objects();
608                                         clip_track = atrack;
609                                         break;
610                                 }
611                         }
612                         break; }
613                 case TRACK_VIDEO: {
614                         while( current_vedit < edits.size() ) {
615                                 Edit *edit = edits[current_vedit++];
616                                 if( edit->track->data_type == TRACK_VIDEO ) {
617                                         source_edit = edit;
618                                         VTrack *vtrack = new VTrack(dest_track->edl, 0);
619                                         vtrack->create_objects();
620                                         clip_track = vtrack;
621                                         break;
622                                 }
623                         }
624                         break; }
625                 }
626                 if( !source_edit ) continue;
627
628                 Track *source_track = source_edit->track;
629                 int64_t start = source_edit->startproject;
630                 int64_t length = source_edit->length, end = start + length;
631                 double source_start = source_track->from_units(start);
632                 double source_end = source_track->from_units(start+length);
633                 double len = source_end - source_start;
634                 double dest_start = position;
635                 double dest_end = dest_start + len;
636
637                 if( edit_labels && dest_track == track ) {
638                         FileXML label_xml;
639                         Labels labels(0, "LABELS");
640                         source_edit->edl->labels->copy(source_start, source_end, &label_xml);
641                         source_edit->edl->labels->clear(source_start, source_end, mode);
642                         if( !label_xml.read_tag() )
643                                 labels.load(&label_xml, LOAD_ALL);
644                         double pos = dest_start;
645                         if( mode && source_start < dest_start ) pos -= len;
646                         edl->labels->insert_labels(&labels, pos, len, mode);
647                         edit_labels = 0;
648                 }
649
650                 FileXML track_xml;
651                 source_track->copy(source_start, source_end, &track_xml, "");
652                 if( !track_xml.read_tag() )
653                         clip_track->load(&track_xml, 0, LOAD_ALL);
654
655                 if( !mode ) { // mute and overwrite
656                         source_track->clear(start, end, 1, 0,
657                                 edit_plugins, edit_autos, 0);
658                         source_track->edits->paste_silence(start, end);
659                         if( edit_autos )
660                                 source_track->shift_keyframes(start, length);
661                         if( edit_plugins ) {
662                                 int n = source_track->plugin_set.size();
663                                 if( n > 0 ) dest_track->expand_view = 1;
664                                 for( int k=0; k<n; ++k )
665                                         source_track->plugin_set[k]->paste_silence(start, end, 1);
666                         }
667                         dest_track->clear(dest_start, dest_end, 1, 0,
668                                 edit_plugins, edit_autos, 0);
669                         dest_track->insert_track(clip_track, dest_start, 0,
670                                 edit_plugins, edit_autos, len);
671                 }
672                 else { // cut and paste
673                         dest_track->insert_track(clip_track, dest_start, 0,
674                                 edit_plugins, edit_autos, len);
675                         if( source_track == dest_track && dest_start < source_start ) {
676                                 source_start += len;   source_end += len;
677                         }
678                         source_track->clear(source_start, source_end, 1, 0,
679                                 edit_plugins, edit_autos, 0);
680                 }
681
682                 delete clip_track;
683                 dest_track->optimize();
684         }
685
686         edits.remove_all_objects();
687 }
688
689 void Tracks::move_effect(Plugin *plugin, Track *track, int64_t position)
690 {
691         Track *source_track = plugin->track;
692         Plugin *result = 0;
693 // Create a new plugin set
694         double start = track->from_units(position);
695         double length = track->from_units(plugin->length);
696
697         result = track->insert_effect("", &plugin->shared_location, 0, 0,
698                                 start, length, plugin->plugin_type);
699         result->copy_from(plugin);
700         result->shift(position - plugin->startproject);
701
702 // Clear new plugin from old set
703         plugin->plugin_set->clear(plugin->startproject,
704                 plugin->startproject + plugin->length,
705                 edl->session->autos_follow_edits);
706
707         source_track->optimize();
708 }
709
710 void Tracks::move_effect(Plugin *plugin, PluginSet *plugin_set, int64_t position)
711 {
712 // src/dest track must be the same
713 // replace plugin in source plugin_set with silence
714         PluginSet *src_plugin_set = plugin->plugin_set;
715         Plugin *silent = new Plugin(edl, src_plugin_set, "");
716         silent->startproject = plugin->startproject;
717         silent->length = plugin->length;
718         src_plugin_set->insert_after(plugin, silent);
719         src_plugin_set->remove_pointer(plugin);
720 // truncate previous plugin
721         Plugin *dest = (Plugin *)plugin_set->editof(position, PLAY_FORWARD, 0);
722 // add plugin after dest
723         plugin_set->insert_after(dest, plugin);
724         if( dest ) {
725                 dest->length = position - dest->startproject;
726                 if( dest->length < 0 ) dest->length = 0;
727         }
728 // update plugin position
729         plugin->startproject = position;
730         plugin->plugin_set = plugin_set;
731         plugin->edits = plugin_set;
732         src_plugin_set->track->optimize();
733 }
734
735 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
736 {
737         Track *output_track, *first_output_track, *input_track;
738         int i, data_type = TRACK_AUDIO;
739         double output_start;
740         int result = 0;
741
742 // Relocate tracks
743         for(i = 0; i < 2; i++)
744         {
745 // Get first output track
746                 for(output_track = first;
747                         output_track;
748                         output_track = output_track->next)
749                         if(output_track->data_type == data_type &&
750                                 output_track->record) break;
751
752                 first_output_track = output_track;
753
754 // Get first input track
755                 for(input_track = first;
756                         input_track;
757                         input_track = input_track->next)
758                 {
759                         if(input_track->data_type == data_type &&
760                                 input_track->play &&
761                                 !input_track->record) break;
762                 }
763
764
765                 if(output_track && input_track)
766                 {
767 // Transfer input track to end of output track one at a time
768                         while(input_track)
769                         {
770                                 output_start = output_track->get_length();
771                                 output_track->insert_track(input_track,
772                                         output_start,
773                                         0,
774                                         edit_plugins,
775                                         edit_autos,
776                                         0);
777
778 // Get next source and destination
779                                 for(input_track = input_track->next;
780                                         input_track;
781                                         input_track = input_track->next)
782                                 {
783
784                                         if(input_track->data_type == data_type &&
785                                                 !input_track->record &&
786                                                 input_track->play) break;
787                                 }
788
789                                 for(output_track = output_track->next;
790                                         output_track;
791                                         output_track = output_track->next)
792                                 {
793                                         if(output_track->data_type == data_type &&
794                                                 output_track->record) break;
795                                 }
796
797                                 if(!output_track)
798                                 {
799                                         output_track = first_output_track;
800                                 }
801                         }
802                         result = 1;
803                 }
804
805                 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
806         }
807
808         return result;
809 }
810
811 int Tracks::delete_all_tracks()
812 {
813         while(last) delete last;
814         return 0;
815 }
816
817
818 void Tracks::change_modules(int old_location, int new_location, int do_swap)
819 {
820         for(Track* current = first ; current; current = current->next)
821         {
822                 current->change_modules(old_location, new_location, do_swap);
823         }
824 }
825
826 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
827 {
828         for(Track* current = first ; current; current = current->next)
829         {
830                 current->change_plugins(old_location, new_location, do_swap);
831         }
832 }
833
834
835
836 // =========================================== EDL editing
837
838
839 int Tracks::copy(double start,
840         double end,
841         int all,
842         FileXML *file,
843         const char *output_path)
844 {
845 // nothing selected
846         if(start == end && !all) return 1;
847
848         Track* current;
849
850         for(current = first;
851                 current;
852                 current = NEXT)
853         {
854                 if(current->record || all)
855                 {
856                         current->copy(start, end, file,output_path);
857                 }
858         }
859
860         return 0;
861 }
862
863
864
865 int Tracks::move_track_up(Track *track)
866 {
867         Track *next_track = track->previous;
868         if(!next_track) next_track = last;
869
870         change_modules(number_of(track), number_of(next_track), 1);
871
872 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
873 // int count = 0;
874 // for(Track *current = first; current && count < 5; current = NEXT, count++)
875 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
876 // printf("Tracks::move_track_up 2\n");
877 //
878         swap(track, next_track);
879
880 // count = 0;
881 // for(Track *current = first; current && count < 5; current = NEXT, count++)
882 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
883 // printf("Tracks::move_track_up 3\n");
884
885         return 0;
886 }
887
888 int Tracks::move_track_down(Track *track)
889 {
890         Track *next_track = track->next;
891         if(!next_track) next_track = first;
892
893         change_modules(number_of(track), number_of(next_track), 1);
894         swap(track, next_track);
895         return 0;
896 }
897
898
899 int Tracks::move_tracks_up()
900 {
901         Track *track, *next_track;
902         int result = 0;
903
904         for(track = first;
905                 track;
906                 track = next_track)
907         {
908                 next_track = track->next;
909
910                 if(track->record)
911                 {
912                         if(track->previous)
913                         {
914                                 change_modules(number_of(track->previous), number_of(track), 1);
915
916                                 swap(track->previous, track);
917                                 result = 1;
918                         }
919                 }
920         }
921
922         return result;
923 }
924
925 int Tracks::move_tracks_down()
926 {
927         Track *track, *previous_track;
928         int result = 0;
929
930         for(track = last;
931                 track;
932                 track = previous_track)
933         {
934                 previous_track = track->previous;
935
936                 if(track->record)
937                 {
938                         if(track->next)
939                         {
940                                 change_modules(number_of(track), number_of(track->next), 1);
941
942                                 swap(track, track->next);
943                                 result = 1;
944                         }
945                 }
946         }
947
948         return result;
949 }
950
951
952
953 void Tracks::paste_audio_transition(PluginServer *server)
954 {
955         for(Track *current = first; current; current = NEXT)
956         {
957                 if(current->data_type == TRACK_AUDIO &&
958                         current->record)
959                 {
960                         int64_t position = current->to_units(
961                                 edl->local_session->get_selectionstart(), 0);
962                         Edit *current_edit = current->edits->editof(position,
963                                 PLAY_FORWARD,
964                                 0);
965                         if( !current_edit && position == current->edits->length() ) {
966                                 double length = edl->session->default_transition_length;
967                                 int64_t units = current->to_units(length, 1);
968                                 current_edit = current->edits->create_silence(position, position+units);
969                         }
970                         if(current_edit)
971                         {
972                                 paste_transition(server, current_edit);
973                         }
974                 }
975         }
976 }
977
978 void Tracks::paste_automation(double selectionstart,
979         FileXML *file,
980         int default_only,
981         int active_only,
982         int typeless)
983 {
984         Track* current_track = 0;
985         Track* current_atrack = 0;
986         Track* current_vtrack = 0;
987         Track* dst_track = 0;
988         int src_type;
989         int result = 0;
990         double length;
991         double frame_rate = edl->session->frame_rate;
992         int64_t sample_rate = edl->session->sample_rate;
993         char string[BCTEXTLEN];
994         string[0] = 0;
995
996 // Search for start
997         do{
998           result = file->read_tag();
999         }while(!result &&
1000                 !file->tag.title_is("AUTO_CLIPBOARD"));
1001
1002         if(!result)
1003         {
1004                 length = file->tag.get_property("LENGTH", 0);
1005                 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
1006                 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
1007
1008
1009                 do
1010                 {
1011                         result = file->read_tag();
1012
1013                         if(!result)
1014                         {
1015                                 if(file->tag.title_is("/AUTO_CLIPBOARD"))
1016                                 {
1017                                         result = 1;
1018                                 }
1019                                 else
1020                                 if(file->tag.title_is("TRACK"))
1021                                 {
1022                                         file->tag.get_property("TYPE", string);
1023                                         if(!strcmp(string, "AUDIO"))
1024                                         {
1025                                                 src_type = TRACK_AUDIO;
1026                                         }
1027                                         else
1028                                         {
1029                                                 src_type = TRACK_VIDEO;
1030                                         }
1031
1032 // paste to any media type
1033                                         if(typeless)
1034                                         {
1035                                                 if(!current_track) current_track = first;
1036                                                 while(current_track && !current_track->record)
1037                                                         current_track = current_track->next;
1038                                                 dst_track = current_track;
1039                                         }
1040                                         else
1041                                         if(!strcmp(string, "AUDIO"))
1042                                         {
1043 // Get next audio track
1044                                                 if(!current_atrack)
1045                                                         current_atrack = first;
1046                                                 else
1047                                                         current_atrack = current_atrack->next;
1048
1049                                                 while(current_atrack &&
1050                                                         (current_atrack->data_type != TRACK_AUDIO ||
1051                                                         !current_atrack->record))
1052                                                         current_atrack = current_atrack->next;
1053                                                 dst_track = current_atrack;
1054                                         }
1055                                         else
1056                                         {
1057 // Get next video track
1058                                                 if(!current_vtrack)
1059                                                         current_vtrack = first;
1060                                                 else
1061                                                         current_vtrack = current_vtrack->next;
1062
1063                                                 while(current_vtrack &&
1064                                                         (current_vtrack->data_type != TRACK_VIDEO ||
1065                                                         !current_vtrack->record))
1066                                                         current_vtrack = current_vtrack->next;
1067
1068                                                 dst_track = current_vtrack;
1069                                         }
1070
1071                                         if(dst_track)
1072                                         {
1073                                                 double frame_rate2 = frame_rate;
1074                                                 double sample_rate2 = sample_rate;
1075
1076                                                 if(src_type != dst_track->data_type)
1077                                                 {
1078                                                         frame_rate2 = sample_rate;
1079                                                         sample_rate2 = frame_rate;
1080                                                 }
1081
1082                                                 dst_track->paste_automation(selectionstart,
1083                                                         length,
1084                                                         frame_rate2,
1085                                                         sample_rate2,
1086                                                         file,
1087                                                         default_only,
1088                                                         active_only);
1089                                         }
1090                                 }
1091                         }
1092                 }while(!result);
1093         }
1094 }
1095
1096 // int Tracks::paste_default_keyframe(FileXML *file)
1097 // {
1098 //      paste_automation(0, file, 1, 0);
1099 //      return 0;
1100 // }
1101
1102 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1103 {
1104         dest_edit->insert_transition(server->title);
1105 }
1106
1107 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1108 {
1109         for(Track *current = first; current; current = NEXT)
1110         {
1111                 if(current->data_type == TRACK_VIDEO &&
1112                         current->record)
1113                 {
1114                         int64_t position = current->to_units(
1115                                 edl->local_session->get_selectionstart(), 0);
1116                         Edit *current_edit = current->edits->editof(position,
1117                                 PLAY_FORWARD,
1118                                 0);
1119                         if( !current_edit && position == current->edits->length() ) {
1120                                 double length = edl->session->default_transition_length;
1121                                 int64_t units = current->to_units(length, 1);
1122                                 current_edit = current->edits->create_silence(position, position+units);
1123                         }
1124                         if(current_edit)
1125                         {
1126                                 paste_transition(server, current_edit);
1127                         }
1128                         if(first_track) break;
1129                 }
1130         }
1131 }
1132
1133
1134 int Tracks::paste_silence(double start,
1135         double end,
1136         int edit_plugins,
1137         int edit_autos)
1138 {
1139         Track* current_track;
1140
1141         for(current_track = first;
1142                 current_track;
1143                 current_track = current_track->next)
1144         {
1145                 if(current_track->record)
1146                 {
1147                         current_track->paste_silence(start,
1148                                 end,
1149                                 edit_plugins,
1150                                 edit_autos);
1151                 }
1152         }
1153         return 0;
1154 }
1155
1156
1157
1158 int Tracks::select_auto(int cursor_x, int cursor_y)
1159 {
1160         int result = 0;
1161         for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1162         return result;
1163 }
1164
1165 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1166 {
1167         int result = 0;
1168
1169         for(Track* current = first; current && !result; current = NEXT)
1170         {
1171                 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1172         }
1173         return 0;
1174 }
1175
1176 int Tracks::modify_edithandles(double &oldposition, double &newposition,
1177         int currentend, int handle_mode, int edit_labels,
1178         int edit_plugins, int edit_autos, int group_id)
1179 {
1180         for( Track *track=first; track; track=track->next ) {
1181                 if( !track->record ) continue;
1182                 track->modify_edithandles(oldposition, newposition,
1183                         currentend, handle_mode, edit_labels,
1184                         edit_plugins, edit_autos, group_id);
1185         }
1186         return 0;
1187 }
1188
1189 int Tracks::modify_pluginhandles(double &oldposition, double &newposition,
1190         int currentend, int handle_mode, int edit_labels,
1191         int edit_autos, Edits *trim_edits)
1192 {
1193         for( Track *track=first; track; track=track->next ) {
1194                 if( !track->record ) continue;
1195                 track->modify_pluginhandles(oldposition, newposition,
1196                         currentend, handle_mode, edit_labels,
1197                         edit_autos, trim_edits);
1198         }
1199         return 0;
1200 }
1201
1202
1203 int Tracks::purge_asset(Asset *asset)
1204 {
1205         Track *current_track;
1206         int result = 0;
1207
1208         for(current_track = first; current_track; current_track = current_track->next)
1209         {
1210                 result += current_track->purge_asset(asset);
1211         }
1212         return result;
1213 }
1214
1215 int Tracks::asset_used(Asset *asset)
1216 {
1217         Track *current_track;
1218         int result = 0;
1219
1220         for(current_track = first; current_track; current_track = current_track->next)
1221         {
1222                 result += current_track->asset_used(asset);
1223         }
1224         return result;
1225 }
1226
1227 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1228 {
1229         Track *current_track;
1230
1231         for(current_track = first;
1232                 current_track;
1233                 current_track = current_track->next)
1234         {
1235                 if((current_track->record || ignore_record) &&
1236                         current_track->data_type == TRACK_VIDEO)
1237                 {
1238                         current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);
1239                 }
1240         }
1241         return 0;
1242 }
1243