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