mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 08:39:46 +02:00
More rewrites of iterations over channels...
... that can generalize to more than stereo
This commit is contained in:
commit
3561154311
@ -2051,25 +2051,6 @@ void AudacityProject::FixScrollbars()
|
||||
GetTrackPanel()->HandleCursorForPresentMouseState(); } );
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> AudacityProject::GetFirstVisible()
|
||||
{
|
||||
std::shared_ptr<Track> pTrack;
|
||||
if (GetTracks()) {
|
||||
TrackListIterator iter(GetTracks());
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
int y = t->GetY();
|
||||
int h = t->GetHeight();
|
||||
if (y + h - 1 >= mViewInfo.vpos) {
|
||||
// At least the bottom row of pixels is not scrolled away above
|
||||
pTrack = Track::Pointer(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pTrack;
|
||||
}
|
||||
|
||||
void AudacityProject::UpdateLayout()
|
||||
{
|
||||
if (!mTrackPanel)
|
||||
@ -4232,23 +4213,35 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
||||
bool initiallyEmpty = mTracks->empty();
|
||||
double newRate = 0;
|
||||
wxString trackNameBase = fileName.AfterLast(wxFILE_SEP_PATH).BeforeLast('.');
|
||||
bool isLinked = false;
|
||||
int i = -1;
|
||||
for (auto &uNewTrack : newTracks) {
|
||||
++i;
|
||||
|
||||
// Must add all tracks first (before using Track::IsLeader)
|
||||
for (auto &uNewTrack : newTracks) {
|
||||
auto newTrack = mTracks->Add(std::move(uNewTrack));
|
||||
results.push_back(Track::Pointer(newTrack));
|
||||
}
|
||||
newTracks.clear();
|
||||
|
||||
// Now name them
|
||||
|
||||
// Add numbers to track names only if there is more than one (mono or stereo)
|
||||
// track (not necessarily, more than one channel)
|
||||
const bool useSuffix =
|
||||
make_iterator_range( results.begin() + 1, results.end() )
|
||||
.any_of( []( decltype(*results.begin()) &pTrack )
|
||||
{ return pTrack->IsLeader(); } );
|
||||
|
||||
for (const auto &newTrack : results) {
|
||||
if ( newTrack->IsLeader() )
|
||||
// Count groups only
|
||||
++i;
|
||||
|
||||
newTrack->SetSelected(true);
|
||||
//we need to check link status based on the first channel only.
|
||||
if(0==i)
|
||||
isLinked = newTrack->GetLinked();
|
||||
if (numTracks > 2 || (numTracks > 1 && !isLinked) ) {
|
||||
|
||||
if ( useSuffix )
|
||||
newTrack->SetName(trackNameBase + wxString::Format(wxT(" %d" ), i + 1));
|
||||
}
|
||||
else {
|
||||
else
|
||||
newTrack->SetName(trackNameBase);
|
||||
}
|
||||
|
||||
newTrack->TypeSwitch( [&](WaveTrack *wt) {
|
||||
if (newRate == 0)
|
||||
@ -4299,8 +4292,6 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
||||
// Moved this call to higher levels to prevent flicker redrawing everything on each file.
|
||||
// HandleResize();
|
||||
|
||||
newTracks.clear();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -213,8 +213,6 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
|
||||
const ViewInfo &GetViewInfo() const { return mViewInfo; }
|
||||
ViewInfo &GetViewInfo() { return mViewInfo; }
|
||||
|
||||
std::shared_ptr<Track> GetFirstVisible();
|
||||
|
||||
void GetPlayRegion(double* playRegionStart, double *playRegionEnd);
|
||||
bool IsPlayRegionLocked() { return mLockPlayRegion; }
|
||||
void SetPlayRegionLocked(bool value) { mLockPlayRegion = value; }
|
||||
|
@ -341,7 +341,6 @@ void TrackArtist::SetMargins(int left, int top, int right, int bottom)
|
||||
|
||||
void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
const TrackList * tracks,
|
||||
Track * start,
|
||||
const wxRegion & reg,
|
||||
const wxRect & rect,
|
||||
const wxRect & clip,
|
||||
@ -351,13 +350,11 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
bool bigPoints,
|
||||
bool drawSliders)
|
||||
{
|
||||
// Copy the horizontal extent of rect; will later change only the vertical.
|
||||
wxRect trackRect = rect;
|
||||
wxRect stereoTrackRect;
|
||||
TrackListConstIterator iter(tracks);
|
||||
const Track *t;
|
||||
|
||||
bool hasSolo = false;
|
||||
for (t = iter.First(); t; t = iter.Next()) {
|
||||
for (const Track *t : *tracks) {
|
||||
t = t->SubstitutePendingChangedTrack().get();
|
||||
auto pt = dynamic_cast<const PlayableTrack *>(t);
|
||||
if (pt && pt->GetSolo()) {
|
||||
@ -381,60 +378,52 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
|
||||
|
||||
gPrefs->Read(wxT("/GUI/ShowTrackNameInWaveform"), &mbShowTrackNameInWaveform, false);
|
||||
|
||||
t = iter.StartWith(start);
|
||||
while (t) {
|
||||
t = t->SubstitutePendingChangedTrack().get();
|
||||
trackRect.y = t->GetY() - zoomInfo.vpos;
|
||||
trackRect.height = t->GetHeight();
|
||||
for(auto leader : tracks->Leaders()) {
|
||||
auto group = TrackList::Channels( leader );
|
||||
leader = leader->SubstitutePendingChangedTrack().get();
|
||||
|
||||
if (trackRect.y > clip.GetBottom() && !t->GetLinked()) {
|
||||
trackRect.y = leader->GetY() - zoomInfo.vpos;
|
||||
trackRect.height = group.sum( [&] (const Track *channel) {
|
||||
channel = channel->SubstitutePendingChangedTrack().get();
|
||||
return channel->GetHeight();
|
||||
});
|
||||
|
||||
if (trackRect.GetBottom() < clip.GetTop())
|
||||
continue;
|
||||
else if (trackRect.GetTop() > clip.GetBottom())
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto t : group) {
|
||||
t = t->SubstitutePendingChangedTrack().get();
|
||||
|
||||
#if defined(DEBUG_CLIENT_AREA)
|
||||
// Filled rectangle to show the interior of the client area
|
||||
wxRect zr = trackRect;
|
||||
zr.x+=1; zr.y+=5; zr.width-=7; zr.height-=7;
|
||||
dc.SetPen(*wxCYAN_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
dc.DrawRectangle(zr);
|
||||
// Filled rectangle to show the interior of the client area
|
||||
wxRect zr = trackRect;
|
||||
zr.x+=1; zr.y+=5; zr.width-=7; zr.height-=7;
|
||||
dc.SetPen(*wxCYAN_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
dc.DrawRectangle(zr);
|
||||
#endif
|
||||
|
||||
stereoTrackRect = trackRect;
|
||||
// For various reasons, the code will break if we display one
|
||||
// of a stereo pair of tracks but not the other - for example,
|
||||
// if you try to edit the envelope of one track when its linked
|
||||
// pair is off the screen, then it won't be able to edit the
|
||||
// offscreen envelope. So we compute the rect of the track and
|
||||
// its linked partner, and see if any part of that rect is on-screen.
|
||||
// If so, we draw both. Otherwise, we can safely draw neither.
|
||||
|
||||
// For various reasons, the code will break if we display one
|
||||
// of a stereo pair of tracks but not the other - for example,
|
||||
// if you try to edit the envelope of one track when its linked
|
||||
// pair is off the screen, then it won't be able to edit the
|
||||
// offscreen envelope. So we compute the rect of the track and
|
||||
// its linked partner, and see if any part of that rect is on-screen.
|
||||
// If so, we draw both. Otherwise, we can safely draw neither.
|
||||
|
||||
Track *link = t->GetLink();
|
||||
if (link) {
|
||||
if (t->GetLinked()) {
|
||||
// If we're the first track
|
||||
stereoTrackRect.height += link->GetHeight();
|
||||
}
|
||||
else {
|
||||
// We're the second of two
|
||||
stereoTrackRect.y -= link->GetHeight();
|
||||
stereoTrackRect.height += link->GetHeight();
|
||||
if (trackRect.Intersects(clip) && reg.Contains(trackRect)) {
|
||||
wxRect rr = trackRect;
|
||||
rr.x += mMarginLeft;
|
||||
rr.y += mMarginTop;
|
||||
rr.width -= (mMarginLeft + mMarginRight);
|
||||
rr.height -= (mMarginTop + mMarginBottom);
|
||||
DrawTrack(context, t, rr,
|
||||
selectedRegion, zoomInfo,
|
||||
drawEnvelope, bigPoints, drawSliders, hasSolo);
|
||||
}
|
||||
}
|
||||
|
||||
if (stereoTrackRect.Intersects(clip) && reg.Contains(stereoTrackRect)) {
|
||||
wxRect rr = trackRect;
|
||||
rr.x += mMarginLeft;
|
||||
rr.y += mMarginTop;
|
||||
rr.width -= (mMarginLeft + mMarginRight);
|
||||
rr.height -= (mMarginTop + mMarginBottom);
|
||||
DrawTrack(context, t, rr,
|
||||
selectedRegion, zoomInfo,
|
||||
drawEnvelope, bigPoints, drawSliders, hasSolo);
|
||||
}
|
||||
|
||||
t = iter.Next();
|
||||
}
|
||||
}
|
||||
|
||||
@ -480,8 +469,7 @@ void TrackArtist::DrawTrack(TrackPanelDrawingContext &context,
|
||||
#endif
|
||||
|
||||
if (mbShowTrackNameInWaveform &&
|
||||
// Exclude right channel of stereo track
|
||||
!(!wt->GetLinked() && wt->GetLink()) &&
|
||||
wt->IsLeader() &&
|
||||
// Exclude empty name.
|
||||
!wt->GetName().IsEmpty()) {
|
||||
wxBrush Brush;
|
||||
|
@ -55,7 +55,7 @@ class AUDACITY_DLL_API TrackArtist {
|
||||
|
||||
void SetColours(int iColorIndex);
|
||||
void DrawTracks(TrackPanelDrawingContext &context,
|
||||
const TrackList *tracks, Track *start,
|
||||
const TrackList *tracks,
|
||||
const wxRegion & reg,
|
||||
const wxRect & rect, const wxRect & clip,
|
||||
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
|
||||
|
@ -1156,8 +1156,7 @@ void TrackPanel::DrawTracks(wxDC * dc)
|
||||
TrackPanelDrawingContext context{ *dc, Target(), mLastMouseState };
|
||||
|
||||
// The track artist actually draws the stuff inside each track
|
||||
auto first = GetProject()->GetFirstVisible();
|
||||
mTrackArtist->DrawTracks(context, GetTracks(), first.get(),
|
||||
mTrackArtist->DrawTracks(context, GetTracks(),
|
||||
region, tracksRect, clip,
|
||||
mViewInfo->selectedRegion, *mViewInfo,
|
||||
envelopeFlag, bigPointsFlag, sliderFlag);
|
||||
@ -1847,14 +1846,12 @@ void TrackPanel::UpdateTrackVRuler(const Track *t)
|
||||
wxRect rect(GetVRulerOffset(),
|
||||
kTopMargin,
|
||||
GetVRulerWidth(),
|
||||
t->GetHeight() - (kTopMargin + kBottomMargin));
|
||||
0);
|
||||
|
||||
mTrackArtist->UpdateVRuler(t, rect);
|
||||
const Track *l = t->GetLink();
|
||||
if (l)
|
||||
{
|
||||
rect.height = l->GetHeight() - (kTopMargin + kBottomMargin);
|
||||
mTrackArtist->UpdateVRuler(l, rect);
|
||||
|
||||
for (auto channel : TrackList::Channels(t)) {
|
||||
rect.height = channel->GetHeight() - (kTopMargin + kBottomMargin);
|
||||
mTrackArtist->UpdateVRuler(channel, rect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2080,30 +2077,29 @@ wxRect TrackPanel::FindTrackRect( const Track * target, bool label )
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
wxRect rect{
|
||||
0,
|
||||
target->GetY() - mViewInfo->vpos,
|
||||
GetSize().GetWidth(),
|
||||
target->GetHeight()
|
||||
};
|
||||
|
||||
// PRL: I think the following very old comment misused the term "race
|
||||
// condition" for a bug that happened with only a single thread. I think the
|
||||
// real problem referred to, was that this function could be reached, via
|
||||
// TrackPanelAx callbacks, during low-level operations while the TrackList
|
||||
// was not in a consistent state. Therefore GetLinked() did not imply
|
||||
// that GetLink() was not null.
|
||||
// was not in a consistent state.
|
||||
// Now the problem is fixed by delaying the handling of events generated
|
||||
// by TrackList.
|
||||
// by TrackList. And besides that, we use Channels() instead of looking
|
||||
// directly at the links.
|
||||
|
||||
// Old comment:
|
||||
// The check for a null linked track is necessary because there's
|
||||
// a possible race condition between the time the 2 linked tracks
|
||||
// are added and when wxAccessible methods are called. This is
|
||||
// most evident when using Jaws.
|
||||
if (target->GetLinked() && target->GetLink()) {
|
||||
rect.height += target->GetLink()->GetHeight();
|
||||
}
|
||||
auto height = TrackList::Channels( target ).sum( &Track::GetHeight );
|
||||
|
||||
wxRect rect{
|
||||
0,
|
||||
target->GetY() - mViewInfo->vpos,
|
||||
GetSize().GetWidth(),
|
||||
height
|
||||
};
|
||||
|
||||
|
||||
rect.x += kLeftMargin;
|
||||
if (label)
|
||||
@ -2151,8 +2147,7 @@ void TrackPanel::SetFocusedCell()
|
||||
void TrackPanel::SetFocusedTrack( Track *t )
|
||||
{
|
||||
// Make sure we always have the first linked track of a stereo track
|
||||
if (t && !t->GetLinked() && t->GetLink())
|
||||
t = (WaveTrack*)t->GetLink();
|
||||
t = *GetTracks()->FindLeader(t);
|
||||
|
||||
auto cell = mAx->SetFocus( Track::Pointer( t ) ).get();
|
||||
|
||||
@ -2657,7 +2652,7 @@ TrackPanelCellIterator &TrackPanelCellIterator::operator++ ()
|
||||
}
|
||||
if ( mpTrack ) {
|
||||
if ( mType == CellType::Label &&
|
||||
mpTrack->GetLink() && !mpTrack->GetLinked() )
|
||||
!mpTrack->IsLeader() )
|
||||
// Visit label of stereo track only once
|
||||
++mType;
|
||||
switch ( mType ) {
|
||||
@ -2723,10 +2718,10 @@ void TrackPanelCellIterator::UpdateRect()
|
||||
mRect.x = kLeftMargin;
|
||||
mRect.width = kTrackInfoWidth - mRect.x;
|
||||
mRect.y += kTopMargin;
|
||||
mRect.height =
|
||||
TrackList::Channels(mpTrack.get())
|
||||
.sum( &Track::GetHeight );
|
||||
mRect.height -= (kBottomMargin + kTopMargin);
|
||||
auto partner = mpTrack->GetLink();
|
||||
if ( partner && mpTrack->GetLinked() )
|
||||
mRect.height += partner->GetHeight();
|
||||
break;
|
||||
}
|
||||
case CellType::VRuler:
|
||||
@ -2742,11 +2737,12 @@ void TrackPanelCellIterator::UpdateRect()
|
||||
// The resizer region encompasses the bottom margin proper to this
|
||||
// track, plus the top margin of the next track (or, an equally
|
||||
// tall zone below, in case there is no next track)
|
||||
auto partner = mpTrack->GetLink();
|
||||
if ( partner && mpTrack->GetLinked() )
|
||||
mRect.x = kTrackInfoWidth;
|
||||
else
|
||||
if ( mpTrack.get() ==
|
||||
*TrackList::Channels(mpTrack.get()).rbegin() )
|
||||
// Last channel has a resizer extending farther leftward
|
||||
mRect.x = kLeftMargin;
|
||||
else
|
||||
mRect.x = kTrackInfoWidth;
|
||||
mRect.width -= (mRect.x + kRightMargin);
|
||||
mRect.y += (mRect.height - kBottomMargin);
|
||||
mRect.height = (kBottomMargin + kTopMargin);
|
||||
|
@ -144,13 +144,9 @@ bool TrackPanelAx::IsFocused( const Track *track )
|
||||
if (origTrack)
|
||||
track = origTrack;
|
||||
|
||||
if( ( track == focusedTrack.get() ) ||
|
||||
( focusedTrack && track == focusedTrack->GetLink() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return focusedTrack
|
||||
? TrackList::Channels(focusedTrack.get()).contains(track)
|
||||
: !track;
|
||||
}
|
||||
|
||||
int TrackPanelAx::TrackNum( const std::shared_ptr<Track> &target )
|
||||
|
@ -143,8 +143,6 @@ UIHandle::Result CutlineHandle::Click
|
||||
|
||||
// Cutline data changed on either branch, so refresh the track display.
|
||||
UIHandle::Result result = RefreshCell;
|
||||
// Assume linked track is wave or null
|
||||
const auto linked = static_cast<WaveTrack*>(mpTrack->GetLink());
|
||||
|
||||
if (event.LeftDown())
|
||||
{
|
||||
@ -156,26 +154,30 @@ UIHandle::Result CutlineHandle::Click
|
||||
|
||||
// When user presses left button on cut line, expand the line again
|
||||
double cutlineStart = 0, cutlineEnd = 0;
|
||||
double *pCutlineStart = &cutlineStart, *pCutlineEnd = &cutlineEnd;
|
||||
|
||||
mpTrack->ExpandCutLine(mLocation.pos, &cutlineStart, &cutlineEnd);
|
||||
|
||||
if (linked)
|
||||
// Expand the cutline in the opposite channel if it is present.
|
||||
linked->ExpandCutLine(mLocation.pos);
|
||||
for (auto channel :
|
||||
TrackList::Channels(mpTrack.get())) {
|
||||
channel->ExpandCutLine(
|
||||
mLocation.pos, pCutlineStart, pCutlineEnd);
|
||||
if ( channel == mpTrack.get() )
|
||||
pCutlineStart = pCutlineEnd = nullptr;
|
||||
}
|
||||
|
||||
viewInfo.selectedRegion.setTimes(cutlineStart, cutlineEnd);
|
||||
result |= UpdateSelection;
|
||||
}
|
||||
else if (mLocation.typ == WaveTrackLocation::locationMergePoint) {
|
||||
const double pos = mLocation.pos;
|
||||
mpTrack->MergeClips(mLocation.clipidx1, mLocation.clipidx2);
|
||||
|
||||
if (linked) {
|
||||
for (auto channel :
|
||||
TrackList::Channels(mpTrack.get())) {
|
||||
// Don't assume correspondence of merge points across channels!
|
||||
int idx = FindMergeLine(linked, pos);
|
||||
int idx = FindMergeLine(channel, pos);
|
||||
if (idx >= 0) {
|
||||
WaveTrack::Location location = linked->GetCachedLocations()[idx];
|
||||
linked->MergeClips(location.clipidx1, location.clipidx2);
|
||||
WaveTrack::Location location =
|
||||
channel->GetCachedLocations()[idx];
|
||||
channel->MergeClips(
|
||||
location.clipidx1, location.clipidx2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,10 +186,10 @@ UIHandle::Result CutlineHandle::Click
|
||||
}
|
||||
else if (event.RightDown())
|
||||
{
|
||||
bool removed = mpTrack->RemoveCutLine(mLocation.pos);
|
||||
|
||||
if (linked)
|
||||
removed = linked->RemoveCutLine(mLocation.pos) || removed;
|
||||
bool removed = false;
|
||||
for (auto channel :
|
||||
TrackList::Channels(mpTrack.get()))
|
||||
removed = channel->RemoveCutLine(mLocation.pos) || removed;
|
||||
|
||||
if (!removed)
|
||||
// Nothing happened, make no Undo item
|
||||
|
@ -213,14 +213,9 @@ void WaveColorMenuTable::OnWaveColorChange(wxCommandEvent & event)
|
||||
int newWaveColor = id - OnInstrument1ID;
|
||||
|
||||
AudacityProject *const project = ::GetActiveProject();
|
||||
// TrackList *const tracks = project->GetTracks();
|
||||
|
||||
pTrack->SetWaveColorIndex(newWaveColor);
|
||||
|
||||
// Assume partner is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(pTrack->GetLink());
|
||||
if (partner)
|
||||
partner->SetWaveColorIndex(newWaveColor);
|
||||
for (auto channel : TrackList::Channels(pTrack))
|
||||
channel->SetWaveColorIndex(newWaveColor);
|
||||
|
||||
project->PushState(wxString::Format(_("Changed '%s' to %s"),
|
||||
pTrack->GetName(),
|
||||
@ -336,12 +331,9 @@ void FormatMenuTable::OnFormatChange(wxCommandEvent & event)
|
||||
return; // Nothing to do.
|
||||
|
||||
AudacityProject *const project = ::GetActiveProject();
|
||||
pTrack->ConvertToSampleFormat(newFormat);
|
||||
|
||||
// Assume partner is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(pTrack->GetLink());
|
||||
if (partner)
|
||||
partner->ConvertToSampleFormat(newFormat);
|
||||
for (auto channel : TrackList::Channels(pTrack))
|
||||
channel->ConvertToSampleFormat(newFormat);
|
||||
|
||||
/* i18n-hint: The strings name a track and a format */
|
||||
project->PushState(wxString::Format(_("Changed '%s' to %s"),
|
||||
@ -439,11 +431,9 @@ int RateMenuTable::IdOfRate(int rate)
|
||||
void RateMenuTable::SetRate(WaveTrack * pTrack, double rate)
|
||||
{
|
||||
AudacityProject *const project = ::GetActiveProject();
|
||||
pTrack->SetRate(rate);
|
||||
// Assume linked track is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(pTrack->GetLink());
|
||||
if (partner)
|
||||
partner->SetRate(rate);
|
||||
for (auto channel : TrackList::Channels(pTrack))
|
||||
channel->SetRate(rate);
|
||||
|
||||
// Separate conversion of "rate" enables changing the decimals without affecting i18n
|
||||
wxString rateString = wxString::Format(wxT("%.3f"), rate);
|
||||
/* i18n-hint: The string names a track */
|
||||
@ -733,22 +723,13 @@ void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event)
|
||||
(id == WaveTrack::Waveform &&
|
||||
pTrack->GetWaveformSettings().isLinear() != linear);
|
||||
if (wrongType || wrongScale) {
|
||||
pTrack->SetLastScaleType();
|
||||
pTrack->SetDisplay(WaveTrack::WaveTrackDisplay(id));
|
||||
if (wrongScale)
|
||||
pTrack->GetIndependentWaveformSettings().scaleType = linear
|
||||
? WaveformSettings::stLinear
|
||||
: WaveformSettings::stLogarithmic;
|
||||
|
||||
// Assume partner is wave or null
|
||||
auto partner = static_cast<WaveTrack *>(pTrack->GetLink());
|
||||
if (partner) {
|
||||
partner->SetLastScaleType();
|
||||
partner->SetDisplay(WaveTrack::WaveTrackDisplay(id));
|
||||
for (auto channel : TrackList::Channels(pTrack)) {
|
||||
channel->SetLastScaleType();
|
||||
channel->SetDisplay(WaveTrack::WaveTrackDisplay(id));
|
||||
if (wrongScale)
|
||||
partner->GetIndependentWaveformSettings().scaleType = linear
|
||||
? WaveformSettings::stLinear
|
||||
: WaveformSettings::stLogarithmic;
|
||||
channel->GetIndependentWaveformSettings().scaleType = linear
|
||||
? WaveformSettings::stLinear
|
||||
: WaveformSettings::stLogarithmic;
|
||||
}
|
||||
|
||||
AudacityProject *const project = ::GetActiveProject();
|
||||
|
@ -47,12 +47,9 @@ UIHandle::Result GainSliderHandle::SetValue
|
||||
auto pTrack = GetWaveTrack();
|
||||
|
||||
if (pTrack) {
|
||||
pTrack->SetGain(newValue);
|
||||
|
||||
// Assume linked track is wave or null
|
||||
const auto link = static_cast<WaveTrack*>(mpTrack.lock()->GetLink());
|
||||
if (link)
|
||||
link->SetGain(newValue);
|
||||
for (auto channel :
|
||||
TrackList::Channels(pTrack.get()))
|
||||
channel->SetGain(newValue);
|
||||
|
||||
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
|
||||
if (pMixerBoard)
|
||||
@ -131,12 +128,9 @@ UIHandle::Result PanSliderHandle::SetValue(AudacityProject *pProject, float newV
|
||||
auto pTrack = GetWaveTrack();
|
||||
|
||||
if (pTrack) {
|
||||
pTrack->SetPan(newValue);
|
||||
|
||||
// Assume linked track is wave or null
|
||||
const auto link = static_cast<WaveTrack*>(pTrack->GetLink());
|
||||
if (link)
|
||||
link->SetPan(newValue);
|
||||
for (auto channel :
|
||||
TrackList::Channels(pTrack.get()))
|
||||
channel->SetPan(newValue);
|
||||
|
||||
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
|
||||
if (pMixerBoard)
|
||||
|
@ -58,13 +58,12 @@ void WaveTrackVRulerControls::DoZoomPreset( int i)
|
||||
|
||||
const auto wt = static_cast<WaveTrack*>(pTrack.get());
|
||||
|
||||
// Don't pass the partner, that causes problems when updating display
|
||||
// Don't do all channels, that causes problems when updating display
|
||||
// during recording and there are special pending tracks.
|
||||
// This function implements WaveTrack::DoSetMinimized which is always
|
||||
// called in a context that loops over linked tracks too and reinvokes.
|
||||
auto partner = nullptr;
|
||||
WaveTrackVZoomHandle::DoZoom(
|
||||
NULL, wt, partner, (i==1)?kZoomHalfWave: kZoom1to1,
|
||||
NULL, wt, false, (i==1)?kZoomHalfWave: kZoom1to1,
|
||||
wxRect(0,0,0,0), 0,0, true);
|
||||
}
|
||||
|
||||
@ -88,9 +87,7 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
wxASSERT(pTrack->GetKind() == Track::Wave);
|
||||
auto steps = evt.steps;
|
||||
|
||||
const auto wt = static_cast<WaveTrack*>(pTrack.get());
|
||||
// Assume linked track is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack.get());
|
||||
const bool isDB =
|
||||
wt->GetDisplay() == WaveTrack::Waveform &&
|
||||
wt->GetWaveformSettings().scaleType == WaveformSettings::stLogarithmic;
|
||||
@ -102,24 +99,20 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
if (!(min < 0.0 && max > 0.0))
|
||||
return RefreshNone;
|
||||
|
||||
WaveformSettings &settings = wt->GetIndependentWaveformSettings();
|
||||
WaveformSettings &settings =
|
||||
wt->GetIndependentWaveformSettings();
|
||||
float olddBRange = settings.dBRange;
|
||||
if (steps < 0)
|
||||
// Zoom out
|
||||
settings.NextLowerDBRange();
|
||||
else
|
||||
settings.NextHigherDBRange();
|
||||
float newdBRange = settings.dBRange;
|
||||
|
||||
if (partner) {
|
||||
WaveformSettings &settings = partner->GetIndependentWaveformSettings();
|
||||
for (auto channel : TrackList::Channels(wt)) {
|
||||
WaveformSettings &channelSettings =
|
||||
channel->GetIndependentWaveformSettings();
|
||||
if (steps < 0)
|
||||
// Zoom out
|
||||
settings.NextLowerDBRange();
|
||||
channelSettings.NextLowerDBRange();
|
||||
else
|
||||
settings.NextHigherDBRange();
|
||||
channelSettings.NextHigherDBRange();
|
||||
}
|
||||
|
||||
float newdBRange = settings.dBRange;
|
||||
|
||||
// Is y coordinate within the rectangle half-height centered about
|
||||
// the zero level?
|
||||
@ -135,19 +128,16 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
const float extreme = (LINEAR_TO_DB(2) + newdBRange) / newdBRange;
|
||||
max = std::min(extreme, max * olddBRange / newdBRange);
|
||||
min = std::max(-extreme, min * olddBRange / newdBRange);
|
||||
wt->SetLastdBRange();
|
||||
wt->SetDisplayBounds(min, max);
|
||||
if (partner) {
|
||||
partner->SetLastdBRange();
|
||||
partner->SetDisplayBounds(min, max);
|
||||
for (auto channel : TrackList::Channels(wt)) {
|
||||
channel->SetLastdBRange();
|
||||
channel->SetDisplayBounds(min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.CmdDown() && !event.ShiftDown()) {
|
||||
const int yy = event.m_y;
|
||||
const auto partner = static_cast<WaveTrack *>(wt);
|
||||
WaveTrackVZoomHandle::DoZoom(
|
||||
pProject, wt, partner, (steps < 0)?kZoomOut:kZoomIn,
|
||||
pProject, wt, true, (steps < 0)?kZoomOut:kZoomIn,
|
||||
evt.rect, yy, yy, true);
|
||||
}
|
||||
else if (!event.CmdDown() && event.ShiftDown()) {
|
||||
@ -173,9 +163,8 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
std::min(bound,
|
||||
numberScale.PositionToValue(numberScale.ValueToPosition(newBottom) + 1.0f));
|
||||
|
||||
wt->SetSpectrumBounds(newBottom, newTop);
|
||||
if (partner)
|
||||
partner->SetSpectrumBounds(newBottom, newTop);
|
||||
for (auto channel : TrackList::Channels(wt))
|
||||
channel->SetSpectrumBounds(newBottom, newTop);
|
||||
}
|
||||
else {
|
||||
float topLimit = 2.0;
|
||||
@ -191,9 +180,8 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
||||
float newTop = std::min(topLimit, top + delta);
|
||||
const float newBottom = std::max(bottomLimit, newTop - range);
|
||||
newTop = std::min(topLimit, newBottom + range);
|
||||
wt->SetDisplayBounds(newBottom, newTop);
|
||||
if (partner)
|
||||
partner->SetDisplayBounds(newBottom, newTop);
|
||||
for (auto channel : TrackList::Channels(wt))
|
||||
channel->SetDisplayBounds(newBottom, newTop);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -65,11 +65,12 @@ void WaveTrackVZoomHandle::Enter(bool)
|
||||
// the zoomKind and cause a drag-zoom-in.
|
||||
void WaveTrackVZoomHandle::DoZoom
|
||||
(AudacityProject *pProject,
|
||||
WaveTrack *pTrack, WaveTrack *partner, int ZoomKind,
|
||||
WaveTrack *pTrack, bool allChannels, int ZoomKind,
|
||||
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||
bool fixedMousePoint)
|
||||
{
|
||||
static const float ZOOMLIMIT = 0.001f;
|
||||
|
||||
int height = rect.height;
|
||||
int ypos = rect.y;
|
||||
|
||||
@ -318,15 +319,13 @@ void WaveTrackVZoomHandle::DoZoom
|
||||
}
|
||||
|
||||
// Now actually apply the zoom.
|
||||
if (spectral) {
|
||||
pTrack->SetSpectrumBounds(min, max);
|
||||
if (partner)
|
||||
partner->SetSpectrumBounds(min, max);
|
||||
}
|
||||
else {
|
||||
pTrack->SetDisplayBounds(min, max);
|
||||
if (partner)
|
||||
partner->SetDisplayBounds(min, max);
|
||||
for (auto channel : TrackList::Channels(pTrack)) {
|
||||
if (!allChannels && channel != pTrack)
|
||||
continue;
|
||||
if (spectral)
|
||||
channel->SetSpectrumBounds(min, max);
|
||||
else
|
||||
channel->SetDisplayBounds(min, max);
|
||||
}
|
||||
|
||||
zoomEnd = zoomStart = 0;
|
||||
@ -389,10 +388,8 @@ void WaveTrackVRulerMenuTable::InitMenu(Menu *, void *pUserData)
|
||||
|
||||
void WaveTrackVRulerMenuTable::OnZoom( int iZoomCode )
|
||||
{
|
||||
// Assume linked track is wave or null
|
||||
const auto partner = static_cast<WaveTrack *>(mpData->pTrack->GetLink());
|
||||
WaveTrackVZoomHandle::DoZoom
|
||||
(::GetActiveProject(), mpData->pTrack, partner,
|
||||
(::GetActiveProject(), mpData->pTrack, true,
|
||||
iZoomCode, mpData->rect, mpData->yy, mpData->yy, false);
|
||||
|
||||
using namespace RefreshCode;
|
||||
@ -467,17 +464,17 @@ void WaveformVRulerMenuTable::OnWaveformScaleType(wxCommandEvent &evt)
|
||||
{
|
||||
WaveTrack *const wt = mpData->pTrack;
|
||||
// Assume linked track is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
const WaveformSettings::ScaleType newScaleType =
|
||||
WaveformSettings::ScaleType(
|
||||
std::max(0,
|
||||
std::min((int)(WaveformSettings::stNumScaleTypes) - 1,
|
||||
evt.GetId() - OnFirstWaveformScaleID
|
||||
)));
|
||||
|
||||
if (wt->GetWaveformSettings().scaleType != newScaleType) {
|
||||
wt->GetIndependentWaveformSettings().scaleType = newScaleType;
|
||||
if (partner)
|
||||
partner->GetIndependentWaveformSettings().scaleType = newScaleType;
|
||||
for (auto channel : TrackList::Channels(wt)) {
|
||||
channel->GetIndependentWaveformSettings().scaleType = newScaleType;
|
||||
}
|
||||
|
||||
::GetActiveProject()->ModifyState(true);
|
||||
|
||||
@ -540,8 +537,7 @@ END_POPUP_MENU()
|
||||
void SpectrumVRulerMenuTable::OnSpectrumScaleType(wxCommandEvent &evt)
|
||||
{
|
||||
WaveTrack *const wt = mpData->pTrack;
|
||||
// Assume linked track is wave or null
|
||||
const auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
|
||||
const SpectrogramSettings::ScaleType newScaleType =
|
||||
SpectrogramSettings::ScaleType(
|
||||
std::max(0,
|
||||
@ -549,9 +545,8 @@ void SpectrumVRulerMenuTable::OnSpectrumScaleType(wxCommandEvent &evt)
|
||||
evt.GetId() - OnFirstSpectrumScaleID
|
||||
)));
|
||||
if (wt->GetSpectrogramSettings().scaleType != newScaleType) {
|
||||
wt->GetIndependentSpectrogramSettings().scaleType = newScaleType;
|
||||
if (partner)
|
||||
partner->GetIndependentSpectrogramSettings().scaleType = newScaleType;
|
||||
for (auto channel : TrackList::Channels(wt))
|
||||
channel->GetIndependentSpectrogramSettings().scaleType = newScaleType;
|
||||
|
||||
::GetActiveProject()->ModifyState(true);
|
||||
|
||||
@ -678,8 +673,7 @@ UIHandle::Result WaveTrackVZoomHandle::Release
|
||||
if( bVZoom ){
|
||||
if( shiftDown )
|
||||
mZoomStart=mZoomEnd;
|
||||
const auto partner = static_cast<WaveTrack *>(pTrack->GetLink());
|
||||
DoZoom(pProject, pTrack.get(), partner,
|
||||
DoZoom(pProject, pTrack.get(), true,
|
||||
shiftDown ? (rightUp ? kZoom1to1 : kZoomOut) : kZoomIn,
|
||||
mRect, mZoomStart, mZoomEnd, !shiftDown);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
|
||||
static void DoZoom
|
||||
(AudacityProject *pProject,
|
||||
WaveTrack *pTrack, WaveTrack *partner, int ZoomKind,
|
||||
WaveTrack *pTrack, bool allChannels, int ZoomKind,
|
||||
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||
bool fixedMousePoint);
|
||||
|
||||
|
@ -178,6 +178,8 @@ UIHandle::Result EnvelopeHandle::Click
|
||||
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||
const auto pTrack = static_cast<Track*>(evt.pCell.get());
|
||||
|
||||
mEnvelopeEditors.clear();
|
||||
|
||||
unsigned result = Cancelled;
|
||||
if (pTrack)
|
||||
result = pTrack->TypeSwitch< decltype(RefreshNone) >(
|
||||
@ -191,18 +193,21 @@ UIHandle::Result EnvelopeHandle::Click
|
||||
mLog = !wt->GetWaveformSettings().isLinear();
|
||||
wt->GetDisplayBounds(&mLower, &mUpper);
|
||||
mdBRange = wt->GetWaveformSettings().dBRange;
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, true );
|
||||
mEnvelopeEditorRight.reset();
|
||||
|
||||
// Assume linked track is wave or null
|
||||
auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||
if (partner)
|
||||
{
|
||||
auto clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||
if (clickedEnvelope)
|
||||
mEnvelopeEditorRight =
|
||||
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||
auto channels = TrackList::Channels( wt );
|
||||
for ( auto channel : channels ) {
|
||||
if (channel == wt)
|
||||
mEnvelopeEditors.push_back(
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, true ) );
|
||||
else {
|
||||
auto e2 = channel->GetEnvelopeAtX(event.GetX());
|
||||
if (e2)
|
||||
mEnvelopeEditors.push_back(
|
||||
std::make_unique< EnvelopeEditor >( *e2, true ) );
|
||||
else {
|
||||
// There isn't necessarily an envelope there; no guarantee a
|
||||
// linked track has the same WaveClip structure...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RefreshNone;
|
||||
@ -211,9 +216,9 @@ UIHandle::Result EnvelopeHandle::Click
|
||||
if (!mEnvelope)
|
||||
return Cancelled;
|
||||
GetTimeTrackData( *pProject, *tt, mdBRange, mLog, mLower, mUpper);
|
||||
mEnvelopeEditor =
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, false );
|
||||
mEnvelopeEditorRight.reset();
|
||||
mEnvelopeEditors.push_back(
|
||||
std::make_unique< EnvelopeEditor >( *mEnvelope, false )
|
||||
);
|
||||
|
||||
return RefreshNone;
|
||||
},
|
||||
@ -289,8 +294,7 @@ UIHandle::Result EnvelopeHandle::Release
|
||||
_("Envelope")
|
||||
);
|
||||
|
||||
mEnvelopeEditor.reset();
|
||||
mEnvelopeEditorRight.reset();
|
||||
mEnvelopeEditors.clear();
|
||||
|
||||
using namespace RefreshCode;
|
||||
return needUpdate ? RefreshCell : RefreshNone;
|
||||
@ -299,8 +303,7 @@ UIHandle::Result EnvelopeHandle::Release
|
||||
UIHandle::Result EnvelopeHandle::Cancel(AudacityProject *pProject)
|
||||
{
|
||||
pProject->RollbackState();
|
||||
mEnvelopeEditor.reset();
|
||||
mEnvelopeEditorRight.reset();
|
||||
mEnvelopeEditors.clear();
|
||||
return RefreshCode::RefreshCell;
|
||||
}
|
||||
|
||||
@ -313,14 +316,13 @@ bool EnvelopeHandle::ForwardEventToEnvelopes
|
||||
|
||||
// AS: I'm not sure why we can't let the Envelope take care of
|
||||
// redrawing itself. ?
|
||||
bool needUpdate =
|
||||
mEnvelopeEditor->MouseEvent(
|
||||
event, mRect, viewInfo, mLog, mdBRange, mLower, mUpper);
|
||||
|
||||
if (mEnvelopeEditorRight)
|
||||
needUpdate |=
|
||||
mEnvelopeEditorRight->MouseEvent(
|
||||
event, mRect, viewInfo, mLog, mdBRange, mLower, mUpper);
|
||||
bool needUpdate = false;
|
||||
for (const auto &pEditor : mEnvelopeEditors) {
|
||||
needUpdate =
|
||||
pEditor->MouseEvent(
|
||||
event, mRect, viewInfo, mLog, mdBRange, mLower, mUpper)
|
||||
|| needUpdate;
|
||||
}
|
||||
|
||||
return needUpdate;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ Paul Licameli split from TrackPanel.cpp
|
||||
#include "../../UIHandle.h"
|
||||
#include "../../MemoryX.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class wxMouseEvent;
|
||||
class wxMouseState;
|
||||
#include <wx/gdicmn.h>
|
||||
@ -85,8 +87,7 @@ private:
|
||||
double mdBRange{};
|
||||
|
||||
Envelope *mEnvelope{};
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditor;
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditorRight;
|
||||
std::vector< std::unique_ptr<EnvelopeEditor> > mEnvelopeEditors;
|
||||
|
||||
bool mTimeTrack{};
|
||||
};
|
||||
|
@ -152,6 +152,21 @@ namespace
|
||||
AddClipsToCaptured( state, t, t->GetStartTime(), t->GetEndTime() );
|
||||
}
|
||||
|
||||
WaveTrack *NthChannel(WaveTrack &leader, int nn)
|
||||
{
|
||||
if (nn < 0)
|
||||
return nullptr;
|
||||
return *TrackList::Channels( &leader ).begin().advance(nn);
|
||||
}
|
||||
|
||||
int ChannelPosition(const Track *pChannel)
|
||||
{
|
||||
return static_cast<int>(
|
||||
TrackList::Channels( pChannel )
|
||||
.EndingAfter( pChannel ).size()
|
||||
) - 1;
|
||||
}
|
||||
|
||||
// Don't count right channels.
|
||||
WaveTrack *NthAudioTrack(TrackList &list, int nn)
|
||||
{
|
||||
@ -206,15 +221,10 @@ namespace
|
||||
clip.track->Offset( offset );
|
||||
}
|
||||
}
|
||||
else if ( pTrack ) {
|
||||
else if ( pTrack )
|
||||
// Was a shift-click
|
||||
for (auto channel =
|
||||
pTrack->GetLink() && !pTrack->GetLinked()
|
||||
? pTrack->GetLink() : pTrack;
|
||||
channel;
|
||||
channel = channel->GetLinked() ? channel->GetLink() : nullptr)
|
||||
for (auto channel : TrackList::Channels( pTrack ))
|
||||
channel->Offset( offset );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,16 +246,12 @@ void TimeShiftHandle::CreateListOfCapturedClips
|
||||
state.capturedClipArray.push_back
|
||||
(TrackClip( &capturedTrack, state.capturedClip ));
|
||||
|
||||
// Check for stereo partner
|
||||
Track *partner = capturedTrack.GetLink();
|
||||
WaveTrack *wt;
|
||||
if (state.capturedClip &&
|
||||
// Assume linked track is wave or null
|
||||
nullptr != (wt = static_cast<WaveTrack*>(partner))) {
|
||||
WaveClip *const clip = FindClipAtTime(wt, clickTime);
|
||||
|
||||
if (clip)
|
||||
state.capturedClipArray.push_back(TrackClip(partner, clip));
|
||||
if (state.capturedClip) {
|
||||
// Check for other channels
|
||||
auto wt = static_cast<WaveTrack*>(&capturedTrack);
|
||||
for ( auto channel : TrackList::Channels( wt ).Excluding( wt ) )
|
||||
if (WaveClip *const clip = FindClipAtTime(channel, clickTime))
|
||||
state.capturedClipArray.push_back(TrackClip(channel, clip));
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,22 +499,28 @@ namespace {
|
||||
for ( auto &trackClip : state.capturedClipArray ) {
|
||||
if (trackClip.clip) {
|
||||
// Move all clips up or down by an equal count of audio tracks.
|
||||
// Can only move between tracks with equal numbers of channels,
|
||||
// and among corresponding channels.
|
||||
|
||||
Track *const pSrcTrack = trackClip.track;
|
||||
auto pDstTrack = NthAudioTrack(trackList,
|
||||
diff + TrackPosition(trackList, pSrcTrack));
|
||||
// Can only move mono to mono, or left to left, or right to right
|
||||
// And that must be so for each captured clip
|
||||
bool stereo = (pSrcTrack->GetLink() != 0);
|
||||
if (pDstTrack && stereo && !pSrcTrack->GetLinked())
|
||||
// Assume linked track is wave or null
|
||||
pDstTrack = static_cast<WaveTrack*>(pDstTrack->GetLink());
|
||||
bool ok = pDstTrack &&
|
||||
(stereo == (pDstTrack->GetLink() != 0)) &&
|
||||
(!stereo || (pSrcTrack->GetLinked() == pDstTrack->GetLinked()));
|
||||
if (ok)
|
||||
trackClip.dstTrack = pDstTrack;
|
||||
else
|
||||
if (!pDstTrack)
|
||||
return false;
|
||||
|
||||
if (TrackList::Channels(pSrcTrack).size() !=
|
||||
TrackList::Channels(pDstTrack).size())
|
||||
return false;
|
||||
|
||||
auto pDstChannel = NthChannel(
|
||||
*pDstTrack, ChannelPosition(pSrcTrack));
|
||||
|
||||
if (!pDstChannel) {
|
||||
wxASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
trackClip.dstTrack = pDstChannel;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -34,9 +34,9 @@ UIHandle::Result MinimizeButtonHandle::CommitChanges
|
||||
auto pTrack = mpTrack.lock();
|
||||
if (pTrack)
|
||||
{
|
||||
pTrack->SetMinimized(!pTrack->GetMinimized());
|
||||
if (pTrack->GetLink())
|
||||
pTrack->GetLink()->SetMinimized(pTrack->GetMinimized());
|
||||
bool wasMinimized = pTrack->GetMinimized();
|
||||
for (auto channel : TrackList::Channels(pTrack.get()))
|
||||
channel->SetMinimized(!wasMinimized);
|
||||
pProject->ModifyState(true);
|
||||
|
||||
// Redraw all tracks when any one of them expands or contracts
|
||||
|
@ -209,11 +209,8 @@ void TrackMenuTable::OnSetName(wxCommandEvent &)
|
||||
if (bResult)
|
||||
{
|
||||
wxString newName = Command.mName;
|
||||
pTrack->SetName(newName);
|
||||
// if we have a linked channel this name should change as well
|
||||
// (otherwise sort by name and time will crash).
|
||||
if (pTrack->GetLinked())
|
||||
pTrack->GetLink()->SetName(newName);
|
||||
for (auto channel : TrackList::Channels(pTrack))
|
||||
channel->SetName(newName);
|
||||
|
||||
MixerBoard *const pMixerBoard = proj->GetMixerBoard();
|
||||
auto pt = dynamic_cast<PlayableTrack*>(pTrack);
|
||||
|
Loading…
x
Reference in New Issue
Block a user