r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / tracksedit.C
blob5928a5fdffd15398784dab951016a7bbb4a48385
1 #include "assets.h"
2 #include "atrack.h"
3 #include "automation.h"
4 #include "aedits.h"
5 #include "edit.h"
6 #include "edits.h"
7 #include "edl.h"
8 #include "edlsession.h"
9 #include "filexml.h"
10 #include "intauto.h"
11 #include "intautos.h"
12 #include "localsession.h"
13 #include "mainundo.h"
14 #include "module.h"
15 #include "mainsession.h"
16 #include "pluginserver.h"
17 #include "pluginset.h"
18 #include "timebar.h"
19 #include "trackcanvas.h"
20 #include "tracks.h"
21 #include "trackscroll.h"
22 #include "transition.h"
23 #include "transportque.h"
24 #include "vtrack.h"
25 #include <string.h>
27 int Tracks::clear(double start, double end, int clear_plugins)
29         Track *current_track;
31         for(current_track = first; 
32                 current_track; 
33                 current_track = current_track->next)
34         {
35                 if(current_track->record) 
36                 {
37                         current_track->clear(start, 
38                                 end, 
39                                 1, 
40                                 1, 
41                                 clear_plugins, 
42                                 1,
43                                 0); 
44                 }
45         }
46         return 0;
49 void Tracks::clear_automation(double selectionstart, double selectionend)
51         Track* current_track;
53         for(current_track = first; current_track; current_track = current_track->next)
54         {
55                 if(current_track->record)
56                 {
57                         current_track->clear_automation(selectionstart, 
58                                 selectionend, 
59                                 0,
60                                 0); 
61                 }
62         }
65 int Tracks::clear_default_keyframe()
67         for(Track *current = first; current; current = NEXT)
68         {
69                 if(current->record)
70                         current->clear_automation(0, 0, 0, 1);
71         }
72         return 0;
75 int Tracks::clear_handle(double start, 
76         double end,
77         double &longest_distance,
78         int clear_labels,
79         int clear_plugins)
81         Track* current_track;
82         double distance;
84         for(current_track = first; current_track; current_track = current_track->next)
85         {
86                 if(current_track->record)
87                 {
88                         current_track->clear_handle(start, 
89                                 end, 
90                                 clear_labels,
91                                 clear_plugins, 
92                                 distance);
93                         if(distance > longest_distance) longest_distance = distance;
94                 }
95         }
97         return 0;
100 int Tracks::copy_automation(double selectionstart, 
101         double selectionend, 
102         FileXML *file,
103         int default_only,
104         int autos_only)
106 // called by MWindow::copy_automation for copying automation alone
107         Track* current_track;
109         file->tag.set_title("AUTO_CLIPBOARD");
110         file->tag.set_property("LENGTH", selectionend - selectionstart);
111         file->tag.set_property("FRAMERATE", edl->session->frame_rate);
112         file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
113         file->append_tag();
114         file->append_newline();
115         file->append_newline();
117         for(current_track = first; 
118                 current_track; 
119                 current_track = current_track->next)
120         {
121                 if(current_track->record)
122                 {
123                         current_track->copy_automation(selectionstart, 
124                                 selectionend, 
125                                 file,
126                                 default_only,
127                                 autos_only);
128                 }
129         }
131         file->tag.set_title("/AUTO_CLIPBOARD");
132         file->append_tag();
133         file->append_newline();
134         file->terminate_string();
135         return 0;
138 int Tracks::copy_default_keyframe(FileXML *file)
140         copy_automation(0, 0, file, 1, 0);
141         return 0;
144 int Tracks::delete_tracks()
146         int total_deleted = 0;
147 repeat:
148         for (Track* current = first;
149                 current;
150                 current = NEXT)
151         {
152                 if(current->record)
153                 {
154                         delete_track(current);
155                         total_deleted++;
156                         // this has garbled the linked list
157                         // scan the shorter list again
158                         goto repeat;
159                 }
160         }
161         return total_deleted;
164 void Tracks::move_edits(ArrayList<Edit*> *edits, 
165         Track *track,
166         double position,
167         int edit_labels,  // Ignored
168         int edit_plugins)  // Ignored
170 //printf("Tracks::move_edits 1\n");
171         for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
172         {
173                 if(dest_track->record)
174                 {
175 // Need a local copy of the source edit since the original source edit may
176 // change in the editing operation.
177                         Edit *source_edit = 0;
178                         Track *source_track = 0;
181 // Get source track
182                         if(dest_track->data_type == TRACK_AUDIO)
183                         {
184                                 int current_aedit = 0;
186                                 while(current_aedit < edits->total &&
187                                         edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
188                                         current_aedit++;
190                                 if(current_aedit < edits->total)
191                                 {
192                                         source_edit = edits->values[current_aedit];
193                                         source_track = source_edit->track;
194                                         edits->remove_number(current_aedit);
195                                 }
196                         }
197                         else
198                         if(dest_track->data_type == TRACK_VIDEO)
199                         {
200                                 int current_vedit = 0;
201                                 while(current_vedit < edits->total &&
202                                         edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
203                                         current_vedit++;
205                                 if(current_vedit < edits->total)
206                                 {
207                                         source_edit = edits->values[current_vedit];
208                                         source_track = source_edit->track;
209                                         edits->remove_number(current_vedit);
210                                 }
211                         }
213 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
214                         if(source_edit)
215                         {
216 // Copy keyframes
217                                 FileXML temp;
218                                 AutoConf temp_autoconf;
219                                 int64_t position_i = source_track->to_units(position, 0);
220 // Source edit changes
221                                 int64_t source_length = source_edit->length;
223                                 temp_autoconf.set_all();
225                                 source_track->automation->copy(source_edit->startproject, 
226                                         source_edit->startproject + source_edit->length, 
227                                         &temp, 
228                                         0,
229                                         0);
230                                 temp.terminate_string();
231                                 temp.rewind();
232 // Insert new keyframes
233 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
234                                 source_track->automation->clear(source_edit->startproject,
235                                         source_edit->startproject + source_edit->length, 
236                                         &temp_autoconf,
237                                         1);
238                                 int64_t position_a = position_i;
239                                 if (dest_track == source_track)
240                 {
241                     if (position_a > source_edit->startproject)
242                             position_a -= source_length;
243                 }               
245                                 dest_track->automation->paste_silence(position_a, 
246                                         position_a + source_length);
247                                 while(!temp.read_tag())
248                                         dest_track->automation->paste(position_a, 
249                                                 source_length, 
250                                                 1.0, 
251                                                 &temp, 
252                                                 0,
253                                                 &temp_autoconf);
257 //printf("Tracks::move_edits 1 %d\n", source_edit->length);
258 // Insert new edit
259                                 Edit *dest_edit = dest_track->edits->shift(position_i, 
260                                         source_length);
261                                 Edit *result = dest_track->edits->insert_before(dest_edit, 
262                                         new Edit(edl, dest_track));
263                                 result->copy_from(source_edit);
264                                 result->startproject = position_i;
265                                 result->length = source_length;
267 //printf("Tracks::move_edits 5\n");
268 //dest_track->dump();
270 // Clear source
271 //printf("Tracks::move_edits 7 %d %d\n", clear_start, clear_end);
272                                 source_track->edits->clear(source_edit->startproject, 
273                                         source_edit->startproject + source_length);
276                                 
277 //printf("Tracks::move_edits 8 %d %d\n", clear_start, source_edit->length);
278 //dest_track->dump();
279 //printf("Tracks::move_edits 9\n");
280                                 source_track->optimize();
281                                 dest_track->optimize();
282 //printf("Tracks::move_edits 10\n");
283 //dump();
284 //                              delete source_edit;
285                         }
287                 }
288         }
291 void Tracks::move_effect(Plugin *plugin,
292         PluginSet *dest_plugin_set,
293         Track *dest_track, 
294         int64_t dest_position)
296         Track *source_track = plugin->track;
297         Plugin *result = 0;
299 // Insert on an existing plugin set
300         if(!dest_track && dest_plugin_set)
301         {
302                 Track *dest_track = dest_plugin_set->track;
305 // Assume this operation never splits a plugin
306 // Shift destination plugins back
307                 dest_plugin_set->shift(dest_position, plugin->length);
309 // Insert new plugin
310                 Plugin *current = 0;
311                 for(current = (Plugin*)dest_plugin_set->first; current; current = (Plugin*)NEXT)
312                         if(current->startproject >= dest_position) break;
314                 result = (Plugin*)dest_plugin_set->insert_before(current, 
315                         new Plugin(edl, dest_plugin_set, ""));
316         }
317         else
318 // Create a new plugin set
319         {
320                 double length = 0;
321                 double start = 0;
322                 if(edl->local_session->get_selectionend() > 
323                         edl->local_session->get_selectionstart())
324                 {
325                         start = edl->local_session->get_selectionstart();
326                         length = edl->local_session->get_selectionend() - 
327                                 start;
328                 }
329                 else
330                 if(dest_track->get_length() > 0)
331                 {
332                         start = 0;
333                         length = dest_track->get_length();
334                 }
335                 else
336                 {
337                         start = 0;
338                         length = dest_track->from_units(plugin->length);
339                 }
342                 result = dest_track->insert_effect("", 
343                                 &plugin->shared_location, 
344                                 0,
345                                 0,
346                                 start,
347                                 length,
348                                 plugin->plugin_type);
349         }
353         result->copy_from(plugin);
354         result->shift(dest_position - plugin->startproject);
356 // Clear new plugin from old set
357         plugin->plugin_set->clear(plugin->startproject, plugin->startproject + plugin->length);
360         source_track->optimize();
365 int Tracks::concatenate_tracks(int edit_plugins)
367         Track *output_track, *first_output_track, *input_track;
368         int i, data_type = TRACK_AUDIO;
369         double output_start;
370         FileXML *clipboard;
371         int result = 0;
372         IntAuto *play_keyframe = 0;
374 // Relocate tracks
375         for(i = 0; i < 2; i++)
376         {
377 // Get first output track
378                 for(output_track = first; 
379                         output_track; 
380                         output_track = output_track->next)
381                         if(output_track->data_type == data_type && 
382                                 output_track->record) break;
384                 first_output_track = output_track;
386 // Get first input track
387                 for(input_track = first;
388                         input_track;
389                         input_track = input_track->next)
390                 {
391                         if(input_track->data_type == data_type &&
392                                 input_track->play && 
393                                 !input_track->record) break;
394                 }
397                 if(output_track && input_track)
398                 {
399 // Transfer input track to end of output track one at a time
400                         while(input_track)
401                         {
402                                 output_start = output_track->get_length();
403                                 output_track->insert_track(input_track, 
404                                         output_start, 
405                                         0,
406                                         edit_plugins);
408 // Get next source and destination
409                                 for(input_track = input_track->next; 
410                                         input_track; 
411                                         input_track = input_track->next)
412                                 {
414                                         if(input_track->data_type == data_type && 
415                                                 !input_track->record && 
416                                                 input_track->play) break;
417                                 }
419                                 for(output_track = output_track->next; 
420                                         output_track; 
421                                         output_track = output_track->next)
422                                 {
423                                         if(output_track->data_type == data_type && 
424                                                 output_track->record) break;
425                                 }
427                                 if(!output_track)
428                                 {
429                                         output_track = first_output_track;
430                                 }
431                         }
432                         result = 1;
433                 }
435                 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
436         }
438         return result;
441 int Tracks::delete_all_tracks()
443         while(last) delete last;
444         return 0;
448 void Tracks::change_modules(int old_location, int new_location, int do_swap)
450         for(Track* current = first ; current; current = current->next)
451         {
452                 current->change_modules(old_location, new_location, do_swap);
453         }
456 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
458         for(Track* current = first ; current; current = current->next)
459         {
460                 current->change_plugins(old_location, new_location, do_swap);
461         }
466 // =========================================== EDL editing
469 int Tracks::copy(double start, 
470         double end, 
471         int all, 
472         FileXML *file, 
473         char *output_path)
475 // nothing selected
476         if(start == end && !all) return 1;
478         Track* current;
480         for(current = first; 
481                 current; 
482                 current = NEXT)
483         {
484                 if(current->record || all)
485                 {
486                         current->copy(start, end, file,output_path);
487                 }
488         }
490         return 0;
495 int Tracks::move_track_up(Track *track)
497         Track *next_track = track->previous;
498         if(!next_track) next_track = last;
500         change_modules(number_of(track), number_of(next_track), 1);
502 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
503 // int count = 0;
504 // for(Track *current = first; current && count < 5; current = NEXT, count++)
505 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
506 // printf("Tracks::move_track_up 2\n");
507 // 
508         swap(track, next_track);
510 // count = 0;
511 // for(Track *current = first; current && count < 5; current = NEXT, count++)
512 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
513 // printf("Tracks::move_track_up 3\n");
515         return 0;
518 int Tracks::move_track_down(Track *track)
520         Track *next_track = track->next;
521         if(!next_track) next_track = first;
523         change_modules(number_of(track), number_of(next_track), 1);
524         swap(track, next_track);
525         return 0;
529 int Tracks::move_tracks_up()
531         Track *track, *next_track;
532         int result = 0;
534         for(track = first;
535                 track; 
536                 track = next_track)
537         {
538                 next_track = track->next;
540                 if(track->record)
541                 {
542                         if(track->previous)
543                         {
544                                 change_modules(number_of(track->previous), number_of(track), 1);
546                                 swap(track->previous, track);
547                                 result = 1;
548                         }
549                 }
550         }
552         return result;
555 int Tracks::move_tracks_down()
557         Track *track, *previous_track;
558         int result = 0;
559         
560         for(track = last;
561                 track; 
562                 track = previous_track)
563         {
564                 previous_track = track->previous;
566                 if(track->record)
567                 {
568                         if(track->next)
569                         {
570                                 change_modules(number_of(track), number_of(track->next), 1);
572                                 swap(track, track->next);
573                                 result = 1;
574                         }
575                 }
576         }
577         
578         return result;
583 void Tracks::paste_audio_transition(PluginServer *server)
585         for(Track *current = first; current; current = NEXT)
586         {
587                 if(current->data_type == TRACK_AUDIO &&
588                         current->record)
589                 {
590                         int64_t position = current->to_units(
591                                 edl->local_session->get_selectionstart(), 0);
592                         Edit *current_edit = current->edits->editof(position, 
593                                 PLAY_FORWARD,
594                                 0);
595                         if(current_edit)
596                         {
597                                 paste_transition(server, current_edit);
598                         }
599                 }
600         }
603 void Tracks::paste_automation(double selectionstart, 
604         FileXML *file,
605         int default_only)
607         Track* current_atrack = 0;
608         Track* current_vtrack = 0;
609         int result = 0;
610         double length;
611         double frame_rate = edl->session->frame_rate;
612         int64_t sample_rate = edl->session->sample_rate;
613         char string[BCTEXTLEN];
614         sprintf(string, "");
616 // Search for start
617         do{
618           result = file->read_tag();
619         }while(!result && 
620                 !file->tag.title_is("AUTO_CLIPBOARD"));
622         if(!result)
623         {
624                 length = file->tag.get_property("LENGTH", 0);
625                 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
626                 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
629                 do
630                 {
631                         result = file->read_tag();
633                         if(!result)
634                         {
635                                 if(file->tag.title_is("/AUTO_CLIPBOARD"))
636                                 {
637                                         result = 1;
638                                 }
639                                 else
640                                 if(file->tag.title_is("TRACK"))
641                                 {
642                                         file->tag.get_property("TYPE", string);
643                                         
644                                         if(!strcmp(string, "AUDIO"))
645                                         {
646 // Get next audio track
647                                                 if(!current_atrack)
648                                                         current_atrack = first;
649                                                 else
650                                                         current_atrack = current_atrack->next;
652                                                 while(current_atrack && 
653                                                         (current_atrack->data_type != TRACK_AUDIO ||
654                                                         !current_atrack->record))
655                                                         current_atrack = current_atrack->next;
657 // Paste it
658                                                 if(current_atrack)
659                                                 {
660                                                         current_atrack->paste_automation(selectionstart,
661                                                                 length,
662                                                                 frame_rate,
663                                                                 sample_rate,
664                                                                 file,
665                                                                 default_only);
666                                                 }
667                                         }
668                                         else
669                                         {
670 // Get next video track
671                                                 if(!current_vtrack)
672                                                         current_vtrack = first;
673                                                 else
674                                                         current_vtrack = current_vtrack->next;
676                                                 while(current_vtrack && 
677                                                         (current_vtrack->data_type != TRACK_VIDEO ||
678                                                         !current_vtrack->record))
679                                                         current_vtrack = current_vtrack->next;
681 // Paste it
682                                                 if(current_vtrack)
683                                                 {
684 //printf("Tracks::paste_automation 1 %s %d\n", current_vtrack->title, current_vtrack->record);
685                                                         current_vtrack->paste_automation(selectionstart,
686                                                                 length,
687                                                                 frame_rate,
688                                                                 sample_rate,
689                                                                 file,
690                                                                 default_only);
691                                                 }
692                                         }
693                                 }
694                         }
695                 }while(!result);
696         }
699 int Tracks::paste_default_keyframe(FileXML *file)
701         paste_automation(0, file, 1);
702         return 0;
705 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
707         dest_edit->insert_transition(server->title);
710 void Tracks::paste_video_transition(PluginServer *server, int first_track)
712         for(Track *current = first; current; current = NEXT)
713         {
714                 if(current->data_type == TRACK_VIDEO &&
715                         current->record)
716                 {
717                         int64_t position = current->to_units(
718                                 edl->local_session->get_selectionstart(), 0);
719                         Edit *current_edit = current->edits->editof(position, 
720                                 PLAY_FORWARD,
721                                 0);
722                         if(current_edit)
723                         {
724                                 paste_transition(server, current_edit);
725                         }
726                         if(first_track) break;
727                 }
728         }
732 int Tracks::paste_silence(double start, double end, int edit_plugins)
734         Track* current_track;
736         for(current_track = first; 
737                 current_track; 
738                 current_track = current_track->next)
739         {
740                 if(current_track->record) 
741                 { 
742                         current_track->paste_silence(start, end, edit_plugins); 
743                 }
744         }
745         return 0;
750 int Tracks::select_auto(int cursor_x, int cursor_y)
752         int result = 0;
753         for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
754         return result;
757 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
759         int result = 0;
761         for(Track* current = first; current && !result; current = NEXT) 
762         {
763                 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down); 
764         }
765         return 0;
768 int Tracks::modify_edithandles(double &oldposition, 
769         double &newposition, 
770         int currentend, 
771         int handle_mode,
772         int edit_labels,
773         int edit_plugins)
775         Track *current;
777         for(current = first; current; current = NEXT)
778         {
779                 if(current->record)
780                 {
781                         current->modify_edithandles(oldposition, 
782                                 newposition, 
783                                 currentend,
784                                 handle_mode,
785                                 edit_labels,
786                                 edit_plugins);
787                 }
788         }
789         return 0;
792 int Tracks::modify_pluginhandles(double &oldposition, 
793         double &newposition, 
794         int currentend, 
795         int handle_mode,
796         int edit_labels,
797         Edits *trim_edits)
799         Track *current;
801         for(current = first; current; current = NEXT)
802         {
803                 if(current->record)
804                 {
805                         current->modify_pluginhandles(oldposition, 
806                                 newposition, 
807                                 currentend, 
808                                 handle_mode,
809                                 edit_labels,
810                                 trim_edits);
811                 }
812         }
813         return 0;
818 int Tracks::purge_asset(Asset *asset)
820         Track *current_track;
821         int result = 0;
822         
823         for(current_track = first; current_track; current_track = current_track->next)
824         {
825                 result += current_track->purge_asset(asset); 
826         }
827         return result;
830 int Tracks::asset_used(Asset *asset)
832         Track *current_track;
833         int result = 0;
834         
835         for(current_track = first; current_track; current_track = current_track->next)
836         {
837                 result += current_track->asset_used(asset); 
838         }
839         return result;
842 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
844         Track *current_track;
846         for(current_track = first; 
847                 current_track; 
848                 current_track = current_track->next)
849         {
850                 if((current_track->record || ignore_record) && 
851                         current_track->data_type == TRACK_VIDEO)
852                 {
853                         current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);
854                 }
855         }
856         return 0;