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