3 #include "automation.h"
9 #include "edlsession.h"
11 #include "floatauto.h"
12 #include "floatautos.h"
14 #include "localsession.h"
19 #include "pluginset.h"
20 #include "mainsession.h"
24 #include "trackcanvas.h"
26 #include "transition.h"
27 #include "transportque.inc"
33 Track::Track(EDL *edl, Tracks *tracks) : ListItem<Track>()
36 this->tracks = tracks;
45 track_w = edl->session->output_w;
46 track_h = edl->session->output_h;
54 plugin_set.remove_all_objects();
57 int Track::create_objects()
63 int Track::copy_settings(Track *track)
65 this->expand_view = track->expand_view;
66 this->draw = track->draw;
67 this->gang = track->gang;
68 this->record = track->record;
69 this->nudge = track->nudge;
70 this->play = track->play;
71 this->track_w = track->track_w;
72 this->track_h = track->track_h;
73 strcpy(this->title, track->title);
83 int Track::load_defaults(BC_Hash *defaults)
88 void Track::equivalent_output(Track *track, double *result)
90 if(data_type != track->data_type ||
91 track_w != track->track_w ||
92 track_h != track->track_h ||
93 play != track->play ||
94 nudge != track->nudge)
97 // Convert result to track units
99 automation->equivalent_output(track->automation, &result2);
100 edits->equivalent_output(track->edits, &result2);
102 int plugin_sets = MIN(plugin_set.total, track->plugin_set.total);
103 // Test existing plugin sets
104 for(int i = 0; i < plugin_sets; i++)
106 plugin_set.values[i]->equivalent_output(
107 track->plugin_set.values[i],
111 // New EDL has more plugin sets. Get starting plugin in new plugin sets
112 for(int i = plugin_sets; i < plugin_set.total; i++)
114 Plugin *current = plugin_set.values[i]->get_first_plugin();
117 if(result2 < 0 || current->startproject < result2)
118 result2 = current->startproject;
122 // New EDL has fewer plugin sets. Get starting plugin in old plugin set
123 for(int i = plugin_sets; i < track->plugin_set.total; i++)
125 Plugin *current = track->plugin_set.values[i]->get_first_plugin();
128 if(result2 < 0 || current->startproject < result2)
129 result2 = current->startproject;
133 // Number of plugin sets differs but somehow we didn't find the start of the
135 if(track->plugin_set.total != plugin_set.total && result2 < 0)
139 (*result < 0 || from_units(result2) < *result))
140 *result = from_units(result2);
144 int Track::is_synthesis(RenderEngine *renderengine,
148 int is_synthesis = 0;
149 for(int i = 0; i < plugin_set.total; i++)
151 Plugin *plugin = get_current_plugin(position,
158 // Assume data from a shared track is synthesized
159 if(plugin->plugin_type == PLUGIN_SHAREDMODULE)
162 is_synthesis = plugin->is_synthesis(renderengine,
165 if(is_synthesis) break;
171 void Track::copy_from(Track *track)
173 copy_settings(track);
174 edits->copy_from(track->edits);
175 for(int i = 0; i < this->plugin_set.total; i++)
176 delete this->plugin_set.values[i];
177 this->plugin_set.remove_all_objects();
179 for(int i = 0; i < track->plugin_set.total; i++)
181 PluginSet *new_plugin_set = plugin_set.append(new PluginSet(edl, this));
182 new_plugin_set->copy_from(track->plugin_set.values[i]);
184 automation->copy_from(track->automation);
185 this->track_w = track->track_w;
186 this->track_h = track->track_h;
189 Track& Track::operator=(Track& track)
191 printf("Track::operator= 1\n");
196 int Track::vertical_span(Theme *theme)
200 result = edl->local_session->zoom_track +
202 theme->get_image("plugin_bg_data")->get_h();
204 result = edl->local_session->zoom_track;
206 if(edl->session->show_titles)
207 result += theme->get_image("title_bg_data")->get_h();
212 double Track::get_length()
214 double total_length = 0;
219 unit_end = edits->last->startproject;
220 if (edits->last->transition)
221 unit_end += edits->last->transition->length + 1; // add one so transition is finished...
222 length = from_units(unit_end);
223 if(length > total_length) total_length = length;
226 for(int i = 0; i < plugin_set.total; i++)
228 length = from_units(plugin_set.values[i]->last->startproject);
229 if(length > total_length) total_length = length;
233 length = from_units(automation->get_length());
234 if(length > total_length) total_length = length;
242 void Track::get_source_dimensions(double position, int &w, int &h)
244 int64_t native_position = to_units(position, 0);
245 for(Edit *current = edits->first; current; current = NEXT)
247 if(current->startproject <= native_position &&
248 current->startproject + current->length > native_position &&
251 w = current->asset->width;
252 h = current->asset->height;
259 int64_t Track::horizontal_span()
261 return (int64_t)(get_length() *
262 edl->session->sample_rate /
263 edl->local_session->zoom_sample +
268 int Track::load(FileXML *file, int track_offset, uint32_t load_flags)
271 int current_channel = 0;
272 int current_plugin = 0;
275 record = file->tag.get_property("RECORD", record);
276 play = file->tag.get_property("PLAY", play);
277 gang = file->tag.get_property("GANG", gang);
278 draw = file->tag.get_property("DRAW", draw);
279 nudge = file->tag.get_property("NUDGE", nudge);
280 expand_view = file->tag.get_property("EXPAND", expand_view);
281 track_w = file->tag.get_property("TRACK_W", track_w);
282 track_h = file->tag.get_property("TRACK_H", track_h);
284 load_header(file, load_flags);
287 result = file->read_tag();
291 if(file->tag.title_is("/TRACK"))
296 if(file->tag.title_is("TITLE"))
298 file->read_text_until("/TITLE", title, BCTEXTLEN);
301 if(load_flags && automation->load(file)
302 /* strstr(file->tag.get_title(), "AUTOS") */)
307 if(file->tag.title_is("EDITS"))
309 if(load_flags & LOAD_EDITS)
310 edits->load(file, track_offset);
313 if(file->tag.title_is("PLUGINSET"))
315 if(load_flags & LOAD_EDITS)
317 PluginSet *plugin_set = new PluginSet(edl, this);
318 this->plugin_set.append(plugin_set);
319 plugin_set->load(file, load_flags);
322 if(load_flags & LOAD_AUTOMATION)
324 if(current_plugin < this->plugin_set.total)
326 PluginSet *plugin_set = this->plugin_set.values[current_plugin];
327 plugin_set->load(file, load_flags);
333 load_derived(file, load_flags);
342 void Track::insert_asset(Asset_GC asset,
347 //printf("Track::insert_asset %f\n", length);
348 edits->insert_asset(asset,
350 to_units(position, 0),
352 edits->loaded_length += to_units(length, 1);
357 // Default keyframes: We don't replace default keyframes in pasting but
358 // when inserting the first EDL of a load operation we need to replace
359 // the default keyframes.
361 // Plugins: This is an arbitrary behavior
363 // 1) No plugin in source track: Paste silence into destination
365 // 2) Plugin in source track: plugin in source track is inserted into
366 // existing destination track plugin sets, new sets being added when
369 void Track::insert_track(Track *track,
375 // Decide whether to copy settings based on load_mode
376 if(replace_default) copy_settings(track);
378 edits->insert_edits(track->edits, to_units(position, 0));
381 insert_plugin_set(track, position);
383 automation->insert_track(track->automation,
384 to_units(position, 0),
385 to_units(track->get_length(), 1),
392 // Called by insert_track
393 void Track::insert_plugin_set(Track *track, double position)
395 // Extend plugins if no incoming plugins
396 if(!track->plugin_set.total)
398 shift_effects(position,
403 for(int i = 0; i < track->plugin_set.total; i++)
405 if(i >= plugin_set.total)
406 plugin_set.append(new PluginSet(edl, this));
408 plugin_set.values[i]->insert_edits(track->plugin_set.values[i],
409 to_units(position, 0));
414 Plugin* Track::insert_effect(char *title,
415 SharedLocation *shared_location,
416 KeyFrame *default_keyframe,
417 PluginSet *plugin_set,
424 plugin_set = new PluginSet(edl, this);
425 this->plugin_set.append(plugin_set);
430 // Position is identical to source plugin
431 if(plugin_type == PLUGIN_SHAREDPLUGIN)
433 Track *source_track = tracks->get_item_number(shared_location->module);
436 Plugin *source_plugin = source_track->get_current_plugin(
437 edl->local_session->get_selectionstart(),
438 shared_location->plugin,
443 // From an attach operation
446 plugin = plugin_set->insert_plugin(title,
447 source_plugin->startproject,
448 source_plugin->length,
455 // From a drag operation
457 plugin = plugin_set->insert_plugin(title,
469 // This should be done in the caller
472 if(edl->local_session->get_selectionend() >
473 edl->local_session->get_selectionstart())
475 start = edl->local_session->get_selectionstart();
476 length = edl->local_session->get_selectionend() - start;
481 length = get_length();
484 //printf("Track::insert_effect %f %f %d %d\n", start, length, to_units(start, 0),
485 // to_units(length, 0));
487 plugin = plugin_set->insert_plugin(title,
495 //printf("Track::insert_effect 2 %f %f\n", start, length);
501 void Track::move_plugins_up(PluginSet *plugin_set)
503 for(int i = 0; i < this->plugin_set.total; i++)
505 if(this->plugin_set.values[i] == plugin_set)
509 PluginSet *temp = this->plugin_set.values[i - 1];
510 this->plugin_set.values[i - 1] = this->plugin_set.values[i];
511 this->plugin_set.values[i] = temp;
513 SharedLocation old_location, new_location;
514 new_location.module = old_location.module = tracks->number_of(this);
515 old_location.plugin = i;
516 new_location.plugin = i - 1;
517 tracks->change_plugins(old_location, new_location, 1);
523 void Track::move_plugins_down(PluginSet *plugin_set)
525 for(int i = 0; i < this->plugin_set.total; i++)
527 if(this->plugin_set.values[i] == plugin_set)
529 if(i == this->plugin_set.total - 1) break;
531 PluginSet *temp = this->plugin_set.values[i + 1];
532 this->plugin_set.values[i + 1] = this->plugin_set.values[i];
533 this->plugin_set.values[i] = temp;
535 SharedLocation old_location, new_location;
536 new_location.module = old_location.module = tracks->number_of(this);
537 old_location.plugin = i;
538 new_location.plugin = i + 1;
539 tracks->change_plugins(old_location, new_location, 1);
546 void Track::remove_asset(Asset_GC asset)
548 for(Edit *edit = edits->first; edit; edit = edit->next)
550 if(edit->asset && edit->asset == asset)
558 void Track::remove_pluginset(PluginSet *plugin_set)
561 for(i = 0; i < this->plugin_set.total; i++)
562 if(plugin_set == this->plugin_set.values[i]) break;
564 this->plugin_set.remove_object(plugin_set);
565 for(i++ ; i < this->plugin_set.total; i++)
567 SharedLocation old_location, new_location;
568 new_location.module = old_location.module = tracks->number_of(this);
569 old_location.plugin = i;
570 new_location.plugin = i - 1;
571 tracks->change_plugins(old_location, new_location, 0);
575 void Track::shift_keyframes(double position, double length, int convert_units)
579 position = to_units(position, 0);
580 length = to_units(length, 1);
583 automation->paste_silence(Units::to_int64(position),
584 Units::to_int64(position + length));
585 // Effect keyframes are shifted in shift_effects
588 void Track::shift_effects(double position, double length, int convert_units)
592 position = to_units(position, 0);
593 length = to_units(length, 1);
596 for(int i = 0; i < plugin_set.total; i++)
598 plugin_set.values[i]->shift_effects(Units::to_int64(position), Units::to_int64(length));
602 void Track::detach_effect(Plugin *plugin)
604 //printf("Track::detach_effect 1\n");
605 for(int i = 0; i < plugin_set.total; i++)
607 PluginSet *plugin_set = this->plugin_set.values[i];
608 for(Plugin *dest = (Plugin*)plugin_set->first;
610 dest = (Plugin*)dest->next)
614 int64_t start = plugin->startproject;
615 int64_t end = plugin->startproject + plugin->length;
617 plugin_set->clear(start, end);
618 plugin_set->paste_silence(start, end);
620 // Delete 0 length pluginsets
621 plugin_set->optimize();
622 //printf("Track::detach_effect 2 %d\n", plugin_set->length());
623 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
624 remove_pluginset(plugin_set);
631 void Track::resample(double old_rate, double new_rate)
633 edits->resample(old_rate, new_rate);
634 automation->resample(old_rate, new_rate);
635 for(int i = 0; i < plugin_set.total; i++)
636 plugin_set.values[i]->resample(old_rate, new_rate);
637 nudge = (int64_t)(nudge * new_rate / old_rate);
640 void Track::detach_shared_effects(int module)
642 for(int i = 0; i < plugin_set.total; i++)
644 PluginSet *plugin_set = this->plugin_set.values[i];
645 for(Plugin *dest = (Plugin*)plugin_set->first;
647 dest = (Plugin*)dest->next)
649 if ((dest->plugin_type == PLUGIN_SHAREDPLUGIN ||
650 dest->plugin_type == PLUGIN_SHAREDMODULE)
652 dest->shared_location.module == module)
654 int64_t start = dest->startproject;
655 int64_t end = dest->startproject + dest->length;
657 plugin_set->clear(start, end);
658 plugin_set->paste_silence(start, end);
660 // Delete 0 length pluginsets
661 plugin_set->optimize();
662 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
664 this->plugin_set.remove_object_number(i);
673 void Track::optimize()
676 for(int i = 0; i < plugin_set.total; i++)
678 PluginSet *plugin_set = this->plugin_set.values[i];
679 plugin_set->optimize();
680 //printf("Track::optimize %d\n", plugin_set.values[i]->total());
681 // new definition of empty track...
682 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
684 remove_pluginset(plugin_set);
690 Plugin* Track::get_current_plugin(double position,
697 if(convert_units) position = to_units(position, 0);
698 if(use_nudge) position += nudge;
700 if(plugin_set >= this->plugin_set.total || plugin_set < 0) return 0;
702 //printf("Track::get_current_plugin 1 %d %d %d\n", position, this->plugin_set.total, direction);
703 if(direction == PLAY_FORWARD)
705 for(current = (Plugin*)this->plugin_set.values[plugin_set]->last;
707 current = (Plugin*)PREVIOUS)
709 // printf("Track::get_current_plugin 2 %d %ld %ld\n",
710 // current->startproject,
711 // current->startproject + current->length,
713 if(current->startproject <= position &&
714 current->startproject + current->length > position)
721 if(direction == PLAY_REVERSE)
723 for(current = (Plugin*)this->plugin_set.values[plugin_set]->first;
725 current = (Plugin*)NEXT)
727 if(current->startproject < position &&
728 current->startproject + current->length >= position)
738 Plugin* Track::get_current_transition(double position,
745 if(convert_units) position = to_units(position, 0);
746 if(use_nudge) position += nudge;
748 if(direction == PLAY_FORWARD)
750 for(current = edits->last; current; current = PREVIOUS)
752 if(current->startproject <= position && current->startproject + current->length > position)
754 //printf("Track::get_current_transition %p\n", current->transition);
755 if(current->transition && position < current->startproject + current->transition->length)
757 result = current->transition;
764 if(direction == PLAY_REVERSE)
766 for(current = edits->first; current; current = NEXT)
768 if(current->startproject < position && current->startproject + current->length >= position)
770 if(current->transition && position <= current->startproject + current->transition->length)
772 result = current->transition;
782 void Track::synchronize_params(Track *track)
784 for(Edit *this_edit = edits->first, *that_edit = track->edits->first;
785 this_edit && that_edit;
786 this_edit = this_edit->next, that_edit = that_edit->next)
788 this_edit->synchronize_params(that_edit);
791 for(int i = 0; i < plugin_set.total && i < track->plugin_set.total; i++)
792 plugin_set.values[i]->synchronize_params(track->plugin_set.values[i]);
794 automation->copy_from(track->automation);
795 this->nudge = track->nudge;
804 printf(" Data type %d\n", data_type);
805 printf(" Title %s\n", title);
807 for(Edit* current = edits->first; current; current = NEXT)
812 printf(" Plugin Sets: %d\n", plugin_set.total);
814 for(int i = 0; i < plugin_set.total; i++)
815 plugin_set.values[i]->dump();
816 //printf("Track::dump 2\n");
840 Track::Track() : ListItem<Track>()
845 // ======================================== accounting
847 int Track::number_of()
849 return tracks->number_of(this);
864 // ================================================= editing
866 int Track::select_auto(AutoConf *auto_conf, int cursor_x, int cursor_y)
871 int Track::move_auto(AutoConf *auto_conf, int cursor_x, int cursor_y, int shift_down)
876 int Track::release_auto()
881 // used for copying automation alone
882 int Track::copy_automation(double selectionstart,
888 int64_t start = to_units(selectionstart, 0);
889 int64_t end = to_units(selectionend, 1);
891 file->tag.set_title("TRACK");
895 file->append_newline();
897 automation->copy(start, end, file, default_only, autos_only);
899 if(edl->session->auto_conf->plugins)
901 file->tag.set_title("PLUGINSETS");
903 file->append_newline();
904 for(int i = 0; i < plugin_set.total; i++)
907 plugin_set.values[i]->copy_keyframes(start,
913 file->tag.set_title("/PLUGINSETS");
915 file->append_newline();
918 file->tag.set_title("/TRACK");
920 file->append_newline();
921 file->append_newline();
922 file->append_newline();
923 file->append_newline();
928 int Track::paste_automation(double selectionstart,
935 // Only used for pasting automation alone.
941 if(data_type == TRACK_AUDIO)
942 scale = edl->session->sample_rate / sample_rate;
944 scale = edl->session->frame_rate / frame_rate;
946 total_length *= scale;
947 start = to_units(selectionstart, 0);
948 length = to_units(total_length, 1);
950 //printf("Track::paste_automation 1\n");
954 result = file->read_tag();
958 if(file->tag.title_is("/TRACK"))
961 if(automation->paste(start,
967 /* strstr(file->tag.get_title(), "AUTOS")) */
972 if(file->tag.title_is("PLUGINSETS"))
974 //printf("Track::paste_automation 2 %d\n", current_pluginset);
975 PluginSet::paste_keyframes(start,
983 //printf("Track::paste_automation 3\n");
989 void Track::clear_automation(double selectionstart,
994 int64_t start = to_units(selectionstart, 0);
995 int64_t end = to_units(selectionend, 1);
997 automation->clear(start, end, edl->session->auto_conf, 0);
999 if(edl->session->auto_conf->plugins)
1001 for(int i = 0; i < plugin_set.total; i++)
1003 plugin_set.values[i]->clear_keyframes(start, end);
1009 void Track::straighten_automation(double selectionstart,
1010 double selectionend)
1012 int64_t start = to_units(selectionstart, 0);
1013 int64_t end = to_units(selectionend, 1);
1015 automation->straighten(start, end, edl->session->auto_conf);
1021 int Track::copy(double start,
1026 // Use a copy of the selection in converted units
1027 // So copy_automation doesn't reconvert.
1028 int64_t start_unit = to_units(start, 0);
1029 int64_t end_unit = to_units(end, 1);
1034 file->tag.set_title("TRACK");
1035 file->tag.set_property("RECORD", record);
1036 file->tag.set_property("NUDGE", nudge);
1037 file->tag.set_property("PLAY", play);
1038 file->tag.set_property("GANG", gang);
1039 file->tag.set_property("DRAW", draw);
1040 file->tag.set_property("EXPAND", expand_view);
1041 file->tag.set_property("TRACK_W", track_w);
1042 file->tag.set_property("TRACK_H", track_h);
1045 file->append_newline();
1048 file->tag.set_title("TITLE");
1050 file->append_text(title);
1051 file->tag.set_title("/TITLE");
1053 file->append_newline();
1055 // if(data_type == TRACK_AUDIO)
1056 // file->tag.set_property("TYPE", "AUDIO");
1058 // file->tag.set_property("TYPE", "VIDEO");
1060 // file->append_tag();
1061 // file->append_newline();
1063 edits->copy(start_unit, end_unit, file, output_path);
1066 auto_conf.set_all(1);
1067 automation->copy(start_unit, end_unit, file, 0, 0);
1070 for(int i = 0; i < plugin_set.total; i++)
1072 plugin_set.values[i]->copy(start_unit, end_unit, file);
1075 copy_derived(start_unit, end_unit, file);
1077 file->tag.set_title("/TRACK");
1079 file->append_newline();
1080 file->append_newline();
1081 file->append_newline();
1082 file->append_newline();
1087 int Track::copy_assets(double start,
1089 Assets_vector &asset_list)
1093 start = to_units(start, 0);
1094 end = to_units(end, 1);
1096 Edit *current = edits->editof((int64_t)start, PLAY_FORWARD, 0);
1099 while(current && current->startproject < end)
1101 // Check for duplicate assets
1104 for(i = 0, result = 0; i < asset_list.size(); i++)
1106 if(asset_list[i] == current->asset) result = 1;
1108 // append pointer to new asset
1109 if(!result) asset_list.push_back(current->asset);
1122 int Track::clear(double start,
1130 // Edits::move_auto calls this routine after the units are converted to the track
1132 //printf("Track::clear 1 %d %d %d\n", edit_edits, edit_labels, edit_plugins);
1135 start = to_units(start, 0);
1136 end = to_units(end, 1);
1140 automation->clear((int64_t)start, (int64_t)end, 0, 1);
1143 for(int i = 0; i < plugin_set.total; i++)
1145 if(!trim_edits || trim_edits == (Edits*)plugin_set.values[i])
1146 plugin_set.values[i]->clear((int64_t)start, (int64_t)end);
1150 edits->clear((int64_t)start, (int64_t)end);
1154 int Track::clear_handle(double start,
1160 edits->clear_handle(start, end, clear_plugins, distance);
1163 int Track::popup_transition(int cursor_x, int cursor_y)
1170 int Track::modify_edithandles(double oldposition,
1177 edits->modify_handles(oldposition,
1190 int Track::modify_pluginhandles(double oldposition,
1197 for(int i = 0; i < plugin_set.total; i++)
1199 if(!trim_edits || trim_edits == (Edits*)plugin_set.values[i])
1200 plugin_set.values[i]->modify_handles(oldposition,
1204 // Don't allow plugin tweeks to affect edits.
1214 int Track::paste_silence(double start, double end, int edit_plugins)
1216 start = to_units(start, 0);
1217 end = to_units(end, 1);
1219 edits->paste_silence((int64_t)start, (int64_t)end);
1220 shift_keyframes(start, end - start, 0);
1221 if(edit_plugins) shift_effects(start, end - start, 0);
1227 int Track::select_edit(int cursor_x,
1235 int Track::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
1240 void Track::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
1242 for(int i = 0; i < plugin_set.total; i++)
1244 for(Plugin *plugin = (Plugin*)plugin_set.values[i]->first;
1246 plugin = (Plugin*)plugin->next)
1248 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
1250 if(plugin->shared_location == old_location)
1251 plugin->shared_location = new_location;
1253 if(do_swap && plugin->shared_location == new_location)
1254 plugin->shared_location = old_location;
1260 void Track::change_modules(int old_location, int new_location, int do_swap)
1262 for(int i = 0; i < plugin_set.total; i++)
1264 for(Plugin *plugin = (Plugin*)plugin_set.values[i]->first;
1266 plugin = (Plugin*)plugin->next)
1268 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
1269 plugin->plugin_type == PLUGIN_SHAREDMODULE)
1271 if(plugin->shared_location.module == old_location)
1272 plugin->shared_location.module = new_location;
1274 if(do_swap && plugin->shared_location.module == new_location)
1275 plugin->shared_location.module = old_location;
1282 int Track::playable_edit(int64_t position, int direction)
1285 if(direction == PLAY_REVERSE) position--;
1286 for(Edit *current = edits->first; current && !result; current = NEXT)
1288 if(current->startproject <= position &&
1289 current->startproject + current->length > position)
1291 //printf("Track::playable_edit %p %p\n", current->transition, current->asset);
1292 if(current->transition || current->asset) result = 1;
1299 int Track::need_edit(Edit *current, int test_transitions)
1301 return ((test_transitions && current->transition) ||
1302 (!test_transitions && current->asset));
1305 int64_t Track::plugin_change_duration(int64_t input_position,
1306 int64_t input_length,
1310 if(use_nudge) input_position += nudge;
1311 for(int i = 0; i < plugin_set.total; i++)
1313 int64_t new_duration = plugin_set.values[i]->plugin_change_duration(
1317 if(new_duration < input_length) input_length = new_duration;
1319 return input_length;
1322 int64_t Track::edit_change_duration(int64_t input_position,
1323 int64_t input_length,
1325 int test_transitions,
1329 int64_t edit_length = input_length;
1330 if(use_nudge) input_position += nudge;
1334 // ================================= Reverse playback
1335 // Get first edit on or after position
1336 for(current = edits->first;
1337 current && current->startproject + current->length <= input_position;
1343 if(current->startproject > input_position)
1345 // Before first edit
1349 if(need_edit(current, test_transitions))
1351 // Over an edit of interest.
1352 if(input_position - current->startproject < input_length)
1353 edit_length = input_position - current->startproject + 1;
1357 // Over an edit that isn't of interest.
1358 // Search for next edit of interest.
1359 for(current = PREVIOUS ;
1361 current->startproject + current->length > input_position - input_length &&
1362 !need_edit(current, test_transitions);
1367 need_edit(current, test_transitions) &&
1368 current->startproject + current->length > input_position - input_length)
1369 edit_length = input_position - current->startproject - current->length + 1;
1374 // Not over an edit. Try the last edit.
1375 current = edits->last;
1377 ((test_transitions && current->transition) ||
1378 (!test_transitions && current->asset)))
1379 edit_length = input_position - edits->length() + 1;
1384 // =================================== forward playback
1385 // Get first edit on or before position
1386 for(current = edits->last;
1387 current && current->startproject > input_position;
1393 if(current->startproject + current->length <= input_position)
1395 // Beyond last edit.
1399 if(need_edit(current, test_transitions))
1401 // Over an edit of interest.
1402 // Next edit is going to require a change.
1403 if(current->length + current->startproject - input_position < input_length)
1404 edit_length = current->startproject + current->length - input_position;
1408 // Over an edit that isn't of interest.
1409 // Search for next edit of interest.
1410 for(current = NEXT ;
1412 current->startproject < input_position + input_length &&
1413 !need_edit(current, test_transitions);
1418 need_edit(current, test_transitions) &&
1419 current->startproject < input_position + input_length)
1420 edit_length = current->startproject - input_position;
1425 // Not over an edit. Try the first edit.
1426 current = edits->first;
1428 ((test_transitions && current->transition) ||
1429 (!test_transitions && current->asset)))
1430 edit_length = edits->first->startproject - input_position;
1434 if(edit_length < input_length)
1437 return input_length;
1440 int Track::purge_asset(Asset_GC asset)
1445 int Track::asset_used(Asset_GC asset)
1450 for(current_edit = edits->first; current_edit; current_edit = current_edit->next)
1452 if(current_edit->asset == asset)
1460 int Track::is_playable(int64_t position, int direction)
1466 int Track::plugin_used(int64_t position, int64_t direction)
1468 //printf("Track::plugin_used 1 %d\n", this->plugin_set.total);
1469 for(int i = 0; i < this->plugin_set.total; i++)
1471 Plugin *current_plugin = get_current_plugin(position,
1477 //printf("Track::plugin_used 2 %p\n", current_plugin);
1478 if(current_plugin &&
1479 (current_plugin->on &&
1480 current_plugin->plugin_type != PLUGIN_NONE))
1485 //printf("Track::plugin_used 3 %p\n", current_plugin);
1489 // Audio is always rendered through VConsole
1490 int Track::direct_copy_possible(int64_t start, int direction, int use_nudge)
1495 int64_t Track::to_units(double position, int round)
1497 return (int64_t)position;
1500 double Track::to_doubleunits(double position)
1505 double Track::from_units(int64_t position)
1507 return (double)position;
1512 // c-file-style: "linux"