r553: Modern gccs require __attribute__((used)) for variables used only in assembly.
[cinelerra_cv/mob.git] / cinelerra / autos.C
blobee2c9cd80cc71cf85c8ba337fbac45a28abe8357
1 #include "autos.h"
2 #include "clip.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "localsession.h"
6 #include "filexml.h"
7 #include "track.h"
8 #include "transportque.inc"
10 #include <string.h>
13 Autos::Autos(EDL *edl, Track *track)
14  : List<Auto>()
16         this->edl = edl;
17         this->track = track;
18 //printf("Autos::Autos 1 %p %p %p\n", this, first, last);
23 Autos::~Autos()
25         while(last) delete last;
26         delete default_auto;
29 int Autos::create_objects()
31 // Default
32         default_auto = new_auto();
33         default_auto->is_default = 1;
34         return 0;
37 Auto* Autos::new_auto()
39         return new Auto(edl, this);
42 void Autos::resample(double old_rate, double new_rate)
44         for(Auto *current = first; current; current = NEXT)
45         {
46                 current->position = (int64_t)((double)current->position * 
47                         new_rate / 
48                         old_rate + 
49                         0.5);
50         }
53 void Autos::equivalent_output(Autos *autos, int64_t startproject, int64_t *result)
55         if(
56 // Default keyframe differs
57                 (!total() && !(*default_auto == *autos->default_auto))
58                 )
59         {
60                 if(*result < 0 || *result > startproject) *result = startproject;
61         }
62         else
63 // Search for difference
64         {
65                 for(Auto *current = first, *that_current = autos->first; 
66                         current || that_current; 
67                         current = NEXT,
68                         that_current = that_current->next)
69                 {
70 // Total differs
71                         if(current && !that_current)
72                         {
73                                 int64_t position1 = (autos->last ? autos->last->position : startproject);
74                                 int64_t position2 = current->position;
75                                 if(*result < 0 || *result > MIN(position1, position2))
76                                         *result = MIN(position1, position2);
77                                 break;
78                         }
79                         else
80                         if(!current && that_current)
81                         {
82                                 int64_t position1 = (last ? last->position : startproject);
83                                 int64_t position2 = that_current->position;
84                                 if(*result < 0 || *result > MIN(position1, position2))
85                                         *result = MIN(position1, position2);
86                                 break;
87                         }
88                         else
89 // Keyframes differ
90                         if(!(*current == *that_current) || 
91                                 current->position != that_current->position)
92                         {
93                                 int64_t position1 = (current->previous ? 
94                                         current->previous->position : 
95                                         startproject);
96                                 int64_t position2 = (that_current->previous ? 
97                                         that_current->previous->position : 
98                                         startproject);
99                                 if(*result < 0 || *result > MIN(position1, position2))
100                                         *result = MIN(position1, position2);
101                                 break;
102                         }
103                 }
104         }
107 void Autos::copy_from(Autos *autos)
109         Auto *current = autos->first, *this_current = first;
111         default_auto->copy_from(autos->default_auto);
113 // Detect common memory leak bug
114         if(autos->first && !autos->last)
115         {
116                 printf("Autos::copy_from inconsistent pointers\n");
117                 exit(1);
118         }
120         for(current = autos->first; current; current = NEXT)
121         {
122 //printf("Autos::copy_from 1 %p\n", current);
123 //sleep(1);
124                 if(!this_current)
125                 {
126                         append(this_current = new_auto());
127                 }
128                 this_current->copy_from(current);
129                 this_current = this_current->next;
130         }
132         for( ; this_current; )
133         {
134                 Auto *next_current = this_current->next;
135                 delete this_current;
136                 this_current = next_current;
137         }
141 // We don't replace it in pasting but
142 // when inserting the first EDL of a load operation we need to replace
143 // the default keyframe.
144 void Autos::insert_track(Autos *automation, 
145         int64_t start_unit, 
146         int64_t length_units,
147         int replace_default)
149 // Insert silence
150         insert(start_unit, start_unit + length_units);
152         if(replace_default) default_auto->copy_from(automation->default_auto);
153         for(Auto *current = automation->first; current; current = NEXT)
154         {
155                 Auto *new_auto = insert_auto(start_unit + current->position);
156                 new_auto->copy_from(current);
157 // Override copy_from
158                 new_auto->position = current->position + start_unit;
159         }
162 Auto* Autos::get_prev_auto(int64_t position, 
163         int direction, 
164         Auto* &current, 
165         int use_default)
167 // Get on or before position
168         if(direction == PLAY_FORWARD)
169         {
170 // Try existing result
171                 if(current)
172                 {
173                         while(current && current->position < position) current = NEXT;
174                         while(current && current->position > position) current = PREVIOUS;
175                 }
177                 if(!current)
178                 {
179                         for(current = last; 
180                                 current && current->position > position; 
181                                 current = PREVIOUS) ;
182                 }
183                 if(!current && use_default) current = (first ? first : default_auto);
184         }
185         else
186 // Get on or after position
187         if(direction == PLAY_REVERSE)
188         {
189                 if(current)
190                 {
191                         while(current && current->position > position) current = PREVIOUS;
192                         while(current && current->position < position) current = NEXT;
193                 }
195                 if(!current)
196                 {
197                         for(current = first; 
198                                 current && current->position < position; 
199                                 current = NEXT) ;
200                 }
202                 if(!current && use_default) current = (last ? last : default_auto);
203         }
205         return current;
208 Auto* Autos::get_prev_auto(int direction, Auto* &current)
210         double position_double = edl->local_session->selectionstart;
211         position_double = edl->align_to_frame(position_double, 0);
212         int64_t position = track->to_units(position_double, 0);
214         return get_prev_auto(position, direction, current);
216         return current;
219 int Autos::auto_exists_for_editing(double position)
221         int result = 0;
222         
223         if(edl->session->auto_keyframes)
224         {
225                 double unit_position = position;
226                 unit_position = edl->align_to_frame(unit_position, 0);
227                 if (get_auto_at_position(unit_position))
228                         result = 1;
229         }
230         else
231         {
232                 result = 1;
233         }
235         return result;
238 Auto* Autos::get_auto_at_position(double position)
240         int64_t unit_position = track->to_units(position, 0);
242         for(Auto *current = first; 
243                 current; 
244                 current = NEXT)
245         {
246                 if(edl->equivalent(current->position, unit_position))
247                 {
248                         return current;
249                 }
250         }
251         return 0;
255 Auto* Autos::get_auto_for_editing(double position)
257         if(position < 0)
258         {
259                 position = edl->local_session->selectionstart;
260         }
262         Auto *result = 0;
263         position = edl->align_to_frame(position, 0);
268 //printf("Autos::get_auto_for_editing %p %p\n", first, default_auto);
270         if(edl->session->auto_keyframes)
271         {
272                 result = insert_auto_for_editing(track->to_units(position, 0));
273         }
274         else
275                 result = get_prev_auto(track->to_units(position, 0), 
276                         PLAY_FORWARD, 
277                         result);
279 //printf("Autos::get_auto_for_editing %p %p %p\n", default_auto, first, result);
280         return result;
284 Auto* Autos::get_next_auto(int64_t position, int direction, Auto* &current, int use_default)
286         if(direction == PLAY_FORWARD)
287         {
288                 if(current)
289                 {
290                         while(current && current->position > position) current = PREVIOUS;
291                         while(current && current->position < position) current = NEXT;
292                 }
294                 if(!current)
295                 {
296                         for(current = first;
297                                 current && current->position <= position;
298                                 current = NEXT)
299                                 ;
300                 }
302                 if(!current && use_default) current = (last ? last : default_auto);
303         }
304         else
305         if(direction == PLAY_REVERSE)
306         {
307                 if(current)
308                 {
309                         while(current && current->position < position) current = NEXT;
310                         while(current && current->position > position) current = PREVIOUS;
311                 }
313                 if(!current)
314                 {
315                         for(current = last;
316                                 current && current->position > position;
317                                 current = PREVIOUS)
318                                 ;
319                 }
321                 if(!current && use_default) current = (first ? first : default_auto);
322         }
324         return current;
327 Auto* Autos::insert_auto(int64_t position)
329         Auto *current, *result;
331 // Test for existence
332         for(current = first; 
333                 current && !edl->equivalent(current->position, position); 
334                 current = NEXT)
335         {
336                 ;
337         }
339 //printf("Autos::insert_auto %p\n", current);
340 // Insert new
341         if(!current)
342         {
343 // Get first one on or before as a template
344                 for(current = last; 
345                         current && current->position > position; 
346                         current = PREVIOUS)
347                 {
348                         ;
349                 }
351                 if(current)
352                 {
353                         insert_after(current, result = new_auto());
354                         result->copy_from(current);
355                 }
356                 else
357                 {
358                         current = first;
359                         if(!current) current = default_auto;
361                         insert_before(first, result = new_auto());
362                         if(current) result->copy_from(current);
363                 }
365                 result->position = position;
366         }
367         else
368         {
369                 result = current;
370         }
372         return result;
375 Auto* Autos::insert_auto_for_editing(int64_t position)
377         Auto *current, *result;
379 // Test for existence
380         for(current = first; 
381                 current && !edl->equivalent(current->position, position); 
382                 current = NEXT)
383         {
384                 ;
385         }
387 //printf("Autos::insert_auto_for_editing %p\n", current);
388 // Insert new
389         if(!current)
390         {
391 // Get first one on or before as a template
392                 for(current = last; 
393                         current && current->position > position; 
394                         current = PREVIOUS)
395                 {
396                         ;
397                 }
399                 if(current)
400                 {
401                         Auto *next = NEXT;
402                         insert_after(current, result = new_auto());
403                         result->interpolate_from(current, next, position);
404                 }
405                 else
406                 {
407                         current = first;
408                         if(!current) current = default_auto;
410                         insert_before(first, result = new_auto());
411                         if(current) result->copy_from(current);
412                 }
414                 result->position = position;
415         }
416         else
417         {
418                 result = current;
419         }
421         return result;
424 int Autos::clear_all()
426         Auto *current_, *current;
427         
428         for(current = first; current; current = current_)
429         {
430                 current_ = NEXT;
431                 remove(current);
432         }
433         add_auto(0, default_);
434         return 0;
437 int Autos::insert(int64_t start, int64_t end)
439         int64_t length;
440         Auto *current = first;
442         for( ; current && current->position < start; current = NEXT)
443                 ;
445         length = end - start;
447         for(; current; current = NEXT)
448         {
449                 current->position += length;
450         }
451         return 0;
454 void Autos::paste(int64_t start, 
455         int64_t length, 
456         double scale, 
457         FileXML *file, 
458         int default_only)
460         int total = 0;
461         int result = 0;
463 //printf("Autos::paste %ld\n", start);
464         do{
465                 result = file->read_tag();
467                 if(!result)
468                 {
469 // End of list
470                         if(strstr(file->tag.get_title(), "AUTOS") && 
471                                 file->tag.get_title()[0] == '/')
472                         {
473                                 result = 1;
474                         }
475                         else
476                         if(!strcmp(file->tag.get_title(), "AUTO"))
477                         {
478                                 Auto *current = 0;
480 // Paste first active auto into default                         
481                                 if(default_only)
482                                 {
483                                         if(total == 1)
484                                         {
485                                                 current = default_auto;
486                                         }
487                                 }
488                                 else
489 // Paste default auto into default
490                                 if(total == 0)
491                                         current = default_auto;
492                                 else
493                                 {
494                                         int64_t position = Units::to_int64(
495                                                 (double)file->tag.get_property("POSITION", 0) *
496                                                         scale + 
497                                                         start);
498 // Paste active auto into track
499                                         current = insert_auto(position);
500                                 }
502                                 if(current)
503                                 {
504                                         current->load(file);
505                                 }
506                                 total++;
507                         }
508                 }
509         }while(!result);
510         
514 int Autos::paste_silence(int64_t start, int64_t end)
516         insert(start, end);
517         return 0;
520 int Autos::copy(int64_t start, 
521         int64_t end, 
522         FileXML *file, 
523         int default_only,
524         int autos_only)
526 // First auto is always loaded into default even if it is discarded in a paste
527 // operation
528 //printf("Autos::copy 1 %d %d %p\n", default_only, start, autoof(start));
529         if(!autos_only)
530         {
531                 default_auto->copy(0, 0, file, default_only);
532         }
534 //printf("Autos::copy 10 %d %d %p\n", default_only, start, autoof(start));
535         if(!default_only)
536         {
537                 for(Auto* current = autoof(start); 
538                         current && current->position <= end; 
539                         current = NEXT)
540                 {
541 // Want to copy single keyframes by putting the cursor on them
542                         if(current->position >= start && current->position <= end)
543                         {
544                                 current->copy(start, end, file, default_only);
545                         }
546                 }
547         }
548 // Copy default auto again to make it the active auto on the clipboard
549         else
550         {
551 // Need to force position to 0 for the case of plugins
552 // and default status to 0.
553                 default_auto->copy(0, 0, file, default_only);
554         }
555 //printf("Autos::copy 20\n");
557         return 0;
560 // Remove 3 consecutive autos with the same value
561 // Remove autos which are out of order
562 void Autos::optimize()
564         int done = 0;
567 // Default auto should always be at 0
568         default_auto->position = 0;
569         while(!done)
570         {
571                 int consecutive = 0;
572                 done = 1;
573                 
574                 
575                 for(Auto *current = first; current; current = NEXT)
576                 {
577 // Get 3rd consecutive auto of equal value
578                         if(current != first)
579                         {
580                                 if(*current == *PREVIOUS)
581                                 {
582                                         consecutive++;
583                                         if(consecutive >= 3)
584                                         {
585                                                 delete PREVIOUS;
586                                                 break;
587                                         }
588                                 }
589                                 else
590                                         consecutive = 0;
591                                 
592                                 if(done && current->position <= PREVIOUS->position)
593                                 {
594                                         delete current;
595                                         break;
596                                 }
597                         }
598                 }
599         }
603 void Autos::remove_nonsequential(Auto *keyframe)
605         if((keyframe->next && keyframe->next->position <= keyframe->position) ||
606                 (keyframe->previous && keyframe->previous->position >= keyframe->position))
607         {
608                 delete keyframe;
609         }
615 void Autos::clear(int64_t start, 
616         int64_t end, 
617         int shift_autos)
619         int64_t length;
620         Auto *next, *current;
621         length = end - start;
624         current = autoof(start);
626 // If a range is selected don't delete the ending keyframe but do delete
627 // the beginning keyframe because shifting end handle forward shouldn't
628 // delete the first keyframe of the next edit.
630         while(current && 
631                 ((end != start && current->position < end) ||
632                 (end == start && current->position <= end)))
633         {
634                 next = NEXT;
635                 remove(current);
636                 current = next;
637         }
639         while(current && shift_autos)
640         {
641                 current->position -= length;
642                 current = NEXT;
643         }
646 int Autos::clear_auto(int64_t position)
648         Auto *current;
649         current = autoof(position);
650         if(current->position == position) remove(current);
654 int Autos::load(FileXML *file)
656         while(last)
657                 remove(last);    // remove any existing autos
659         int result = 0, first_auto = 1;
660         Auto *current;
661         
662         do{
663                 result = file->read_tag();
664                 
665                 if(!result)
666                 {
667                         if(strstr(file->tag.get_title(), "AUTOS") && file->tag.get_title()[0] == '/')
668                         {
669                                 result = 1;
670                         }
671                         else
672                         if(!strcmp(file->tag.get_title(), "AUTO"))
673                         {
674                                 if(first_auto)
675                                 {
676                                         default_auto->load(file);
677                                         default_auto->position = 0;
678                                         first_auto = 0;
679                                 }
680                                 else
681                                 {
682                                         current = append(new_auto());
683                                         current->position = file->tag.get_property("POSITION", (int64_t)0);
684                                         current->load(file);
685                                 }
686                         }
687                 }
688         }while(!result);
689         return 0;
697 int Autos::slope_adjustment(int64_t ax, double slope)
699         return (int)(ax * slope);
703 int Autos::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
705         Auto *current;
706         
707         for(current = first; current && scale_autos; current = NEXT)
708         {
709 //              if(current->position >= start && current->position <= end)
710 //              {
711                         current->position = (int64_t)((current->position - start) * rate_scale + start + 0.5);
712 //              }
713         }
714         return 0;
717 Auto* Autos::autoof(int64_t position)
719         Auto *current;
721         for(current = first; 
722                 current && current->position < position; 
723                 current = NEXT)
724         { 
725                 ;
726         }
727         return current;     // return 0 on failure
730 Auto* Autos::nearest_before(int64_t position)
732         Auto *current;
734         for(current = last; current && current->position >= position; current = PREVIOUS)
735         { ; }
738         return current;     // return 0 on failure
741 Auto* Autos::nearest_after(int64_t position)
743         Auto *current;
745         for(current = first; current && current->position <= position; current = NEXT)
746         { ; }
749         return current;     // return 0 on failure
752 int Autos::get_neighbors(int64_t start, int64_t end, Auto **before, Auto **after)
754         if(*before == 0) *before = first;
755         if(*after == 0) *after = last; 
757         while(*before && (*before)->next && (*before)->next->position <= start)
758                 *before = (*before)->next;
759         
760         while(*after && (*after)->previous && (*after)->previous->position >= end)
761                 *after = (*after)->previous;
763         while(*before && (*before)->position > start) *before = (*before)->previous;
764         
765         while(*after && (*after)->position < end) *after = (*after)->next;
766         return 0;
769 int Autos::automation_is_constant(int64_t start, int64_t end)
771         return 0;
774 double Autos::get_automation_constant(int64_t start, int64_t end)
776         return 0;
780 int Autos::init_automation(int64_t &buffer_position,
781                                 int64_t &input_start, 
782                                 int64_t &input_end, 
783                                 int &automate, 
784                                 double &constant, 
785                                 int64_t input_position,
786                                 int64_t buffer_len,
787                                 Auto **before, 
788                                 Auto **after,
789                                 int reverse)
791         buffer_position = 0;
793 // set start and end boundaries for automation info
794         input_start = reverse ? input_position - buffer_len : input_position;
795         input_end = reverse ? input_position : input_position + buffer_len;
797 // test automation for constant value
798 // and set up *before and *after
799         if(automate)
800         {
801                 if(automation_is_constant(input_start, input_end))
802                 {
803                         constant += get_automation_constant(input_start, input_end);
804                         automate = 0;
805                 }
806         }
807         return automate;
811 int Autos::init_slope(Auto **current_auto, 
812                                 double &slope_start, 
813                                 double &slope_value,
814                                 double &slope_position, 
815                                 int64_t &input_start, 
816                                 int64_t &input_end, 
817                                 Auto **before, 
818                                 Auto **after,
819                                 int reverse)
821 // apply automation
822         *current_auto = reverse ? *after : *before;
823 // no auto before start so use first auto in range
824 // already know there is an auto since automation isn't constant
825         if(!*current_auto)
826         {
827                 *current_auto = reverse ? last : first;
828 //              slope_value = (*current_auto)->value;
829                 slope_start = input_start;
830                 slope_position = 0;
831         }
832         else
833         {
834 // otherwise get the first slope point and advance auto
835 //              slope_value = (*current_auto)->value;
836                 slope_start = (*current_auto)->position;
837                 slope_position = reverse ? slope_start - input_end : input_start - slope_start;
838                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
839         }
840         return 0;
844 int Autos::get_slope(Auto **current_auto, 
845                                 double &slope_start, 
846                                 double &slope_end, 
847                                 double &slope_value,
848                                 double &slope, 
849                                 int64_t buffer_len, 
850                                 int64_t buffer_position,
851                                 int reverse)
853 // get the slope
854         if(*current_auto)
855         {
856                 slope_end = reverse ? slope_start - (*current_auto)->position : (*current_auto)->position - slope_start;
857                 if(slope_end) 
858 //                      slope = ((*current_auto)->value - slope_value) / slope_end;
859 //              else
860                         slope = 0;
861         }
862         else
863         {
864                 slope = 0;
865                 slope_end = buffer_len - buffer_position;
866         }
867         return 0;
870 int Autos::advance_slope(Auto **current_auto, 
871                                 double &slope_start, 
872                                 double &slope_value,
873                                 double &slope_position, 
874                                 int reverse)
876         if(*current_auto) 
877         {
878                 slope_start = (*current_auto)->position;
879 //              slope_value = (*current_auto)->value;
880                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
881                 slope_position = 0;
882         }
883         return 0;
886 float Autos::value_to_percentage()
888         return 0;
891 int64_t Autos::get_length()
893         if(last) 
894                 return last->position + 1;
895         else
896                 return 0;