bool Track::LinkConsistencyCheck() { // Sanity checks for linked tracks; unsetting the linked property // doesn't fix the problem, but it likely leaves us with orphaned // blockfiles instead of much worse problems. bool err = false; if (GetLinked()) { Track *l = GetLink(); if (l) { // A linked track's partner should never itself be linked if (l->GetLinked()) { wxLogWarning( wxT("Left track %s had linked right track %s with extra right track link.\n Removing extra link from right track."), GetName(), l->GetName()); err = true; l->SetLinked(false); } // Channels should be left and right if ( !( (GetChannel() == Track::LeftChannel && l->GetChannel() == Track::RightChannel) || (GetChannel() == Track::RightChannel && l->GetChannel() == Track::LeftChannel) ) ) { wxLogWarning( wxT("Track %s and %s had left/right track links out of order. Setting tracks to not be linked."), GetName(), l->GetName()); err = true; SetLinked(false); } } else { wxLogWarning( wxT("Track %s had link to NULL track. Setting it to not be linked."), GetName()); err = true; SetLinked(false); } } return ! err; }
bool EffectFindClipping::Process() { LabelTrack *l = NULL; Track *original = NULL; TrackListOfKindIterator iter(Track::Label, mTracks); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetName() == wxT("Clipping")) { l = (LabelTrack *) t; // copy LabelTrack here, so it can be undone on cancel l->Copy(l->GetStartTime(), l->GetEndTime(), &original); original->SetOffset(l->GetStartTime()); original->SetName(wxT("Clipping")); break; } } if (!l) { l = mFactory->NewLabelTrack(); l->SetName(_("Clipping")); mTracks->Add((Track *) l); } int count = 0; // JC: Only process selected tracks. SelectedTrackListOfKindIterator waves(Track::Wave, mTracks); WaveTrack *t = (WaveTrack *) waves.First(); while (t) { double trackStart = t->GetStartTime(); double trackEnd = t->GetEndTime(); double t0 = mT0 < trackStart ? trackStart : mT0; double t1 = mT1 > trackEnd ? trackEnd : mT1; if (t1 > t0) { sampleCount start = t->TimeToLongSamples(t0); sampleCount end = t->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (!ProcessOne(l, count, t, start, len)) { //put it back how it was mTracks->Remove((Track *) l); if(original) { mTracks->Add((Track *) original); } return false; } } count++; t = (WaveTrack *) waves.Next(); } return true; }
// Gets the name of the specified object. wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) { #if defined(__WXMSW__) if( childId == wxACC_SELF ) { *name = _( "TrackView" ); } else { Track *t = FindTrack( childId ); if( t == NULL ) { return wxACC_FAIL; } else { *name = t->GetName(); if( *name == t->GetDefaultName() ) { /* i18n-hint: The %d is replaced by th enumber of the track.*/ name->Printf(_("Track %d"), TrackNum( t ) ); } // LLL: Remove these during "refactor" if( t->GetMute() ) { /* i18n-hint: This is for screen reader software and indicates that on this track mute is on.*/ *name->Append( _( " Mute On" ) ); } if( t->GetSolo() ) { /* i18n-hint: This is for screen reader software and indicates that on this track solo is on.*/ *name->Append( _( " Solo On" ) ); } if( t->GetSelected() ) { /* i18n-hint: This is for screen reader software and indicates that this track is selected.*/ *name->Append( _( " Select On" ) ); } } } return wxACC_OK; #endif #if defined(__WXMAC__) return wxACC_NOT_IMPLEMENTED; #endif }
wxAccStatus TrackPanelAx::GetValue( int WXUNUSED(childId), wxString* WXUNUSED(strValue) ) #endif { #if defined(__WXMSW__) return wxACC_NOT_IMPLEMENTED; #endif #if defined(__WXMAC__) if( childId == wxACC_SELF ) { *strValue = _( "TrackView" ); } else { Track *t = FindTrack( childId ); if( t == NULL ) { return wxACC_FAIL; } else { *strValue = t->GetName(); if( *strValue == t->GetDefaultName() ) { strValue->Printf(_("Track %d"), TrackNum( t ) ); } // LLL: Remove these during "refactor" if( t->GetMute() ) { strValue->Append( _( " Mute On" ) ); } if( t->GetSolo() ) { strValue->Append( _( " Solo On" ) ); } if( t->GetSelected() ) { strValue->Append( _( " Select On" ) ); } } } return wxACC_OK; #endif }
Track *ActiveTrack::DoExtendDaily() { Track *pExtendTrack = NULL; TrackPoint *pExtendPoint = NULL; TrackPoint *pLastPoint = GetPoint( 0 ); wxTrackListNode *track_node = pTrackList->GetFirst(); while( track_node ) { Track *ptrack = track_node->GetData(); if( !ptrack->m_bIsInLayer && ptrack->m_GUID != m_GUID ) { TrackPoint *track_node = ptrack->GetLastPoint(); if( track_node->GetCreateTime() <= pLastPoint->GetCreateTime() ) { if( !pExtendPoint || track_node->GetCreateTime() > pExtendPoint->GetCreateTime() ) { pExtendPoint = track_node; pExtendTrack = ptrack; } } } track_node = track_node->GetNext(); // next track } if( pExtendTrack && pExtendTrack->GetPoint( 0 )->GetCreateTime().FromTimezone( wxDateTime::GMT0 ).IsSameDate(pLastPoint->GetCreateTime().FromTimezone( wxDateTime::GMT0 ) ) ) { int begin = 1; if( pLastPoint->GetCreateTime() == pExtendPoint->GetCreateTime() ) begin = 2; pSelect->DeleteAllSelectableTrackSegments( pExtendTrack ); wxString suffix = _T(""); if( GetName().IsNull() ) { suffix = pExtendTrack->GetName(); if( suffix.IsNull() ) suffix = wxDateTime::Today().FormatISODate(); } pExtendTrack->Clone( this, begin, GetnPoints(), suffix ); pSelect->AddAllSelectableTrackSegments( pExtendTrack ); pSelect->DeleteAllSelectableTrackSegments( this ); return pExtendTrack; } else { if( GetName().IsNull() ) SetName(wxDateTime::Today().FormatISODate()); return NULL; } }
// Gets the name of the specified object. wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) { if( childId == wxACC_SELF ) { *name = _( "TrackView" ); } else { Track *t = FindTrack( childId ); if( t == NULL ) { *name = _( "Track Accessible out of sync" ); return wxACC_FAIL; } else { *name = t->GetName(); if( *name == t->GetDefaultName() ) { name->Printf(_("Track %d"), TrackNum( t ) ); } // LLL: Remove these during "refactor" if( t->GetMute() ) { *name->Append( _( " Mute On" ) ); } if( t->GetSolo() ) { *name->Append( _( " Solo On" ) ); } if( t->GetSelected() ) { *name->Append( _( " Select On" ) ); } } } return wxACC_OK; }
// Gets the name of the specified object. wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) { #if defined(__WXMSW__) if( childId == wxACC_SELF ) { *name = _( "TrackView" ); } else { Track *t = FindTrack( childId ); if( t == NULL ) { return wxACC_FAIL; } else { *name = t->GetName(); if( *name == t->GetDefaultName() ) { /* i18n-hint: The %d is replaced by th enumber of the track.*/ name->Printf(_("Track %d"), TrackNum( t ) ); } if (t->GetKind() == Track::Label) { /* i18n-hint: This is for screen reader software and indicates that this is a Label track.*/ name->Append( wxT(" ") + wxString(_("Label Track"))); } else if (t->GetKind() == Track::Time) { /* i18n-hint: This is for screen reader software and indicates that this is a Time track.*/ name->Append( wxT(" ") + wxString(_("Time Track"))); } else if (t->GetKind() == Track::Note) { /* i18n-hint: This is for screen reader software and indicates that this is a Note track.*/ name->Append( wxT(" ") + wxString(_("Note Track"))); } // LLL: Remove these during "refactor" if( t->GetMute() ) { // The following comment also applies to the solo, selected, // and synclockselected states. // Many of translations of the strings with a leading space omitted // the leading space. Therefore a space has been added using wxT(" "). // Because screen readers won't be affected by multiple spaces, the // leading spaces have not been removed, so that no new translations are needed. /* i18n-hint: This is for screen reader software and indicates that on this track mute is on.*/ name->Append( wxT(" ") + wxString(_( " Mute On" )) ); } if( t->GetSolo() ) { /* i18n-hint: This is for screen reader software and indicates that on this track solo is on.*/ name->Append( wxT(" ") + wxString(_( " Solo On" )) ); } if( t->GetSelected() ) { /* i18n-hint: This is for screen reader software and indicates that this track is selected.*/ name->Append( wxT(" ") + wxString(_( " Select On" )) ); } if( t->IsSyncLockSelected() ) { /* i18n-hint: This is for screen reader software and indicates that this track is shown with a sync-locked icon.*/ // The absence of a dash between Sync and Locked is deliberate - // if present, Jaws reads it as "dash". name->Append( wxT(" ") + wxString(_( " Sync Lock Selected" )) ); } } } return wxACC_OK; #endif #if defined(__WXMAC__) return wxACC_NOT_IMPLEMENTED; #endif }
ExportMixerDialog::ExportMixerDialog( TrackList *tracks, bool selectionOnly, int maxNumChannels, wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style ) : wxDialog( parent, id, title, position, size, style | wxRESIZE_BORDER ) { int numTracks = 0; TrackListIterator iter( tracks ); for( Track *t = iter.First(); t; t = iter.Next() ) if( t->GetKind() == Track::Wave && ( t->GetSelected() || !selectionOnly ) ) { numTracks++; if( t->GetChannel() == Track::LeftChannel ) { mTrackNames.Add( t->GetName() + _( " - Left" ) ); mTrackNames.Add( t->GetName() + _( " - Right" ) ); t = iter.Next(); numTracks++; } else mTrackNames.Add( t->GetName() ); } mMixerSpec = new MixerSpec( numTracks, maxNumChannels ); wxBoxSizer *vertSizer = new wxBoxSizer( wxVERTICAL ); wxWindow *mixerPanel = new ExportMixerPanel( mMixerSpec, mTrackNames, this, ID_MIXERPANEL, wxDefaultPosition, wxSize( 400, -1 ) ); vertSizer->Add( mixerPanel, 1, wxEXPAND | wxALIGN_CENTRE | wxALL, 5 ); wxBoxSizer *horSizer = new wxBoxSizer( wxHORIZONTAL ); mChannelsText = new wxStaticText( this, -1, wxString::Format( _( "Output Channels: %2d" ), mMixerSpec->GetNumChannels() ) ); horSizer->Add( mChannelsText, 0, wxALIGN_LEFT | wxALL, 5 ); wxSlider *channels = new wxSlider( this, ID_SLIDER_CHANNEL, mMixerSpec->GetNumChannels(), 1, mMixerSpec->GetMaxNumChannels(), wxDefaultPosition, wxSize( 300, -1 ) ); horSizer->Add( channels, 0, wxEXPAND | wxALL, 5 ); vertSizer->Add( horSizer, 0, wxALIGN_CENTRE | wxALL, 5 ); horSizer = new wxBoxSizer( wxHORIZONTAL ); wxButton *cancel = new wxButton( this, wxID_CANCEL, _( "&Cancel" ) ); horSizer->Add( cancel, 0, wxALIGN_CENTRE | wxALL, 5 ); wxButton *ok = new wxButton( this, wxID_OK, _( "&OK" ) ); ok->SetDefault(); horSizer->Add( ok, 0, wxALIGN_CENTRE | wxALL, 5 ); vertSizer->Add( horSizer, 0, wxALIGN_CENTRE | wxALL, 5 ); SetAutoLayout( true ); SetSizer( vertSizer ); vertSizer->Fit( this ); vertSizer->SetSizeHints( this ); SetSizeHints( 640, 480, 20000, 20000 ); SetSize( 640, 480 ); }
bool GetTrackInfoCommand::Apply(CommandExecutionContext context) { wxString mode = GetString(wxT("Type")); long trackIndex = GetLong(wxT("TrackIndex")); // Get the track indicated by the TrackIndex parameter // (Note: this ought to be somewhere else) long i = 0; TrackListIterator iter(context.proj->GetTracks()); Track *t = iter.First(); while (t && i != trackIndex) { t = iter.Next(); ++i; } if (i != trackIndex || !t) { Error(wxT("TrackIndex was invalid.")); return false; } // Now get the particular desired item about the track of interest if (mode.IsSameAs(wxT("Name"))) { Status(t->GetName()); } else if (mode.IsSameAs(wxT("StartTime"))) { Status(wxString::Format(wxT("%f"), t->GetStartTime())); } else if (mode.IsSameAs(wxT("EndTime"))) { Status(wxString::Format(wxT("%f"), t->GetEndTime())); } else if (mode.IsSameAs(wxT("Pan"))) { if(t->GetKind() == Track::Wave) Status(wxString::Format(wxT("%f"), static_cast<WaveTrack*>(t)->GetPan())); } else if (mode.IsSameAs(wxT("Gain"))) { if(t->GetKind() == Track::Wave) Status(wxString::Format(wxT("%f"), static_cast<WaveTrack*>(t)->GetGain())); } else if (mode.IsSameAs(wxT("Focused"))) { TrackPanel *panel = context.proj->GetTrackPanel(); SendBooleanStatus(panel->GetFocusedTrack() == t); } else if (mode.IsSameAs(wxT("Selected"))) { SendBooleanStatus(t->GetSelected()); } else if (mode.IsSameAs(wxT("Linked"))) { SendBooleanStatus(t->GetLinked()); } else if (mode.IsSameAs(wxT("Solo"))) { if (t->GetKind() == Track::Wave) SendBooleanStatus(t->GetSolo()); else SendBooleanStatus(false); } else if (mode.IsSameAs(wxT("Mute"))) { if (t->GetKind() == Track::Wave) SendBooleanStatus(t->GetMute()); else SendBooleanStatus(false); } else { Error(wxT("Invalid info type!")); return false; } return true; }
bool SelectCommand::Apply(CommandExecutionContext context) { wxString mode = GetString(wxT("Mode")); if (mode.IsSameAs(wxT("None"))) { // select none context.proj->OnSelectNone(); } else if (mode.IsSameAs(wxT("All"))) { // select all context.proj->OnSelectAll(); } else if (mode.IsSameAs(wxT("Range"))) { // select range double t0 = GetDouble(wxT("StartTime")); double t1 = GetDouble(wxT("EndTime")); TrackList *tracks = context.proj->GetTracks(); if (t0 < context.proj->GetTracks()->GetMinOffset()) { Error(wxT("Start time is before start of track!")); return false; } if (t1 > context.proj->GetTracks()->GetEndTime()) { Error(wxT("End time is after end of track!")); return false; } context.proj->mViewInfo.sel0 = t0; context.proj->mViewInfo.sel1 = t1; // select specified tracks long firstTrack = GetLong(wxT("FirstTrack")); long lastTrack = GetLong(wxT("LastTrack")); if (firstTrack < 0) { Error(wxT("Trying to select a negatively numbered track!")); return false; } if (lastTrack >= tracks->GetCount()) { Error(wxT("Trying to select higher number track than exists!")); return false; } int index = 0; TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { bool sel = firstTrack <= index && index <= lastTrack; t->SetSelected(sel); if (sel) Status(wxT("Selected track '") + t->GetName() + wxT("'")); t = iter.Next(); ++index; } wxASSERT(index >= lastTrack); } else if (mode.IsSameAs(wxT("Name"))) { wxString name = GetString(wxT("TrackName")); TrackList *tracks = context.proj->GetTracks(); TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { bool sel = t->GetName().IsSameAs(name); t->SetSelected(sel); if (sel) Status(wxT("Selected track '") + t->GetName() + wxT("'")); t = iter.Next(); } } else { Error(wxT("Invalid selection mode!")); return false; } return true; }
bool SelectCommand::Apply(CommandExecutionContext context) { wxString mode = GetString(wxT("Mode")); if (mode.IsSameAs(wxT("None"))) { // select none context.GetProject()->OnSelectNone(); } else if (mode.IsSameAs(wxT("All"))) { // select all context.GetProject()->OnSelectAll(); } else if (mode.IsSameAs(wxT("Range"))) { // select range double t0 = GetDouble(wxT("StartTime")); double t1 = GetDouble(wxT("EndTime")); TrackList *tracks = context.GetProject()->GetTracks(); if (t0 < context.GetProject()->GetTracks()->GetMinOffset()) { Error(wxT("Start time is before start of track!")); return false; } if (t1 > context.GetProject()->GetTracks()->GetEndTime()) { Error(wxT("End time is after end of track!")); return false; } // PRL: to do: only setting time boundaries of current selection. // Should other fields be left alone, or rather // defaulted, as in the second branch? // Or should this command take more parameters? #if 1 context.GetProject()->mViewInfo.selectedRegion.setTimes(t0, t1); #else context.GetProject()->mViewInfo.selectedRegion = SelectedRegion(t0, t1); #endif // select specified tracks long firstTrack = GetLong(wxT("FirstTrack")); long lastTrack = GetLong(wxT("LastTrack")); if (firstTrack < 0) { Error(wxT("Trying to select a negatively numbered track!")); return false; } if (lastTrack >= tracks->GetCount()) { Error(wxT("Trying to select higher number track than exists!")); return false; } int index = 0; TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { bool sel = firstTrack <= index && index <= lastTrack; t->SetSelected(sel); if (sel) Status(wxT("Selected track '") + t->GetName() + wxT("'")); t = iter.Next(); ++index; } wxASSERT(index >= lastTrack); } else if (mode.IsSameAs(wxT("Name"))) { wxString name = GetString(wxT("TrackName")); TrackList *tracks = context.GetProject()->GetTracks(); TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { bool sel = t->GetName().IsSameAs(name); t->SetSelected(sel); if (sel) Status(wxT("Selected track '") + t->GetName() + wxT("'")); t = iter.Next(); } } else { Error(wxT("Invalid selection mode!")); return false; } return true; }
ExportMixerDialog::ExportMixerDialog( TrackList *tracks, bool selectedOnly, int maxNumChannels, wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style ) : wxDialog( parent, id, title, position, size, style | wxRESIZE_BORDER ) { int numTracks = 0; TrackListIterator iter( tracks ); for( Track *t = iter.First(); t; t = iter.Next() ) { if( t->GetKind() == Track::Wave && ( t->GetSelected() || !selectedOnly ) ) { numTracks++; if( t->GetChannel() == Track::LeftChannel ) { mTrackNames.Add( t->GetName() + _( " - Left" ) ); mTrackNames.Add( t->GetName() + _( " - Right" ) ); t = iter.Next(); numTracks++; } else mTrackNames.Add( t->GetName() ); } } // JKC: This is an attempt to fix a 'watching brief' issue, where the slider is // sometimes not slidable. My suspicion is that a mixer may incorrectly // state the number of channels - so we assume there are always at least two. // The downside is that if someone is exporting to a mono device, the dialog // will allow them to output to two channels. Hmm. We may need to revisit this. if (maxNumChannels < 2 ) maxNumChannels = 2; if (maxNumChannels > 32) maxNumChannels = 32; mMixerSpec = new MixerSpec( numTracks, maxNumChannels ); wxBoxSizer *vertSizer = new wxBoxSizer( wxVERTICAL ); wxWindow *mixerPanel = new ExportMixerPanel( mMixerSpec, mTrackNames, this, ID_MIXERPANEL, wxDefaultPosition, wxSize( 400, -1 ) ); vertSizer->Add( mixerPanel, 1, wxEXPAND | wxALIGN_CENTRE | wxALL, 5 ); wxBoxSizer *horSizer = new wxBoxSizer( wxHORIZONTAL ); mChannelsText = new wxStaticText( this, -1, wxString::Format( _( "Output Channels: %2d" ), mMixerSpec->GetNumChannels() ) ); horSizer->Add( mChannelsText, 0, wxALIGN_LEFT | wxALL, 5 ); wxSlider *channels = new wxSlider( this, ID_SLIDER_CHANNEL, mMixerSpec->GetNumChannels(), 1, mMixerSpec->GetMaxNumChannels(), wxDefaultPosition, wxSize( 300, -1 ) ); horSizer->Add( channels, 0, wxEXPAND | wxALL, 5 ); vertSizer->Add( horSizer, 0, wxALIGN_CENTRE | wxALL, 5 ); vertSizer->Add( CreateStdButtonSizer(this, eCancelButton|eOkButton), 0, wxEXPAND ); SetAutoLayout( true ); SetSizer( vertSizer ); vertSizer->Fit( this ); vertSizer->SetSizeHints( this ); SetSizeHints( 640, 480, 20000, 20000 ); SetSize( 640, 480 ); }