00001 #include "automation.inc"
00002 #include "clip.h"
00003 #include "edl.h"
00004 #include "edlsession.h"
00005 #include "filexml.h"
00006 #include "floatauto.h"
00007 #include "floatautos.h"
00008 #include "track.h"
00009 #include "localsession.h"
00010 #include "transportque.inc"
00011
00012 FloatAutos::FloatAutos(EDL *edl,
00013 Track *track,
00014 float default_)
00015 : Autos(edl, track)
00016 {
00017 this->default_ = default_;
00018 type = AUTOMATION_TYPE_FLOAT;
00019 }
00020
00021 FloatAutos::~FloatAutos()
00022 {
00023 }
00024
00025 void FloatAutos::straighten(int64_t start, int64_t end)
00026 {
00027 FloatAuto *current = (FloatAuto*)first;
00028 while(current)
00029 {
00030 FloatAuto *previous_auto = (FloatAuto*)PREVIOUS;
00031 FloatAuto *next_auto = (FloatAuto*)NEXT;
00032
00033
00034 if(current->position >= start && current->position < end)
00035 {
00036 float current_value = current->value;
00037
00038
00039 if(previous_auto && previous_auto->position >= start)
00040 {
00041 float previous_value = previous_auto->value;
00042 current->control_in_value = (previous_value - current_value) / 6.0;
00043 if(!current->control_in_position)
00044 current->control_in_position = -track->to_units(1.0, 0);
00045 }
00046
00047
00048 if(next_auto && next_auto->position < end)
00049 {
00050 float next_value = next_auto->value;
00051 current->control_out_value = (next_value - current_value) / 6.0;
00052 if(!current->control_out_position)
00053 current->control_out_position = track->to_units(1.0, 0);
00054 }
00055 }
00056 current = (FloatAuto*)NEXT;
00057 }
00058 }
00059
00060 int FloatAutos::draw_joining_line(BC_SubWindow *canvas, int vertical, int center_pixel, int x1, int y1, int x2, int y2)
00061 {
00062 if(vertical)
00063 canvas->draw_line(center_pixel - y1, x1, center_pixel - y2, x2);
00064 else
00065 canvas->draw_line(x1, center_pixel + y1, x2, center_pixel + y2);
00066 }
00067
00068 Auto* FloatAutos::add_auto(int64_t position, float value)
00069 {
00070 FloatAuto* current = (FloatAuto*)autoof(position);
00071 FloatAuto* result;
00072
00073 insert_before(current, result = (FloatAuto*)new_auto());
00074
00075 result->position = position;
00076 result->value = value;
00077
00078 return result;
00079 }
00080
00081 Auto* FloatAutos::new_auto()
00082 {
00083 FloatAuto *result = new FloatAuto(edl, this);
00084 result->value = default_;
00085 return result;
00086 }
00087
00088 int FloatAutos::get_testy(float slope, int cursor_x, int ax, int ay)
00089 {
00090 return (int)(slope * (cursor_x - ax)) + ay;
00091 }
00092
00093 int FloatAutos::automation_is_constant(int64_t start,
00094 int64_t length,
00095 int direction,
00096 double &constant)
00097 {
00098 int total_autos = total();
00099 int64_t end;
00100 if(direction == PLAY_FORWARD)
00101 {
00102 end = start + length;
00103 }
00104 else
00105 {
00106 end = start + 1;
00107 start -= length;
00108 }
00109
00110
00111
00112 if(total_autos == 0)
00113 {
00114 constant = ((FloatAuto*)default_auto)->value;
00115 return 1;
00116 }
00117 else
00118
00119 if(total_autos == 1)
00120 {
00121 constant = ((FloatAuto*)first)->value;
00122 return 1;
00123 }
00124 else
00125
00126 if(last->position <= start)
00127 {
00128 constant = ((FloatAuto*)last)->value;
00129 return 1;
00130 }
00131 else
00132
00133 if(first->position > end)
00134 {
00135 constant = ((FloatAuto*)first)->value;
00136 return 1;
00137 }
00138
00139
00140 int64_t prev_position = -1;
00141 for(Auto *current = first; current; current = NEXT)
00142 {
00143 int test_current_next = 0;
00144 int test_previous_current = 0;
00145 FloatAuto *float_current = (FloatAuto*)current;
00146
00147
00148 if(prev_position >= 0 &&
00149 prev_position < start &&
00150 current->position >= end)
00151 {
00152
00153 constant = float_current->value;
00154 test_previous_current = 1;
00155 }
00156 prev_position = current->position;
00157
00158
00159 if(!test_previous_current &&
00160 current->position < end &&
00161 current->position >= start)
00162 {
00163
00164
00165 constant = float_current->value;
00166
00167
00168 if(current->previous)
00169 {
00170 test_previous_current = 1;
00171 }
00172
00173 if(current->next)
00174 {
00175 test_current_next = 1;
00176 }
00177 }
00178
00179 if(test_current_next)
00180 {
00181
00182 FloatAuto *float_next = (FloatAuto*)current->next;
00183
00184
00185 if(!EQUIV(float_current->value, float_next->value) ||
00186 !EQUIV(float_current->control_out_value, 0) ||
00187 !EQUIV(float_next->control_in_value, 0))
00188 {
00189 return 0;
00190 }
00191 }
00192
00193 if(test_previous_current)
00194 {
00195 FloatAuto *float_previous = (FloatAuto*)current->previous;
00196
00197
00198 if(!EQUIV(float_current->value, float_previous->value) ||
00199 !EQUIV(float_current->control_in_value, 0) ||
00200 !EQUIV(float_previous->control_out_value, 0))
00201 {
00202
00203
00204
00205
00206
00207
00208
00209
00210 return 0;
00211 }
00212 }
00213 }
00214
00215
00216 return 1;
00217 }
00218
00219 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
00220 {
00221 Auto *current_auto, *before = 0, *after = 0;
00222
00223
00224 get_neighbors(start, end, &before, &after);
00225
00226
00227 if(before)
00228 current_auto = before;
00229 else
00230 current_auto = first;
00231
00232
00233 if(!current_auto) current_auto = default_auto;
00234
00235 return ((FloatAuto*)current_auto)->value;
00236 }
00237
00238
00239 float FloatAutos::get_value(int64_t position,
00240 int direction,
00241 FloatAuto* &previous,
00242 FloatAuto* &next)
00243 {
00244 double slope;
00245 double intercept;
00246 int64_t slope_len;
00247
00248 float y0, y1, y2, y3;
00249 float t;
00250
00251 previous = (FloatAuto*)get_prev_auto(position, direction, (Auto* &)previous, 0);
00252 next = (FloatAuto*)get_next_auto(position, direction, (Auto* &)next, 0);
00253
00254
00255 if(!next && !previous)
00256 {
00257 return ((FloatAuto*)default_auto)->value;
00258 }
00259 else
00260 if(!previous)
00261 {
00262 return next->value;
00263 }
00264 else
00265 if(!next)
00266 {
00267 return previous->value;
00268 }
00269 else
00270 if(next == previous)
00271 {
00272 return previous->value;
00273 }
00274 else
00275 {
00276 if(direction == PLAY_FORWARD &&
00277 EQUIV(previous->value, next->value) &&
00278 EQUIV(previous->control_out_value, 0) &&
00279 EQUIV(next->control_in_value, 0))
00280 {
00281 return previous->value;
00282 }
00283 else
00284 if(direction == PLAY_REVERSE &&
00285 EQUIV(previous->value, next->value) &&
00286 EQUIV(previous->control_in_value, 0) &&
00287 EQUIV(next->control_out_value, 0))
00288 {
00289 return previous->value;
00290 }
00291 }
00292
00293
00294
00295 y0 = previous->value;
00296 y3 = next->value;
00297
00298 if(direction == PLAY_FORWARD)
00299 {
00300 y1 = previous->value + previous->control_out_value * 2;
00301 y2 = next->value + next->control_in_value * 2;
00302 t = (double)(position - previous->position) /
00303 (next->position - previous->position);
00304
00305 if(next->position - previous->position == 0) return previous->value;
00306 }
00307 else
00308 {
00309 y1 = previous->value + previous->control_in_value * 2;
00310 y2 = next->value + next->control_out_value * 2;
00311 t = (double)(previous->position - position) /
00312 (previous->position - next->position);
00313
00314 if(previous->position - next->position == 0) return previous->value;
00315 }
00316
00317 float tpow2 = t * t;
00318 float tpow3 = t * t * t;
00319 float invt = 1 - t;
00320 float invtpow2 = invt * invt;
00321 float invtpow3 = invt * invt * invt;
00322
00323 float result = ( invtpow3 * y0
00324 + 3 * t * invtpow2 * y1
00325 + 3 * tpow2 * invt * y2
00326 + tpow3 * y3);
00327
00328
00329 return result;
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 }
00341
00342
00343 void FloatAutos::get_fade_automation(double &slope,
00344 double &intercept,
00345 int64_t input_position,
00346 int64_t &slope_len,
00347 int direction)
00348 {
00349 Auto *current = 0;
00350 FloatAuto *prev_keyframe =
00351 (FloatAuto*)get_prev_auto(input_position, direction, current);
00352 FloatAuto *next_keyframe =
00353 (FloatAuto*)get_next_auto(input_position, direction, current);
00354 int64_t new_slope_len;
00355
00356 if(direction == PLAY_FORWARD)
00357 {
00358 new_slope_len = next_keyframe->position - prev_keyframe->position;
00359
00360
00361
00362
00363
00364 if(next_keyframe->position > prev_keyframe->position)
00365 {
00366 slope = ((double)next_keyframe->value - prev_keyframe->value) /
00367 new_slope_len;
00368 intercept = ((double)input_position - prev_keyframe->position) * slope + prev_keyframe->value;
00369
00370 if(next_keyframe->position < input_position + new_slope_len)
00371 new_slope_len = next_keyframe->position - input_position;
00372 slope_len = MIN(slope_len, new_slope_len);
00373 }
00374 else
00375
00376 {
00377 slope = 0;
00378 intercept = prev_keyframe->value;
00379 }
00380 }
00381 else
00382 {
00383 new_slope_len = prev_keyframe->position - next_keyframe->position;
00384
00385 if(next_keyframe->position < prev_keyframe->position)
00386 {
00387 slope = ((double)next_keyframe->value - prev_keyframe->value) / new_slope_len;
00388 intercept = ((double)prev_keyframe->position - input_position) * slope + prev_keyframe->value;
00389
00390 if(prev_keyframe->position > input_position - new_slope_len)
00391 new_slope_len = input_position - prev_keyframe->position;
00392 slope_len = MIN(slope_len, new_slope_len);
00393 }
00394 else
00395
00396 {
00397 slope = 0;
00398 intercept = next_keyframe->value;
00399 }
00400 }
00401 }
00402
00403 void FloatAutos::get_extents(float *min,
00404 float *max,
00405 int *coords_undefined,
00406 int64_t unit_start,
00407 int64_t unit_end)
00408 {
00409 if(!edl)
00410 {
00411 printf("FloatAutos::get_extents edl == NULL\n");
00412 return;
00413 }
00414
00415 if(!track)
00416 {
00417 printf("FloatAutos::get_extents track == NULL\n");
00418 return;
00419 }
00420
00421
00422 if(!first)
00423 {
00424 FloatAuto *current = (FloatAuto*)default_auto;
00425 if(*coords_undefined)
00426 {
00427 *min = *max = current->value;
00428 *coords_undefined = 0;
00429 }
00430
00431 *min = MIN(current->value, *min);
00432 *max = MAX(current->value, *max);
00433 }
00434
00435
00436 for(FloatAuto *current = (FloatAuto*)first; current; current = (FloatAuto*)NEXT)
00437 {
00438 if(current->position >= unit_start && current->position < unit_end)
00439 {
00440 if(*coords_undefined)
00441 {
00442 *min = *max = current->value;
00443 *coords_undefined = 0;
00444 }
00445
00446 *min = MIN(current->value, *min);
00447 *min = MIN(current->value + current->control_in_value, *min);
00448 *min = MIN(current->value + current->control_out_value, *min);
00449
00450 *max = MAX(current->value, *max);
00451 *max = MAX(current->value + current->control_in_value, *max);
00452 *max = MAX(current->value + current->control_out_value, *max);
00453 }
00454 }
00455
00456
00457 FloatAuto *prev = 0;
00458 FloatAuto *next = 0;
00459 int64_t unit_step = edl->local_session->zoom_sample;
00460 if(track->data_type == TRACK_VIDEO)
00461 unit_step = (int64_t)(unit_step *
00462 edl->session->frame_rate /
00463 edl->session->sample_rate);
00464 unit_step = MAX(unit_step, 1);
00465 for(int64_t position = unit_start;
00466 position < unit_end;
00467 position += unit_step)
00468 {
00469 float value = get_value(position,
00470 PLAY_FORWARD,
00471 prev,
00472 next);
00473 if(*coords_undefined)
00474 {
00475 *min = *max = value;
00476 *coords_undefined = 0;
00477 }
00478 else
00479 {
00480 *min = MIN(value, *min);
00481 *max = MAX(value, *max);
00482 }
00483 }
00484 }
00485
00486 void FloatAutos::dump()
00487 {
00488 printf(" FloatAutos::dump %p\n", this);
00489 printf(" Default: position %lld value=%f\n",
00490 default_auto->position,
00491 ((FloatAuto*)default_auto)->value);
00492 for(Auto* current = first; current; current = NEXT)
00493 {
00494 printf(" position %lld value=%f invalue=%f outvalue=%f inposition=%lld outposition=%lld\n",
00495 current->position,
00496 ((FloatAuto*)current)->value,
00497 ((FloatAuto*)current)->control_in_value,
00498 ((FloatAuto*)current)->control_out_value,
00499 ((FloatAuto*)current)->control_in_position,
00500 ((FloatAuto*)current)->control_out_position);
00501 }
00502 }