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