00001 #include "autos.h"
00002 #include "clip.h"
00003 #include "edl.h"
00004 #include "edlsession.h"
00005 #include "localsession.h"
00006 #include "filexml.h"
00007 #include "track.h"
00008 #include "transportque.inc"
00009
00010 #include <string.h>
00011
00012
00013 Autos::Autos(EDL *edl, Track *track)
00014 : List<Auto>()
00015 {
00016 this->edl = edl;
00017 this->track = track;
00018 type = -1;
00019 }
00020
00021
00022
00023 Autos::~Autos()
00024 {
00025 while(last) delete last;
00026 delete default_auto;
00027 }
00028
00029 void Autos::create_objects()
00030 {
00031
00032 default_auto = new_auto();
00033 default_auto->is_default = 1;
00034 }
00035
00036 int Autos::get_type()
00037 {
00038 return type;
00039 }
00040
00041 Auto* Autos::append_auto()
00042 {
00043 return append(new_auto());
00044 }
00045
00046
00047 Auto* Autos::new_auto()
00048 {
00049 return new Auto(edl, this);
00050 }
00051
00052 void Autos::resample(double old_rate, double new_rate)
00053 {
00054 for(Auto *current = first; current; current = NEXT)
00055 {
00056 current->position = (int64_t)((double)current->position *
00057 new_rate /
00058 old_rate +
00059 0.5);
00060 }
00061 }
00062
00063 void Autos::equivalent_output(Autos *autos, int64_t startproject, int64_t *result)
00064 {
00065
00066 if(!total() && !(*default_auto == *autos->default_auto))
00067 {
00068 if(*result < 0 || *result > startproject) *result = startproject;
00069 }
00070 else
00071
00072 {
00073 for(Auto *current = first, *that_current = autos->first;
00074 current || that_current;
00075 current = NEXT,
00076 that_current = that_current->next)
00077 {
00078
00079 if(current && !that_current)
00080 {
00081 int64_t position1 = (autos->last ? autos->last->position : startproject);
00082 int64_t position2 = current->position;
00083 if(*result < 0 || *result > MIN(position1, position2))
00084 *result = MIN(position1, position2);
00085 break;
00086 }
00087 else
00088 if(!current && that_current)
00089 {
00090 int64_t position1 = (last ? last->position : startproject);
00091 int64_t position2 = that_current->position;
00092 if(*result < 0 || *result > MIN(position1, position2))
00093 *result = MIN(position1, position2);
00094 break;
00095 }
00096 else
00097
00098 if(!(*current == *that_current) ||
00099 current->position != that_current->position)
00100 {
00101 int64_t position1 = (current->previous ?
00102 current->previous->position :
00103 startproject);
00104 int64_t position2 = (that_current->previous ?
00105 that_current->previous->position :
00106 startproject);
00107 if(*result < 0 || *result > MIN(position1, position2))
00108 *result = MIN(position1, position2);
00109 break;
00110 }
00111 }
00112 }
00113 }
00114
00115 void Autos::copy_from(Autos *autos)
00116 {
00117 Auto *current = autos->first, *this_current = first;
00118
00119 default_auto->copy_from(autos->default_auto);
00120
00121
00122 if(autos->first && !autos->last)
00123 {
00124 printf("Autos::copy_from inconsistent pointers\n");
00125 exit(1);
00126 }
00127
00128 for(current = autos->first; current; current = NEXT)
00129 {
00130
00131
00132 if(!this_current)
00133 {
00134 append(this_current = new_auto());
00135 }
00136 this_current->copy_from(current);
00137 this_current = this_current->next;
00138 }
00139
00140 for( ; this_current; )
00141 {
00142 Auto *next_current = this_current->next;
00143 delete this_current;
00144 this_current = next_current;
00145 }
00146 }
00147
00148
00149
00150
00151
00152 void Autos::insert_track(Autos *automation,
00153 int64_t start_unit,
00154 int64_t length_units,
00155 int replace_default)
00156 {
00157
00158 insert(start_unit, start_unit + length_units);
00159
00160 if(replace_default) default_auto->copy_from(automation->default_auto);
00161 for(Auto *current = automation->first; current; current = NEXT)
00162 {
00163 Auto *new_auto = insert_auto(start_unit + current->position);
00164 new_auto->copy_from(current);
00165
00166 new_auto->position = current->position + start_unit;
00167 }
00168 }
00169
00170 Auto* Autos::get_prev_auto(int64_t position,
00171 int direction,
00172 Auto* ¤t,
00173 int use_default)
00174 {
00175
00176 if(direction == PLAY_FORWARD)
00177 {
00178
00179 if(current)
00180 {
00181 while(current && current->position < position) current = NEXT;
00182 while(current && current->position > position) current = PREVIOUS;
00183 }
00184
00185 if(!current)
00186 {
00187 for(current = last;
00188 current && current->position > position;
00189 current = PREVIOUS) ;
00190 }
00191 if(!current && use_default) current = (first ? first : default_auto);
00192 }
00193 else
00194
00195 if(direction == PLAY_REVERSE)
00196 {
00197 if(current)
00198 {
00199 while(current && current->position > position) current = PREVIOUS;
00200 while(current && current->position < position) current = NEXT;
00201 }
00202
00203 if(!current)
00204 {
00205 for(current = first;
00206 current && current->position < position;
00207 current = NEXT) ;
00208 }
00209
00210 if(!current && use_default) current = (last ? last : default_auto);
00211 }
00212
00213 return current;
00214 }
00215
00216 Auto* Autos::get_prev_auto(int direction, Auto* ¤t)
00217 {
00218 double position_double = edl->local_session->get_selectionstart(1);
00219 position_double = edl->align_to_frame(position_double, 0);
00220 int64_t position = track->to_units(position_double, 0);
00221
00222 return get_prev_auto(position, direction, current);
00223
00224 return current;
00225 }
00226
00227 int Autos::auto_exists_for_editing(double position)
00228 {
00229 int result = 0;
00230
00231 if(edl->session->auto_keyframes)
00232 {
00233 double unit_position = position;
00234 unit_position = edl->align_to_frame(unit_position, 0);
00235 if (get_auto_at_position(unit_position))
00236 result = 1;
00237 }
00238 else
00239 {
00240 result = 1;
00241 }
00242
00243 return result;
00244 }
00245
00246 Auto* Autos::get_auto_at_position(double position)
00247 {
00248 int64_t unit_position = track->to_units(position, 0);
00249
00250 for(Auto *current = first;
00251 current;
00252 current = NEXT)
00253 {
00254 if(edl->equivalent(current->position, unit_position))
00255 {
00256 return current;
00257 }
00258 }
00259 return 0;
00260 }
00261
00262
00263 Auto* Autos::get_auto_for_editing(double position)
00264 {
00265 if(position < 0)
00266 {
00267 position = edl->local_session->get_selectionstart(1);
00268 }
00269
00270 Auto *result = 0;
00271 position = edl->align_to_frame(position, 0);
00272
00273
00274
00275
00276
00277
00278 if(edl->session->auto_keyframes)
00279 {
00280 result = insert_auto_for_editing(track->to_units(position, 0));
00281 }
00282 else
00283 result = get_prev_auto(track->to_units(position, 0),
00284 PLAY_FORWARD,
00285 result);
00286
00287
00288 return result;
00289 }
00290
00291
00292 Auto* Autos::get_next_auto(int64_t position, int direction, Auto* ¤t, int use_default)
00293 {
00294 if(direction == PLAY_FORWARD)
00295 {
00296 if(current)
00297 {
00298 while(current && current->position > position) current = PREVIOUS;
00299 while(current && current->position < position) current = NEXT;
00300 }
00301
00302 if(!current)
00303 {
00304 for(current = first;
00305 current && current->position <= position;
00306 current = NEXT)
00307 ;
00308 }
00309
00310 if(!current && use_default) current = (last ? last : default_auto);
00311 }
00312 else
00313 if(direction == PLAY_REVERSE)
00314 {
00315 if(current)
00316 {
00317 while(current && current->position < position) current = NEXT;
00318 while(current && current->position > position) current = PREVIOUS;
00319 }
00320
00321 if(!current)
00322 {
00323 for(current = last;
00324 current && current->position > position;
00325 current = PREVIOUS)
00326 ;
00327 }
00328
00329 if(!current && use_default) current = (first ? first : default_auto);
00330 }
00331
00332 return current;
00333 }
00334
00335 Auto* Autos::insert_auto(int64_t position)
00336 {
00337 Auto *current, *result;
00338
00339
00340 for(current = first;
00341 current && !edl->equivalent(current->position, position);
00342 current = NEXT)
00343 {
00344 ;
00345 }
00346
00347
00348
00349 if(!current)
00350 {
00351
00352 for(current = last;
00353 current && current->position > position;
00354 current = PREVIOUS)
00355 {
00356 ;
00357 }
00358
00359 if(current)
00360 {
00361 insert_after(current, result = new_auto());
00362 result->copy_from(current);
00363 }
00364 else
00365 {
00366 current = first;
00367 if(!current) current = default_auto;
00368
00369 insert_before(first, result = new_auto());
00370 if(current) result->copy_from(current);
00371 }
00372
00373 result->position = position;
00374 }
00375 else
00376 {
00377 result = current;
00378 }
00379
00380 return result;
00381 }
00382
00383 Auto* Autos::insert_auto_for_editing(int64_t position)
00384 {
00385 Auto *current, *result;
00386
00387
00388 for(current = first;
00389 current && !edl->equivalent(current->position, position);
00390 current = NEXT)
00391 {
00392 ;
00393 }
00394
00395
00396
00397 if(!current)
00398 {
00399
00400 for(current = last;
00401 current && current->position > position;
00402 current = PREVIOUS)
00403 {
00404 ;
00405 }
00406
00407 if(current)
00408 {
00409 Auto *next = NEXT;
00410 insert_after(current, result = new_auto());
00411 result->interpolate_from(current, next, position);
00412 }
00413 else
00414 {
00415 current = first;
00416 if(!current) current = default_auto;
00417
00418 insert_before(first, result = new_auto());
00419 if(current) result->copy_from(current);
00420 }
00421
00422 result->position = position;
00423 }
00424 else
00425 {
00426 result = current;
00427 }
00428
00429 return result;
00430 }
00431
00432 int Autos::clear_all()
00433 {
00434 Auto *current_, *current;
00435
00436 for(current = first; current; current = current_)
00437 {
00438 current_ = NEXT;
00439 remove(current);
00440 }
00441 append_auto();
00442 return 0;
00443 }
00444
00445 int Autos::insert(int64_t start, int64_t end)
00446 {
00447 int64_t length;
00448 Auto *current = first;
00449
00450 for( ; current && current->position < start; current = NEXT)
00451 ;
00452
00453 length = end - start;
00454
00455 for(; current; current = NEXT)
00456 {
00457 current->position += length;
00458 }
00459 return 0;
00460 }
00461
00462 void Autos::paste(int64_t start,
00463 int64_t length,
00464 double scale,
00465 FileXML *file,
00466 int default_only)
00467 {
00468 int total = 0;
00469 int result = 0;
00470
00471
00472 do{
00473 result = file->read_tag();
00474
00475 if(!result && !file->tag.title_is("/AUTO"))
00476 {
00477
00478 if(
00479 file->tag.get_title()[0] == '/')
00480 {
00481 result = 1;
00482 }
00483 else
00484 if(!strcmp(file->tag.get_title(), "AUTO"))
00485 {
00486 Auto *current = 0;
00487
00488
00489 if(default_only)
00490 {
00491 if(total == 1)
00492 {
00493 current = default_auto;
00494 }
00495 }
00496 else
00497
00498 if(total == 0)
00499 current = default_auto;
00500 else
00501 {
00502 int64_t position = Units::to_int64(
00503 (double)file->tag.get_property("POSITION", 0) *
00504 scale +
00505 start);
00506
00507 current = insert_auto(position);
00508 }
00509
00510 if(current)
00511 {
00512 current->load(file);
00513 }
00514 total++;
00515 }
00516 }
00517 }while(!result);
00518
00519 }
00520
00521
00522 int Autos::paste_silence(int64_t start, int64_t end)
00523 {
00524 insert(start, end);
00525 return 0;
00526 }
00527
00528 int Autos::copy(int64_t start,
00529 int64_t end,
00530 FileXML *file,
00531 int default_only,
00532 int autos_only)
00533 {
00534
00535
00536
00537 if(!autos_only)
00538 {
00539 default_auto->copy(0, 0, file, default_only);
00540 }
00541
00542
00543 if(!default_only)
00544 {
00545 for(Auto* current = autoof(start);
00546 current && current->position <= end;
00547 current = NEXT)
00548 {
00549
00550 if(current->position >= start && current->position <= end)
00551 {
00552 current->copy(start, end, file, default_only);
00553 }
00554 }
00555 }
00556
00557 else
00558 {
00559
00560
00561 default_auto->copy(0, 0, file, default_only);
00562 }
00563
00564
00565 return 0;
00566 }
00567
00568
00569
00570 void Autos::optimize()
00571 {
00572 int done = 0;
00573
00574
00575
00576 default_auto->position = 0;
00577 while(!done)
00578 {
00579 int consecutive = 0;
00580 done = 1;
00581
00582
00583 for(Auto *current = first; current; current = NEXT)
00584 {
00585
00586 if(current != first)
00587 {
00588 if(*current == *PREVIOUS)
00589 {
00590 consecutive++;
00591 if(consecutive >= 3)
00592 {
00593 delete PREVIOUS;
00594 break;
00595 }
00596 }
00597 else
00598 consecutive = 0;
00599
00600 if(done && current->position <= PREVIOUS->position)
00601 {
00602 delete current;
00603 break;
00604 }
00605 }
00606 }
00607 }
00608 }
00609
00610
00611 void Autos::remove_nonsequential(Auto *keyframe)
00612 {
00613 if((keyframe->next && keyframe->next->position <= keyframe->position) ||
00614 (keyframe->previous && keyframe->previous->position >= keyframe->position))
00615 {
00616 delete keyframe;
00617 }
00618 }
00619
00620
00621
00622
00623 void Autos::clear(int64_t start,
00624 int64_t end,
00625 int shift_autos)
00626 {
00627 int64_t length;
00628 Auto *next, *current;
00629 length = end - start;
00630
00631
00632 current = autoof(start);
00633
00634
00635
00636
00637
00638 while(current &&
00639 ((end != start && current->position < end) ||
00640 (end == start && current->position <= end)))
00641 {
00642 next = NEXT;
00643 remove(current);
00644 current = next;
00645 }
00646
00647 while(current && shift_autos)
00648 {
00649 current->position -= length;
00650 current = NEXT;
00651 }
00652 }
00653
00654 int Autos::clear_auto(int64_t position)
00655 {
00656 Auto *current;
00657 current = autoof(position);
00658 if(current->position == position) remove(current);
00659 }
00660
00661
00662 int Autos::load(FileXML *file)
00663 {
00664 while(last)
00665 remove(last);
00666
00667 int result = 0, first_auto = 1;
00668 Auto *current;
00669
00670 do{
00671 result = file->read_tag();
00672
00673 if(!result && !file->tag.title_is("/AUTO"))
00674 {
00675
00676 if(
00677
00678 file->tag.get_title()[0] == '/')
00679 {
00680 result = 1;
00681 }
00682 else
00683 if(!strcmp(file->tag.get_title(), "AUTO"))
00684 {
00685 if(first_auto)
00686 {
00687 default_auto->load(file);
00688 default_auto->position = 0;
00689 first_auto = 0;
00690 }
00691 else
00692 {
00693 current = append(new_auto());
00694 current->position = file->tag.get_property("POSITION", (int64_t)0);
00695 current->load(file);
00696 }
00697 }
00698 }
00699 }while(!result);
00700 return 0;
00701 }
00702
00703
00704
00705
00706
00707
00708 int Autos::slope_adjustment(int64_t ax, double slope)
00709 {
00710 return (int)(ax * slope);
00711 }
00712
00713
00714 int Autos::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
00715 {
00716 Auto *current;
00717
00718 for(current = first; current && scale_autos; current = NEXT)
00719 {
00720
00721
00722 current->position = (int64_t)((current->position - start) * rate_scale + start + 0.5);
00723
00724 }
00725 return 0;
00726 }
00727
00728 Auto* Autos::autoof(int64_t position)
00729 {
00730 Auto *current;
00731
00732 for(current = first;
00733 current && current->position < position;
00734 current = NEXT)
00735 {
00736 ;
00737 }
00738 return current;
00739 }
00740
00741 Auto* Autos::nearest_before(int64_t position)
00742 {
00743 Auto *current;
00744
00745 for(current = last; current && current->position >= position; current = PREVIOUS)
00746 { ; }
00747
00748
00749 return current;
00750 }
00751
00752 Auto* Autos::nearest_after(int64_t position)
00753 {
00754 Auto *current;
00755
00756 for(current = first; current && current->position <= position; current = NEXT)
00757 { ; }
00758
00759
00760 return current;
00761 }
00762
00763 int Autos::get_neighbors(int64_t start, int64_t end, Auto **before, Auto **after)
00764 {
00765 if(*before == 0) *before = first;
00766 if(*after == 0) *after = last;
00767
00768 while(*before && (*before)->next && (*before)->next->position <= start)
00769 *before = (*before)->next;
00770
00771 while(*after && (*after)->previous && (*after)->previous->position >= end)
00772 *after = (*after)->previous;
00773
00774 while(*before && (*before)->position > start) *before = (*before)->previous;
00775
00776 while(*after && (*after)->position < end) *after = (*after)->next;
00777 return 0;
00778 }
00779
00780 int Autos::automation_is_constant(int64_t start, int64_t end)
00781 {
00782 return 0;
00783 }
00784
00785 double Autos::get_automation_constant(int64_t start, int64_t end)
00786 {
00787 return 0;
00788 }
00789
00790
00791 int Autos::init_automation(int64_t &buffer_position,
00792 int64_t &input_start,
00793 int64_t &input_end,
00794 int &automate,
00795 double &constant,
00796 int64_t input_position,
00797 int64_t buffer_len,
00798 Auto **before,
00799 Auto **after,
00800 int reverse)
00801 {
00802 buffer_position = 0;
00803
00804
00805 input_start = reverse ? input_position - buffer_len : input_position;
00806 input_end = reverse ? input_position : input_position + buffer_len;
00807
00808
00809
00810 if(automate)
00811 {
00812 if(automation_is_constant(input_start, input_end))
00813 {
00814 constant += get_automation_constant(input_start, input_end);
00815 automate = 0;
00816 }
00817 }
00818 return automate;
00819 }
00820
00821
00822 int Autos::init_slope(Auto **current_auto,
00823 double &slope_start,
00824 double &slope_value,
00825 double &slope_position,
00826 int64_t &input_start,
00827 int64_t &input_end,
00828 Auto **before,
00829 Auto **after,
00830 int reverse)
00831 {
00832
00833 *current_auto = reverse ? *after : *before;
00834
00835
00836 if(!*current_auto)
00837 {
00838 *current_auto = reverse ? last : first;
00839
00840 slope_start = input_start;
00841 slope_position = 0;
00842 }
00843 else
00844 {
00845
00846
00847 slope_start = (*current_auto)->position;
00848 slope_position = reverse ? slope_start - input_end : input_start - slope_start;
00849 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
00850 }
00851 return 0;
00852 }
00853
00854
00855 int Autos::get_slope(Auto **current_auto,
00856 double &slope_start,
00857 double &slope_end,
00858 double &slope_value,
00859 double &slope,
00860 int64_t buffer_len,
00861 int64_t buffer_position,
00862 int reverse)
00863 {
00864
00865 if(*current_auto)
00866 {
00867 slope_end = reverse ? slope_start - (*current_auto)->position : (*current_auto)->position - slope_start;
00868 if(slope_end)
00869
00870
00871 slope = 0;
00872 }
00873 else
00874 {
00875 slope = 0;
00876 slope_end = buffer_len - buffer_position;
00877 }
00878 return 0;
00879 }
00880
00881 int Autos::advance_slope(Auto **current_auto,
00882 double &slope_start,
00883 double &slope_value,
00884 double &slope_position,
00885 int reverse)
00886 {
00887 if(*current_auto)
00888 {
00889 slope_start = (*current_auto)->position;
00890
00891 (*current_auto) = reverse ? (*current_auto)->previous : (*current_auto)->next;
00892 slope_position = 0;
00893 }
00894 return 0;
00895 }
00896
00897 int64_t Autos::get_length()
00898 {
00899 if(last)
00900 return last->position + 1;
00901 else
00902 return 0;
00903 }
00904
00905 void Autos::get_extents(float *min,
00906 float *max,
00907 int *coords_undefined,
00908 int64_t unit_start,
00909 int64_t unit_end)
00910 {
00911
00912 }
00913
00914
00915 void Autos::dump()
00916 {
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927