• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files

hvirtual/cinelerra/track.C

Go to the documentation of this file.
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(BC_Hash *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 // Convert result to track units
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 // Test existing plugin sets
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 // New EDL has more plugin sets.  Get starting plugin in new plugin sets
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 // New EDL has fewer plugin sets.  Get starting plugin in old plugin set
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 // Number of plugin sets differs but somehow we didn't find the start of the
00134 // change.  Assume 0
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 // Assume data from a shared track is synthesized
00159                         if(plugin->plugin_type == PLUGIN_SHAREDMODULE) 
00160                                 is_synthesis = 1;
00161                         else
00162                                 is_synthesis = plugin->is_synthesis(renderengine, 
00163                                         position, 
00164                                         direction);
00165                         if(is_synthesis) break;
00166                 }
00167         }
00168         return is_synthesis;
00169 }
00170 
00171 void Track::copy_from(Track *track)
00172 {
00173         copy_settings(track);
00174         edits->copy_from(track->edits);
00175         for(int i = 0; i < this->plugin_set.total; i++)
00176                 delete this->plugin_set.values[i];
00177         this->plugin_set.remove_all_objects();
00178 
00179         for(int i = 0; i < track->plugin_set.total; i++)
00180         {
00181                 PluginSet *new_plugin_set = plugin_set.append(new PluginSet(edl, this));
00182                 new_plugin_set->copy_from(track->plugin_set.values[i]);
00183         }
00184         automation->copy_from(track->automation);
00185         this->track_w = track->track_w;
00186         this->track_h = track->track_h;
00187 }
00188 
00189 Track& Track::operator=(Track& track)
00190 {
00191 printf("Track::operator= 1\n");
00192         copy_from(&track);
00193         return *this;
00194 }
00195 
00196 int Track::vertical_span(Theme *theme)
00197 {
00198         int result = 0;
00199         if(expand_view)
00200                 result = edl->local_session->zoom_track + 
00201                         plugin_set.total * 
00202                         theme->get_image("plugin_bg_data")->get_h();
00203         else
00204                 result = edl->local_session->zoom_track;
00205 
00206         if(edl->session->show_titles)
00207                 result += theme->get_image("title_bg_data")->get_h();
00208 
00209         return result;
00210 }
00211 
00212 double Track::get_length()
00213 {
00214         double total_length = 0;
00215         double length = 0;
00216 
00217 // Test edits
00218         int64_t unit_end;
00219         unit_end = edits->last->startproject;
00220         if (edits->last->transition)
00221                 unit_end += edits->last->transition->length + 1; // add one so transition is finished...
00222         length = from_units(unit_end);
00223         if(length > total_length) total_length = length;
00224 
00225 // Test plugins
00226         for(int i = 0; i < plugin_set.total; i++)
00227         {
00228                 length = from_units(plugin_set.values[i]->last->startproject);
00229                 if(length > total_length) total_length = length;
00230         }
00231 
00232 // Test keyframes
00233         length = from_units(automation->get_length());
00234         if(length > total_length) total_length = length;
00235         
00236 
00237         return total_length;
00238 }
00239 
00240 
00241 
00242 void Track::get_source_dimensions(double position, int &w, int &h)
00243 {
00244         int64_t native_position = to_units(position, 0);
00245         for(Edit *current = edits->first; current; current = NEXT)
00246         {
00247                 if(current->startproject <= native_position &&
00248                         current->startproject + current->length > native_position &&
00249                         current->asset)
00250                 {
00251                         w = current->asset->width;
00252                         h = current->asset->height;
00253                         return;
00254                 }
00255         }
00256 }
00257 
00258 
00259 int64_t Track::horizontal_span()
00260 {
00261         return (int64_t)(get_length() * 
00262                 edl->session->sample_rate / 
00263                 edl->local_session->zoom_sample + 
00264                 0.5);
00265 }
00266 
00267 
00268 int Track::load(FileXML *file, int track_offset, uint32_t load_flags)
00269 {
00270         int result = 0;
00271         int current_channel = 0;
00272         int current_plugin = 0;
00273 
00274 
00275         record = file->tag.get_property("RECORD", record);
00276         play = file->tag.get_property("PLAY", play);
00277         gang = file->tag.get_property("GANG", gang);
00278         draw = file->tag.get_property("DRAW", draw);
00279         nudge = file->tag.get_property("NUDGE", nudge);
00280         expand_view = file->tag.get_property("EXPAND", expand_view);
00281         track_w = file->tag.get_property("TRACK_W", track_w);
00282         track_h = file->tag.get_property("TRACK_H", track_h);
00283 
00284         load_header(file, load_flags);
00285 
00286         do{
00287                 result = file->read_tag();
00288 
00289                 if(!result)
00290                 {
00291                         if(file->tag.title_is("/TRACK"))
00292                         {
00293                                 result = 1;
00294                         }
00295                         else
00296                         if(file->tag.title_is("TITLE"))
00297                         {
00298                                 file->read_text_until("/TITLE", title, BCTEXTLEN);
00299                         }
00300                         else
00301                         if(load_flags && automation->load(file)
00302                         /* strstr(file->tag.get_title(), "AUTOS") */)
00303                         {
00304                                 ;
00305                         }
00306                         else
00307                         if(file->tag.title_is("EDITS"))
00308                         {
00309                                 if(load_flags & LOAD_EDITS)
00310                                         edits->load(file, track_offset);
00311                         }
00312                         else
00313                         if(file->tag.title_is("PLUGINSET"))
00314                         {
00315                                 if(load_flags & LOAD_EDITS)
00316                                 {
00317                                         PluginSet *plugin_set = new PluginSet(edl, this);
00318                                         this->plugin_set.append(plugin_set);
00319                                         plugin_set->load(file, load_flags);
00320                                 }
00321                                 else
00322                                 if(load_flags & LOAD_AUTOMATION)
00323                                 {
00324                                         if(current_plugin < this->plugin_set.total)
00325                                         {
00326                                                 PluginSet *plugin_set = this->plugin_set.values[current_plugin];
00327                                                 plugin_set->load(file, load_flags);
00328                                                 current_plugin++;
00329                                         }
00330                                 }
00331                         }
00332                         else
00333                                 load_derived(file, load_flags);
00334                 }
00335         }while(!result);
00336 
00337 
00338 
00339         return 0;
00340 }
00341 
00342 void Track::insert_asset(Asset *asset, 
00343                 double length, 
00344                 double position, 
00345                 int track_number)
00346 {
00347 //printf("Track::insert_asset %f\n", length);
00348         edits->insert_asset(asset, 
00349                 to_units(length, 1), 
00350                 to_units(position, 0), 
00351                 track_number);
00352         edits->loaded_length += to_units(length, 1);
00353 }
00354 
00355 // Insert data
00356 
00357 // Default keyframes: We don't replace default keyframes in pasting but
00358 // when inserting the first EDL of a load operation we need to replace
00359 // the default keyframes.
00360 
00361 // Plugins:  This is an arbitrary behavior
00362 //
00363 // 1) No plugin in source track: Paste silence into destination
00364 // plugin sets.
00365 // 2) Plugin in source track: plugin in source track is inserted into
00366 // existing destination track plugin sets, new sets being added when
00367 // necessary.
00368 
00369 void Track::insert_track(Track *track, 
00370         double position, 
00371         int replace_default,
00372         int edit_plugins)
00373 {
00374 
00375 // Decide whether to copy settings based on load_mode
00376         if(replace_default) copy_settings(track);
00377 
00378         edits->insert_edits(track->edits, to_units(position, 0));
00379 
00380         if(edit_plugins)
00381                 insert_plugin_set(track, position);
00382 
00383         automation->insert_track(track->automation, 
00384                 to_units(position, 0), 
00385                 to_units(track->get_length(), 1),
00386                 replace_default);
00387 
00388         optimize();
00389 
00390 }
00391 
00392 // Called by insert_track
00393 void Track::insert_plugin_set(Track *track, double position)
00394 {
00395 // Extend plugins if no incoming plugins
00396         if(!track->plugin_set.total)
00397         {
00398                 shift_effects(position, 
00399                         track->get_length(), 
00400                         1);
00401         }
00402         else
00403         for(int i = 0; i < track->plugin_set.total; i++)
00404         {
00405                 if(i >= plugin_set.total)
00406                         plugin_set.append(new PluginSet(edl, this));
00407 
00408                 plugin_set.values[i]->insert_edits(track->plugin_set.values[i], 
00409                         to_units(position, 0));
00410         }
00411 }
00412 
00413 
00414 Plugin* Track::insert_effect(char *title, 
00415                 SharedLocation *shared_location, 
00416                 KeyFrame *default_keyframe,
00417                 PluginSet *plugin_set,
00418                 double start,
00419                 double length,
00420                 int plugin_type)
00421 {
00422         if(!plugin_set)
00423         {
00424                 plugin_set = new PluginSet(edl, this);
00425                 this->plugin_set.append(plugin_set);
00426         }
00427 
00428         Plugin *plugin = 0;
00429 
00430 // Position is identical to source plugin
00431         if(plugin_type == PLUGIN_SHAREDPLUGIN)
00432         {
00433                 Track *source_track = tracks->get_item_number(shared_location->module);
00434                 if(source_track)
00435                 {
00436                         Plugin *source_plugin = source_track->get_current_plugin(
00437                                 edl->local_session->get_selectionstart(), 
00438                                 shared_location->plugin, 
00439                                 PLAY_FORWARD, 
00440                                 1,
00441                                 0);
00442 
00443 // From an attach operation
00444                         if(source_plugin)
00445                         {
00446                                 plugin = plugin_set->insert_plugin(title, 
00447                                         source_plugin->startproject, 
00448                                         source_plugin->length,
00449                                         plugin_type, 
00450                                         shared_location,
00451                                         default_keyframe,
00452                                         1);
00453                         }
00454                         else
00455 // From a drag operation
00456                         {
00457                                 plugin = plugin_set->insert_plugin(title, 
00458                                         to_units(start, 0), 
00459                                         to_units(length, 1),
00460                                         plugin_type, 
00461                                         shared_location,
00462                                         default_keyframe,
00463                                         1);
00464                         }
00465                 }
00466         }
00467         else
00468         {
00469 // This should be done in the caller
00470                 if(EQUIV(length, 0))
00471                 {
00472                         if(edl->local_session->get_selectionend() > 
00473                                 edl->local_session->get_selectionstart())
00474                         {
00475                                 start = edl->local_session->get_selectionstart();
00476                                 length = edl->local_session->get_selectionend() - start;
00477                         }
00478                         else
00479                         {
00480                                 start = 0;
00481                                 length = get_length();
00482                         }
00483                 }
00484 //printf("Track::insert_effect %f %f %d %d\n", start, length, to_units(start, 0), 
00485 //                      to_units(length, 0));
00486 
00487                 plugin = plugin_set->insert_plugin(title, 
00488                         to_units(start, 0), 
00489                         to_units(length, 1),
00490                         plugin_type, 
00491                         shared_location,
00492                         default_keyframe,
00493                         1);
00494         }
00495 //printf("Track::insert_effect 2 %f %f\n", start, length);
00496 
00497         expand_view = 1;
00498         return plugin;
00499 }
00500 
00501 void Track::move_plugins_up(PluginSet *plugin_set)
00502 {
00503         for(int i = 0; i < this->plugin_set.total; i++)
00504         {
00505                 if(this->plugin_set.values[i] == plugin_set)
00506                 {
00507                         if(i == 0) break;
00508 
00509                         PluginSet *temp = this->plugin_set.values[i - 1];
00510                         this->plugin_set.values[i - 1] = this->plugin_set.values[i];
00511                         this->plugin_set.values[i] = temp;
00512 
00513                         SharedLocation old_location, new_location;
00514                         new_location.module = old_location.module = tracks->number_of(this);
00515                         old_location.plugin = i;
00516                         new_location.plugin = i - 1;
00517                         tracks->change_plugins(old_location, new_location, 1);
00518                         break;
00519                 }
00520         }
00521 }
00522 
00523 void Track::move_plugins_down(PluginSet *plugin_set)
00524 {
00525         for(int i = 0; i < this->plugin_set.total; i++)
00526         {
00527                 if(this->plugin_set.values[i] == plugin_set)
00528                 {
00529                         if(i == this->plugin_set.total - 1) break;
00530 
00531                         PluginSet *temp = this->plugin_set.values[i + 1];
00532                         this->plugin_set.values[i + 1] = this->plugin_set.values[i];
00533                         this->plugin_set.values[i] = temp;
00534 
00535                         SharedLocation old_location, new_location;
00536                         new_location.module = old_location.module = tracks->number_of(this);
00537                         old_location.plugin = i;
00538                         new_location.plugin = i + 1;
00539                         tracks->change_plugins(old_location, new_location, 1);
00540                         break;
00541                 }
00542         }
00543 }
00544 
00545 
00546 void Track::remove_asset(Asset *asset)
00547 {
00548         for(Edit *edit = edits->first; edit; edit = edit->next)
00549         {
00550                 if(edit->asset && edit->asset == asset)
00551                 {
00552                         edit->asset = 0;
00553                 }
00554         }
00555         optimize();
00556 }
00557 
00558 void Track::remove_pluginset(PluginSet *plugin_set)
00559 {
00560         int i;
00561         for(i = 0; i < this->plugin_set.total; i++)
00562                 if(plugin_set == this->plugin_set.values[i]) break;
00563 
00564         this->plugin_set.remove_object(plugin_set);
00565         for(i++ ; i < this->plugin_set.total; i++)
00566         {
00567                 SharedLocation old_location, new_location;
00568                 new_location.module = old_location.module = tracks->number_of(this);
00569                 old_location.plugin = i;
00570                 new_location.plugin = i - 1;
00571                 tracks->change_plugins(old_location, new_location, 0);
00572         }
00573 }
00574 
00575 void Track::shift_keyframes(double position, double length, int convert_units)
00576 {
00577         if(convert_units)
00578         {
00579                 position = to_units(position, 0);
00580                 length = to_units(length, 1);
00581         }
00582 
00583         automation->paste_silence(Units::to_int64(position), 
00584                 Units::to_int64(position + length));
00585 // Effect keyframes are shifted in shift_effects
00586 }
00587 
00588 void Track::shift_effects(double position, double length, int convert_units)
00589 {
00590         if(convert_units)
00591         {
00592                 position = to_units(position, 0);
00593                 length = to_units(length, 1);
00594         }
00595 
00596         for(int i = 0; i < plugin_set.total; i++)
00597         {
00598                 plugin_set.values[i]->shift_effects(Units::to_int64(position), Units::to_int64(length));
00599         }
00600 }
00601 
00602 void Track::detach_effect(Plugin *plugin)
00603 {
00604 //printf("Track::detach_effect 1\n");           
00605         for(int i = 0; i < plugin_set.total; i++)
00606         {
00607                 PluginSet *plugin_set = this->plugin_set.values[i];
00608                 for(Plugin *dest = (Plugin*)plugin_set->first; 
00609                         dest; 
00610                         dest = (Plugin*)dest->next)
00611                 {
00612                         if(dest == plugin)
00613                         {
00614                                 int64_t start = plugin->startproject;
00615                                 int64_t end = plugin->startproject + plugin->length;
00616 
00617                                 plugin_set->clear(start, end);
00618                                 plugin_set->paste_silence(start, end);
00619 
00620 // Delete 0 length pluginsets   
00621                                 plugin_set->optimize();
00622 //printf("Track::detach_effect 2 %d\n", plugin_set->length());
00623                                 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
00624                                         remove_pluginset(plugin_set);
00625                                 return;
00626                         }
00627                 }
00628         }
00629 }
00630 
00631 void Track::resample(double old_rate, double new_rate)
00632 {
00633         edits->resample(old_rate, new_rate);
00634         automation->resample(old_rate, new_rate);
00635         for(int i = 0; i < plugin_set.total; i++)
00636                 plugin_set.values[i]->resample(old_rate, new_rate);
00637         nudge = (int64_t)(nudge * new_rate / old_rate);
00638 }
00639 
00640 void Track::detach_shared_effects(int module)
00641 {
00642         for(int i = 0; i < plugin_set.total; i++)
00643         {
00644                 PluginSet *plugin_set = this->plugin_set.values[i];
00645                 for(Plugin *dest = (Plugin*)plugin_set->first; 
00646                         dest; 
00647                         dest = (Plugin*)dest->next)
00648                 {
00649                         if ((dest->plugin_type == PLUGIN_SHAREDPLUGIN ||
00650                                 dest->plugin_type == PLUGIN_SHAREDMODULE)
00651                             &&
00652                                 dest->shared_location.module == module)
00653                         {
00654                                 int64_t start = dest->startproject;
00655                                 int64_t end = dest->startproject + dest->length;
00656 
00657                                 plugin_set->clear(start, end);
00658                                 plugin_set->paste_silence(start, end);
00659 
00660 // Delete 0 length pluginsets   
00661                                 plugin_set->optimize();
00662                                 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
00663                                 {
00664                                         this->plugin_set.remove_object_number(i);
00665                                         --i;
00666                                 }
00667                         }
00668                 }
00669         }
00670 }
00671 
00672 
00673 void Track::optimize()
00674 {
00675         edits->optimize();
00676         for(int i = 0; i < plugin_set.total; i++)
00677         {
00678                 PluginSet *plugin_set = this->plugin_set.values[i];
00679                 plugin_set->optimize();
00680 //printf("Track::optimize %d\n", plugin_set.values[i]->total());
00681 // new definition of empty track...
00682                 if(plugin_set->last == plugin_set->first && plugin_set->last->silence())
00683                 {
00684                         remove_pluginset(plugin_set);
00685                         i--;
00686                 }
00687         }
00688 }
00689 
00690 Plugin* Track::get_current_plugin(double position, 
00691         int plugin_set, 
00692         int direction, 
00693         int convert_units,
00694         int use_nudge)
00695 {
00696         Plugin *current;
00697         if(convert_units) position = to_units(position, 0);
00698         if(use_nudge) position += nudge;
00699         
00700         if(plugin_set >= this->plugin_set.total || plugin_set < 0) return 0;
00701 
00702 //printf("Track::get_current_plugin 1 %d %d %d\n", position, this->plugin_set.total, direction);
00703         if(direction == PLAY_FORWARD)
00704         {
00705                 for(current = (Plugin*)this->plugin_set.values[plugin_set]->last; 
00706                         current; 
00707                         current = (Plugin*)PREVIOUS)
00708                 {
00709 // printf("Track::get_current_plugin 2 %d %ld %ld\n", 
00710 // current->startproject, 
00711 // current->startproject + current->length, 
00712 // position);
00713                         if(current->startproject <= position && 
00714                                 current->startproject + current->length > position)
00715                         {
00716                                 return current;
00717                         }
00718                 }
00719         }
00720         else
00721         if(direction == PLAY_REVERSE)
00722         {
00723                 for(current = (Plugin*)this->plugin_set.values[plugin_set]->first; 
00724                         current; 
00725                         current = (Plugin*)NEXT)
00726                 {
00727                         if(current->startproject < position && 
00728                                 current->startproject + current->length >= position)
00729                         {
00730                                 return current;
00731                         }
00732                 }
00733         }
00734 
00735         return 0;
00736 }
00737 
00738 Plugin* Track::get_current_transition(double position, 
00739         int direction, 
00740         int convert_units,
00741         int use_nudge)
00742 {
00743         Edit *current;
00744         Plugin *result = 0;
00745         if(convert_units) position = to_units(position, 0);
00746         if(use_nudge) position += nudge;
00747 
00748         if(direction == PLAY_FORWARD)
00749         {
00750                 for(current = edits->last; current; current = PREVIOUS)
00751                 {
00752                         if(current->startproject <= position && current->startproject + current->length > position)
00753                         {
00754 //printf("Track::get_current_transition %p\n", current->transition);
00755                                 if(current->transition && position < current->startproject + current->transition->length)
00756                                 {
00757                                         result = current->transition;
00758                                         break;
00759                                 }
00760                         }
00761                 }
00762         }
00763         else
00764         if(direction == PLAY_REVERSE)
00765         {
00766                 for(current = edits->first; current; current = NEXT)
00767                 {
00768                         if(current->startproject < position && current->startproject + current->length >= position)
00769                         {
00770                                 if(current->transition && position <= current->startproject + current->transition->length)
00771                                 {
00772                                         result = current->transition;
00773                                         break;
00774                                 }
00775                         }
00776                 }
00777         }
00778 
00779         return result;
00780 }
00781 
00782 void Track::synchronize_params(Track *track)
00783 {
00784         for(Edit *this_edit = edits->first, *that_edit = track->edits->first;
00785                 this_edit && that_edit;
00786                 this_edit = this_edit->next, that_edit = that_edit->next)
00787         {
00788                 this_edit->synchronize_params(that_edit);
00789         }
00790 
00791         for(int i = 0; i < plugin_set.total && i < track->plugin_set.total; i++)
00792                 plugin_set.values[i]->synchronize_params(track->plugin_set.values[i]);
00793 
00794         automation->copy_from(track->automation);
00795         this->nudge = track->nudge;
00796 }
00797 
00798 
00799 
00800 
00801 
00802 int Track::dump()
00803 {
00804         printf("   Data type %d\n", data_type);
00805         printf("   Title %s\n", title);
00806         printf("   Edits:\n");
00807         for(Edit* current = edits->first; current; current = NEXT)
00808         {
00809                 current->dump();
00810         }
00811         automation->dump();
00812         printf("   Plugin Sets: %d\n", plugin_set.total);
00813 
00814         for(int i = 0; i < plugin_set.total; i++)
00815                 plugin_set.values[i]->dump();
00816 //printf("Track::dump 2\n");
00817         return 0;
00818 }
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837 
00838 
00839 
00840 Track::Track() : ListItem<Track>()
00841 {
00842         y_pixel = 0;
00843 }
00844 
00845 // ======================================== accounting
00846 
00847 int Track::number_of() 
00848 { 
00849         return tracks->number_of(this); 
00850 }
00851 
00852 
00853 
00854 
00855 
00856         
00857         
00858 
00859 
00860 
00861 
00862 
00863 
00864 // ================================================= editing
00865 
00866 int Track::select_auto(AutoConf *auto_conf, int cursor_x, int cursor_y)
00867 {
00868         return 0;
00869 }
00870 
00871 int Track::move_auto(AutoConf *auto_conf, int cursor_x, int cursor_y, int shift_down)
00872 {
00873         return 0;
00874 }
00875 
00876 int Track::release_auto()
00877 {
00878         return 0;
00879 }
00880 
00881 // used for copying automation alone
00882 int Track::copy_automation(double selectionstart, 
00883         double selectionend, 
00884         FileXML *file,
00885         int default_only,
00886         int autos_only)
00887 {
00888         int64_t start = to_units(selectionstart, 0);
00889         int64_t end = to_units(selectionend, 1);
00890 
00891         file->tag.set_title("TRACK");
00892 // Video or audio
00893     save_header(file);
00894         file->append_tag();
00895         file->append_newline();
00896 
00897         automation->copy(start, end, file, default_only, autos_only);
00898 
00899         if(edl->session->auto_conf->plugins)
00900         {
00901                 file->tag.set_title("PLUGINSETS");
00902                 file->append_tag();
00903                 file->append_newline();
00904                 for(int i = 0; i < plugin_set.total; i++)
00905                 {
00906                 
00907                         plugin_set.values[i]->copy_keyframes(start, 
00908                                 end, 
00909                                 file, 
00910                                 default_only,
00911                                 autos_only);
00912                 }
00913                 file->tag.set_title("/PLUGINSETS");
00914                 file->append_tag();
00915                 file->append_newline();
00916         }
00917 
00918         file->tag.set_title("/TRACK");
00919         file->append_tag();
00920         file->append_newline();
00921         file->append_newline();
00922         file->append_newline();
00923         file->append_newline();
00924 
00925         return 0;
00926 }
00927 
00928 int Track::paste_automation(double selectionstart, 
00929         double total_length, 
00930         double frame_rate,
00931         int64_t sample_rate,
00932         FileXML *file,
00933         int default_only)
00934 {
00935 // Only used for pasting automation alone.
00936         int64_t start;
00937         int64_t length;
00938         int result;
00939         double scale;
00940 
00941         if(data_type == TRACK_AUDIO)
00942                 scale = edl->session->sample_rate / sample_rate;
00943         else
00944                 scale = edl->session->frame_rate / frame_rate;
00945 
00946         total_length *= scale;
00947         start = to_units(selectionstart, 0);
00948         length = to_units(total_length, 1);
00949         result = 0;
00950 //printf("Track::paste_automation 1\n");
00951 
00952         while(!result)
00953         {
00954                 result = file->read_tag();
00955 
00956                 if(!result)
00957                 {
00958                         if(file->tag.title_is("/TRACK"))
00959                                 result = 1;
00960                         else
00961                         if(automation->paste(start, 
00962                                         length, 
00963                                         scale,
00964                                         file,
00965                                         default_only,
00966                                         0))
00967                         /* strstr(file->tag.get_title(), "AUTOS")) */
00968                         {
00969                                 ;
00970                         }
00971                         else
00972                         if(file->tag.title_is("PLUGINSETS"))
00973                         {
00974 //printf("Track::paste_automation 2 %d\n", current_pluginset);
00975                                 PluginSet::paste_keyframes(start, 
00976                                         length, 
00977                                         file,
00978                                         default_only,
00979                                         this);
00980                         }
00981                 }
00982         }
00983 //printf("Track::paste_automation 3\n");
00984         
00985 
00986         return 0;
00987 }
00988 
00989 void Track::clear_automation(double selectionstart, 
00990         double selectionend, 
00991         int shift_autos,
00992         int default_only)
00993 {
00994         int64_t start = to_units(selectionstart, 0);
00995         int64_t end = to_units(selectionend, 1);
00996 
00997         automation->clear(start, end, edl->session->auto_conf, 0);
00998 
00999         if(edl->session->auto_conf->plugins)
01000         {
01001                 for(int i = 0; i < plugin_set.total; i++)
01002                 {
01003                         plugin_set.values[i]->clear_keyframes(start, end);
01004                 }
01005         }
01006 
01007 }
01008 
01009 void Track::straighten_automation(double selectionstart, 
01010         double selectionend)
01011 {
01012         int64_t start = to_units(selectionstart, 0);
01013         int64_t end = to_units(selectionend, 1);
01014 
01015         automation->straighten(start, end, edl->session->auto_conf);
01016 }
01017 
01018 
01019 
01020 
01021 int Track::copy(double start, 
01022         double end, 
01023         FileXML *file, 
01024         char *output_path)
01025 {
01026 // Use a copy of the selection in converted units
01027 // So copy_automation doesn't reconvert.
01028         int64_t start_unit = to_units(start, 0);
01029         int64_t end_unit = to_units(end, 1);
01030 
01031 
01032 
01033 
01034         file->tag.set_title("TRACK");
01035         file->tag.set_property("RECORD", record);
01036         file->tag.set_property("NUDGE", nudge);
01037         file->tag.set_property("PLAY", play);
01038         file->tag.set_property("GANG", gang);
01039         file->tag.set_property("DRAW",