r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / tracksedit.C
blob2f007ab167319dc498b07965315aa387118476ef
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                 }
44         }
45         return 0;
48 void Tracks::clear_automation(double selectionstart, double selectionend)
50         Track* current_track;
52         for(current_track = first; current_track; current_track = current_track->next)
53         {
54                 if(current_track->record)
55                 {
56                         current_track->clear_automation(selectionstart, 
57                                 selectionend, 
58                                 0,
59                                 0); 
60                 }
61         }
64 int Tracks::clear_default_keyframe()
66         for(Track *current = first; current; current = NEXT)
67         {
68                 if(current->record)
69                         current->clear_automation(0, 0, 0, 1);
70         }
71         return 0;
74 int Tracks::clear_handle(double start, 
75         double end,
76         double &longest_distance,
77         int clear_labels,
78         int clear_plugins)
80         Track* current_track;
81         double distance;
83         for(current_track = first; current_track; current_track = current_track->next)
84         {
85                 if(current_track->record)
86                 {
87                         current_track->clear_handle(start, 
88                                 end, 
89                                 clear_labels,
90                                 clear_plugins, 
91                                 distance);
92                         if(distance > longest_distance) longest_distance = distance;
93                 }
94         }
96         return 0;
99 int Tracks::copy_automation(double selectionstart, 
100         double selectionend, 
101         FileXML *file,
102         int default_only,
103         int autos_only)
105 // called by MWindow::copy_automation for copying automation alone
106         Track* current_track;
108         file->tag.set_title("AUTO_CLIPBOARD");
109         file->tag.set_property("LENGTH", selectionend - selectionstart);
110         file->tag.set_property("FRAMERATE", edl->session->frame_rate);
111         file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
112         file->append_tag();
113         file->append_newline();
114         file->append_newline();
116         for(current_track = first; 
117                 current_track; 
118                 current_track = current_track->next)
119         {
120                 if(current_track->record)
121                 {
122                         current_track->copy_automation(selectionstart, 
123                                 selectionend, 
124                                 file,
125                                 default_only,
126                                 autos_only);
127                 }
128         }
130         file->tag.set_title("/AUTO_CLIPBOARD");
131         file->append_tag();
132         file->append_newline();
133         file->terminate_string();
134         return 0;
137 int Tracks::copy_default_keyframe(FileXML *file)
139         copy_automation(0, 0, file, 1, 0);
140         return 0;
143 int Tracks::delete_tracks()
145         int result = 1, total_deleted = 0;
146         Track *track, *next_track, *shifted_track;
147         int deleted_number;
148         
149         while(result)
150         {
151 // keep deleting until all the recordable tracks are gone
152                 result = 0;
154 //printf("Tracks::delete_tracks 1\n");
155 // Stop when first recordable track is reached
156                 for(track = first; 
157                         track && !result;  
158                         track = next_track)
159                 {
160 //printf("Tracks::delete_tracks 2\n");
161                         next_track = track->next;
162                         
163                         if(track->record)
164                         {
165                                 deleted_number = number_of(track);
166 // Delete the track.
167                                 delete track;
169 // Shift all the plugin pointers.
170                                 for(shifted_track = next_track;
171                                         shifted_track;
172                                         shifted_track = shifted_track->next)
173                                 {
174                                         shifted_track->delete_module_pointers(deleted_number);
175                                 }
176                                 result = 1;
177                                 total_deleted++;
178                         }
179                 }
180 //printf("Tracks::delete_tracks 3\n");
181         }
182 //printf("Tracks::delete_tracks 4\n");
183         return total_deleted;
186 void Tracks::move_edits(ArrayList<Edit*> *edits, 
187         Track *track,
188         double position,
189         int edit_labels,  // Ignored
190         int edit_plugins)  // Ignored
192 //printf("Tracks::move_edits 1\n");
193         for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
194         {
195                 if(dest_track->record)
196                 {
197 // Need a local copy of the source edit since the original source edit may
198 // change in the editing operation.
199                         Edit *source_edit = 0;
200                         Track *source_track = 0;
203 // Get source track
204                         if(dest_track->data_type == TRACK_AUDIO)
205                         {
206                                 int current_aedit = 0;
208                                 while(current_aedit < edits->total &&
209                                         edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
210                                         current_aedit++;
212                                 if(current_aedit < edits->total)
213                                 {
214                                         source_edit = edits->values[current_aedit];
215                                         source_track = source_edit->track;
216                                         edits->remove_number(current_aedit);
217                                 }
218                         }
219                         else
220                         if(dest_track->data_type == TRACK_VIDEO)
221                         {
222                                 int current_vedit = 0;
223                                 while(current_vedit < edits->total &&
224                                         edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
225                                         current_vedit++;
227                                 if(current_vedit < edits->total)
228                                 {
229                                         source_edit = edits->values[current_vedit];
230                                         source_track = source_edit->track;
231                                         edits->remove_number(current_vedit);
232                                 }
233                         }
235 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
236                         if(source_edit)
237                         {
238 // Copy keyframes
239                                 FileXML temp;
240                                 AutoConf temp_autoconf;
241                                 int64_t position_i = source_track->to_units(position, 0);
242 // Source edit changes
243                                 int64_t source_length = source_edit->length;
245                                 temp_autoconf.set_all();
247                                 source_track->automation->copy(source_edit->startproject, 
248                                         source_edit->startproject + source_edit->length, 
249                                         &temp, 
250                                         0,
251                                         0);
252                                 temp.terminate_string();
253                                 temp.rewind();
254 // Insert new keyframes
255 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
256                                 source_track->automation->clear(source_edit->startproject,
257                                         source_edit->startproject + source_edit->length, 
258                                         &temp_autoconf,
259                                         1);
260                                 int64_t position_a = position_i;
261                                 if (dest_track == source_track)
262                 {
263                     if (position_a > source_edit->startproject)
264                             position_a -= source_length;
265                 }               
267                                 dest_track->automation->paste_silence(position_a, 
268                                         position_a + source_length);
269                                 while(!temp.read_tag())
270                                         dest_track->automation->paste(position_a, 
271                                                 source_length, 
272                                                 1.0, 
273                                                 &temp, 
274                                                 0,
275                                                 &temp_autoconf);
279 //printf("Tracks::move_edits 1 %d\n", source_edit->length);
280 // Insert new edit
281                                 Edit *dest_edit = dest_track->edits->shift(position_i, 
282                                         source_length);
283                                 Edit *result = dest_track->edits->insert_before(dest_edit, 
284                                         new Edit(edl, dest_track));
285                                 result->copy_from(source_edit);
286                                 result->startproject = position_i;
287                                 result->length = source_length;
289 //printf("Tracks::move_edits 5\n");
290 //dest_track->dump();
292 // Clear source
293 //printf("Tracks::move_edits 7 %d %d\n", clear_start, clear_end);
294                                 source_track->edits->clear(source_edit->startproject, 
295                                         source_edit->startproject + source_length);
298                                 
299 //printf("Tracks::move_edits 8 %d %d\n", clear_start, source_edit->length);
300 //dest_track->dump();
301 //printf("Tracks::move_edits 9\n");
302                                 source_track->optimize();
303                                 dest_track->optimize();
304 //printf("Tracks::move_edits 10\n");
305 //dump();
306 //                              delete source_edit;
307                         }
309                 }
310         }
313 void Tracks::move_effect(Plugin *plugin,
314         PluginSet *dest_plugin_set,
315         Track *dest_track, 
316         int64_t dest_position)
318         Track *source_track = plugin->track;
319         Plugin *result = 0;
321 // Insert on an existing plugin set
322         if(!dest_track && dest_plugin_set)
323         {
324                 Track *dest_track = dest_plugin_set->track;
327 // Assume this operation never splits a plugin
328 // Shift destination plugins back
329                 dest_plugin_set->shift(dest_position, plugin->length);
331 // Insert new plugin
332                 Plugin *current = 0;
333                 for(current = (Plugin*)dest_plugin_set->first; current; current = (Plugin*)NEXT)
334                         if(current->startproject >= dest_position) break;
336                 result = (Plugin*)dest_plugin_set->insert_before(current, 
337                         new Plugin(edl, dest_plugin_set, ""));
338         }
339         else
340 // Create a new plugin set
341         {
342                 double length = 0;
343                 double start = 0;
344                 if(edl->local_session->get_selectionend() > 
345                         edl->local_session->get_selectionstart())
346                 {
347                         start = edl->local_session->get_selectionstart();
348                         length = edl->local_session->get_selectionend() - 
349                                 start;
350                 }
351                 else
352                 if(dest_track->get_length() > 0)
353                 {
354                         start = 0;
355                         length = dest_track->get_length();
356                 }
357                 else
358                 {
359                         start = 0;
360                         length = dest_track->from_units(plugin->length);
361                 }
364                 result = dest_track->insert_effect("", 
365                                 &plugin->shared_location, 
366                                 0,
367                                 0,
368                                 start,
369                                 length,
370                                 plugin->plugin_type);
371         }
375         result->copy_from(plugin);
376         result->shift(dest_position - plugin->startproject);
378 // Clear new plugin from old set
379         plugin->plugin_set->clear(plugin->startproject, plugin->startproject + plugin->length);
382         source_track->optimize();
387 int Tracks::concatenate_tracks(int edit_plugins)
389         Track *output_track, *first_output_track, *input_track;
390         int i, data_type = TRACK_AUDIO;
391         double output_start;
392         FileXML *clipboard;
393         int result = 0;
394         IntAuto *play_keyframe = 0;
396 // Relocate tracks
397         for(i = 0; i < 2; i++)
398         {
399 // Get first output track
400                 for(output_track = first; 
401                         output_track; 
402                         output_track = output_track->next)
403                         if(output_track->data_type == data_type && 
404                                 output_track->record) break;
406                 first_output_track = output_track;
408 // Get first input track
409                 for(input_track = first;
410                         input_track;
411                         input_track = input_track->next)
412                 {
413                         if(input_track->data_type == data_type &&
414                                 input_track->play && 
415                                 !input_track->record) break;
416                 }
419                 if(output_track && input_track)
420                 {
421 // Transfer input track to end of output track one at a time
422                         while(input_track)
423                         {
424                                 output_start = output_track->get_length();
425                                 output_track->insert_track(input_track, 
426                                         output_start, 
427                                         0,
428                                         edit_plugins);
430 // Get next source and destination
431                                 for(input_track = input_track->next; 
432                                         input_track; 
433                                         input_track = input_track->next)
434                                 {
436                                         if(input_track->data_type == data_type && 
437                                                 !input_track->record && 
438                                                 input_track->play) break;
439                                 }
441                                 for(output_track = output_track->next; 
442                                         output_track; 
443                                         output_track = output_track->next)
444                                 {
445                                         if(output_track->data_type == data_type && 
446                                                 output_track->record) break;
447                                 }
449                                 if(!output_track)
450                                 {
451                                         output_track = first_output_track;
452                                 }
453                         }
454                         result = 1;
455                 }
457                 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
458         }
460         return result;
463 int Tracks::delete_audio_track()
465         Track *current;
467         for(current = last; current && current->data_type != TRACK_AUDIO; current = PREVIOUS)
468         {
469                 ;
470         }
472         if(current) delete_track(current);
475 int Tracks::delete_video_track()
477         Track *current;
479         for(current = last; current && current->data_type != TRACK_VIDEO; current = PREVIOUS)
480         {
481                 ;
482         }
484         if(current) delete_track(current);
487 int Tracks::delete_all_tracks()
489         while(last) delete last;
490         return 0;
494 void Tracks::change_modules(int old_location, int new_location, int do_swap)
496         for(Track* current = first ; current; current = current->next)
497         {
498                 current->change_modules(old_location, new_location, do_swap);
499         }
502 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
504         for(Track* current = first ; current; current = current->next)
505         {
506                 current->change_plugins(old_location, new_location, do_swap);
507         }
512 // =========================================== EDL editing
515 int Tracks::copy(double start, 
516         double end, 
517         int all, 
518         FileXML *file, 
519         char *output_path)
521 // nothing selected
522         if(start == end && !all) return 1;
524         Track* current;
526         for(current = first; 
527                 current; 
528                 current = NEXT)
529         {
530                 if(current->record || all)
531                 {
532                         current->copy(start, end, file,output_path);
533                 }
534         }
536         return 0;
541 int Tracks::move_track_up(Track *track)
543         Track *next_track = track->previous;
544         if(!next_track) next_track = last;
546         change_modules(number_of(track), number_of(next_track), 1);
548 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
549 // int count = 0;
550 // for(Track *current = first; current && count < 5; current = NEXT, count++)
551 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
552 // printf("Tracks::move_track_up 2\n");
553 // 
554         swap(track, next_track);
556 // count = 0;
557 // for(Track *current = first; current && count < 5; current = NEXT, count++)
558 //      printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
559 // printf("Tracks::move_track_up 3\n");
561         return 0;
564 int Tracks::move_track_down(Track *track)
566         Track *next_track = track->next;
567         if(!next_track) next_track = first;
569         change_modules(number_of(track), number_of(next_track), 1);
570         swap(track, next_track);
571         return 0;
575 int Tracks::move_tracks_up()
577         Track *track, *next_track;
578         int result = 0;
580         for(track = first;
581                 track; 
582                 track = next_track)
583         {
584                 next_track = track->next;
586                 if(track->record)
587                 {
588                         if(track->previous)
589                         {
590                                 change_modules(number_of(track->previous), number_of(track), 1);
592                                 swap(track->previous, track);
593                                 result = 1;
594                         }
595                 }
596         }
598         return result;
601 int Tracks::move_tracks_down()
603         Track *track, *previous_track;
604         int result = 0;
605         
606         for(track = last;
607                 track; 
608                 track = previous_track)
609         {
610                 previous_track = track->previous;
612                 if(track->record)
613                 {
614                         if(track->next)
615                         {
616                                 change_modules(number_of(track), number_of(track->next), 1);
618                                 swap(track, track->next);
619                                 result = 1;
620                         }
621                 }
622         }
623         
624         return result;
629 void Tracks::paste_audio_transition(PluginServer *server)
631         for(Track *current = first; current; current = NEXT)
632         {
633                 if(current->data_type == TRACK_AUDIO &&
634                         current->record)
635                 {
636                         int64_t position = current->to_units(
637                                 edl->local_session->get_selectionstart(), 0);
638                         Edit *current_edit = current->edits->editof(position, 
639                                 PLAY_FORWARD,
640                                 0);
641                         if(current_edit)
642                         {
643                                 paste_transition(server, current_edit);
644                         }
645                 }
646         }
649 void Tracks::paste_automation(double selectionstart, 
650         FileXML *file,
651         int default_only)
653         Track* current_atrack = 0;
654         Track* current_vtrack = 0;
655         int result = 0;
656         double length;
657         double frame_rate = edl->session->frame_rate;
658         int64_t sample_rate = edl->session->sample_rate;
659         char string[BCTEXTLEN];
660         sprintf(string, "");
662 // Search for start
663         do{
664           result = file->read_tag();
665         }while(!result && 
666                 !file->tag.title_is("AUTO_CLIPBOARD"));
668         if(!result)
669         {
670                 length = file->tag.get_property("LENGTH", 0);
671                 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
672                 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
675                 do
676                 {
677                         result = file->read_tag();
679                         if(!result)
680                         {
681                                 if(file->tag.title_is("/AUTO_CLIPBOARD"))
682                                 {
683                                         result = 1;
684                                 }
685                                 else
686                                 if(file->tag.title_is("TRACK"))
687                                 {
688                                         file->tag.get_property("TYPE", string);
689                                         
690                                         if(!strcmp(string, "AUDIO"))
691                                         {
692 // Get next audio track
693                                                 if(!current_atrack)
694                                                         current_atrack = first;
695                                                 else
696                                                         current_atrack = current_atrack->next;
698                                                 while(current_atrack && 
699                                                         (current_atrack->data_type != TRACK_AUDIO ||
700                                                         !current_atrack->record))
701                                                         current_atrack = current_atrack->next;
703 // Paste it
704                                                 if(current_atrack)
705                                                 {
706                                                         current_atrack->paste_automation(selectionstart,
707                                                                 length,
708                                                                 frame_rate,
709                                                                 sample_rate,
710                                                                 file,
711                                                                 default_only);
712                                                 }
713                                         }
714                                         else
715                                         {
716 // Get next video track
717                                                 if(!current_vtrack)
718                                                         current_vtrack = first;
719                                                 else
720                                                         current_vtrack = current_vtrack->next;
722                                                 while(current_vtrack && 
723                                                         (current_vtrack->data_type != TRACK_VIDEO ||
724                                                         !current_vtrack->record))
725                                                         current_vtrack = current_vtrack->next;
727 // Paste it
728                                                 if(current_vtrack)
729                                                 {
730 //printf("Tracks::paste_automation 1 %s %d\n", current_vtrack->title, current_vtrack->record);
731                                                         current_vtrack->paste_automation(selectionstart,
732                                                                 length,
733                                                                 frame_rate,
734                                                                 sample_rate,
735                                                                 file,
736                                                                 default_only);
737                                                 }
738                                         }
739                                 }
740                         }
741                 }while(!result);
742         }
745 int Tracks::paste_default_keyframe(FileXML *file)
747         paste_automation(0, file, 1);
748         return 0;
751 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
753         dest_edit->insert_transition(server->title);
756 void Tracks::paste_video_transition(PluginServer *server, int first_track)
758         for(Track *current = first; current; current = NEXT)
759         {
760                 if(current->data_type == TRACK_VIDEO &&
761                         current->record)
762                 {
763                         int64_t position = current->to_units(
764                                 edl->local_session->get_selectionstart(), 0);
765                         Edit *current_edit = current->edits->editof(position, 
766                                 PLAY_FORWARD,
767                                 0);
768                         if(current_edit)
769                         {
770                                 paste_transition(server, current_edit);
771                         }
772                         if(first_track) break;
773                 }
774         }
778 int Tracks::paste_silence(double start, double end, int edit_plugins)
780         Track* current_track;
782         for(current_track = first; 
783                 current_track; 
784                 current_track = current_track->next)
785         {
786                 if(current_track->record) 
787                 { 
788                         current_track->paste_silence(start, end, edit_plugins); 
789                 }
790         }
791         return 0;
796 int Tracks::select_auto(int cursor_x, int cursor_y)
798         int result = 0;
799         for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
800         return result;
803 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
805         int result = 0;
807         for(Track* current = first; current && !result; current = NEXT) 
808         {
809                 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down); 
810         }
811         return 0;
814 int Tracks::modify_edithandles(double &oldposition, 
815         double &newposition, 
816         int currentend, 
817         Edit *sole_edit,
818         int handle_mode,
819         int edit_labels,
820         int edit_plugins)
822         Track *current;
824         for(current = first; current; current = NEXT)
825         {
826                 if(current->record)
827                 {
828                         current->modify_edithandles(oldposition, 
829                                 newposition, 
830                                 currentend,
831                                 sole_edit, 
832                                 handle_mode,
833                                 edit_labels,
834                                 edit_plugins);
835                 }
836         }
837         return 0;
840 int Tracks::modify_pluginhandles(double &oldposition, 
841         double &newposition, 
842         int currentend, 
843         Edit *sole_edit,
844         int handle_mode,
845         int edit_labels)
847         Track *current;
849         for(current = first; current; current = NEXT)
850         {
851                 if(current->record)
852                 {
853                         current->modify_pluginhandles(oldposition, 
854                                 newposition, 
855                                 currentend, 
856                                 sole_edit,
857                                 handle_mode,
858                                 edit_labels);
859                 }
860         }
861         return 0;
866 int Tracks::purge_asset(Asset *asset)
868         Track *current_track;
869         int result = 0;
870         
871         for(current_track = first; current_track; current_track = current_track->next)
872         {
873                 result += current_track->purge_asset(asset); 
874         }
875         return result;
878 int Tracks::asset_used(Asset *asset)
880         Track *current_track;
881         int result = 0;
882         
883         for(current_track = first; current_track; current_track = current_track->next)
884         {
885                 result += current_track->asset_used(asset); 
886         }
887         return result;
890 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
892         Track *current_track;
894         for(current_track = first; 
895                 current_track; 
896                 current_track = current_track->next)
897         {
898                 if((current_track->record || ignore_record) && 
899                         current_track->data_type == TRACK_VIDEO)
900                 {
901                         current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);
902                 }
903         }
904         return 0;