3 * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "automation.h"
25 #include "bcsignals.h"
29 #include "edlsession.h"
34 #include "localsession.h"
37 #include "mainsession.h"
38 #include "pluginserver.h"
39 #include "pluginset.h"
42 #include "trackcanvas.h"
44 #include "trackscroll.h"
45 #include "transition.h"
46 #include "transportque.h"
50 int Tracks::clear(double start, double end, int clear_plugins, int edit_autos)
54 for(current_track = first;
56 current_track = current_track->next)
58 if(current_track->record)
60 current_track->clear(start,
73 void Tracks::clear_automation(double selectionstart, double selectionend)
77 for(current_track = first; current_track; current_track = current_track->next)
79 if(current_track->record)
81 current_track->clear_automation(selectionstart,
89 void Tracks::clear_transitions(double start, double end)
91 for(Track *current_track = first;
93 current_track = current_track->next)
95 if(current_track->record)
97 int64_t start_units = current_track->to_units(start, 0);
98 int64_t end_units = current_track->to_units(end, 0);
100 for(Edit *current_edit = current_track->edits->first;
102 current_edit = current_edit->next)
104 if(current_edit->startproject >= start_units &&
105 current_edit->startproject < end_units &&
106 current_edit->transition)
108 current_edit->detach_transition();
115 void Tracks::shuffle_edits(double start, double end)
117 // This doesn't affect automation or effects
118 // Labels follow the first track.
120 for(Track *current_track = first;
122 current_track = current_track->next)
124 if(current_track->record)
126 current_track->shuffle_edits(start, end, first_track);
133 void Tracks::align_edits(double start, double end)
135 // This doesn't affect automation or effects
136 ArrayList<double> times;
138 for(Track *current_track = first;
140 current_track = current_track->next)
142 if(current_track->record)
144 current_track->align_edits(start, end, ×);
149 void Tracks::set_edit_length(double start, double end, double length)
152 for(Track *current_track = first;
154 current_track = current_track->next)
156 if(current_track->record)
158 #define USE_FLOATING_LENGTHS
160 #ifdef USE_FLOATING_LENGTHS
163 // The first edit anchors the length offsets.
164 // Round edits up & down so they end where they would if they all had floating point lengths.
165 //int first_edit = 1;
166 int64_t start_units = current_track->to_units(start, 0);
167 int64_t end_units = current_track->to_units(end, 0);
168 // Total time of edits accumulated, in track units
169 int64_t total_units = 0;
170 // Number of length offsets added so far
171 int total_lengths = 0;
173 for(Edit *current_edit = current_track->edits->last;
175 current_edit = current_edit->previous)
177 if(current_edit->startproject >= start_units &&
178 current_edit->startproject + current_edit->length <= end_units)
180 // Calculate true length based on number of length offsets & total time
181 double end_time = (1 + total_lengths) * length;
182 int64_t length_units = current_track->to_units(end_time, 0) -
184 if(length_units < 1) length_units = 1;
185 printf("Tracks::set_edit_length %d %f %f\n", __LINE__, end_time, current_track->from_units(total_units));
186 total_units += length_units;
188 // Go in using the edit handle interface
189 int64_t starting_length = current_edit->length;
191 if(length_units < current_edit->length)
193 current_edit->shift_end_in(MOVE_ALL_EDITS,
194 current_edit->startproject + length_units,
195 current_edit->startproject + current_edit->length,
197 edl->session->labels_follow_edits,
198 edl->session->plugins_follow_edits,
199 edl->session->autos_follow_edits,
204 current_edit->shift_end_out(MOVE_ALL_EDITS,
205 current_edit->startproject + length_units,
206 current_edit->startproject + current_edit->length,
208 edl->session->labels_follow_edits,
209 edl->session->plugins_follow_edits,
210 edl->session->autos_follow_edits,
214 int64_t ending_length = current_edit->length;
216 if(edl->session->labels_follow_edits && first_track)
218 // printf("Tracks::set_edit_length %d %f %f\n",
220 // current_track->from_units(current_edit->startproject + starting_length),
221 // current_track->from_units(current_edit->startproject + ending_length));
222 edl->labels->modify_handles(
223 current_track->from_units(current_edit->startproject + starting_length),
224 current_track->from_units(current_edit->startproject + ending_length),
238 #else // USE_FLOATING_LENGTHS
240 // The first edit anchors the length offsets.
241 // The idea was to round edits up & down so they end where they should
242 // if they all had floating point lengths. It's easier just to make sure the framerate
243 // is divisible by the required length.
244 // int first_edit = 1;
245 int64_t start_units = current_track->to_units(start, 0);
246 int64_t end_units = current_track->to_units(end, 0);
247 int64_t length_units = current_track->to_units(length, 1);
248 // Starting time of the length offsets in seconds
249 // double start_time = 0;
250 // Number of length offsets added so far
251 // int total_lengths = 0;
253 for(Edit *current_edit = current_track->edits->last;
255 current_edit = current_edit->previous)
257 if(current_edit->startproject >= start_units &&
258 current_edit->startproject + current_edit->length <= end_units)
260 // Calculate starting time of length offsets
263 // start_time = current_track->from_units(current_edit->startproject);
266 // Calculate true length based on number of length offsets
267 // double end_time = start_time + (1 + total_lengths) * length;
268 // int64_t length_units = current_track->to_units(end_time, 0) -
269 // current_edit->startproject;
270 // if(length_units < 1) length_units = 1;
272 // Go in using the edit handle interface
273 int64_t starting_length = current_edit->length;
275 if(length_units < current_edit->length)
277 current_edit->shift_end_in(MOVE_ALL_EDITS,
278 current_edit->startproject + length_units,
279 current_edit->startproject + current_edit->length,
281 edl->session->labels_follow_edits,
282 edl->session->plugins_follow_edits,
283 edl->session->autos_follow_edits,
288 current_edit->shift_end_out(MOVE_ALL_EDITS,
289 current_edit->startproject + length_units,
290 current_edit->startproject + current_edit->length,
292 edl->session->labels_follow_edits,
293 edl->session->plugins_follow_edits,
294 edl->session->autos_follow_edits,
298 int64_t ending_length = current_edit->length;
300 if(edl->session->labels_follow_edits && first_track)
302 // printf("Tracks::set_edit_length %d %f %f\n",
304 // current_track->from_units(current_edit->startproject + starting_length),
305 // current_track->from_units(current_edit->startproject + ending_length));
306 edl->labels->modify_handles(
307 current_track->from_units(current_edit->startproject + starting_length),
308 current_track->from_units(current_edit->startproject + ending_length),
319 #endif // !USE_FLOATING_LENGTHS
326 void Tracks::set_transition_length(double start, double end, double length)
328 for(Track *current_track = first;
330 current_track = current_track->next)
332 if(current_track->record)
334 int64_t start_units = current_track->to_units(start, 0);
335 int64_t end_units = current_track->to_units(end, 0);
337 for(Edit *current_edit = current_track->edits->first;
339 current_edit = current_edit->next)
341 if(current_edit->startproject >= start_units &&
342 current_edit->startproject < end_units &&
343 current_edit->transition)
345 current_edit->transition->length =
346 current_track->to_units(length, 1);
353 void Tracks::set_transition_length(Transition *transition, double length)
355 // Must verify existence of transition
357 if(!transition) return;
358 for(Track *current_track = first;
359 current_track && !done;
360 current_track = current_track->next)
362 for(Edit *current_edit = current_track->edits->first;
363 current_edit && !done;
364 current_edit = current_edit->next)
366 if(current_edit->transition == transition)
368 transition->length = current_track->to_units(length, 1);
375 void Tracks::paste_transitions(double start, double end, int track_type, char* title)
377 for(Track *current_track = first;
379 current_track = current_track->next)
381 if(current_track->record && current_track->data_type == track_type)
383 int64_t start_units = current_track->to_units(start, 0);
384 int64_t end_units = current_track->to_units(end, 0);
386 for(Edit *current_edit = current_track->edits->first;
388 current_edit = current_edit->next)
390 if(current_edit->startproject > 0 &&
391 ((end_units > start_units &&
392 current_edit->startproject >= start_units &&
393 current_edit->startproject < end_units) ||
394 (end_units == start_units &&
395 current_edit->startproject <= start_units &&
396 current_edit->startproject + current_edit->length > start_units)))
398 current_edit->insert_transition(title);
405 void Tracks::set_automation_mode(double selectionstart,
409 Track* current_track;
411 for(current_track = first; current_track; current_track = current_track->next)
413 if(current_track->record)
415 current_track->set_automation_mode(selectionstart,
422 int Tracks::clear_default_keyframe()
424 for(Track *current = first; current; current = NEXT)
427 current->clear_automation(0, 0, 0, 1);
432 int Tracks::clear_handle(double start,
434 double &longest_distance,
439 Track* current_track;
442 for(current_track = first; current_track; current_track = current_track->next)
444 if(current_track->record)
446 current_track->clear_handle(start,
452 if(distance > longest_distance) longest_distance = distance;
459 int Tracks::copy_automation(double selectionstart,
465 // called by MWindow::copy_automation for copying automation alone
466 Track* current_track;
468 file->tag.set_title("AUTO_CLIPBOARD");
469 file->tag.set_property("LENGTH", selectionend - selectionstart);
470 file->tag.set_property("FRAMERATE", edl->session->frame_rate);
471 file->tag.set_property("SAMPLERATE", edl->session->sample_rate);
473 file->append_newline();
474 file->append_newline();
476 for(current_track = first;
478 current_track = current_track->next)
480 if(current_track->record)
482 current_track->copy_automation(selectionstart,
490 file->tag.set_title("/AUTO_CLIPBOARD");
492 file->append_newline();
493 file->terminate_string();
497 // int Tracks::copy_default_keyframe(FileXML *file)
499 // copy_automation(0, 0, file, 1, 0);
503 int Tracks::delete_tracks()
505 int total_deleted = 0;
511 Track *next_track = 0;
512 for (Track* current = first;
514 current = next_track)
516 next_track = current->next;
519 delete_track(current);
525 return total_deleted;
528 void Tracks::move_edits(ArrayList<Edit*> *edits,
531 int edit_labels, // Ignored
532 int edit_plugins, // Ignored
533 int edit_autos) // Ignored
535 //printf("Tracks::move_edits 1\n");
536 for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
538 if(dest_track->record)
540 // Need a local copy of the source edit since the original source edit may
541 // change in the editing operation.
542 Edit *source_edit = 0;
543 Track *source_track = 0;
547 if(dest_track->data_type == TRACK_AUDIO)
549 int current_aedit = 0;
551 while(current_aedit < edits->total &&
552 edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
555 if(current_aedit < edits->total)
557 source_edit = edits->values[current_aedit];
558 source_track = source_edit->track;
559 edits->remove_number(current_aedit);
563 if(dest_track->data_type == TRACK_VIDEO)
565 int current_vedit = 0;
566 while(current_vedit < edits->total &&
567 edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
570 if(current_vedit < edits->total)
572 source_edit = edits->values[current_vedit];
573 source_track = source_edit->track;
574 edits->remove_number(current_vedit);
578 //printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
583 AutoConf temp_autoconf;
584 int64_t position_i = source_track->to_units(position, 0);
585 // Source edit changes
586 int64_t source_length = source_edit->length;
588 temp_autoconf.set_all(1);
590 source_track->automation->copy(source_edit->startproject,
591 source_edit->startproject + source_edit->length,
595 temp.terminate_string();
597 // Insert new keyframes
598 //printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
599 source_track->automation->clear(source_edit->startproject,
600 source_edit->startproject + source_edit->length,
603 int64_t position_a = position_i;
604 if (dest_track == source_track)
606 if (position_a > source_edit->startproject)
607 position_a -= source_length;
610 dest_track->automation->paste_silence(position_a,
611 position_a + source_length);
612 while(!temp.read_tag())
613 dest_track->automation->paste(position_a,
624 Edit *dest_edit = dest_track->edits->shift(position_i,
626 Edit *result = dest_track->edits->insert_before(dest_edit,
627 new Edit(edl, dest_track));
628 result->copy_from(source_edit);
629 result->startproject = position_i;
630 result->length = source_length;
633 source_track->edits->clear(source_edit->startproject,
634 source_edit->startproject + source_length);
635 source_track->optimize();
636 dest_track->optimize();
642 void Tracks::move_effect(Plugin *plugin,
643 PluginSet *dest_plugin_set,
645 int64_t dest_position)
647 Track *source_track = plugin->track;
650 // Insert on an existing plugin set
651 if(!dest_track && dest_plugin_set)
653 //Track *dest_track = dest_plugin_set->track;
656 // Assume this operation never splits a plugin
657 // Shift destination plugins back
658 dest_plugin_set->shift(dest_position, plugin->length);
662 for(current = (Plugin*)dest_plugin_set->first; current; current = (Plugin*)NEXT)
663 if(current->startproject >= dest_position) break;
665 result = (Plugin*)dest_plugin_set->insert_before(current,
666 new Plugin(edl, dest_plugin_set, ""));
669 // Create a new plugin set
673 if(edl->local_session->get_selectionend() >
674 edl->local_session->get_selectionstart())
676 start = edl->local_session->get_selectionstart();
677 length = edl->local_session->get_selectionend() -
681 if(dest_track->get_length() > 0)
684 length = dest_track->get_length();
689 length = dest_track->from_units(plugin->length);
693 result = dest_track->insert_effect("",
694 &plugin->shared_location,
699 plugin->plugin_type);
704 result->copy_from(plugin);
705 result->shift(dest_position - plugin->startproject);
707 // Clear new plugin from old set
708 plugin->plugin_set->clear(plugin->startproject,
709 plugin->startproject + plugin->length,
710 edl->session->autos_follow_edits);
713 source_track->optimize();
717 int Tracks::concatenate_tracks(int edit_plugins, int edit_autos)
719 Track *output_track, *first_output_track, *input_track;
720 int i, data_type = TRACK_AUDIO;
725 for(i = 0; i < 2; i++)
727 // Get first output track
728 for(output_track = first;
730 output_track = output_track->next)
731 if(output_track->data_type == data_type &&
732 output_track->record) break;
734 first_output_track = output_track;
736 // Get first input track
737 for(input_track = first;
739 input_track = input_track->next)
741 if(input_track->data_type == data_type &&
743 !input_track->record) break;
747 if(output_track && input_track)
749 // Transfer input track to end of output track one at a time
752 output_start = output_track->get_length();
753 output_track->insert_track(input_track,
760 // Get next source and destination
761 for(input_track = input_track->next;
763 input_track = input_track->next)
766 if(input_track->data_type == data_type &&
767 !input_track->record &&
768 input_track->play) break;
771 for(output_track = output_track->next;
773 output_track = output_track->next)
775 if(output_track->data_type == data_type &&
776 output_track->record) break;
781 output_track = first_output_track;
787 if(data_type == TRACK_AUDIO) data_type = TRACK_VIDEO;
793 int Tracks::delete_all_tracks()
795 while(last) delete last;
800 void Tracks::change_modules(int old_location, int new_location, int do_swap)
802 for(Track* current = first ; current; current = current->next)
804 current->change_modules(old_location, new_location, do_swap);
808 void Tracks::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
810 for(Track* current = first ; current; current = current->next)
812 current->change_plugins(old_location, new_location, do_swap);
818 // =========================================== EDL editing
821 int Tracks::copy(double start,
825 const char *output_path)
828 if(start == end && !all) return 1;
836 if(current->record || all)
838 current->copy(start, end, file,output_path);
847 int Tracks::move_track_up(Track *track)
849 Track *next_track = track->previous;
850 if(!next_track) next_track = last;
852 change_modules(number_of(track), number_of(next_track), 1);
854 // printf("Tracks::move_track_up 1 %p %p\n", track, next_track);
856 // for(Track *current = first; current && count < 5; current = NEXT, count++)
857 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
858 // printf("Tracks::move_track_up 2\n");
860 swap(track, next_track);
863 // for(Track *current = first; current && count < 5; current = NEXT, count++)
864 // printf("Tracks::move_track_up %p %p %p\n", current->previous, current, current->next);
865 // printf("Tracks::move_track_up 3\n");
870 int Tracks::move_track_down(Track *track)
872 Track *next_track = track->next;
873 if(!next_track) next_track = first;
875 change_modules(number_of(track), number_of(next_track), 1);
876 swap(track, next_track);
881 int Tracks::move_tracks_up()
883 Track *track, *next_track;
890 next_track = track->next;
896 change_modules(number_of(track->previous), number_of(track), 1);
898 swap(track->previous, track);
907 int Tracks::move_tracks_down()
909 Track *track, *previous_track;
914 track = previous_track)
916 previous_track = track->previous;
922 change_modules(number_of(track), number_of(track->next), 1);
924 swap(track, track->next);
935 void Tracks::paste_audio_transition(PluginServer *server)
937 for(Track *current = first; current; current = NEXT)
939 if(current->data_type == TRACK_AUDIO &&
942 int64_t position = current->to_units(
943 edl->local_session->get_selectionstart(), 0);
944 Edit *current_edit = current->edits->editof(position,
949 paste_transition(server, current_edit);
955 void Tracks::paste_automation(double selectionstart,
961 Track* current_track = 0;
962 Track* current_atrack = 0;
963 Track* current_vtrack = 0;
964 Track* dst_track = 0;
968 double frame_rate = edl->session->frame_rate;
969 int64_t sample_rate = edl->session->sample_rate;
970 char string[BCTEXTLEN];
975 result = file->read_tag();
977 !file->tag.title_is("AUTO_CLIPBOARD"));
981 length = file->tag.get_property("LENGTH", 0);
982 frame_rate = file->tag.get_property("FRAMERATE", frame_rate);
983 sample_rate = file->tag.get_property("SAMPLERATE", sample_rate);
988 result = file->read_tag();
992 if(file->tag.title_is("/AUTO_CLIPBOARD"))
997 if(file->tag.title_is("TRACK"))
999 file->tag.get_property("TYPE", string);
1000 if(!strcmp(string, "AUDIO"))
1002 src_type = TRACK_AUDIO;
1006 src_type = TRACK_VIDEO;
1009 // paste to any media type
1012 if(!current_track) current_track = first;
1013 while(current_track && !current_track->record)
1014 current_track = current_track->next;
1015 dst_track = current_track;
1018 if(!strcmp(string, "AUDIO"))
1020 // Get next audio track
1022 current_atrack = first;
1024 current_atrack = current_atrack->next;
1026 while(current_atrack &&
1027 (current_atrack->data_type != TRACK_AUDIO ||
1028 !current_atrack->record))
1029 current_atrack = current_atrack->next;
1030 dst_track = current_atrack;
1034 // Get next video track
1036 current_vtrack = first;
1038 current_vtrack = current_vtrack->next;
1040 while(current_vtrack &&
1041 (current_vtrack->data_type != TRACK_VIDEO ||
1042 !current_vtrack->record))
1043 current_vtrack = current_vtrack->next;
1045 dst_track = current_vtrack;
1050 double frame_rate2 = frame_rate;
1051 double sample_rate2 = sample_rate;
1053 if(src_type != dst_track->data_type)
1055 frame_rate2 = sample_rate;
1056 sample_rate2 = frame_rate;
1059 dst_track->paste_automation(selectionstart,
1073 // int Tracks::paste_default_keyframe(FileXML *file)
1075 // paste_automation(0, file, 1, 0);
1079 void Tracks::paste_transition(PluginServer *server, Edit *dest_edit)
1081 dest_edit->insert_transition(server->title);
1084 void Tracks::paste_video_transition(PluginServer *server, int first_track)
1086 for(Track *current = first; current; current = NEXT)
1088 if(current->data_type == TRACK_VIDEO &&
1091 int64_t position = current->to_units(
1092 edl->local_session->get_selectionstart(), 0);
1093 Edit *current_edit = current->edits->editof(position,
1098 paste_transition(server, current_edit);
1100 if(first_track) break;
1106 int Tracks::paste_silence(double start,
1111 Track* current_track;
1113 for(current_track = first;
1115 current_track = current_track->next)
1117 if(current_track->record)
1119 current_track->paste_silence(start,
1130 int Tracks::select_auto(int cursor_x, int cursor_y)
1133 for(Track* current = first; current && !result; current = NEXT) { result = current->select_auto(&auto_conf, cursor_x, cursor_y); }
1137 int Tracks::move_auto(int cursor_x, int cursor_y, int shift_down)
1141 for(Track* current = first; current && !result; current = NEXT)
1143 result = current->move_auto(&auto_conf, cursor_x, cursor_y, shift_down);
1148 int Tracks::modify_edithandles(double &oldposition,
1149 double &newposition,
1158 for(current = first; current; current = NEXT)
1162 current->modify_edithandles(oldposition,
1174 int Tracks::modify_pluginhandles(double &oldposition,
1175 double &newposition,
1184 for(current = first; current; current = NEXT)
1188 current->modify_pluginhandles(oldposition,
1202 int Tracks::purge_asset(Asset *asset)
1204 Track *current_track;
1207 for(current_track = first; current_track; current_track = current_track->next)
1209 result += current_track->purge_asset(asset);
1214 int Tracks::asset_used(Asset *asset)
1216 Track *current_track;
1219 for(current_track = first; current_track; current_track = current_track->next)
1221 result += current_track->asset_used(asset);
1226 int Tracks::scale_time(float rate_scale, int ignore_record, int scale_edits, int scale_autos, int64_t start, int64_t end)
1228 Track *current_track;
1230 for(current_track = first;
1232 current_track = current_track->next)
1234 if((current_track->record || ignore_record) &&
1235 current_track->data_type == TRACK_VIDEO)
1237 current_track->scale_time(rate_scale, scale_edits, scale_autos, start, end);