1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-02 08:39:46 +02:00

Fix for bug #949

This removes the TrackInfo's slider "cache".

Originally, the cache would build to the maximum number of tracks you
had created in an Audacity session.  So, if you created 128 tracks
and then reduced that to 1, you'd still have 256 sliders, 1 gain and
1 pan per track.

But, the only real thing the cache did was prevent continuous allocations
of sliders since the allocated sliders position and values wer still
being updated nearly with ever interaction since they were redrawn each
time.

In April 2010, the slider cache was changed to reduce its size by
creating a sort of ring buffer based on how many tracks were displayed
and how many tracks were in the project (I guess).  Unfortunately, it
didn't really handle large number of tracks and this bug was born.

While trying to find the proper fix for this, I realized that the
cache really wasn't saving anything.  Maybe a little when dragging
the thumb, but during normal track redraws and interaction, it really
didn't serve a purpose, other than use additional memory.

So, I've removed the cache and have allocated a single gain and a
single pan slider.  As before, their position and value are changed
as needed when drawn and manipulated.
This commit is contained in:
Leland Lucius 2015-05-24 22:54:10 -05:00
parent 7ba51bdf36
commit 8f77334286
3 changed files with 83 additions and 222 deletions

243
src/TrackPanel.cpp Normal file → Executable file
View File

@ -1473,9 +1473,6 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */)
// (See TrackPanel::Refresh())
if (mRefreshBacking || (box == GetRect()))
{
// Update visible sliders
mTrackInfo.UpdateSliderOffset(mViewInfo->track);
// Reset (should a mutex be used???)
mRefreshBacking = false;
@ -5410,12 +5407,12 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan)
// On the Mac, we'll lose track capture if the slider dialog
// is displayed, but it doesn't hurt to do this for all plats.
Track *capturedTrack = mCapturedTrack;
WaveTrack *capturedTrack = (WaveTrack *) mCapturedTrack;
if (pan)
slider = mTrackInfo.PanSlider(capturedTrack->GetIndex());
slider = mTrackInfo.PanSlider(capturedTrack);
else
slider = mTrackInfo.GainSlider(capturedTrack->GetIndex());
slider = mTrackInfo.GainSlider(capturedTrack);
slider->OnMouseEvent(event);
@ -5468,11 +5465,7 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan)
}
#endif
VisibleTrackIterator iter(GetProject());
for (Track *t = iter.First(); t; t = iter.Next())
{
RefreshTrack(t);
}
RefreshTrack(capturedTrack);
if (event.ButtonUp()) {
#ifdef EXPERIMENTAL_MIDI_OUT
@ -8318,7 +8311,7 @@ void TrackPanel::OnTrackPan()
return;
}
LWSlider *slider = mTrackInfo.PanSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.PanSlider((WaveTrack *) t);
if (slider->ShowDialog()) {
SetTrackPan(t, slider);
}
@ -8331,7 +8324,7 @@ void TrackPanel::OnTrackPanLeft()
return;
}
LWSlider *slider = mTrackInfo.PanSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.PanSlider((WaveTrack *) t);
slider->Decrease(1);
SetTrackPan(t, slider);
}
@ -8343,7 +8336,7 @@ void TrackPanel::OnTrackPanRight()
return;
}
LWSlider *slider = mTrackInfo.PanSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.PanSlider((WaveTrack *) t);
slider->Increase(1);
SetTrackPan(t, slider);
}
@ -8373,7 +8366,7 @@ void TrackPanel::OnTrackGain()
return;
}
LWSlider *slider = mTrackInfo.GainSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.GainSlider((WaveTrack *) t);
if (slider->ShowDialog()) {
SetTrackGain(t, slider);
}
@ -8386,7 +8379,7 @@ void TrackPanel::OnTrackGainInc()
return;
}
LWSlider *slider = mTrackInfo.GainSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.GainSlider((WaveTrack *) t);
slider->Increase(1);
SetTrackGain(t, slider);
}
@ -8398,7 +8391,7 @@ void TrackPanel::OnTrackGainDec()
return;
}
LWSlider *slider = mTrackInfo.GainSlider(t->GetIndex());
LWSlider *slider = mTrackInfo.GainSlider((WaveTrack *) t);
slider->Decrease(1);
SetTrackGain(t, slider);
}
@ -9782,16 +9775,30 @@ void TrackPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event))
**********************************************************************/
TrackInfo::TrackInfo(wxWindow * pParentIn)
TrackInfo::TrackInfo(TrackPanel * pParentIn)
{
pParent = pParentIn;
// Populate sliders array
for (unsigned int i = 0; i < kInitialSliders; ++i) {
MakeMoreSliders();
}
mSliderOffset = 0;
wxRect r(0, 0, 1000, 1000);
wxRect sliderRect;
GetGainRect(r, sliderRect);
/* i18n-hint: Title of the Gain slider, used to adjust the volume */
mGain = new LWSlider(pParent, _("Gain"),
wxPoint(sliderRect.x, sliderRect.y),
wxSize(sliderRect.width, sliderRect.height),
DB_SLIDER);
mGain->SetDefaultValue(1.0);
GetPanRect(r, sliderRect);
/* i18n-hint: Title of the Pan slider, used to move the sound left or right */
mPan = new LWSlider(pParent, _("Pan"),
wxPoint(sliderRect.x, sliderRect.y),
wxSize(sliderRect.width, sliderRect.height),
PAN_SLIDER);
mPan->SetDefaultValue(0.0);
int fontSize = 10;
mFont.Create(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
@ -9812,11 +9819,8 @@ TrackInfo::TrackInfo(wxWindow * pParentIn)
TrackInfo::~TrackInfo()
{
unsigned int i;
for(i=0; i<mGains.Count(); i++)
delete mGains[i];
for(i=0; i<mPans.Count(); i++)
delete mPans[i];
delete mGain;
delete mPan;
}
static const int kTrackInfoWidth = 100;
@ -9896,12 +9900,12 @@ void TrackInfo::GetSyncLockIconRect(const wxRect & r, wxRect &dest) const
/// \todo Probably should move to 'Utils.cpp'.
void TrackInfo::SetTrackInfoFont(wxDC * dc)
void TrackInfo::SetTrackInfoFont(wxDC * dc) const
{
dc->SetFont(mFont);
}
void TrackInfo::DrawBordersWithin(wxDC* dc, const wxRect & r, bool bHasMuteSolo)
void TrackInfo::DrawBordersWithin(wxDC* dc, const wxRect & r, bool bHasMuteSolo) const
{
AColor::Dark(dc, false); // same color as border of toolbars (ToolBar::OnPaint())
@ -9928,7 +9932,7 @@ void TrackInfo::DrawBordersWithin(wxDC* dc, const wxRect & r, bool bHasMuteSolo)
}
void TrackInfo::DrawBackground(wxDC * dc, const wxRect & r, bool bSelected,
bool WXUNUSED(bHasMuteSolo), const int labelw, const int WXUNUSED(vrul))
bool WXUNUSED(bHasMuteSolo), const int labelw, const int WXUNUSED(vrul)) const
{
// fill in label
wxRect fill = r;
@ -9967,7 +9971,7 @@ void TrackInfo::GetTrackControlsRect(const wxRect & r, wxRect & dest) const
}
void TrackInfo::DrawCloseBox(wxDC * dc, const wxRect & r, bool down)
void TrackInfo::DrawCloseBox(wxDC * dc, const wxRect & r, bool down) const
{
wxRect bev;
GetCloseBoxRect(r, bev);
@ -9997,7 +10001,7 @@ void TrackInfo::DrawCloseBox(wxDC * dc, const wxRect & r, bool down)
}
void TrackInfo::DrawTitleBar(wxDC * dc, const wxRect & r, Track * t,
bool down)
bool down) const
{
wxRect bev;
GetTitleBarRect(r, bev);
@ -10043,7 +10047,7 @@ void TrackInfo::DrawTitleBar(wxDC * dc, const wxRect & r, Track * t,
/// Draw the Mute or the Solo button, depending on the value of solo.
void TrackInfo::DrawMuteSolo(wxDC * dc, const wxRect & r, Track * t,
bool down, bool solo, bool bHasSoloButton)
bool down, bool solo, bool bHasSoloButton) const
{
wxRect bev;
if( solo && !bHasSoloButton )
@ -10095,7 +10099,7 @@ void TrackInfo::DrawMuteSolo(wxDC * dc, const wxRect & r, Track * t,
}
// Draw the minimize button *and* the sync-lock track icon, if necessary.
void TrackInfo::DrawMinimize(wxDC * dc, const wxRect & r, Track * t, bool down)
void TrackInfo::DrawMinimize(wxDC * dc, const wxRect & r, Track * t, bool down) const
{
wxRect bev;
GetMinimizeRect(r, bev);
@ -10121,43 +10125,8 @@ void TrackInfo::DrawMinimize(wxDC * dc, const wxRect & r, Track * t, bool down)
AColor::BevelTrackInfo(*dc, !down, bev);
}
void TrackInfo::MakeMoreSliders()
{
wxRect r(0, 0, 1000, 1000);
wxRect gainRect;
wxRect panRect;
GetGainRect(r, gainRect);
GetPanRect(r, panRect);
/* i18n-hint: Title of the Gain slider, used to adjust the volume */
LWSlider *slider = new LWSlider(pParent, _("Gain"),
wxPoint(gainRect.x, gainRect.y),
wxSize(gainRect.width, gainRect.height),
DB_SLIDER);
slider->SetDefaultValue(1.0);
mGains.Add(slider);
/* i18n-hint: Title of the Pan slider, used to move the sound left or right */
slider = new LWSlider(pParent, _("Pan"),
wxPoint(panRect.x, panRect.y),
wxSize(panRect.width, panRect.height),
PAN_SLIDER);
slider->SetDefaultValue(0.0);
mPans.Add(slider);
}
// This covers the case where kInitialSliders - kSliderPageFlip is not big
// enough
void TrackInfo::EnsureSufficientSliders(int index)
{
while (mGains.Count() < (unsigned int)index - mSliderOffset + 1 ||
mPans.Count() < (unsigned int)index - mSliderOffset + 1)
MakeMoreSliders();
}
#ifdef EXPERIMENTAL_MIDI_OUT
void TrackInfo::DrawVelocitySlider(wxDC *dc, NoteTrack *t, wxRect r)
void TrackInfo::DrawVelocitySlider(wxDC *dc, NoteTrack *t, wxRect r) const
{
wxRect gainRect;
int index = t->GetIndex();
@ -10172,127 +10141,43 @@ void TrackInfo::DrawVelocitySlider(wxDC *dc, NoteTrack *t, wxRect r)
}
#endif
void TrackInfo::DrawSliders(wxDC *dc, WaveTrack *t, wxRect r)
void TrackInfo::DrawSliders(wxDC *dc, WaveTrack *t, wxRect r) const
{
wxRect gainRect;
wxRect panRect;
int index = t->GetIndex();
wxRect sliderRect;
EnsureSufficientSliders( index );
GetGainRect(r, gainRect);
GetPanRect(r, panRect);
if (gainRect.y + gainRect.height < r.y + r.height - 19) {
#ifdef EXPERIMENTAL_MIDI_OUT
GainSlider(index)->SetStyle(DB_SLIDER);
#endif
GainSlider(index)->Move(wxPoint(gainRect.x, gainRect.y));
GainSlider(index)->Set(t->GetGain());
GainSlider(index)->OnPaint(*dc, t->GetSelected());
GetGainRect(r, sliderRect);
if (sliderRect.y + sliderRect.height < r.y + r.height - 19) {
GainSlider(t)->OnPaint(*dc, t->GetSelected());
}
if (panRect.y + panRect.height < r.y + r.height - 19) {
PanSlider(index)->Move(wxPoint(panRect.x, panRect.y));
PanSlider(index)->Set(t->GetPan());
PanSlider(index)->OnPaint(*dc, t->GetSelected());
GetPanRect(r, sliderRect);
if (sliderRect.y + sliderRect.height < r.y + r.height - 19) {
PanSlider(t)->OnPaint(*dc, t->GetSelected());
}
}
void TrackInfo::UpdateSliderOffset(Track *t)
LWSlider * TrackInfo::GainSlider(WaveTrack *t) const
{
if (!t)
return;
wxRect r(kLeftInset, t->GetY() - pParent->GetViewInfo()->vpos + kTopInset, 1, t->GetHeight());
wxRect sliderRect;
GetGainRect(r, sliderRect);
// Ensure that the specified track is: (a) at least the second track in the
// arrays (if it's the second track in a stereo pair the first must be in);
// (b) no farther in than kSliderPageFlip
int newSliderOffset = (int)mSliderOffset;
if ((unsigned int)t->GetIndex() < mSliderOffset + 1 ||
(unsigned int)t->GetIndex() > mSliderOffset + kSliderPageFlip) {
newSliderOffset = t->GetIndex() - (int)kSliderPageFlip / 2;
}
// Slider offset can't be negative
if (newSliderOffset < 0) newSliderOffset = 0;
mGain->Move(wxPoint(sliderRect.x, sliderRect.y));
mGain->Set(t->GetGain());
// Rotate the array values if necessary
int delta = newSliderOffset - (int)mSliderOffset;
// If the rotation is greater than the array size, none of the old values
// are preserved, so don't bother rotating.
if (abs(delta) >= (int)mGains.Count())
delta = 0;
if (delta > 0) {
// Circularly shift values down in the arrays (temp arrays needed to
// avoid reading written-over values)
LWSliderArray tempGains;
LWSliderArray tempPans;
tempGains.SetCount(delta);
tempPans.SetCount(delta);
for (int i = 0; i < (int)mGains.Count(); ++i) {
int src = (i + delta) % (int)mGains.Count();
if (src < 0) src += (int)mGains.Count();
if (i < delta) {
// Save a copy of the first `delta` values
tempGains[i] = mGains[i];
tempPans[i] = mPans[i];
}
if (src >= delta) {
// These values have not been overwritten
mGains[i] = mGains[src];
mPans[i] = mPans[src];
}
else {
// These ones have
mGains[i] = tempGains[src];
mPans[i] = tempPans[src];
}
}
}
else if (delta < 0) {
// Circularly shift values up in the arrays
LWSliderArray tempGains;
LWSliderArray tempPans;
tempGains.SetCount(mGains.Count());
tempPans.SetCount(mPans.Count());
// Iterating backwards to do this
for (int i = mGains.Count() - 1; i >= 0; --i) {
int src = (i + delta) % (int)mGains.Count();
if (src < 0) src += (int)mGains.Count();
if (i >= (int)mGains.Count() + delta) {
// Save a copy of the last `delta` values
tempGains[i] = mGains[i];
tempPans[i] = mPans[i];
}
if (src < (int)mGains.Count() + delta) {
// These values have not been overwritten
mGains[i] = mGains[src];
mPans[i] = mPans[src];
}
else {
// These ones have
mGains[i] = tempGains[src];
mPans[i] = tempPans[src];
}
}
}
mSliderOffset = newSliderOffset;
return mGain;
}
LWSlider * TrackInfo::GainSlider(int trackIndex)
LWSlider * TrackInfo::PanSlider(WaveTrack *t) const
{
return mGains[trackIndex - mSliderOffset];
}
wxRect r(kLeftInset, t->GetY() - pParent->GetViewInfo()->vpos + kTopInset, 1, t->GetHeight());
wxRect sliderRect;
GetPanRect(r, sliderRect);
LWSlider * TrackInfo::PanSlider(int trackIndex)
{
return mPans[trackIndex - mSliderOffset];
mPan->Move(wxPoint(sliderRect.x, sliderRect.y));
mPan->Set(t->GetPan());
return mPan;
}
static TrackPanel * TrackPanelFactory(wxWindow * parent,

61
src/TrackPanel.h Normal file → Executable file
View File

@ -62,19 +62,6 @@ WX_DECLARE_OBJARRAY(TrackClip, TrackClipArray);
// Declared elsewhere, to reduce compilation dependencies
class TrackPanelListener;
//
// TrackInfo sliders: we keep a pool of sliders, and attach them to tracks as
// they come on screen (this helps deal with very large numbers of tracks, esp.
// on MSW).
//
// With the initial set of sliders smaller than the page size, a new slider is
// created at track-creation time for tracks between 16 and when 80 goes past
// the top of the screen. After that, existing sliders are re-used for new
// tracks.
//
const unsigned int kInitialSliders = 16;
const unsigned int kSliderPageFlip = 80;
// JKC Nov 2011: Disabled warning C4251 which is to do with DLL linkage
// and only a worry when there are DLLs using the structures.
// LWSliderArray and TrackClipArray are private in TrackInfo, so we will not
@ -91,31 +78,26 @@ const unsigned int kSliderPageFlip = 80;
class AUDACITY_DLL_API TrackInfo
{
public:
TrackInfo(wxWindow * pParentIn);
TrackInfo(TrackPanel * pParentIn);
~TrackInfo();
int GetTrackInfoWidth() const;
void UpdateSliderOffset(Track *t);
private:
void MakeMoreSliders();
void EnsureSufficientSliders(int index);
int GetTrackInfoWidth() const;
void SetTrackInfoFont(wxDC *dc) const;
void SetTrackInfoFont(wxDC *dc);
void DrawBackground(wxDC * dc, const wxRect & r, bool bSelected, bool bHasMuteSolo, const int labelw, const int vrul);
void DrawBordersWithin(wxDC * dc, const wxRect & r, bool bHasMuteSolo );
void DrawCloseBox(wxDC * dc, const wxRect & r, bool down);
void DrawTitleBar(wxDC * dc, const wxRect & r, Track * t, bool down);
void DrawMuteSolo(wxDC * dc, const wxRect & r, Track * t, bool down, bool solo, bool bHasSoloButton);
void DrawVRuler(wxDC * dc, const wxRect & r, Track * t);
void DrawBackground(wxDC * dc, const wxRect & r, bool bSelected, bool bHasMuteSolo, const int labelw, const int vrul) const;
void DrawBordersWithin(wxDC * dc, const wxRect & r, bool bHasMuteSolo ) const;
void DrawCloseBox(wxDC * dc, const wxRect & r, bool down) const;
void DrawTitleBar(wxDC * dc, const wxRect & r, Track * t, bool down) const;
void DrawMuteSolo(wxDC * dc, const wxRect & r, Track * t, bool down, bool solo, bool bHasSoloButton) const;
void DrawVRuler(wxDC * dc, const wxRect & r, Track * t) const;
#ifdef EXPERIMENTAL_MIDI_OUT
void DrawVelocitySlider(wxDC * dc, NoteTrack *t, wxRect r);
void DrawVelocitySlider(wxDC * dc, NoteTrack *t, wxRect r) const ;
#endif
void DrawSliders(wxDC * dc, WaveTrack *t, wxRect r);
void DrawSliders(wxDC * dc, WaveTrack *t, wxRect r) const;
// Draw the minimize button *and* the sync-lock track icon, if necessary.
void DrawMinimize(wxDC * dc, const wxRect & r, Track * t, bool down);
void DrawMinimize(wxDC * dc, const wxRect & r, Track * t, bool down) const;
void GetTrackControlsRect(const wxRect & r, wxRect &dest) const;
void GetCloseBoxRect(const wxRect & r, wxRect &dest) const;
@ -126,21 +108,14 @@ private:
void GetMinimizeRect(const wxRect & r, wxRect &dest) const;
void GetSyncLockIconRect(const wxRect & r, wxRect &dest) const;
// These arrays are always kept the same size.
LWSliderArray mGains;
LWSliderArray mPans;
LWSlider * GainSlider(WaveTrack *t) const;
LWSlider * PanSlider(WaveTrack *t) const;
// index of track whose pan/gain sliders are at index 0 in the above arrays
unsigned int mSliderOffset;
public:
// Slider access by track index
LWSlider * GainSlider(int trackIndex);
LWSlider * PanSlider(int trackIndex);
wxWindow * pParent;
private:
TrackPanel * pParent;
wxFont mFont;
LWSlider *mGain;
LWSlider *mPan;
friend class TrackPanel;
};

1
src/widgets/ASlider.cpp Normal file → Executable file
View File

@ -883,6 +883,7 @@ void LWSlider::Draw()
}
}
dc->SelectObject(wxNullBitmap);
// Must preceed creating the mask as that will attempt to
// select the bitmap into another DC.