RafaMar + programmer friend Help button in Batch Render addition
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / autos.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "autos.h"
23 #include "clip.h"
24 #include "edl.h"
25 #include "edlsession.h"
26 #include "floatauto.h"
27 #include "localsession.h"
28 #include "filexml.h"
29 #include "track.h"
30 #include "transportque.inc"
31
32
33 Autos::Autos(EDL *edl, Track *track)
34  : List<Auto>()
35 {
36         this->edl = edl;
37         this->track = track;
38         type = -1;
39         autoidx = -1;
40         autogrouptype = -1;
41 }
42
43
44
45 Autos::~Autos()
46 {
47         while(last) delete last;
48         delete default_auto;
49 }
50
51 void Autos::create_objects()
52 {
53 // Default
54         default_auto = new_auto();
55         default_auto->is_default = 1;
56 }
57
58 int Autos::get_type()
59 {
60         return type;
61 }
62
63 Auto* Autos::append_auto()
64 {
65         return append(new_auto());
66 }
67
68
69 Auto* Autos::new_auto()
70 {
71         return new Auto(edl, this);
72 }
73
74 void Autos::resample(double old_rate, double new_rate)
75 {
76         for(Auto *current = first; current; current = NEXT)
77         {
78                 current->position = (int64_t)((double)current->position *
79                         new_rate /
80                         old_rate +
81                         0.5);
82         }
83 }
84
85 void Autos::equivalent_output(Autos *autos, int64_t startproject, int64_t *result)
86 {
87 // Default keyframe differs
88         if(!total() && !(*default_auto == *autos->default_auto))
89         {
90                 if(*result < 0 || *result > startproject) *result = startproject;
91         }
92         else
93 // Search for difference
94         {
95                 for(Auto *current = first, *that_current = autos->first;
96                         current || that_current;
97                         current = NEXT,
98                         that_current = that_current->next)
99                 {
100 // Total differs
101                         if(current && !that_current)
102                         {
103                                 int64_t position1 = (autos->last ? autos->last->position : startproject);
104                                 int64_t position2 = current->position;
105                                 if(*result < 0 || *result > MIN(position1, position2))
106                                         *result = MIN(position1, position2);
107                                 break;
108                         }
109                         else
110                         if(!current && that_current)
111                         {
112                                 int64_t position1 = (last ? last->position : startproject);
113                                 int64_t position2 = that_current->position;
114                                 if(*result < 0 || *result > MIN(position1, position2))
115                                         *result = MIN(position1, position2);
116                                 break;
117                         }
118                         else
119 // Keyframes differ
120                         if(!(*current == *that_current) ||
121                                 current->position != that_current->position)
122                         {
123                                 int64_t position1 = (current->previous ?
124                                         current->previous->position :
125                                         startproject);
126                                 int64_t position2 = (that_current->previous ?
127                                         that_current->previous->position :
128                                         startproject);
129                                 if(*result < 0 || *result > MIN(position1, position2))
130                                         *result = MIN(position1, position2);
131                                 break;
132                         }
133                 }
134         }
135 }
136
137 void Autos::copy_from(Autos *autos)
138 {
139         Auto *current = autos->first, *this_current = first;
140
141         default_auto->copy_from(autos->default_auto);
142
143 // Detect common memory leak bug
144         if(autos->first && !autos->last)
145         {
146                 printf("Autos::copy_from inconsistent pointers\n");
147                 exit(1);
148         }
149
150         for(current = autos->first; current; current = NEXT)
151         {
152 //printf("Autos::copy_from 1 %p\n", current);
153 //sleep(1);
154                 if(!this_current)
155                 {
156                         append(this_current = new_auto());
157                 }
158                 this_current->copy_from(current);
159                 this_current = this_current->next;
160         }
161
162         for( ; this_current; )
163         {
164                 Auto *next_current = this_current->next;
165                 delete this_current;
166                 this_current = next_current;
167         }
168 }
169
170
171 // We don't replace it in pasting but
172 // when inserting the first EDL of a load operation we need to replace
173 // the default keyframe.
174 void Autos::insert_track(Autos *automation,
175         int64_t start_unit,
176         int64_t length_units,
177         int replace_default)
178 {
179 // Insert silence
180         insert(start_unit, start_unit + length_units);
181
182         if(replace_default) default_auto->copy_from(automation->default_auto);
183         for(Auto *current = automation->first; current; current = NEXT)
184         {
185 // fill new auto with values from current (template), interpolate values if possible
186                 Auto *new_auto = insert_auto(start_unit + current->position, current);
187 // Override copy_from
188                 new_auto->position = current->position + start_unit;
189         }
190 }
191
192 Auto* Autos::get_prev_auto(int64_t position,
193         int direction,
194         Auto* &current,
195         int use_default)
196 {
197 // Get on or before position
198         if(direction == PLAY_FORWARD)
199         {
200 // Try existing result
201                 if(current)
202                 {
203                         while(current && current->position < position) current = NEXT;
204                         while(current && current->position > position) current = PREVIOUS;
205                 }
206
207                 if(!current && first && first->position <= position)
208                 {
209                         for(current = last;
210                                 current && current->position > position;
211                                 current = PREVIOUS) ;
212                 }
213                 if(!current && use_default) current = (first ? first : default_auto);
214         }
215         else
216 // Get on or after position
217         if(direction == PLAY_REVERSE)
218         {
219                 if(current)
220                 {
221                         while(current && current->position > position) current = PREVIOUS;
222                         while(current && current->position < position) current = NEXT;
223                 }
224
225                 if(!current && last && last->position >= position)
226                 {
227                         for(current = first;
228                                 current && current->position < position;
229                                 current = NEXT) ;
230                 }
231
232                 if(!current && use_default) current = (last ? last : default_auto);
233         }
234
235         return current;
236 }
237
238 Auto* Autos::get_prev_auto(int direction, Auto* &current)
239 {
240         double position_double = edl->local_session->get_selectionstart(1);
241         position_double = edl->align_to_frame(position_double, 0);
242         int64_t position = track->to_units(position_double, 0);
243
244         return get_prev_auto(position, direction, current);
245 }
246
247 int Autos::auto_exists_for_editing(double position)
248 {
249         int result = 0;
250
251         if(edl->session->auto_keyframes)
252         {
253                 double unit_position = position;
254                 unit_position = edl->align_to_frame(unit_position, 0);
255                 if (get_auto_at_position(unit_position))
256                         result = 1;
257         }
258         else
259         {
260                 result = 1;
261         }
262
263         return result;
264 }
265
266 Auto* Autos::get_auto_at_position(double position)
267 {
268
269         for( Auto *current=first; current; current=NEXT ) {
270                 double pos = track->from_units(current->position);
271                 if( edl->equivalent(position, pos) )
272                         return current;
273         }
274         return 0;
275 }
276
277 Auto* Autos::get_auto(int id)
278 {
279         Auto *current = first;
280         while( current && current->orig_id != id ) current = NEXT;
281         return current;
282 }
283
284 Auto* Autos::get_auto_for_editing(double position, int create)
285 {
286         if(position < 0) {
287                 position = edl->local_session->get_selectionstart(1);
288         }
289
290         Auto *result = 0;
291         get_prev_auto(track->to_units(position, 0), PLAY_FORWARD, result);
292         if( create > 0 ) create = edl->session->auto_keyframes;
293         if( create && (!result || result->is_default ||
294             !EQUIV(track->from_units(result->position), position)) ) {
295 //printf("Autos::get_auto_for_editing %p %p %p\n", default_auto, first, result);
296                 position = edl->align_to_frame(position, 0);
297                 result = insert_auto(track->to_units(position, 0));
298         }
299 //printf("Autos::get_auto_for_editing %p %p\n", first, default_auto);
300
301         return result;
302 }
303
304
305 Auto* Autos::get_next_auto(int64_t position, int direction, Auto* &current, int use_default)
306 {
307         if(direction == PLAY_FORWARD)
308         {
309                 if(current)
310                 {
311                         while(current && current->position > position) current = PREVIOUS;
312                         while(current && current->position < position) current = NEXT;
313                 }
314
315                 if(!current && last && last->position > position)
316                 {
317                         for(current = first;
318                                 current && current->position <= position;
319                                 current = NEXT)
320                                 ;
321                 }
322
323                 if(!current && use_default) current = (last ? last : default_auto);
324         }
325         else
326         if(direction == PLAY_REVERSE)
327         {
328                 if(current)
329                 {
330                         while(current && current->position < position) current = NEXT;
331                         while(current && current->position > position) current = PREVIOUS;
332                 }
333
334                 if(!current && first && first->position <= position)
335                 {
336                         for(current = last;
337                                 current && current->position > position;
338                                 current = PREVIOUS)
339                                 ;
340                 }
341
342                 if(!current && use_default) current = (first ? first : default_auto);
343         }
344
345         return current;
346 }
347 Auto* Autos::insert_auto(int64_t position, Auto *templ)
348 {
349         Auto *current, *result;
350
351 // Test for existence
352         for(current = first;
353                 current && !edl->equivalent(current->position, position);
354                 current = NEXT)
355         {
356                 ;
357         }
358
359 // Insert new
360         if(!current)
361         {
362 // Get first one on or before as a template
363                 for(current = last;
364                         current && current->position > position;
365                         current = PREVIOUS)
366                 {
367                         ;
368                 }
369
370                 if(current)
371                 {
372                         insert_after(current, result = new_auto());
373                 }
374                 else
375                 {
376                         current = first;
377                         if(!current) current = default_auto;
378
379                         insert_before(first, result = new_auto());
380                 }
381
382 // interpolate if possible, else copy from template
383                 result->interpolate_from(0, 0, position, templ);
384 // Set curve mode
385                 if( !templ && result->is_floatauto() ) {
386                         FloatAuto *floatauto = (FloatAuto *)result;
387                         FloatAuto::t_mode new_mode =
388                                 edl->local_session->playback_start >= 0 &&
389                                 edl->local_session->playback_end < 0 ? FloatAuto::SMOOTH :
390                                         (FloatAuto::t_mode) edl->local_session->floatauto_type;
391                         floatauto->change_curve_mode(new_mode, 0);
392                 }
393         }
394         else
395         {
396                 result = current;
397         }
398
399         return result;
400 }
401
402 void Autos::clear_all()
403 {
404         while( last ) delete last;
405         delete default_auto;
406         create_objects();
407 }
408
409 int Autos::insert(int64_t start, int64_t end)
410 {
411         int64_t length;
412         Auto *current = first;
413
414         for( ; current && current->position < start; current = NEXT)
415                 ;
416
417         length = end - start;
418
419         for(; current; current = NEXT)
420         {
421                 current->position += length;
422         }
423         return 0;
424 }
425
426 void Autos::paste(int64_t start,
427         int64_t length,
428         double scale,
429         FileXML *file,
430         int default_only,
431         int active_only)
432 {
433         int total = 0;
434         int result = 0;
435
436 //printf("Autos::paste %d start=%jd\n", __LINE__, start);
437         do{
438                 result = file->read_tag();
439
440                 if(!result && !file->tag.title_is("/AUTO"))
441                 {
442 // End of list
443                         if(file->tag.get_title()[0] == '/')
444                         {
445                                 result = 1;
446                         }
447                         else
448                         if(!strcmp(file->tag.get_title(), "AUTO"))
449                         {
450                                 Auto *current = 0;
451
452 // Paste first auto into default
453                                 if(default_only && total == 0)
454                                 {
455                                         current = default_auto;
456                                 }
457                                 else
458 // Paste default auto into default
459                                 if(!default_only)
460                                 {
461                                         int64_t position = Units::to_int64(
462                                                 (double)file->tag.get_property("POSITION", 0) *
463                                                         scale +
464                                                         start);
465 // Paste active auto into track
466                                         current = insert_auto(position);
467                                 }
468
469                                 if(current)
470                                 {
471                                         current->load(file);
472                                 }
473                                 total++;
474                         }
475                 }
476         } while( !result );
477 }
478
479
480 int Autos::paste_silence(int64_t start, int64_t end)
481 {
482         insert(start, end);
483         return 0;
484 }
485
486 int Autos::copy(int64_t start,
487         int64_t end,
488         FileXML *file,
489         int default_only,
490         int active_only)
491 {
492 // First auto always loaded with default
493 //printf("Autos::copy %d %d %d\n", __LINE__, default_only, active_only);
494         if(default_only || (!active_only && !default_only))
495         {
496                 default_auto->copy(0, 0, file, default_only);
497         }
498
499 //printf("Autos::copy 10 %d %d %p\n", default_only, start, autoof(start));
500         if(active_only || (!default_only && !active_only))
501         {
502                 Auto *current = autoof(start);
503
504                 while( current && current->position <= end ) {
505 // Want to copy single keyframes by putting the cursor on them
506                         if( current->position >= start && current->position <= end ) {
507                                 current->copy(start, end, file, default_only);
508                         }
509                         current = NEXT;
510                 }
511         }
512 // Copy default auto again to make it the active auto on the clipboard
513 //      else
514 //      {
515 // Need to force position to 0 for the case of plugins
516 // and default status to 0.
517 //              default_auto->copy(0, 0, file, default_only);
518 //      }
519 //printf("Autos::copy 20\n");
520
521         return 0;
522 }
523
524 // Remove 3 consecutive autos with the same value
525 // Remove autos which are out of order
526 void Autos::optimize()
527 {
528         int done = 0;
529
530
531 // Default auto should always be at 0
532         default_auto->position = 0;
533         while(!done)
534         {
535                 int consecutive = 0;
536                 done = 1;
537
538
539                 for(Auto *current = first; current; current = NEXT)
540                 {
541 // Get 3rd consecutive auto of equal value
542                         if(current != first)
543                         {
544                                 if(*current == *PREVIOUS)
545                                 {
546                                         consecutive++;
547                                         if(consecutive >= 3)
548                                         {
549                                                 delete PREVIOUS;
550                                                 break;
551                                         }
552                                 }
553                                 else
554                                         consecutive = 0;
555
556                                 if(done && current->position <= PREVIOUS->position)
557                                 {
558                                         delete current;
559                                         break;
560                                 }
561                         }
562                 }
563         }
564 }
565
566
567 void Autos::remove_nonsequential(Auto *keyframe)
568 {
569         if((keyframe->next && keyframe->next->position <= keyframe->position) ||
570                 (keyframe->previous && keyframe->previous->position >= keyframe->position))
571         {
572                 delete keyframe;
573         }
574 }
575
576
577 void Autos::set_automation_mode(int64_t start, int64_t end, int mode)
578 {
579 }
580
581 void Autos::clear(int64_t start,
582         int64_t end,
583         int shift_autos)
584 {
585         int64_t length;
586         Auto *next, *current;
587         length = end - start;
588
589
590         current = autoof(start);
591
592 // If a range is selected don't delete the ending keyframe but do delete
593 // the beginning keyframe because shifting end handle forward shouldn't
594 // delete the first keyframe of the next edit.
595
596         while(current &&
597                 ((end != start && current->position < end) ||
598                 (end == start && current->position <= end)))
599         {
600                 next = NEXT;
601                 remove(current);
602                 current = next;
603         }
604
605         while(current && shift_autos)
606         {
607                 current->position -= length;
608                 current = NEXT;
609         }
610 }
611
612 int Autos::clear_auto(int64_t position)
613 {
614         Auto *current;
615         current = autoof(position);
616         return current->position==position ? (remove(current), 1) : 0;
617 }
618
619
620 int Autos::load(FileXML *file)
621 {
622         while(last)
623                 remove(last);    // remove any existing autos
624
625         int result = 0, first_auto = 1;
626         Auto *current;
627
628         do{
629                 result = file->read_tag();
630
631                 if(!result && !file->tag.title_is("/AUTO"))
632                 {
633 // First tag with leading / is taken as end of autos
634                         if(/* strstr(file->tag.get_title(), "AUTOS") && */
635
636                                 file->tag.get_title()[0] == '/')
637                         {
638                                 result = 1;
639                         }
640                         else
641                         if(!strcmp(file->tag.get_title(), "AUTO"))
642                         {
643                                 if(first_auto)
644                                 {
645                                         default_auto->load(file);
646                                         default_auto->position = 0;
647                                         first_auto = 0;
648                                 }
649                                 else
650                                 {
651                                         current = append(new_auto());
652                                         current->position = file->tag.get_property("POSITION", (int64_t)0);
653                                         current->load(file);
654                                 }
655                         }
656                 }
657         } while( !result );
658         return 0;
659 }
660
661
662
663
664
665
666 int Autos::slope_adjustment(int64_t ax, double slope)
667 {
668         return (int)(ax * slope);
669 }
670
671
672 int Autos::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
673 {
674         Auto *current;
675
676         for(current = first; current && scale_autos; current = NEXT)
677         {
678 //              if(current->position >= start && current->position <= end)
679 //              {
680                         current->position = (int64_t)((current->position - start) * rate_scale + start + 0.5);
681 //              }
682         }
683         return 0;
684 }
685
686 Auto* Autos::autoof(int64_t position)
687 {
688         Auto *current;
689
690         for(current = first;
691                 current && current->position < position;
692                 current = NEXT)
693         {
694                 ;
695         }
696         return current;     // return 0 on failure
697 }
698
699 Auto* Autos::nearest_before(int64_t position)
700 {
701         Auto *current;
702         for(current = last; current && current->position >= position; current = PREVIOUS);
703         return current;     // return 0 on failure
704 }
705
706 Auto* Autos::nearest_after(int64_t position)
707 {
708         Auto *current;
709         for(current = first; current && current->position <= position; current = NEXT);
710         return current;     // return 0 on failure
711 }
712
713 int Autos::get_neighbors(int64_t start, int64_t end, Auto **before, Auto **after)
714 {
715         if(*before == 0) *before = first;
716         if(*after == 0) *after = last;
717
718         while(*before && (*before)->next && (*before)->next->position <= start)
719                 *before = (*before)->next;
720
721         while(*after && (*after)->previous && (*after)->previous->position >= end)
722                 *after = (*after)->previous;
723
724         while(*before && (*before)->position > start) *before = (*before)->previous;
725
726         while(*after && (*after)->position < end) *after = (*after)->next;
727         return 0;
728 }
729
730 int Autos::automation_is_constant(int64_t start, int64_t end)
731 {
732         return 0;
733 }
734
735 double Autos::get_automation_constant(int64_t start, int64_t end)
736 {
737         return 0;
738 }
739
740
741 int Autos::init_automation(int64_t &buffer_position,
742                                 int64_t &input_start,
743                                 int64_t &input_end,
744                                 int &automate,
745                                 double &constant,
746                                 int64_t input_position,
747                                 int64_t buffer_len,
748                                 Auto **before,
749                                 Auto **after,
750                                 int reverse)
751 {
752         buffer_position = 0;
753
754 // set start and end boundaries for automation info
755         input_start = reverse ? input_position - buffer_len : input_position;
756         input_end = reverse ? input_position : input_position + buffer_len;
757
758 // test automation for constant value
759 // and set up *before and *after
760         if(automate)
761         {
762                 if(automation_is_constant(input_start, input_end))
763                 {
764                         constant += get_automation_constant(input_start, input_end);
765                         automate = 0;
766                 }
767         }
768         return automate;
769 }
770
771
772 int Autos::init_slope(Auto **current_auto,
773                                 double &slope_start,
774                                 double &slope_value,
775                                 double &slope_position,
776                                 int64_t &input_start,
777                                 int64_t &input_end,
778                                 Auto **before,
779                                 Auto **after,
780                                 int reverse)
781 {
782 // apply automation
783         *current_auto = reverse ? *after : *before;
784 // no auto before start so use first auto in range
785 // already know there is an auto since automation isn't constant
786         if(!*current_auto)
787         {
788                 *current_auto = reverse ? last : first;
789 //              slope_value = (*current_auto)->value;
790                 slope_start = input_start;
791                 slope_position = 0;
792         }
793         else
794         {
795 // otherwise get the first slope point and advance auto
796 //              slope_value = (*current_auto)->value;
797                 slope_start = (*current_auto)->position;
798                 slope_position = reverse ? slope_start - input_end : input_start - slope_start;
799                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
800         }
801         return 0;
802 }
803
804
805 int Autos::get_slope(Auto **current_auto,
806                                 double &slope_start,
807                                 double &slope_end,
808                                 double &slope_value,
809                                 double &slope,
810                                 int64_t buffer_len,
811                                 int64_t buffer_position,
812                                 int reverse)
813 {
814 // get the slope
815         if(*current_auto)
816         {
817                 slope_end = reverse ? slope_start - (*current_auto)->position : (*current_auto)->position - slope_start;
818                 if(slope_end)
819 //                      slope = ((*current_auto)->value - slope_value) / slope_end;
820 //              else
821                         slope = 0;
822         }
823         else
824         {
825                 slope = 0;
826                 slope_end = buffer_len - buffer_position;
827         }
828         return 0;
829 }
830
831 int Autos::advance_slope(Auto **current_auto,
832                                 double &slope_start,
833                                 double &slope_value,
834                                 double &slope_position,
835                                 int reverse)
836 {
837         if(*current_auto)
838         {
839                 slope_start = (*current_auto)->position;
840 //              slope_value = (*current_auto)->value;
841                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
842                 slope_position = 0;
843         }
844         return 0;
845 }
846
847 int64_t Autos::get_length()
848 {
849         if(last)
850                 return last->position + 1;
851         else
852                 return 0;
853 }
854
855 void Autos::get_extents(float *min,
856         float *max,
857         int *coords_undefined,
858         int64_t unit_start,
859         int64_t unit_end)
860 {
861
862 }
863
864
865 void Autos::dump(FILE *fp)
866 {
867 }
868
869
870
871
872
873
874
875
876
877