+void Track::get_fauto_xyz(int fauto, float &x, float &y, float &z)
+{
+ FloatAutos **fautos = (FloatAutos **)&automation->autos;
+ FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->get_auto_for_editing(-1, 1);
+ if( xauto ) x = xauto->get_value();
+ FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->get_auto_for_editing(-1, 1);
+ if( yauto ) y = yauto->get_value();
+ FloatAuto *zauto = (FloatAuto *)fautos[fauto+2]->get_auto_for_editing(-1, 1);
+ if( zauto ) z = zauto->get_value();
+}
+void Track::set_fauto_xyz(int fauto, float x, float y, float z)
+{
+ FloatAutos **fautos = (FloatAutos **)&automation->autos;
+ FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->get_auto_for_editing(-1, 1);
+ if( xauto ) xauto->set_value(x);
+ FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->get_auto_for_editing(-1, 1);
+ if( yauto ) yauto->set_value(y);
+ FloatAuto *zauto = (FloatAuto *)fautos[fauto+2]->get_auto_for_editing(-1, 1);
+ if( zauto ) zauto->set_value(z);
+}
+
+void Track::get_projector(float &x, float &y, float &z)
+{
+ get_fauto_xyz(AUTOMATION_PROJECTOR_X, x, y, z);
+}
+void Track::set_projector(float x, float y, float z)
+{
+ set_fauto_xyz(AUTOMATION_PROJECTOR_X, x, y, z);
+}
+
+void Track::get_camera(float &x, float &y, float &z)
+{
+ get_fauto_xyz(AUTOMATION_CAMERA_X, x, y, z);
+}
+void Track::set_camera(float x, float y, float z)
+{
+ set_fauto_xyz(AUTOMATION_CAMERA_X, x, y, z);
+}
+
+int Track::is_hidden()
+{
+ if( master ) return 0;
+ if( edl->local_session->gang_tracks == GANG_MEDIA ) return 1;
+ if( edl->local_session->gang_tracks == GANG_CHANNELS ) {
+ for( Track *track=previous; track; track=track->previous ) {
+ if( track->data_type == data_type ) return 1;
+ if( track->master ) return 0;
+ }
+ }
+ return 0;
+}
+
+Track *Track::gang_master()
+{
+ Track *track = this;
+ switch( edl->local_session->gang_tracks ) {
+ case GANG_NONE:
+ return track;
+ case GANG_CHANNELS: {
+ Track *current = track;
+ int data_type = track->data_type;
+ while( current && !current->master ) {
+ if( !(current = current->previous) ) break;
+ if( current->data_type == data_type ) track = current;
+ }
+ break; }
+ case GANG_MEDIA: {
+ while( track && !track->master ) track = track->previous;
+ break; }
+ }
+ if( !track ) track = tracks->first;
+ return track;
+}
+
+int Track::in_gang(Track *track)
+{
+ if( edl->local_session->gang_tracks == GANG_NONE ) return ganged;
+ Track *current = this;
+ while( current && !current->master ) current = current->previous;
+ while( track && !track->master ) track = track->previous;
+ return current == track ? 1 : 0;
+}
+
+int Track::is_armed()
+{
+ return armed && gang_master()->armed;
+}
+
+int Track::is_ganged()
+{
+ return ganged && gang_master()->ganged;
+}
+
+int Track::armed_gang(Track *track)
+{
+ if( !track->ganged ) return 0;
+ if( edl->local_session->gang_tracks == GANG_NONE ) return ganged;
+ Track *current = gang_master();
+ if( !current->ganged ) return 0;
+ for(;;) {
+ if( track == current ) return 1;
+ current = current->next;
+ if( !current || current->master ) return 0;
+ }
+ return 1;
+}
+
+int Track::plays()
+{
+ return play && gang_master()->play;
+}
+
+int Track::index_in(Mixer *mixer)
+{
+ if( !mixer || mixer_id < 0 ) return -1;
+ int k = mixer->mixer_ids.size();
+ while( --k >= 0 && mixer_id != mixer->mixer_ids[k] );
+ return k;
+}
+
+void Track::create_keyframes(double position, int mask, int mode)
+{
+ for( int idx=0; idx<AUTOMATION_TOTAL; mask>>=1,++idx ) {
+ if( !(mask & 1) ) continue;
+ Autos *autos = automation->autos[idx];
+ if( !autos ) continue;
+ FloatAuto *float_auto = (FloatAuto *)
+ autos->get_auto_for_editing(position, -1);
+ float_auto->change_curve_mode((FloatAuto::t_mode)mode, 0);
+ }
+}
+