4 #include "edlsession.h"
5 #include "localsession.h"
8 #include "transportque.inc"
13 Autos::Autos(EDL *edl, Track *track)
25 while(last) delete last;
29 void Autos::create_objects()
32 default_auto = new_auto();
33 default_auto->is_default = 1;
41 Auto* Autos::append_auto()
43 return append(new_auto());
47 Auto* Autos::new_auto()
49 return new Auto(edl, this);
52 void Autos::resample(double old_rate, double new_rate)
54 for(Auto *current = first; current; current = NEXT)
56 current->position = (int64_t)((double)current->position *
63 void Autos::equivalent_output(Autos *autos, int64_t startproject, int64_t *result)
65 // Default keyframe differs
66 if(!total() && !(*default_auto == *autos->default_auto))
68 if(*result < 0 || *result > startproject) *result = startproject;
71 // Search for difference
73 for(Auto *current = first, *that_current = autos->first;
74 current || that_current;
76 that_current = that_current->next)
79 if(current && !that_current)
81 int64_t position1 = (autos->last ? autos->last->position : startproject);
82 int64_t position2 = current->position;
83 if(*result < 0 || *result > MIN(position1, position2))
84 *result = MIN(position1, position2);
88 if(!current && that_current)
90 int64_t position1 = (last ? last->position : startproject);
91 int64_t position2 = that_current->position;
92 if(*result < 0 || *result > MIN(position1, position2))
93 *result = MIN(position1, position2);
98 if(!(*current == *that_current) ||
99 current->position != that_current->position)
101 int64_t position1 = (current->previous ?
102 current->previous->position :
104 int64_t position2 = (that_current->previous ?
105 that_current->previous->position :
107 if(*result < 0 || *result > MIN(position1, position2))
108 *result = MIN(position1, position2);
115 void Autos::copy_from(Autos *autos)
117 Auto *current = autos->first, *this_current = first;
119 default_auto->copy_from(autos->default_auto);
121 // Detect common memory leak bug
122 if(autos->first && !autos->last)
124 printf("Autos::copy_from inconsistent pointers\n");
128 for(current = autos->first; current; current = NEXT)
130 //printf("Autos::copy_from 1 %p\n", current);
134 append(this_current = new_auto());
136 this_current->copy_from(current);
137 this_current = this_current->next;
140 for( ; this_current; )
142 Auto *next_current = this_current->next;
144 this_current = next_current;
149 // We don't replace it in pasting but
150 // when inserting the first EDL of a load operation we need to replace
151 // the default keyframe.
152 void Autos::insert_track(Autos *automation,
154 int64_t length_units,
158 insert(start_unit, start_unit + length_units);
160 if(replace_default) default_auto->copy_from(automation->default_auto);
161 for(Auto *current = automation->first; current; current = NEXT)
163 Auto *new_auto = insert_auto(start_unit + current->position);
164 new_auto->copy_from(current);
165 // Override copy_from
166 new_auto->position = current->position + start_unit;
170 Auto* Autos::get_prev_auto(int64_t position,
175 // Get on or before position
176 if(direction == PLAY_FORWARD)
178 // Try existing result
181 while(current && current->position < position) current = NEXT;
182 while(current && current->position > position) current = PREVIOUS;
188 current && current->position > position;
189 current = PREVIOUS) ;
191 if(!current && use_default) current = (first ? first : default_auto);
194 // Get on or after position
195 if(direction == PLAY_REVERSE)
199 while(current && current->position > position) current = PREVIOUS;
200 while(current && current->position < position) current = NEXT;
206 current && current->position < position;
210 if(!current && use_default) current = (last ? last : default_auto);
216 Auto* Autos::get_prev_auto(int direction, Auto* ¤t)
218 double position_double = edl->local_session->get_selectionstart(1);
219 position_double = edl->align_to_frame(position_double, 0);
220 int64_t position = track->to_units(position_double, 0);
222 return get_prev_auto(position, direction, current);
227 int Autos::auto_exists_for_editing(double position)
231 if(edl->session->auto_keyframes)
233 double unit_position = position;
234 unit_position = edl->align_to_frame(unit_position, 0);
235 if (get_auto_at_position(unit_position))
246 Auto* Autos::get_auto_at_position(double position)
248 int64_t unit_position = track->to_units(position, 0);
250 for(Auto *current = first;
254 if(edl->equivalent(current->position, unit_position))
263 Auto* Autos::get_auto_for_editing(double position)
267 position = edl->local_session->get_selectionstart(1);
271 position = edl->align_to_frame(position, 0);
276 //printf("Autos::get_auto_for_editing %p %p\n", first, default_auto);
278 if(edl->session->auto_keyframes)
280 result = insert_auto_for_editing(track->to_units(position, 0));
283 result = get_prev_auto(track->to_units(position, 0),
287 //printf("Autos::get_auto_for_editing %p %p %p\n", default_auto, first, result);
292 Auto* Autos::get_next_auto(int64_t position, int direction, Auto* ¤t, int use_default)
294 if(direction == PLAY_FORWARD)
298 while(current && current->position > position) current = PREVIOUS;
299 while(current && current->position < position) current = NEXT;
305 current && current->position <= position;
310 if(!current && use_default) current = (last ? last : default_auto);
313 if(direction == PLAY_REVERSE)
317 while(current && current->position < position) current = NEXT;
318 while(current && current->position > position) current = PREVIOUS;
324 current && current->position > position;
329 if(!current && use_default) current = (first ? first : default_auto);
335 Auto* Autos::insert_auto(int64_t position)
337 Auto *current, *result;
339 // Test for existence
341 current && !edl->equivalent(current->position, position);
350 // Get first one on or before as a template
352 current && current->position > position;
360 insert_after(current, result = new_auto());
361 result->copy_from(current);
366 if(!current) current = default_auto;
368 insert_before(first, result = new_auto());
369 if(current) result->copy_from(current);
372 result->position = position;
382 Auto* Autos::insert_auto_for_editing(int64_t position)
384 Auto *current, *result;
386 // Test for existence
388 current && !edl->equivalent(current->position, position);
394 //printf("Autos::insert_auto_for_editing %p\n", current);
398 // Get first one on or before as a template
400 current && current->position > position;
409 insert_after(current, result = new_auto());
410 result->interpolate_from(current, next, position);
415 if(!current) current = default_auto;
417 insert_before(first, result = new_auto());
418 if(current) result->copy_from(current);
421 result->position = position;
431 int Autos::clear_all()
433 Auto *current_, *current;
435 for(current = first; current; current = current_)
444 int Autos::insert(int64_t start, int64_t end)
447 Auto *current = first;
449 for( ; current && current->position < start; current = NEXT)
452 length = end - start;
454 for(; current; current = NEXT)
456 current->position += length;
461 void Autos::paste(int64_t start,
470 //printf("Autos::paste %ld\n", start);
472 result = file->read_tag();
474 if(!result && !file->tag.title_is("/AUTO"))
477 if(/* strstr(file->tag.get_title(), "AUTOS") && */
478 file->tag.get_title()[0] == '/')
483 if(!strcmp(file->tag.get_title(), "AUTO"))
487 // Paste first active auto into default
492 current = default_auto;
496 // Paste default auto into default
498 current = default_auto;
501 int64_t position = Units::to_int64(
502 (double)file->tag.get_property("POSITION", 0) *
505 // Paste active auto into track
506 current = insert_auto(position);
521 int Autos::paste_silence(int64_t start, int64_t end)
527 int Autos::copy(int64_t start,
533 // First auto is always loaded into default even if it is discarded in a paste
535 //printf("Autos::copy 1 %d %d %p\n", default_only, start, autoof(start));
538 default_auto->copy(0, 0, file, default_only);
541 //printf("Autos::copy 10 %d %d %p\n", default_only, start, autoof(start));
544 for(Auto* current = autoof(start);
545 current && current->position <= end;
548 // Want to copy single keyframes by putting the cursor on them
549 if(current->position >= start && current->position <= end)
551 current->copy(start, end, file, default_only);
555 // Copy default auto again to make it the active auto on the clipboard
558 // Need to force position to 0 for the case of plugins
559 // and default status to 0.
560 default_auto->copy(0, 0, file, default_only);
562 //printf("Autos::copy 20\n");
567 // Remove 3 consecutive autos with the same value
568 // Remove autos which are out of order
569 void Autos::optimize()
574 // Default auto should always be at 0
575 default_auto->position = 0;
582 for(Auto *current = first; current; current = NEXT)
584 // Get 3rd consecutive auto of equal value
587 if(*current == *PREVIOUS)
599 if(done && current->position <= PREVIOUS->position)
610 void Autos::remove_nonsequential(Auto *keyframe)
612 if((keyframe->next && keyframe->next->position <= keyframe->position) ||
613 (keyframe->previous && keyframe->previous->position >= keyframe->position))
620 void Autos::straighten(int64_t start, int64_t end)
624 void Autos::clear(int64_t start,
629 Auto *next, *current;
630 length = end - start;
633 current = autoof(start);
635 // If a range is selected don't delete the ending keyframe but do delete
636 // the beginning keyframe because shifting end handle forward shouldn't
637 // delete the first keyframe of the next edit.
640 ((end != start && current->position < end) ||
641 (end == start && current->position <= end)))
648 while(current && shift_autos)
650 current->position -= length;
655 int Autos::clear_auto(int64_t position)
658 current = autoof(position);
659 if(current->position == position) remove(current);
663 int Autos::load(FileXML *file)
666 remove(last); // remove any existing autos
668 int result = 0, first_auto = 1;
672 result = file->read_tag();
674 if(!result && !file->tag.title_is("/AUTO"))
676 // First tag with leading / is taken as end of autos
677 if(/* strstr(file->tag.get_title(), "AUTOS") && */
679 file->tag.get_title()[0] == '/')
684 if(!strcmp(file->tag.get_title(), "AUTO"))
688 default_auto->load(file);
689 default_auto->position = 0;
694 current = append(new_auto());
695 current->position = file->tag.get_property("POSITION", (int64_t)0);
709 int Autos::slope_adjustment(int64_t ax, double slope)
711 return (int)(ax * slope);
715 int Autos::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
719 for(current = first; current && scale_autos; current = NEXT)
721 // if(current->position >= start && current->position <= end)
723 current->position = (int64_t)((current->position - start) * rate_scale + start + 0.5);
729 Auto* Autos::autoof(int64_t position)
734 current && current->position < position;
739 return current; // return 0 on failure
742 Auto* Autos::nearest_before(int64_t position)
746 for(current = last; current && current->position >= position; current = PREVIOUS)
750 return current; // return 0 on failure
753 Auto* Autos::nearest_after(int64_t position)
757 for(current = first; current && current->position <= position; current = NEXT)
761 return current; // return 0 on failure
764 int Autos::get_neighbors(int64_t start, int64_t end, Auto **before, Auto **after)
766 if(*before == 0) *before = first;
767 if(*after == 0) *after = last;
769 while(*before && (*before)->next && (*before)->next->position <= start)
770 *before = (*before)->next;
772 while(*after && (*after)->previous && (*after)->previous->position >= end)
773 *after = (*after)->previous;
775 while(*before && (*before)->position > start) *before = (*before)->previous;
777 while(*after && (*after)->position < end) *after = (*after)->next;
781 int Autos::automation_is_constant(int64_t start, int64_t end)
786 double Autos::get_automation_constant(int64_t start, int64_t end)
792 int Autos::init_automation(int64_t &buffer_position,
793 int64_t &input_start,
797 int64_t input_position,
805 // set start and end boundaries for automation info
806 input_start = reverse ? input_position - buffer_len : input_position;
807 input_end = reverse ? input_position : input_position + buffer_len;
809 // test automation for constant value
810 // and set up *before and *after
813 if(automation_is_constant(input_start, input_end))
815 constant += get_automation_constant(input_start, input_end);
823 int Autos::init_slope(Auto **current_auto,
826 double &slope_position,
827 int64_t &input_start,
834 *current_auto = reverse ? *after : *before;
835 // no auto before start so use first auto in range
836 // already know there is an auto since automation isn't constant
839 *current_auto = reverse ? last : first;
840 // slope_value = (*current_auto)->value;
841 slope_start = input_start;
846 // otherwise get the first slope point and advance auto
847 // slope_value = (*current_auto)->value;
848 slope_start = (*current_auto)->position;
849 slope_position = reverse ? slope_start - input_end : input_start - slope_start;
850 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
856 int Autos::get_slope(Auto **current_auto,
862 int64_t buffer_position,
868 slope_end = reverse ? slope_start - (*current_auto)->position : (*current_auto)->position - slope_start;
870 // slope = ((*current_auto)->value - slope_value) / slope_end;
877 slope_end = buffer_len - buffer_position;
882 int Autos::advance_slope(Auto **current_auto,
885 double &slope_position,
890 slope_start = (*current_auto)->position;
891 // slope_value = (*current_auto)->value;
892 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
898 int64_t Autos::get_length()
901 return last->position + 1;
906 void Autos::get_extents(float *min,
908 int *coords_undefined,