00001 #include "asset.h"
00002 #include "assets.h"
00003 #include "clip.h"
00004 #include "edit.h"
00005 #include "edits.h"
00006 #include "edl.h"
00007 #include "edlsession.h"
00008 #include "filexml.h"
00009 #include "filesystem.h"
00010 #include "localsession.h"
00011 #include "plugin.h"
00012 #include "mainsession.h"
00013 #include "trackcanvas.h"
00014 #include "tracks.h"
00015 #include "transition.h"
00016 #include <string.h>
00017
00018
00019 Edit::Edit()
00020 {
00021 reset();
00022 }
00023
00024 Edit::Edit(EDL *edl, Track *track)
00025 {
00026 reset();
00027 this->edl = edl;
00028 this->track = track;
00029 if(track) this->edits = track->edits;
00030 id = EDL::next_id();
00031 }
00032
00033 Edit::Edit(EDL *edl, Edits *edits)
00034 {
00035 reset();
00036 this->edl = edl;
00037 this->edits = edits;
00038 if(edits) this->track = edits->track;
00039 id = EDL::next_id();
00040 }
00041
00042 Edit::~Edit()
00043 {
00044
00045 if(transition) delete transition;
00046
00047 }
00048
00049 void Edit::reset()
00050 {
00051 edl = 0;
00052 track = 0;
00053 edits = 0;
00054 startsource = 0;
00055 startproject = 0;
00056 length = 0;
00057 asset = 0;
00058 transition = 0;
00059 channel = 0;
00060 user_title[0] = 0;
00061 }
00062
00063 int Edit::copy(int64_t start, int64_t end, FileXML *file, char *output_path)
00064 {
00065
00066
00067
00068 int64_t endproject = startproject + length;
00069 int result;
00070
00071 if((startproject >= start && startproject <= end) ||
00072 (endproject <= end && endproject >= start) ||
00073 (startproject <= start && endproject >= end))
00074 {
00075
00076 int64_t startproject_in_selection = startproject;
00077 int64_t startsource_in_selection = startsource;
00078 int64_t endsource_in_selection = startsource + length;
00079 int64_t length_in_selection = length;
00080
00081
00082 if(startproject < start)
00083 {
00084 int64_t length_difference = start - startproject;
00085
00086 startsource_in_selection += length_difference;
00087 startproject_in_selection += length_difference;
00088 length_in_selection -= length_difference;
00089 }
00090
00091
00092 if(endproject > end)
00093 {
00094 length_in_selection = end - startproject_in_selection;
00095 }
00096
00097
00098 if(file)
00099 {
00100 file->tag.set_title("EDIT");
00101 file->tag.set_property("STARTSOURCE", startsource_in_selection);
00102 file->tag.set_property("CHANNEL", (int64_t)channel);
00103 file->tag.set_property("LENGTH", length_in_selection);
00104 if(user_title[0]) file->tag.set_property("USER_TITLE", user_title);
00105
00106
00107 copy_properties_derived(file, length_in_selection);
00108
00109 file->append_tag();
00110
00111
00112
00113 if(asset)
00114 {
00115
00116 char stored_path[1024];
00117 char asset_directory[1024], output_directory[1024];
00118 FileSystem fs;
00119
00120
00121 fs.extract_dir(asset_directory, asset->path);
00122
00123
00124 if(output_path)
00125 fs.extract_dir(output_directory, output_path);
00126 else
00127 output_directory[0] = 0;
00128
00129
00130 if(output_path && !strcmp(asset_directory, output_directory))
00131 fs.extract_name(stored_path, asset->path);
00132 else
00133 strcpy(stored_path, asset->path);
00134
00135 file->tag.set_title("FILE");
00136 file->tag.set_property("SRC", stored_path);
00137 file->append_tag();
00138 file->tag.set_title("/FILE");
00139 file->append_tag();
00140 }
00141
00142 if(transition)
00143 {
00144 transition->save_xml(file);
00145 }
00146
00147
00148 file->tag.set_title("/EDIT");
00149 file->append_tag();
00150 file->append_newline();
00151
00152 }
00153
00154 result = 1;
00155 }
00156 else
00157 {
00158 result = 0;
00159 }
00160
00161 return result;
00162 }
00163
00164
00165 int64_t Edit::get_source_end(int64_t default_)
00166 {
00167 return default_;
00168 }
00169
00170 void Edit::insert_transition(char *title)
00171 {
00172
00173 transition = new Transition(edl,
00174 this,
00175 title,
00176 track->to_units(edl->session->default_transition_length, 1));
00177 }
00178
00179 void Edit::detach_transition()
00180 {
00181 if(transition) delete transition;
00182 transition = 0;
00183 }
00184
00185 int Edit::silence()
00186 {
00187 if(asset)
00188 return 0;
00189 else
00190 return 1;
00191 }
00192
00193
00194 void Edit::copy_from(Edit *edit)
00195 {
00196 this->asset = edl->assets->update(edit->asset);
00197 this->startsource = edit->startsource;
00198 this->startproject = edit->startproject;
00199 this->length = edit->length;
00200 strcpy (this->user_title, edit->user_title);
00201
00202 if(edit->transition)
00203 {
00204 if(!transition) transition = new Transition(edl,
00205 this,
00206 edit->transition->title,
00207 edit->transition->length);
00208 *this->transition = *edit->transition;
00209 }
00210 this->channel = edit->channel;
00211 }
00212
00213 void Edit::equivalent_output(Edit *edit, int64_t *result)
00214 {
00215
00216 if(startproject + length != edit->startproject + edit->length)
00217 {
00218 int64_t new_length = MIN(startproject + length, edit->startproject + edit->length);
00219 if(*result < 0 || new_length < *result)
00220 *result = new_length;
00221 }
00222
00223
00224 if(
00225
00226 edit->asset == 0 && asset != 0 ||
00227 edit->asset != 0 && asset == 0 ||
00228
00229 edit->transition == 0 && transition != 0 ||
00230 edit->transition != 0 && transition == 0 ||
00231
00232 startproject != edit->startproject ||
00233 startsource != edit->startsource ||
00234
00235 (transition &&
00236 edit->transition &&
00237 !transition->identical(edit->transition)) ||
00238
00239 (asset &&
00240 edit->asset &&
00241 !asset->equivalent(*edit->asset, 1, 1))
00242 )
00243 {
00244 if(*result < 0 || startproject < *result) *result = startproject;
00245 }
00246 }
00247
00248
00249 Edit& Edit::operator=(Edit& edit)
00250 {
00251
00252 copy_from(&edit);
00253 return *this;
00254 }
00255
00256 void Edit::synchronize_params(Edit *edit)
00257 {
00258 copy_from(edit);
00259 }
00260
00261
00262
00263 int Edit::identical(Edit &edit)
00264 {
00265 int result = (this->asset == edit.asset &&
00266 this->startsource == edit.startsource &&
00267 this->startproject == edit.startproject &&
00268 this->length == edit.length &&
00269 this->transition == edit.transition &&
00270 this->channel == edit.channel);
00271 return result;
00272 }
00273
00274 int Edit::operator==(Edit &edit)
00275 {
00276 return identical(edit);
00277 }
00278
00279 double Edit::frames_per_picon()
00280 {
00281 return picon_w() / frame_w();
00282 }
00283
00284 double Edit::frame_w()
00285 {
00286 return track->from_units(1) * edl->session->sample_rate / edl->local_session->zoom_sample;
00287 }
00288
00289 double Edit::picon_w()
00290 {
00291 return (double)edl->local_session->zoom_track * asset->width / asset->height;
00292 }
00293
00294 int Edit::picon_h()
00295 {
00296 return edl->local_session->zoom_track;
00297 }
00298
00299
00300 int Edit::dump()
00301 {
00302 printf(" EDIT %p\n", this); fflush(stdout);
00303 printf(" asset %p\n", asset); fflush(stdout);
00304 printf(" channel %d\n", channel);
00305 if(transition)
00306 {
00307 printf(" TRANSITION %p\n", transition);
00308 transition->dump();
00309 }
00310 printf(" startsource %lld startproject %lld length %lld\n", startsource, startproject, length); fflush(stdout);
00311 return 0;
00312 }
00313
00314 int Edit::load_properties(FileXML *file, int64_t &startproject)
00315 {
00316 startsource = file->tag.get_property("STARTSOURCE", (int64_t)0);
00317 length = file->tag.get_property("LENGTH", (int64_t)0);
00318 user_title[0] = 0;
00319 file->tag.get_property("USER_TITLE", user_title);
00320 this->startproject = startproject;
00321 load_properties_derived(file);
00322 return 0;
00323 }
00324
00325 void Edit::shift(int64_t difference)
00326 {
00327
00328 startproject += difference;
00329
00330 }
00331
00332 int Edit::shift_start_in(int edit_mode,
00333 int64_t newposition,
00334 int64_t oldposition,
00335 int edit_edits,
00336 int edit_labels,
00337 int edit_plugins,
00338 Edits *trim_edits)
00339 {
00340 int64_t cut_length = newposition - oldposition;
00341 int64_t end_previous_source, end_source;
00342
00343 if(edit_mode == MOVE_ALL_EDITS)
00344 {
00345 if(cut_length < length)
00346 {
00347 edits->clear_recursive(oldposition,
00348 newposition,
00349 edit_edits,
00350 edit_labels,
00351 edit_plugins,
00352 trim_edits);
00353 }
00354 else
00355 {
00356 edits->clear_recursive(oldposition,
00357 startproject + length,
00358 edit_edits,
00359 edit_labels,
00360 edit_plugins,
00361 trim_edits);
00362 }
00363 }
00364 else
00365 if(edit_mode == MOVE_ONE_EDIT)
00366 {
00367
00368
00369 if(!previous)
00370 {
00371 Edit *new_edit = edits->create_edit();
00372 new_edit->startproject = this->startproject;
00373 new_edit->length = 0;
00374 edits->insert_before(this,
00375 new_edit);
00376 }
00377
00378
00379 end_previous_source = previous->get_source_end(previous->startsource + previous->length + cut_length);
00380 if(end_previous_source > 0 &&
00381 previous->startsource + previous->length + cut_length > end_previous_source)
00382 cut_length = end_previous_source - previous->startsource - previous->length;
00383
00384 if(cut_length < length)
00385 {
00386 startproject += cut_length;
00387 startsource += cut_length;
00388 length -= cut_length;
00389 previous->length += cut_length;
00390
00391 }
00392 else
00393 {
00394 cut_length = length;
00395 previous->length += cut_length;
00396 for(Edit* current_edit = this; current_edit; current_edit = current_edit->next)
00397 {
00398 current_edit->startproject += cut_length;
00399 }
00400 edits->clear_recursive(oldposition + cut_length,
00401 startproject + cut_length,
00402 edit_edits,
00403 edit_labels,
00404 edit_plugins,
00405 trim_edits);
00406 }
00407
00408 }
00409 else
00410 if(edit_mode == MOVE_NO_EDITS)
00411 {
00412 end_source = get_source_end(startsource + length + cut_length);
00413 if(end_source > 0 && startsource + length + cut_length > end_source)
00414 cut_length = end_source - startsource - length;
00415
00416 startsource += cut_length;
00417 }
00418 return 0;
00419 }
00420
00421 int Edit::shift_start_out(int edit_mode,
00422 int64_t newposition,
00423 int64_t oldposition,
00424 int edit_edits,
00425 int edit_labels,
00426 int edit_plugins,
00427 Edits *trim_edits)
00428 {
00429 int64_t cut_length = oldposition - newposition;
00430
00431 if(asset)
00432 {
00433 int64_t end_source = get_source_end(1);
00434
00435
00436 if(end_source > 0 && startsource < cut_length)
00437 {
00438 cut_length = startsource;
00439 }
00440 }
00441
00442 if(edit_mode == MOVE_ALL_EDITS)
00443 {
00444
00445 startsource -= cut_length;
00446 length += cut_length;
00447
00448 edits->shift_keyframes_recursive(startproject,
00449 cut_length);
00450 if(edit_plugins)
00451 edits->shift_effects_recursive(startproject,
00452 cut_length);
00453
00454 for(Edit* current_edit = next; current_edit; current_edit = current_edit->next)
00455 {
00456 current_edit->startproject += cut_length;
00457 }
00458 }
00459 else
00460 if(edit_mode == MOVE_ONE_EDIT)
00461 {
00462 if(previous)
00463 {
00464 if(cut_length < previous->length)
00465 {
00466 previous->length -= cut_length;
00467 startproject -= cut_length;
00468 startsource -= cut_length;
00469 length += cut_length;
00470 printf("Edit::shift_start_out 2\n");
00471 }
00472 else
00473 {
00474 cut_length = previous->length;
00475 previous->length = 0;
00476 length += cut_length;
00477 startsource -= cut_length;
00478 startproject -= cut_length;
00479 }
00480 }
00481 }
00482 else
00483 if(edit_mode == MOVE_NO_EDITS)
00484 {
00485 startsource -= cut_length;
00486 }
00487
00488
00489 if(startsource < 0) startsource = 0;
00490 return 0;
00491 }
00492
00493 int Edit::shift_end_in(int edit_mode,
00494 int64_t newposition,
00495 int64_t oldposition,
00496 int edit_edits,
00497 int edit_labels,
00498 int edit_plugins,
00499 Edits *trim_edits)
00500 {
00501 int64_t cut_length = oldposition - newposition;
00502
00503 if(edit_mode == MOVE_ALL_EDITS)
00504 {
00505
00506 if(newposition > startproject)
00507 {
00508
00509 edits->clear_recursive(newposition,
00510 oldposition,
00511 edit_edits,
00512 edit_labels,
00513 edit_plugins,
00514 trim_edits);
00515 }
00516 else
00517 {
00518 edits->clear_recursive(startproject,
00519 oldposition,
00520 edit_edits,
00521 edit_labels,
00522 edit_plugins,
00523 trim_edits);
00524 }
00525 }
00526 else
00527 if(edit_mode == MOVE_ONE_EDIT)
00528 {
00529 if(next)
00530 {
00531 if(next->asset)
00532 {
00533 int64_t end_source = next->get_source_end(1);
00534
00535 if(end_source > 0 && next->startsource - cut_length < 0)
00536 {
00537 cut_length = next->startsource;
00538 }
00539 }
00540
00541 if(cut_length < length)
00542 {
00543 length -= cut_length;
00544 next->startproject -= cut_length;
00545 next->startsource -= cut_length;
00546 next->length += cut_length;
00547
00548 }
00549 else
00550 {
00551 cut_length = length;
00552 next->length += cut_length;
00553 next->startsource -= cut_length;
00554 next->startproject -= cut_length;
00555 length -= cut_length;
00556 }
00557 }
00558 else
00559 {
00560 if(cut_length < length)
00561 {
00562 length -= cut_length;
00563 }
00564 else
00565 {
00566 cut_length = length;
00567 edits->clear_recursive(startproject,
00568 oldposition,
00569 edit_edits,
00570 edit_labels,
00571 edit_plugins,
00572 trim_edits);
00573 }
00574 }
00575 }
00576 else
00577
00578 if(edit_mode == MOVE_NO_EDITS)
00579 {
00580
00581 int64_t end_source = get_source_end(1);
00582 if(end_source > 0 && startsource < cut_length)
00583 {
00584 cut_length = startsource;
00585 }
00586 startsource -= cut_length;
00587 }
00588 return 0;
00589 }
00590
00591 int Edit::shift_end_out(int edit_mode,
00592 int64_t newposition,
00593 int64_t oldposition,
00594 int edit_edits,
00595 int edit_labels,
00596 int edit_plugins,
00597 Edits *trim_edits)
00598 {
00599 int64_t cut_length = newposition - oldposition;
00600 int64_t endsource = get_source_end(startsource + length + cut_length);
00601
00602
00603 if(endsource > 0 && startsource + length + cut_length > endsource)
00604 cut_length = endsource - startsource - length;
00605
00606
00607 if(edit_mode == MOVE_ALL_EDITS)
00608 {
00609
00610 this->length += cut_length;
00611
00612
00613 if(edit_plugins)
00614 edits->shift_effects_recursive(oldposition ,
00615 cut_length);
00616 edits->shift_keyframes_recursive(oldposition ,
00617 cut_length);
00618
00619 for(Edit* current_edit = next; current_edit; current_edit = current_edit->next)
00620 {
00621 current_edit->startproject += cut_length;
00622 }
00623 }
00624 else
00625 if(edit_mode == MOVE_ONE_EDIT)
00626 {
00627 if(next)
00628 {
00629 if(cut_length < next->length)
00630 {
00631 length += cut_length;
00632 next->startproject += cut_length;
00633 next->startsource += cut_length;
00634 next->length -= cut_length;
00635
00636 }
00637 else
00638 {
00639 cut_length = next->length;
00640 next->length = 0;
00641 length += cut_length;
00642 }
00643 }
00644 else
00645 {
00646 length += cut_length;
00647 }
00648 }
00649 else
00650 if(edit_mode == MOVE_NO_EDITS)
00651 {
00652 startsource += cut_length;
00653 }
00654 return 0;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 int Edit::popup_transition(float view_start, float zoom_units, int cursor_x, int cursor_y)
00686 {
00687 int64_t left, right, left_unit, right_unit;
00688 if(!transition) return 0;
00689 get_handle_parameters(left, right, left_unit, right_unit, view_start, zoom_units);
00690
00691 if(cursor_x > left && cursor_x < right)
00692 {
00693
00694 return 1;
00695 }
00696 return 0;
00697 }
00698
00699 int Edit::select_handle(float view_start, float zoom_units, int cursor_x, int cursor_y, int64_t &selection)
00700 {
00701 int64_t left, right, left_unit, right_unit;
00702 get_handle_parameters(left, right, left_unit, right_unit, view_start, zoom_units);
00703
00704 int64_t pixel1, pixel2;
00705 pixel1 = left;
00706 pixel2 = pixel1 + 10;
00707
00708
00709
00710 if(cursor_x >= pixel1 && cursor_x <= pixel2)
00711 {
00712 selection = left_unit;
00713 return 1;
00714 }
00715
00716 int64_t endproject = startproject + length;
00717 pixel2 = right;
00718 pixel1 = pixel2 - 10;
00719
00720
00721 if(cursor_x >= pixel1 && cursor_x <= pixel2)
00722 {
00723 selection = right_unit;
00724 return 2;
00725 }
00726 return 0;
00727 }
00728