add grouping, default proxy vcodec h264.mp4, default titlebar alpha=1, green bar bug
[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         int64_t unit_position = track->to_units(position, 0);
269
270         for(Auto *current = first;
271                 current;
272                 current = NEXT)
273         {
274                 if(edl->equivalent(current->position, unit_position))
275                 {
276                         return current;
277                 }
278         }
279         return 0;
280 }
281
282
283 Auto* Autos::get_auto_for_editing(double position)
284 {
285         if(position < 0) {
286                 position = edl->local_session->get_selectionstart(1);
287         }
288
289         Auto *result = 0;
290         get_prev_auto(track->to_units(position, 0), PLAY_FORWARD, result);
291         if( edl->session->auto_keyframes && (!result || result->is_default ||
292               !EQUIV(track->from_units(result->position), position)) ) {
293 //printf("Autos::get_auto_for_editing %p %p %p\n", default_auto, first, result);
294                 position = edl->align_to_frame(position, 0);
295                 result = insert_auto(track->to_units(position, 0));
296         }
297 //printf("Autos::get_auto_for_editing %p %p\n", first, default_auto);
298
299         return result;
300 }
301
302
303 Auto* Autos::get_next_auto(int64_t position, int direction, Auto* &current, int use_default)
304 {
305         if(direction == PLAY_FORWARD)
306         {
307                 if(current)
308                 {
309                         while(current && current->position > position) current = PREVIOUS;
310                         while(current && current->position < position) current = NEXT;
311                 }
312
313                 if(!current && last && last->position > position)
314                 {
315                         for(current = first;
316                                 current && current->position <= position;
317                                 current = NEXT)
318                                 ;
319                 }
320
321                 if(!current && use_default) current = (last ? last : default_auto);
322         }
323         else
324         if(direction == PLAY_REVERSE)
325         {
326                 if(current)
327                 {
328                         while(current && current->position < position) current = NEXT;
329                         while(current && current->position > position) current = PREVIOUS;
330                 }
331
332                 if(!current && first && first->position <= position)
333                 {
334                         for(current = last;
335                                 current && current->position > position;
336                                 current = PREVIOUS)
337                                 ;
338                 }
339
340                 if(!current && use_default) current = (first ? first : default_auto);
341         }
342
343         return current;
344 }
345 Auto* Autos::insert_auto(int64_t position, Auto *templ)
346 {
347         Auto *current, *result;
348
349 // Test for existence
350         for(current = first;
351                 current && !edl->equivalent(current->position, position);
352                 current = NEXT)
353         {
354                 ;
355         }
356
357 // Insert new
358         if(!current)
359         {
360 // Get first one on or before as a template
361                 for(current = last;
362                         current && current->position > position;
363                         current = PREVIOUS)
364                 {
365                         ;
366                 }
367
368                 if(current)
369                 {
370                         insert_after(current, result = new_auto());
371                 }
372                 else
373                 {
374                         current = first;
375                         if(!current) current = default_auto;
376
377                         insert_before(first, result = new_auto());
378                 }
379
380 // interpolate if possible, else copy from template
381                 result->interpolate_from(0, 0, position, templ);
382 // Set curve mode
383                 if( !templ && result->is_floatauto() ) {
384                         FloatAuto *floatauto = (FloatAuto *)result;
385                         floatauto->curve_mode =
386                                 edl->local_session->playback_start >= 0 &&
387                                 edl->local_session->playback_end < 0 ? FloatAuto::SMOOTH :
388                                         (FloatAuto::t_mode) edl->local_session->floatauto_type;
389                 }
390         }
391         else
392         {
393                 result = current;
394         }
395
396         return result;
397 }
398
399 int Autos::clear_all()
400 {
401         Auto *current_, *current;
402
403         for(current = first; current; current = current_)
404         {
405                 current_ = NEXT;
406                 remove(current);
407         }
408         append_auto();
409         return 0;
410 }
411
412 int Autos::insert(int64_t start, int64_t end)
413 {
414         int64_t length;
415         Auto *current = first;
416
417         for( ; current && current->position < start; current = NEXT)
418                 ;
419
420         length = end - start;
421
422         for(; current; current = NEXT)
423         {
424                 current->position += length;
425         }
426         return 0;
427 }
428
429 void Autos::paste(int64_t start,
430         int64_t length,
431         double scale,
432         FileXML *file,
433         int default_only,
434         int active_only)
435 {
436         int total = 0;
437         int result = 0;
438
439 //printf("Autos::paste %d start=%jd\n", __LINE__, start);
440         do{
441                 result = file->read_tag();
442
443                 if(!result && !file->tag.title_is("/AUTO"))
444                 {
445 // End of list
446                         if(file->tag.get_title()[0] == '/')
447                         {
448                                 result = 1;
449                         }
450                         else
451                         if(!strcmp(file->tag.get_title(), "AUTO"))
452                         {
453                                 Auto *current = 0;
454
455 // Paste first auto into default
456                                 if(default_only && total == 0)
457                                 {
458                                         current = default_auto;
459                                 }
460                                 else
461 // Paste default auto into default
462                                 if(!default_only)
463                                 {
464                                         int64_t position = Units::to_int64(
465                                                 (double)file->tag.get_property("POSITION", 0) *
466                                                         scale +
467                                                         start);
468 // Paste active auto into track
469                                         current = insert_auto(position);
470                                 }
471
472                                 if(current)
473                                 {
474                                         current->load(file);
475                                 }
476                                 total++;
477                         }
478                 }
479         } while( !result );
480 }
481
482
483 int Autos::paste_silence(int64_t start, int64_t end)
484 {
485         insert(start, end);
486         return 0;
487 }
488
489 int Autos::copy(int64_t start,
490         int64_t end,
491         FileXML *file,
492         int default_only,
493         int active_only)
494 {
495 // First auto always loaded with default
496 //printf("Autos::copy %d %d %d\n", __LINE__, default_only, active_only);
497         if(default_only || (!active_only && !default_only))
498         {
499                 default_auto->copy(0, 0, file, default_only);
500         }
501
502 //printf("Autos::copy 10 %d %d %p\n", default_only, start, autoof(start));
503         if(active_only || (!default_only && !active_only))
504         {
505                 Auto *current = autoof(start);
506 // need the last one if past the end
507                 if( !current && last )
508                         last->copy(start, end, file, default_only);
509
510                 while( current && current->position <= end ) {
511 // Want to copy single keyframes by putting the cursor on them
512                         if( current->position >= start && current->position <= end ) {
513                                 current->copy(start, end, file, default_only);
514                         }
515                         current = NEXT;
516                 }
517         }
518 // Copy default auto again to make it the active auto on the clipboard
519 //      else
520 //      {
521 // Need to force position to 0 for the case of plugins
522 // and default status to 0.
523 //              default_auto->copy(0, 0, file, default_only);
524 //      }
525 //printf("Autos::copy 20\n");
526
527         return 0;
528 }
529
530 // Remove 3 consecutive autos with the same value
531 // Remove autos which are out of order
532 void Autos::optimize()
533 {
534         int done = 0;
535
536
537 // Default auto should always be at 0
538         default_auto->position = 0;
539         while(!done)
540         {
541                 int consecutive = 0;
542                 done = 1;
543
544
545                 for(Auto *current = first; current; current = NEXT)
546                 {
547 // Get 3rd consecutive auto of equal value
548                         if(current != first)
549                         {
550                                 if(*current == *PREVIOUS)
551                                 {
552                                         consecutive++;
553                                         if(consecutive >= 3)
554                                         {
555                                                 delete PREVIOUS;
556                                                 break;
557                                         }
558                                 }
559                                 else
560                                         consecutive = 0;
561
562                                 if(done && current->position <= PREVIOUS->position)
563                                 {
564                                         delete current;
565                                         break;
566                                 }
567                         }
568                 }
569         }
570 }
571
572
573 void Autos::remove_nonsequential(Auto *keyframe)
574 {
575         if((keyframe->next && keyframe->next->position <= keyframe->position) ||
576                 (keyframe->previous && keyframe->previous->position >= keyframe->position))
577         {
578                 delete keyframe;
579         }
580 }
581
582
583 void Autos::set_automation_mode(int64_t start, int64_t end, int mode)
584 {
585 }
586
587 void Autos::clear(int64_t start,
588         int64_t end,
589         int shift_autos)
590 {
591         int64_t length;
592         Auto *next, *current;
593         length = end - start;
594
595
596         current = autoof(start);
597
598 // If a range is selected don't delete the ending keyframe but do delete
599 // the beginning keyframe because shifting end handle forward shouldn't
600 // delete the first keyframe of the next edit.
601
602         while(current &&
603                 ((end != start && current->position < end) ||
604                 (end == start && current->position <= end)))
605         {
606                 next = NEXT;
607                 remove(current);
608                 current = next;
609         }
610
611         while(current && shift_autos)
612         {
613                 current->position -= length;
614                 current = NEXT;
615         }
616 }
617
618 int Autos::clear_auto(int64_t position)
619 {
620         Auto *current;
621         current = autoof(position);
622         return current->position==position ? (remove(current), 1) : 0;
623 }
624
625
626 int Autos::load(FileXML *file)
627 {
628         while(last)
629                 remove(last);    // remove any existing autos
630
631         int result = 0, first_auto = 1;
632         Auto *current;
633
634         do{
635                 result = file->read_tag();
636
637                 if(!result && !file->tag.title_is("/AUTO"))
638                 {
639 // First tag with leading / is taken as end of autos
640                         if(/* strstr(file->tag.get_title(), "AUTOS") && */
641
642                                 file->tag.get_title()[0] == '/')
643                         {
644                                 result = 1;
645                         }
646                         else
647                         if(!strcmp(file->tag.get_title(), "AUTO"))
648                         {
649                                 if(first_auto)
650                                 {
651                                         default_auto->load(file);
652                                         default_auto->position = 0;
653                                         first_auto = 0;
654                                 }
655                                 else
656                                 {
657                                         current = append(new_auto());
658                                         current->position = file->tag.get_property("POSITION", (int64_t)0);
659                                         current->load(file);
660                                 }
661                         }
662                 }
663         } while( !result );
664         return 0;
665 }
666
667
668
669
670
671
672 int Autos::slope_adjustment(int64_t ax, double slope)
673 {
674         return (int)(ax * slope);
675 }
676
677
678 int Autos::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
679 {
680         Auto *current;
681
682         for(current = first; current && scale_autos; current = NEXT)
683         {
684 //              if(current->position >= start && current->position <= end)
685 //              {
686                         current->position = (int64_t)((current->position - start) * rate_scale + start + 0.5);
687 //              }
688         }
689         return 0;
690 }
691
692 Auto* Autos::autoof(int64_t position)
693 {
694         Auto *current;
695
696         for(current = first;
697                 current && current->position < position;
698                 current = NEXT)
699         {
700                 ;
701         }
702         return current;     // return 0 on failure
703 }
704
705 Auto* Autos::nearest_before(int64_t position)
706 {
707         Auto *current;
708         for(current = last; current && current->position >= position; current = PREVIOUS);
709         return current;     // return 0 on failure
710 }
711
712 Auto* Autos::nearest_after(int64_t position)
713 {
714         Auto *current;
715         for(current = first; current && current->position <= position; current = NEXT);
716         return current;     // return 0 on failure
717 }
718
719 int Autos::get_neighbors(int64_t start, int64_t end, Auto **before, Auto **after)
720 {
721         if(*before == 0) *before = first;
722         if(*after == 0) *after = last;
723
724         while(*before && (*before)->next && (*before)->next->position <= start)
725                 *before = (*before)->next;
726
727         while(*after && (*after)->previous && (*after)->previous->position >= end)
728                 *after = (*after)->previous;
729
730         while(*before && (*before)->position > start) *before = (*before)->previous;
731
732         while(*after && (*after)->position < end) *after = (*after)->next;
733         return 0;
734 }
735
736 int Autos::automation_is_constant(int64_t start, int64_t end)
737 {
738         return 0;
739 }
740
741 double Autos::get_automation_constant(int64_t start, int64_t end)
742 {
743         return 0;
744 }
745
746
747 int Autos::init_automation(int64_t &buffer_position,
748                                 int64_t &input_start,
749                                 int64_t &input_end,
750                                 int &automate,
751                                 double &constant,
752                                 int64_t input_position,
753                                 int64_t buffer_len,
754                                 Auto **before,
755                                 Auto **after,
756                                 int reverse)
757 {
758         buffer_position = 0;
759
760 // set start and end boundaries for automation info
761         input_start = reverse ? input_position - buffer_len : input_position;
762         input_end = reverse ? input_position : input_position + buffer_len;
763
764 // test automation for constant value
765 // and set up *before and *after
766         if(automate)
767         {
768                 if(automation_is_constant(input_start, input_end))
769                 {
770                         constant += get_automation_constant(input_start, input_end);
771                         automate = 0;
772                 }
773         }
774         return automate;
775 }
776
777
778 int Autos::init_slope(Auto **current_auto,
779                                 double &slope_start,
780                                 double &slope_value,
781                                 double &slope_position,
782                                 int64_t &input_start,
783                                 int64_t &input_end,
784                                 Auto **before,
785                                 Auto **after,
786                                 int reverse)
787 {
788 // apply automation
789         *current_auto = reverse ? *after : *before;
790 // no auto before start so use first auto in range
791 // already know there is an auto since automation isn't constant
792         if(!*current_auto)
793         {
794                 *current_auto = reverse ? last : first;
795 //              slope_value = (*current_auto)->value;
796                 slope_start = input_start;
797                 slope_position = 0;
798         }
799         else
800         {
801 // otherwise get the first slope point and advance auto
802 //              slope_value = (*current_auto)->value;
803                 slope_start = (*current_auto)->position;
804                 slope_position = reverse ? slope_start - input_end : input_start - slope_start;
805                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
806         }
807         return 0;
808 }
809
810
811 int Autos::get_slope(Auto **current_auto,
812                                 double &slope_start,
813                                 double &slope_end,
814                                 double &slope_value,
815                                 double &slope,
816                                 int64_t buffer_len,
817                                 int64_t buffer_position,
818                                 int reverse)
819 {
820 // get the slope
821         if(*current_auto)
822         {
823                 slope_end = reverse ? slope_start - (*current_auto)->position : (*current_auto)->position - slope_start;
824                 if(slope_end)
825 //                      slope = ((*current_auto)->value - slope_value) / slope_end;
826 //              else
827                         slope = 0;
828         }
829         else
830         {
831                 slope = 0;
832                 slope_end = buffer_len - buffer_position;
833         }
834         return 0;
835 }
836
837 int Autos::advance_slope(Auto **current_auto,
838                                 double &slope_start,
839                                 double &slope_value,
840                                 double &slope_position,
841                                 int reverse)
842 {
843         if(*current_auto)
844         {
845                 slope_start = (*current_auto)->position;
846 //              slope_value = (*current_auto)->value;
847                 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
848                 slope_position = 0;
849         }
850         return 0;
851 }
852
853 int64_t Autos::get_length()
854 {
855         if(last)
856                 return last->position + 1;
857         else
858                 return 0;
859 }
860
861 void Autos::get_extents(float *min,
862         float *max,
863         int *coords_undefined,
864         int64_t unit_start,
865         int64_t unit_end)
866 {
867
868 }
869
870
871 void Autos::dump(FILE *fp)
872 {
873 }
874
875
876
877
878
879
880
881
882
883