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 Units::round(picon_w()) / frame_w();
00282 }
00283
00284 double Edit::frame_w()
00285 {
00286 return track->from_units(1) *
00287 edl->session->sample_rate /
00288 edl->local_session->zoom_sample;
00289 }
00290
00291 double Edit::picon_w()
00292 {
00293 return (double)edl->local_session->zoom_track *
00294 asset->width /
00295 asset->height;
00296 }
00297
00298 int Edit::picon_h()
00299 {
00300 return edl->local_session->zoom_track;
00301 }
00302
00303
00304 int Edit::dump()
00305 {
00306 printf(" EDIT %p\n", this); fflush(stdout);
00307 printf(" asset %p\n", asset); fflush(stdout);
00308 printf(" channel %d\n", channel);
00309 if(transition)
00310 {
00311 printf(" TRANSITION %p\n", transition);
00312 transition->dump();
00313 }
00314 printf(" startsource %lld startproject %lld length %lld\n", startsource, startproject, length); fflush(stdout);
00315 return 0;
00316 }
00317
00318 int Edit::load_properties(FileXML *file, int64_t &startproject)
00319 {
00320 startsource = file->tag.get_property("STARTSOURCE", (int64_t)0);
00321 length = file->tag.get_property("LENGTH", (int64_t)0);
00322 user_title[0] = 0;
00323 file->tag.get_property("USER_TITLE", user_title);
00324 this->startproject = startproject;
00325 load_properties_derived(file);
00326 return 0;
00327 }
00328
00329 void Edit::shift(int64_t difference)
00330 {
00331
00332 startproject += difference;
00333
00334 }
00335
00336 int Edit::shift_start_in(int edit_mode,
00337 int64_t newposition,
00338 int64_t oldposition,
00339 int edit_edits,
00340 int edit_labels,
00341 int edit_plugins,
00342 Edits *trim_edits)
00343 {
00344 int64_t cut_length = newposition - oldposition;
00345 int64_t end_previous_source, end_source;
00346
00347 if(edit_mode == MOVE_ALL_EDITS)
00348 {
00349 if(cut_length < length)
00350 {
00351 edits->clear_recursive(oldposition,
00352 newposition,
00353 edit_edits,
00354 edit_labels,
00355 edit_plugins,
00356 trim_edits);
00357 }
00358 else
00359 {
00360 edits->clear_recursive(oldposition,
00361 startproject + length,
00362 edit_edits,
00363 edit_labels,
00364 edit_plugins,
00365 trim_edits);
00366 }
00367 }
00368 else
00369 if(edit_mode == MOVE_ONE_EDIT)
00370 {
00371
00372
00373 if(!previous)
00374 {
00375 Edit *new_edit = edits->create_edit();
00376 new_edit->startproject = this->startproject;
00377 new_edit->length = 0;
00378 edits->insert_before(this,
00379 new_edit);
00380 }
00381
00382
00383 end_previous_source = previous->get_source_end(previous->startsource + previous->length + cut_length);
00384 if(end_previous_source > 0 &&
00385 previous->startsource + previous->length + cut_length > end_previous_source)
00386 cut_length = end_previous_source - previous->startsource - previous->length;
00387
00388 if(cut_length < length)
00389 {
00390 startproject += cut_length;
00391 startsource += cut_length;
00392 length -= cut_length;
00393 previous->length += cut_length;
00394
00395 }
00396 else
00397 {
00398 cut_length = length;
00399 previous->length += cut_length;
00400 for(Edit* current_edit = this; current_edit; current_edit = current_edit->next)
00401 {
00402 current_edit->startproject += cut_length;
00403 }
00404 edits->clear_recursive(oldposition + cut_length,
00405 startproject + cut_length,
00406 edit_edits,
00407 edit_labels,
00408 edit_plugins,
00409 trim_edits);
00410 }
00411
00412 }
00413 else
00414 if(edit_mode == MOVE_NO_EDITS)
00415 {
00416 end_source = get_source_end(startsource + length + cut_length);
00417 if(end_source > 0 && startsource + length + cut_length > end_source)
00418 cut_length = end_source - startsource - length;
00419
00420 startsource += cut_length;
00421 }
00422 return 0;
00423 }
00424
00425 int Edit::shift_start_out(int edit_mode,
00426 int64_t newposition,
00427 int64_t oldposition,
00428 int edit_edits,
00429 int edit_labels,
00430 int edit_plugins,
00431 Edits *trim_edits)
00432 {
00433 int64_t cut_length = oldposition - newposition;
00434
00435 if(asset)
00436 {
00437 int64_t end_source = get_source_end(1);
00438
00439
00440 if(end_source > 0 && startsource < cut_length)
00441 {
00442 cut_length = startsource;
00443 }
00444 }
00445
00446 if(edit_mode == MOVE_ALL_EDITS)
00447 {
00448
00449 startsource -= cut_length;
00450 length += cut_length;
00451
00452 edits->shift_keyframes_recursive(startproject,
00453 cut_length);
00454 if(edit_plugins)
00455 edits->shift_effects_recursive(startproject,
00456 cut_length);
00457
00458 for(Edit* current_edit = next; current_edit; current_edit = current_edit->next)
00459 {
00460 current_edit->startproject += cut_length;
00461 }
00462 }
00463 else
00464 if(edit_mode == MOVE_ONE_EDIT)
00465 {
00466 if(previous)
00467 {
00468 if(cut_length < previous->length)
00469 {
00470 previous->length -= cut_length;
00471 startproject -= cut_length;
00472 startsource -= cut_length;
00473 length += cut_length;
00474 printf("Edit::shift_start_out 2\n");
00475 }
00476 else
00477 {
00478 cut_length = previous->length;
00479 previous->length = 0;
00480 length += cut_length;
00481 startsource -= cut_length;
00482 startproject -= cut_length;
00483 }
00484 }
00485 }
00486 else
00487 if(edit_mode == MOVE_NO_EDITS)
00488 {
00489 startsource -= cut_length;
00490 }
00491
00492
00493 if(startsource < 0) startsource = 0;
00494 return 0;
00495 }
00496
00497 int Edit::shift_end_in(int edit_mode,
00498 int64_t newposition,
00499 int64_t oldposition,
00500 int edit_edits,
00501 int edit_labels,
00502 int edit_plugins,
00503 Edits *trim_edits)
00504 {
00505 int64_t cut_length = oldposition - newposition;
00506
00507 if(edit_mode == MOVE_ALL_EDITS)
00508 {
00509
00510 if(newposition > startproject)
00511 {
00512
00513 edits->clear_recursive(newposition,
00514 oldposition,
00515 edit_edits,
00516 edit_labels,
00517 edit_plugins,
00518 trim_edits);
00519 }
00520 else
00521 {
00522 edits->clear_recursive(startproject,
00523 oldposition,
00524 edit_edits,
00525 edit_labels,
00526 edit_plugins,
00527 trim_edits);
00528 }
00529 }
00530 else
00531 if(edit_mode == MOVE_ONE_EDIT)
00532 {
00533 if(next)
00534 {
00535 if(next->asset)
00536 {
00537 int64_t end_source = next->get_source_end(1);
00538
00539 if(end_source > 0 && next->startsource - cut_length < 0)
00540 {
00541 cut_length = next->startsource;
00542 }
00543 }
00544
00545 if(cut_length < length)
00546 {
00547 length -= cut_length;
00548 next->startproject -= cut_length;
00549 next->startsource -= cut_length;
00550 next->length += cut_length;
00551
00552 }
00553 else
00554 {
00555 cut_length = length;
00556 next->length += cut_length;
00557 next->startsource -= cut_length;
00558 next->startproject -= cut_length;
00559 length -= cut_length;
00560 }
00561 }
00562 else
00563 {
00564 if(cut_length < length)
00565 {
00566 length -= cut_length;
00567 }
00568 else
00569 {
00570 cut_length = length;
00571 edits->clear_recursive(startproject,
00572 oldposition,
00573 edit_edits,
00574 edit_labels,
00575 edit_plugins,
00576 trim_edits);
00577 }
00578 }
00579 }
00580 else
00581
00582 if(edit_mode == MOVE_NO_EDITS)
00583 {
00584
00585 int64_t end_source = get_source_end(1);
00586 if(end_source > 0 && startsource < cut_length)
00587 {
00588 cut_length = startsource;
00589 }
00590 startsource -= cut_length;
00591 }
00592 return 0;
00593 }
00594
00595 int Edit::shift_end_out(int edit_mode,
00596 int64_t newposition,
00597 int64_t oldposition,
00598 int edit_edits,
00599 int edit_labels,
00600 int edit_plugins,
00601 Edits *trim_edits)
00602 {
00603 int64_t cut_length = newposition - oldposition;
00604 int64_t endsource = get_source_end(startsource + length + cut_length);
00605
00606
00607 if(endsource > 0 && startsource + length + cut_length > endsource)
00608 cut_length = endsource - startsource - length;
00609
00610
00611 if(edit_mode == MOVE_ALL_EDITS)
00612 {
00613
00614 this->length += cut_length;
00615
00616
00617 if(edit_plugins)
00618 edits->shift_effects_recursive(oldposition ,
00619 cut_length);
00620 edits->shift_keyframes_recursive(oldposition ,
00621 cut_length);
00622
00623 for(Edit* current_edit = next; current_edit; current_edit = current_edit->next)
00624 {
00625 current_edit->startproject += cut_length;
00626 }
00627 }
00628 else
00629 if(edit_mode == MOVE_ONE_EDIT)
00630 {
00631 if(next)
00632 {
00633 if(cut_length < next->length)
00634 {
00635 length += cut_length;
00636 next->startproject += cut_length;
00637 next->startsource += cut_length;
00638 next->length -= cut_length;
00639
00640 }
00641 else
00642 {
00643 cut_length = next->length;
00644 next->length = 0;
00645 length += cut_length;
00646 }
00647 }
00648 else
00649 {
00650 length += cut_length;
00651 }
00652 }
00653 else
00654 if(edit_mode == MOVE_NO_EDITS)
00655 {
00656 startsource += cut_length;
00657 }
00658 return 0;
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
00686
00687
00688
00689 int Edit::popup_transition(float view_start, float zoom_units, int cursor_x, int cursor_y)
00690 {
00691 int64_t left, right, left_unit, right_unit;
00692 if(!transition) return 0;
00693 get_handle_parameters(left, right, left_unit, right_unit, view_start, zoom_units);
00694
00695 if(cursor_x > left && cursor_x < right)
00696 {
00697
00698 return 1;
00699 }
00700 return 0;
00701 }
00702
00703 int Edit::select_handle(float view_start, float zoom_units, int cursor_x, int cursor_y, int64_t &selection)
00704 {
00705 int64_t left, right, left_unit, right_unit;
00706 get_handle_parameters(left, right, left_unit, right_unit, view_start, zoom_units);
00707
00708 int64_t pixel1, pixel2;
00709 pixel1 = left;
00710 pixel2 = pixel1 + 10;
00711
00712
00713
00714 if(cursor_x >= pixel1 && cursor_x <= pixel2)
00715 {
00716 selection = left_unit;
00717 return 1;
00718 }
00719
00720 int64_t endproject = startproject + length;
00721 pixel2 = right;
00722 pixel1 = pixel2 - 10;
00723
00724
00725 if(cursor_x >= pixel1 && cursor_x <= pixel2)
00726 {
00727 selection = right_unit;
00728 return 2;
00729 }
00730 return 0;
00731 }
00732