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