00001 #include "asset.h"
00002 #include "autoconf.h"
00003 #include "automation.h"
00004 #include "bcsignals.h"
00005 #include "clip.h"
00006 #include "edit.h"
00007 #include "edits.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "filexml.h"
00011 #include "floatauto.h"
00012 #include "floatautos.h"
00013 #include "keyframe.h"
00014 #include "localsession.h"
00015 #include "module.h"
00016 #include "patch.h"
00017 #include "patchbay.h"
00018 #include "plugin.h"
00019 #include "pluginset.h"
00020 #include "mainsession.h"
00021 #include "theme.h"
00022 #include "intautos.h"
00023 #include "track.h"
00024 #include "trackcanvas.h"
00025 #include "tracks.h"
00026 #include "transition.h"
00027 #include "transportque.inc"
00028 #include "vedit.h"
00029 #include "vframe.h"
00030 #include <string.h>
00031
00032
00033 Track::Track(EDL *edl, Tracks *tracks) : ListItem<Track>()
00034 {
00035 this->edl = edl;
00036 this->tracks = tracks;
00037 y_pixel = 0;
00038 expand_view = 0;
00039 draw = 1;
00040 gang = 1;
00041 title[0] = 0;
00042 record = 1;
00043 play = 1;
00044 nudge = 0;
00045 track_w = edl->session->output_w;
00046 track_h = edl->session->output_h;
00047 id = EDL::next_id();
00048 }
00049
00050 Track::~Track()
00051 {
00052 delete automation;
00053 delete edits;
00054 plugin_set.remove_all_objects();
00055 }
00056
00057 int Track::create_objects()
00058 {
00059 return 0;
00060 }
00061
00062
00063 int Track::copy_settings(Track *track)
00064 {
00065 this->expand_view = track->expand_view;
00066 this->draw = track->draw;
00067 this->gang = track->gang;
00068 this->record = track->record;
00069 this->nudge = track->nudge;
00070 this->play = track->play;
00071 this->track_w = track->track_w;
00072 this->track_h = track->track_h;
00073 strcpy(this->title, track->title);
00074 return 0;
00075 }
00076
00077 int Track::get_id()
00078 {
00079 return id;
00080 }
00081
00082
00083 int Track::load_defaults(Defaults *defaults)
00084 {
00085 return 0;
00086 }
00087
00088 void Track::equivalent_output(Track *track, double *result)
00089 {
00090 if(data_type != track->data_type ||
00091 track_w != track->track_w ||
00092 track_h != track->track_h ||
00093 play != track->play ||
00094 nudge != track->nudge)
00095 *result = 0;
00096
00097
00098 int64_t result2 = -1;
00099 automation->equivalent_output(track->automation, &result2);
00100 edits->equivalent_output(track->edits, &result2);
00101
00102 int plugin_sets = MIN(plugin_set.total, track->plugin_set.total);
00103
00104 for(int i = 0; i < plugin_sets; i++)
00105 {
00106 plugin_set.values[i]->equivalent_output(
00107 track->plugin_set.values[i],
00108 &result2);
00109 }
00110
00111
00112 for(int i = plugin_sets; i < plugin_set.total; i++)
00113 {
00114 Plugin *current = plugin_set.values[i]->get_first_plugin();
00115 if(current)
00116 {
00117 if(result2 < 0 || current->startproject < result2)
00118 result2 = current->startproject;
00119 }
00120 }
00121
00122
00123 for(int i = plugin_sets; i < track->plugin_set.total; i++)
00124 {
00125 Plugin *current = track->plugin_set.values[i]->get_first_plugin();
00126 if(current)
00127 {
00128 if(result2 < 0 || current->startproject < result2)
00129 result2 = current->startproject;
00130 }
00131 }
00132
00133
00134
00135 if(track->plugin_set.total != plugin_set.total && result2 < 0)
00136 result2 = 0;
00137
00138 if(result2 >= 0 &&
00139 (*result < 0 || from_units(result2) < *result))
00140 *result = from_units(result2);
00141 }
00142
00143
00144 int Track::is_synthesis(RenderEngine *renderengine,
00145 int64_t position,
00146 int direction)
00147 {
00148 int is_synthesis = 0;
00149 for(int i = 0; i < plugin_set.total; i++)
00150 {
00151 Plugin *plugin = get_current_plugin(position,
00152 i,
00153 direction,
00154 0,
00155 0);
00156 if(plugin)
00157 {
00158 is_synthesis = plugin->is_synthesis(renderengine,
00159 position,
00160 direction);
00161 if(is_synthesis) break;
00162 }
00163 }
00164 return is_synthesis;
00165 }
00166
00167 void Track::copy_from(Track *track)
00168 {
00169 copy_settings(track);
00170 edits->copy_from(track->edits);
00171 for(int i = 0; i < this->plugin_set.total; i++)
00172 delete this->plugin_set.values[i];
00173 this->plugin_set.remove_all_objects();
00174
00175 for(int i = 0; i < track->plugin_set.total; i++)
00176 {
00177 PluginSet *new_plugin_set = plugin_set.append(new PluginSet(edl, this));
00178 new_plugin_set->copy_from(track->plugin_set.values[i]);
00179 }
00180 automation->copy_from(track->automation);
00181 this->track_w = track->track_w;
00182 this->track_h = track->track_h;
00183 }
00184
00185 Track& Track::operator=(Track& track)
00186 {
00187 printf("Track::operator= 1\n");
00188 copy_from(&track);
00189 return *this;
00190 }
00191
00192 int Track::vertical_span(Theme *theme)
00193 {
00194 int result = 0;
00195 if(expand_view)
00196 result = edl->local_session->zoom_track +
00197 plugin_set.total *
00198 theme->plugin_bg_data->get_h();
00199 else
00200 result = edl->local_session->zoom_track;
00201
00202 if(edl->session->show_titles)
00203 result += theme->title_bg_data->get_h();
00204
00205 return result;
00206 }
00207
00208 double Track::get_length()
00209 {
00210 double total_length = 0;
00211 double length = 0;
00212
00213
00214 if(edits->last)
00215 {
00216 length = from_units(edits->last->startproject + edits->last->length);
00217 if(length > total_length) total_length = length;
00218 }
00219
00220
00221 for(int i = 0; i < plugin_set.total; i++)
00222 {
00223 if(plugin_set.values[i]->last)
00224 {
00225 length = from_units(plugin_set.values[i]->last->startproject +
00226 plugin_set.values[i]->last->length);
00227 if(length > total_length) total_length = length;
00228 }
00229 }
00230
00231
00232 length = from_units(automation->get_length());
00233 if(length > total_length) total_length = length;
00234
00235
00236 return total_length;
00237 }
00238
00239
00240
00241 void Track::get_source_dimensions(double position, int &w, int &h)
00242 {
00243 int64_t native_position = to_units(position, 0);
00244 for(Edit *current = edits->first; current; current = NEXT)
00245 {
00246 if(current->startproject <= native_position &&
00247 current->startproject + current->length > native_position &&
00248 current->asset)
00249 {
00250 w = current->asset->width;
00251 h = current->asset->height;
00252 return;
00253 }
00254 }
00255 }
00256
00257
00258 int64_t Track::horizontal_span()
00259 {
00260 return (int64_t)(get_length() *
00261 edl->session->sample_rate /
00262 edl->local_session->zoom_sample +
00263 0.5);
00264 }
00265
00266
00267 int Track::load(FileXML *file, int track_offset, uint32_t load_flags)
00268 {
00269 int result = 0;
00270 int current_channel = 0;
00271 int current_plugin = 0;
00272
00273
00274 record = file->tag.get_property("RECORD", record);
00275 play = file->tag.get_property("PLAY", play);
00276 gang = file->tag.get_property("GANG", gang);
00277 draw = file->tag.get_property("DRAW", draw);
00278 nudge = file->tag.get_property("NUDGE", nudge);
00279 expand_view = file->tag.get_property("EXPAND", expand_view);
00280 track_w = file->tag.get_property("TRACK_W", track_w);
00281 track_h = file->tag.get_property("TRACK_H", track_h);
00282
00283 load_header(file, load_flags);
00284
00285 do{
00286 result = file->read_tag();
00287
00288 if(!result)
00289 {
00290 if(file->tag.title_is("/TRACK"))
00291 {
00292 result = 1;
00293 }
00294 else
00295 if(file->tag.title_is("TITLE"))
00296 {
00297 file->read_text_until("/TITLE", title, BCTEXTLEN);
00298 }
00299 else
00300 if(load_flags && automation->load(file)
00301 )
00302 {
00303 ;
00304 }
00305 else
00306 if(file->tag.title_is("EDITS"))
00307 {
00308 if(load_flags & LOAD_EDITS)
00309 edits->load(file, track_offset);
00310 }
00311 else
00312 if(file->tag.title_is("PLUGINSET"))
00313 {
00314 if(load_flags & LOAD_EDITS)
00315 {
00316 PluginSet *plugin_set = new PluginSet(edl, this);
00317 this->plugin_set.append(plugin_set);
00318 plugin_set->load(file, load_flags);
00319 }
00320 else
00321 if(load_flags & LOAD_AUTOMATION)
00322 {
00323 if(current_plugin < this->plugin_set.total)
00324 {
00325 PluginSet *plugin_set = this->plugin_set.values[current_plugin];
00326 plugin_set->load(file, load_flags);
00327 current_plugin++;
00328 }
00329 }
00330 }
00331 else
00332 load_derived(file, load_flags);
00333 }
00334 }while(!result);
00335
00336
00337
00338 return 0;
00339 }
00340
00341 void Track::insert_asset(Asset *asset,
00342 double length,
00343 double position,
00344 int track_number)
00345 {
00346
00347 edits->insert_asset(asset,
00348 to_units(length, 1),
00349 to_units(position, 0),
00350 track_number);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 void Track::insert_track(Track *track,
00368 double position,
00369 int replace_default,
00370 int edit_plugins)
00371 {
00372 SET_TRACE
00373
00374 if(replace_default) copy_settings(track);
00375
00376 edits->insert_edits(track->edits, to_units(position, 0));
00377
00378 if(edit_plugins)
00379 insert_plugin_set(track, position);
00380
00381 automation->insert_track(track->automation,
00382 to_units(position, 0),
00383 to_units(track->get_length(), 1),
00384 replace_default);
00385
00386 optimize();
00387 SET_TRACE
00388 }
00389
00390
00391 void Track::insert_plugin_set(Track *track, double position)
00392 {
00393
00394 if(!track->plugin_set.total)
00395 {
00396 shift_effects(position,
00397 track->get_length(),
00398 1);
00399 }
00400 else
00401 for(int i = 0; i < track->plugin_set.total; i++)
00402 {
00403 if(i >= plugin_set.total)
00404 plugin_set.append(new PluginSet(edl, this));
00405
00406 plugin_set.values[i]->insert_edits(track->plugin_set.values[i],
00407 to_units(position, 0));
00408 }
00409 }
00410
00411
00412 Plugin* Track::insert_effect(char *title,
00413 SharedLocation *shared_location,
00414 KeyFrame *default_keyframe,
00415 PluginSet *plugin_set,
00416 double start,
00417 double length,
00418 int plugin_type)
00419 {
00420 if(!plugin_set)
00421 {
00422 plugin_set = new PluginSet(edl, this);
00423 this->plugin_set.append(plugin_set);
00424 }
00425
00426 Plugin *plugin = 0;
00427
00428
00429 if(plugin_type == PLUGIN_SHAREDPLUGIN)
00430 {
00431 Track *source_track = tracks->get_item_number(shared_location->module);
00432 if(source_track)
00433 {
00434 Plugin *source_plugin = source_track->get_current_plugin(
00435 edl->local_session->get_selectionstart(),
00436 shared_location->plugin,
00437 PLAY_FORWARD,
00438 1,
00439 0);
00440
00441
00442 if(source_plugin)
00443 {
00444 plugin = plugin_set->insert_plugin(title,
00445 source_plugin->startproject,
00446 source_plugin->length,
00447 plugin_type,
00448 shared_location,
00449 default_keyframe,
00450 1);
00451 }
00452 else
00453
00454 {
00455 plugin = plugin_set->insert_plugin(title,
00456 to_units(start, 0),
00457 to_units(length, 0),
00458 plugin_type,
00459 shared_location,
00460 default_keyframe,
00461 1);
00462 }
00463 }
00464 }
00465 else
00466 {
00467
00468 if(EQUIV(length, 0))
00469 {
00470 if(edl->local_session->get_selectionend() >
00471 edl->local_session->get_selectionstart())
00472 {
00473 start = edl->local_session->get_selectionstart();
00474 length = edl->local_session->get_selectionend() - start;
00475 }
00476 else
00477 {
00478 start = 0;
00479 length = get_length();
00480 }
00481 }
00482
00483
00484
00485 plugin = plugin_set->insert_plugin(title,
00486 to_units(start, 0),
00487 to_units(length, 0),
00488 plugin_type,
00489 shared_location,
00490 default_keyframe,
00491 1);
00492 }
00493
00494
00495 expand_view = 1;
00496 return plugin;
00497 }
00498
00499 void Track::move_plugins_up(PluginSet *plugin_set)
00500 {
00501 for(int i = 0; i < this->plugin_set.total; i++)
00502 {
00503 if(this->plugin_set.values[i] == plugin_set)
00504 {
00505 if(i == 0) break;
00506
00507 PluginSet *temp = this->plugin_set.values[i - 1];
00508 this->plugin_set.values[i - 1] = this->plugin_set.values[i];
00509 this->plugin_set.values[i] = temp;
00510
00511 SharedLocation old_location, new_location;
00512 new_location.module = old_location.module = tracks->number_of(this);
00513 old_location.plugin = i;
00514 new_location.plugin = i - 1;
00515 tracks->change_plugins(old_location, new_location, 1);
00516 break;
00517 }
00518 }
00519 }
00520
00521 void Track::move_plugins_down(PluginSet *plugin_set)
00522 {
00523 for(int i = 0; i < this->plugin_set.total; i++)
00524 {
00525 if(this->plugin_set.values[i] == plugin_set)
00526 {
00527 if(i == this->plugin_set.total - 1) break;
00528
00529 PluginSet *temp = this->plugin_set.values[i + 1];
00530 this->plugin_set.values[i + 1] = this->plugin_set.values[i];
00531 this->plugin_set.values[i] = temp;
00532
00533 SharedLocation old_location, new_location;
00534 new_location.module = old_location.module = tracks->number_of(this);
00535 old_location.plugin = i;
00536 new_location.plugin = i + 1;
00537 tracks->change_plugins(old_location, new_location, 1);
00538 break;
00539 }
00540 }
00541 }
00542
00543
00544 void Track::remove_asset(Asset *asset)
00545 {
00546 for(Edit *edit = edits->first; edit; edit = edit->next)
00547 {
00548 if(edit->asset && edit->asset == asset)
00549 {
00550 edit->asset = 0;
00551 }
00552 }
00553 optimize();
00554 }
00555
00556 void Track::remove_pluginset(PluginSet *plugin_set)
00557 {
00558 int i;
00559 for(i = 0; i < this->plugin_set.total; i++)
00560 if(plugin_set == this->plugin_set.values[i]) break;
00561
00562 this->plugin_set.remove_object(plugin_set);
00563 for(i++ ; i < this->plugin_set.total; i++)
00564 {
00565 SharedLocation old_location, new_location;
00566 new_location.module = old_location.module = tracks->number_of(this);
00567 old_location.plugin = i;
00568 new_location.plugin = i - 1;
00569 tracks->change_plugins(old_location, new_location, 0);
00570 }
00571 }
00572
00573 void Track::shift_keyframes(double position, double length, int convert_units)
00574 {
00575 if(convert_units)
00576 {
00577 position = to_units(position, 0);
00578 length = to_units(length, 0);
00579 }
00580
00581 automation->paste_silence(Units::to_int64(position),
00582 Units::to_int64(position + length));
00583
00584 }
00585
00586 void Track::shift_effects(double position, double length, int convert_units)
00587 {
00588 if(convert_units)
00589 {
00590 position = to_units(position, 0);
00591 length = to_units(length, 0);
00592 }
00593
00594 for(int i = 0; i < plugin_set.total; i++)
00595 {
00596 plugin_set.values[i]->shift_effects(Units::to_int64(position), Units::to_int64(length));
00597 }
00598 }
00599
00600 void Track::detach_effect(Plugin *plugin)
00601 {
00602
00603 for(int i = 0; i < plugin_set.total; i++)
00604 {
00605 PluginSet *plugin_set = this->plugin_set.values[i];
00606 for(Plugin *dest = (Plugin*)plugin_set->first;
00607 dest;
00608 dest = (Plugin*)dest->next)
00609 {
00610 if(dest == plugin)
00611 {
00612 int64_t start = plugin->startproject;
00613 int64_t end = plugin->startproject + plugin->length;
00614
00615 plugin_set->clear(start, end);
00616 plugin_set->paste_silence(start, end);
00617
00618
00619 plugin_set->optimize();
00620
00621 if(!plugin_set->length())
00622 this->plugin_set.remove_object(plugin_set);
00623
00624 return;
00625 }
00626 }
00627 }
00628 }
00629
00630 void Track::resample(double old_rate, double new_rate)
00631 {
00632 edits->resample(old_rate, new_rate);
00633 automation->resample(old_rate, new_rate);
00634 for(int i = 0; i < plugin_set.total; i++)
00635 plugin_set.values[i]->resample(old_rate, new_rate);
00636 nudge = (int64_t)(nudge * new_rate / old_rate);
00637 }
00638
00639 void Track::detach_shared_effects(int module)
00640 {
00641 for(int i = 0; i < plugin_set.total; i++)
00642 {
00643 PluginSet *plugin_set = this->plugin_set.values[i];
00644 for(Plugin *dest = (Plugin*)plugin_set->first;
00645 dest;
00646 dest = (Plugin*)dest->next)
00647 {
00648 if ((dest->plugin_type == PLUGIN_SHAREDPLUGIN ||
00649 dest->plugin_type == PLUGIN_SHAREDMODULE)
00650 &&
00651 dest->shared_location.module == module)
00652 {
00653 int64_t start = dest->startproject;
00654 int64_t end = dest->startproject + dest->length;
00655
00656 plugin_set->clear(start, end);
00657 plugin_set->paste_silence(start, end);
00658
00659
00660 plugin_set->optimize();
00661 if(!plugin_set->length())
00662 {
00663 this->plugin_set.remove_object_number(i);
00664 --i;
00665 }
00666 }
00667 }
00668 }
00669 }
00670
00671
00672 void Track::optimize()
00673 {
00674 edits->optimize();
00675 for(int i = 0; i < plugin_set.total; i++)
00676 {
00677 plugin_set.values[i]->optimize();
00678
00679 if(plugin_set.values[i]->total() <= 0)
00680 {
00681 remove_pluginset(plugin_set.values[i]);
00682 i--;
00683 }
00684 }
00685 }
00686
00687 Plugin* Track::get_current_plugin(double position,
00688 int plugin_set,
00689 int direction,
00690 int convert_units,
00691 int use_nudge)
00692 {
00693 Plugin *current;
00694 if(convert_units) position = to_units(position, 0);
00695 if(use_nudge) position += nudge;
00696
00697 if(plugin_set >= this->plugin_set.total || plugin_set < 0) return 0;
00698
00699
00700 if(direction == PLAY_FORWARD)
00701 {
00702 for(current = (Plugin*)this->plugin_set.values[plugin_set]->last;
00703 current;
00704 current = (Plugin*)PREVIOUS)
00705 {
00706
00707
00708
00709
00710 if(current->startproject <= position &&
00711 current->startproject + current->length > position)
00712 {
00713 return current;
00714 }
00715 }
00716 }
00717 else
00718 if(direction == PLAY_REVERSE)
00719 {
00720 for(current = (Plugin*)this->plugin_set.values[plugin_set]->first;
00721 current;
00722 current = (Plugin*)NEXT)
00723 {
00724 if(current->startproject < position &&
00725 current->startproject + current->length >= position)
00726 {
00727 return current;
00728 }
00729 }
00730 }
00731
00732 return 0;
00733 }
00734
00735 Plugin* Track::get_current_transition(double position,
00736 int direction,
00737 int convert_units,
00738 int use_nudge)
00739 {
00740 Edit *current;
00741 Plugin *result = 0;
00742 if(convert_units) position = to_units(position, 0);
00743 if(use_nudge) position += nudge;
00744
00745 if(direction == PLAY_FORWARD)
00746 {
00747 for(current = edits->last; current; current = PREVIOUS)
00748 {
00749 if(current->startproject <= position && current->startproject + current->length > position)
00750 {
00751
00752 if(current->transition && position < current->startproject + current->transition->length)
00753 {
00754 result = current->transition;
00755 break;
00756 }
00757 }
00758 }
00759 }
00760 else
00761 if(direction == PLAY_REVERSE)
00762 {
00763 for(current = edits->first; current; current = NEXT)
00764 {
00765 if(current->startproject < position && current->startproject + current->length >= position)
00766 {
00767 if(current->transition && position <= current->startproject + current->transition->length)
00768 {
00769 result = current->transition;
00770 break;
00771 }
00772 }
00773 }
00774 }
00775
00776 return result;
00777 }
00778
00779 void Track::synchronize_params(Track *track)
00780 {
00781 for(Edit *this_edit = edits->first, *that_edit = track->edits->first;
00782 this_edit && that_edit;
00783 this_edit = this_edit->next, that_edit = that_edit->next)
00784 {
00785 this_edit->synchronize_params(that_edit);
00786 }
00787
00788 for(int i = 0; i < plugin_set.total && i < track->plugin_set.total; i++)
00789 plugin_set.values[i]->synchronize_params(track->plugin_set.values[i]);
00790
00791 automation->copy_from(track->automation);
00792 this->nudge = track->nudge;
00793 }
00794
00795
00796
00797
00798
00799 int Track::dump()
00800 {
00801 printf(" Data type %d\n", data_type);
00802 printf(" Title %s\n", title);
00803 printf(" Edits:\n");
00804 for(Edit* current = edits->first; current; current = NEXT)
00805 {
00806 current->dump();
00807 }
00808 automation->dump();
00809 printf(" Plugin Sets: %d\n", plugin_set.total);
00810
00811 for(int i = 0; i < plugin_set.total; i++)
00812 plugin_set.values[i]->dump();
00813
00814 return 0;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 Track::Track() : ListItem<Track>()
00838 {
00839 y_pixel = 0;
00840 }
00841
00842
00843
00844 int Track::number_of()
00845 {
00846 return tracks->number_of(this);
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 int Track::select_auto(AutoConf *auto_conf, int cursor_x, int cursor_y)
00864 {
00865 return 0;
00866 }
00867
00868 int Track::move_auto(AutoConf *auto_conf, int cursor_x, int cursor_y, int shift_down)
00869 {
00870 return 0;
00871 }
00872
00873 int Track::release_auto()
00874 {
00875 return 0;
00876 }
00877
00878
00879 int Track::copy_automation(double selectionstart,
00880 double selectionend,
00881 FileXML *file,
00882 int default_only,
00883 int autos_only)
00884 {
00885 int64_t start = to_units(selectionstart, 0);
00886 int64_t end = to_units(selectionend, 0);
00887
00888 file->tag.set_title("TRACK");
00889
00890 save_header(file);
00891 file->append_tag();
00892 file->append_newline();
00893
00894 automation->copy(start, end, file, default_only, autos_only);
00895
00896 if(edl->session->auto_conf->plugins)
00897 {
00898 file->tag.set_title("PLUGINSETS");
00899 file->append_tag();
00900 file->append_newline();
00901 for(int i = 0; i < plugin_set.total; i++)
00902 {
00903
00904 plugin_set.values[i]->copy_keyframes(start,
00905 end,
00906 file,
00907 default_only,
00908 autos_only);
00909 }
00910 file->tag.set_title("/PLUGINSETS");
00911 file->append_tag();
00912 file->append_newline();
00913 }
00914
00915 file->tag.set_title("/TRACK");
00916 file->append_tag();
00917 file->append_newline();
00918 file->append_newline();
00919 file->append_newline();
00920 file->append_newline();
00921
00922 return 0;
00923 }
00924
00925 int Track::paste_automation(double selectionstart,
00926 double total_length,
00927 double frame_rate,
00928 int64_t sample_rate,
00929 FileXML *file,
00930 int default_only)
00931 {
00932
00933 int64_t start;
00934 int64_t length;
00935 int result;
00936 double scale;
00937
00938 if(data_type == TRACK_AUDIO)
00939 scale = edl->session->sample_rate / sample_rate;
00940 else
00941 scale = edl->session->frame_rate / frame_rate;
00942
00943 total_length *= scale;
00944 start = to_units(selectionstart, 0);
00945 length = to_units(total_length, 0);
00946 result = 0;
00947
00948
00949 while(!result)
00950 {
00951 result = file->read_tag();
00952
00953 if(!result)
00954 {
00955 if(file->tag.title_is("/TRACK"))
00956 result = 1;
00957 else
00958 if(automation->paste(start,
00959 length,
00960 scale,
00961 file,
00962 default_only,
00963 0))
00964
00965 {
00966 ;
00967 }
00968 else
00969 if(file->tag.title_is("PLUGINSETS"))
00970 {
00971
00972 PluginSet::paste_keyframes(start,
00973 length,
00974 file,
00975 default_only,
00976 this);
00977 }
00978 }
00979 }
00980
00981
00982
00983 return 0;
00984 }
00985
00986 void Track::clear_automation(double selectionstart,
00987 double selectionend,
00988 int shift_autos,
00989 int default_only)
00990 {
00991 int64_t start = to_units(selectionstart, 0);
00992 int64_t end = to_units(selectionend, 0);
00993
00994 automation->clear(start, end, edl->session->auto_conf, 0);
00995
00996 if(edl->session->auto_conf->plugins)
00997 {
00998 for(int i = 0; i < plugin_set.total; i++)
00999 {
01000 plugin_set.values[i]->clear_keyframes(start, end);
01001 }
01002 }
01003
01004 }
01005
01006
01007 int Track::copy(double start,
01008 double end,
01009 FileXML *file,
01010 char *output_path)
01011 {
01012
01013
01014 int64_t start_unit = to_units(start, 0);
01015 int64_t end_unit = to_units(end, 1);
01016
01017
01018
01019
01020 file->tag.set_title("TRACK");
01021 file->tag.set_property("RECORD", record);
01022 file->tag.set_property("NUDGE", nudge);
01023 file->tag.set_property("PLAY", play);
01024 file->tag.set_property("GANG", gang);
01025 file->tag.set_property("DRAW", draw);
01026 file->tag.set_property("EXPAND", expand_view);
01027 file->tag.set_property("TRACK_W", track_w);
01028 file->tag.set_property("TRACK_H", track_h);
01029 save_header(file);
01030 file->append_tag();
01031 file->append_newline();
01032 save_derived(file);
01033
01034 file->tag.set_title("TITLE");
01035 file->append_tag();
01036 file->append_text(title);
01037 file->tag.set_title("/TITLE");
01038 file->append_tag();
01039 file->append_newline();
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 edits->copy(start_unit, end_unit, file, output_path);
01050
01051 AutoConf auto_conf;
01052 auto_conf.set_all();
01053 automation->copy(start_unit, end_unit, file, 0, 0);
01054
01055
01056 for(int i = 0; i < plugin_set.total; i++)
01057 {
01058 plugin_set.values[i]->copy(start_unit, end_unit, file);
01059 }
01060
01061 copy_derived(start_unit, end_unit, file);
01062
01063 file->tag.set_title("/TRACK");
01064 file->append_tag();
01065 file->append_newline();
01066 file->append_newline();
01067 file->append_newline();
01068 file->append_newline();
01069
01070 return 0;
01071 }
01072
01073 int Track::copy_assets(double start,
01074 double end,
01075 ArrayList<Asset*> *asset_list)
01076 {
01077 int i, result = 0;
01078
01079 start = to_units(start, 0);
01080 end = to_units(end, 0);
01081
01082 Edit *current = edits->editof((int64_t)start, PLAY_FORWARD, 0);
01083
01084
01085 while(current && current->startproject < end)
01086 {
01087
01088 if(current->asset)
01089 {
01090 for(i = 0, result = 0; i < asset_list->total; i++)
01091 {
01092 if(asset_list->values[i] == current->asset) result = 1;
01093 }
01094
01095 if(!result) asset_list->append(current->asset);
01096 }
01097
01098 current = NEXT;
01099 }
01100
01101 return 0;
01102 }
01103
01104
01105
01106
01107
01108 int Track::clear(double start,
01109 double end,
01110 int edit_edits,
01111 int edit_labels,
01112 int edit_plugins,
01113 int convert_units,
01114 Edits *trim_edits)
01115 {
01116
01117
01118
01119 if(convert_units)
01120 {
01121 start = to_units(start, 0);
01122 end = to_units(end, 0);
01123 }
01124
01125 if(edit_edits)
01126 automation->clear((int64_t)start, (int64_t)end, 0, 1);
01127
01128 if(edit_plugins)
01129 for(int i = 0; i < plugin_set.total; i++)
01130 {
01131 if(!trim_edits || trim_edits == (Edits*)plugin_set.values[i])
01132 plugin_set.values[i]->clear((int64_t)start, (int64_t)end);
01133 }
01134
01135 if(edit_edits)
01136 edits->clear((int64_t)start, (int64_t)end);
01137 return 0;
01138 }
01139
01140 int Track::clear_handle(double start,
01141 double end,
01142 int clear_labels,
01143 int clear_plugins,
01144 double &distance)
01145 {
01146 edits->clear_handle(start, end, clear_plugins, distance);
01147 }
01148
01149 int Track::popup_transition(int cursor_x, int cursor_y)
01150 {
01151 return 0;
01152 }
01153
01154
01155
01156 int Track::modify_edithandles(double oldposition,
01157 double newposition,
01158 int currentend,
01159 int handle_mode,
01160 int edit_labels,
01161 int edit_plugins)
01162 {
01163 edits->modify_handles(oldposition,
01164 newposition,
01165 currentend,
01166 handle_mode,
01167 1,
01168 edit_labels,
01169 edit_plugins,
01170 0);
01171
01172
01173 return 0;
01174 }
01175
01176 int Track::modify_pluginhandles(double oldposition,
01177 double newposition,
01178 int currentend,
01179 int handle_mode,
01180 int edit_labels,
01181 Edits *trim_edits)
01182 {
01183 for(int i = 0; i < plugin_set.total; i++)
01184 {
01185 if(!trim_edits || trim_edits == (Edits*)plugin_set.values[i])
01186 plugin_set.values[i]->modify_handles(oldposition,
01187 newposition,
01188 currentend,
01189 handle_mode,
01190
01191 0,
01192 edit_labels,
01193 1,
01194 trim_edits);
01195 }
01196 return 0;
01197 }
01198
01199
01200 int Track::paste_silence(double start, double end, int edit_plugins)
01201 {
01202 start = to_units(start, 0);
01203 end = to_units(end, 1);
01204
01205 edits->paste_silence((int64_t)start, (int64_t)end);
01206 shift_keyframes(start, end - start, 0);
01207 if(edit_plugins) shift_effects(start, end - start, 0);
01208
01209 edits->optimize();
01210 return 0;
01211 }
01212
01213 int Track::select_edit(int cursor_x,
01214 int cursor_y,
01215 double &new_start,
01216 double &new_end)
01217 {
01218 return 0;
01219 }
01220
01221 int Track::scale_time(float rate_scale, int scale_edits, int scale_autos, int64_t start, int64_t end)
01222 {
01223 return 0;
01224 }
01225
01226 void Track::change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap)
01227 {
01228 for(int i = 0; i < plugin_set.total; i++)
01229 {
01230 for(Plugin *plugin = (Plugin*)plugin_set.values[i]->first;
01231 plugin;
01232 plugin = (Plugin*)plugin->next)
01233 {
01234 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
01235 {
01236 if(plugin->shared_location == old_location)
01237 plugin->shared_location = new_location;
01238 else
01239 if(do_swap && plugin->shared_location == new_location)
01240 plugin->shared_location = old_location;
01241 }
01242 }
01243 }
01244 }
01245
01246 void Track::change_modules(int old_location, int new_location, int do_swap)
01247 {
01248 for(int i = 0; i < plugin_set.total; i++)
01249 {
01250 for(Plugin *plugin = (Plugin*)plugin_set.values[i]->first;
01251 plugin;
01252 plugin = (Plugin*)plugin->next)
01253 {
01254 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
01255 plugin->plugin_type == PLUGIN_SHAREDMODULE)
01256 {
01257 if(plugin->shared_location.module == old_location)
01258 plugin->shared_location.module = new_location;
01259 else
01260 if(do_swap && plugin->shared_location.module == new_location)
01261 plugin->shared_location.module = old_location;
01262 }
01263 }
01264 }
01265 }
01266
01267
01268 int Track::playable_edit(int64_t position, int direction)
01269 {
01270 int result = 0;
01271 if(direction == PLAY_REVERSE) position--;
01272 for(Edit *current = edits->first; current && !result; current = NEXT)
01273 {
01274 if(current->startproject <= position &&
01275 current->startproject + current->length > position)
01276 {
01277
01278 if(current->transition || current->asset) result = 1;
01279 }
01280 }
01281 return result;
01282 }
01283
01284
01285 int Track::need_edit(Edit *current, int test_transitions)
01286 {
01287 return ((test_transitions && current->transition) ||
01288 (!test_transitions && current->asset));
01289 }
01290
01291 int64_t Track::plugin_change_duration(int64_t input_position,
01292 int64_t input_length,
01293 int reverse,
01294 int use_nudge)
01295 {
01296 if(use_nudge) input_position += nudge;
01297 for(int i = 0; i < plugin_set.total; i++)
01298 {
01299 int64_t new_duration = plugin_set.values[i]->plugin_change_duration(
01300 input_position,
01301 input_length,
01302 reverse);
01303 if(new_duration < input_length) input_length = new_duration;
01304 }
01305 return input_length;
01306 }
01307
01308 int64_t Track::edit_change_duration(int64_t input_position,
01309 int64_t input_length,
01310 int reverse,
01311 int test_transitions,
01312 int use_nudge)
01313 {
01314 Edit *current;
01315 int64_t edit_length = input_length;
01316 if(use_nudge) input_position += nudge;
01317
01318 if(reverse)
01319 {
01320
01321
01322 for(current = edits->first;
01323 current && current->startproject + current->length <= input_position;
01324 current = NEXT)
01325 ;
01326
01327 if(current)
01328 {
01329 if(current->startproject > input_position)
01330 {
01331
01332 ;
01333 }
01334 else
01335 if(need_edit(current, test_transitions))
01336 {
01337
01338 if(input_position - current->startproject < input_length)
01339 edit_length = input_position - current->startproject + 1;
01340 }
01341 else
01342 {
01343
01344
01345 for(current = PREVIOUS ;
01346 current &&
01347 current->startproject + current->length > input_position - input_length &&
01348 !need_edit(current, test_transitions);
01349 current = PREVIOUS)
01350 ;
01351
01352 if(current &&
01353 need_edit(current, test_transitions) &&
01354 current->startproject + current->length > input_position - input_length)
01355 edit_length = input_position - current->startproject - current->length + 1;
01356 }
01357 }
01358 else
01359 {
01360
01361 current = edits->last;
01362 if(current &&
01363 ((test_transitions && current->transition) ||
01364 (!test_transitions && current->asset)))
01365 edit_length = input_position - edits->last->startproject - edits->last->length + 1;
01366 }
01367 }
01368 else
01369 {
01370
01371
01372 for(current = edits->last;
01373 current && current->startproject > input_position;
01374 current = PREVIOUS)
01375 ;
01376
01377 if(current)
01378 {
01379 if(current->startproject + current->length <= input_position)
01380 {
01381
01382 ;
01383 }
01384 else
01385 if(need_edit(current, test_transitions))
01386 {
01387
01388
01389 if(current->length + current->startproject - input_position < input_length)
01390 edit_length = current->startproject + current->length - input_position;
01391 }
01392 else
01393 {
01394
01395
01396 for(current = NEXT ;
01397 current &&
01398 current->startproject < input_position + input_length &&
01399 !need_edit(current, test_transitions);
01400 current = NEXT)
01401 ;
01402
01403 if(current &&
01404 need_edit(current, test_transitions) &&
01405 current->startproject < input_position + input_length)
01406 edit_length = current->startproject - input_position;
01407 }
01408 }
01409 else
01410 {
01411
01412 current = edits->first;
01413 if(current &&
01414 ((test_transitions && current->transition) ||
01415 (!test_transitions && current->asset)))
01416 edit_length = edits->first->startproject - input_position;
01417 }
01418 }
01419
01420 if(edit_length < input_length)
01421 return edit_length;
01422 else
01423 return input_length;
01424 }
01425
01426 int Track::purge_asset(Asset *asset)
01427 {
01428 return 0;
01429 }
01430
01431 int Track::asset_used(Asset *asset)
01432 {
01433 Edit* current_edit;
01434 int result = 0;
01435
01436 for(current_edit = edits->first; current_edit; current_edit = current_edit->next)
01437 {
01438 if(current_edit->asset == asset)
01439 {
01440 result++;
01441 }
01442 }
01443 return result;
01444 }
01445
01446 int Track::channel_is_playable(int64_t position, int direction, int *do_channel)
01447 {
01448 return 1;
01449 }
01450
01451
01452 int Track::plugin_used(int64_t position, int64_t direction)
01453 {
01454
01455 for(int i = 0; i < this->plugin_set.total; i++)
01456 {
01457 Plugin *current_plugin = get_current_plugin(position,
01458 i,
01459 direction,
01460 0,
01461 0);
01462
01463
01464 if(current_plugin &&
01465 (current_plugin->on &&
01466 current_plugin->plugin_type != PLUGIN_NONE))
01467 {
01468 return 1;
01469 }
01470 }
01471
01472 return 0;
01473 }
01474
01475
01476 int Track::direct_copy_possible(int64_t start, int direction, int use_nudge)
01477 {
01478 return 1;
01479 }
01480
01481 int64_t Track::to_units(double position, int round)
01482 {
01483 return (int64_t)position;
01484 }
01485
01486 double Track::to_doubleunits(double position)
01487 {
01488 return position;
01489 }
01490
01491 double Track::from_units(int64_t position)
01492 {
01493 return (double)position;
01494 }