1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Define TrackPanelOverlay, use it to reimplement play indicator and cursor...

... but scrub speed display is disabled
This commit is contained in:
Paul Licameli 2015-08-25 13:35:32 -04:00 committed by Paul Licameli
parent 54ac17c086
commit 1722ee9e32
20 changed files with 895 additions and 352 deletions

View File

@ -1208,6 +1208,10 @@
28FC1AFB0A47762C00A188AE /* WrappedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FC1AF90A47762C00A188AE /* WrappedType.cpp */; };
28FE4A080ABF4E960056F5C4 /* mmx_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A060ABF4E960056F5C4 /* mmx_optimized.cpp */; };
28FE4A090ABF4E960056F5C4 /* sse_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */; };
5E74D2D81CC4425D00D88B0B /* TrackPanelOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2D61CC4425D00D88B0B /* TrackPanelOverlay.cpp */; };
5E74D2E31CC4429700D88B0B /* EditCursorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */; };
5E74D2E41CC4429700D88B0B /* PlayIndicatorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */; };
5E74D2E51CC4429700D88B0B /* Scrubbing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */; };
8406A93812D0F2510011EA01 /* EQDefaultCurves.xml in Resources */ = {isa = PBXBuildFile; fileRef = 8406A93712D0F2510011EA01 /* EQDefaultCurves.xml */; };
8484F31413086237002DF7F0 /* DeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8484F31213086237002DF7F0 /* DeviceManager.cpp */; };
ED15214D163C22F000451B5F /* lsr.c in Sources */ = {isa = PBXBuildFile; fileRef = ED152123163C220300451B5F /* lsr.c */; };
@ -2968,6 +2972,16 @@
28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = sse_optimized.cpp; sourceTree = "<group>"; tabWidth = 3; };
28FEC1B21A12B6FB00FACE48 /* EffectAutomationParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EffectAutomationParameters.h; path = ../include/audacity/EffectAutomationParameters.h; sourceTree = SOURCE_ROOT; };
5E61EE0C1CBAA6BB0009FCF1 /* MemoryX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryX.h; sourceTree = "<group>"; };
5E74D2D61CC4425D00D88B0B /* TrackPanelOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackPanelOverlay.cpp; sourceTree = "<group>"; };
5E74D2D71CC4425D00D88B0B /* TrackPanelOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelOverlay.h; sourceTree = "<group>"; };
5E74D2D91CC4427B00D88B0B /* TrackPanelCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelCell.h; sourceTree = "<group>"; };
5E74D2DA1CC4427B00D88B0B /* TrackPanelCellIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelCellIterator.h; sourceTree = "<group>"; };
5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditCursorOverlay.cpp; sourceTree = "<group>"; };
5E74D2DE1CC4429700D88B0B /* EditCursorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditCursorOverlay.h; sourceTree = "<group>"; };
5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlayIndicatorOverlay.cpp; sourceTree = "<group>"; };
5E74D2E01CC4429700D88B0B /* PlayIndicatorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayIndicatorOverlay.h; sourceTree = "<group>"; };
5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scrubbing.cpp; sourceTree = "<group>"; };
5E74D2E21CC4429700D88B0B /* Scrubbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scrubbing.h; sourceTree = "<group>"; };
5ED18DB61CC16B1E00FAFE95 /* Reverb_libSoX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reverb_libSoX.h; sourceTree = "<group>"; };
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wxFileNameWrapper.h; sourceTree = "<group>"; };
82FF184D13CF01A600C1B664 /* dBTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dBTable.cpp; path = sbsms/src/dBTable.cpp; sourceTree = "<group>"; };
@ -3793,7 +3807,6 @@
1790AFC409883BFD008A330A /* src */ = {
isa = PBXGroup;
children = (
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */,
1790AFC709883BFD008A330A /* AboutDialog.cpp */,
1790AFC909883BFD008A330A /* AColor.cpp */,
1790AFCE09883BFD008A330A /* AudacityApp.cpp */,
@ -3870,6 +3883,7 @@
1790B0EA09883BFD008A330A /* TrackArtist.cpp */,
1790B0EC09883BFD008A330A /* TrackPanel.cpp */,
1790B0EE09883BFD008A330A /* TrackPanelAx.cpp */,
5E74D2D61CC4425D00D88B0B /* TrackPanelOverlay.cpp */,
1790B0F209883BFD008A330A /* UndoManager.cpp */,
28C8211C1B5C661E00B53328 /* ViewInfo.cpp */,
1790B0F709883BFD008A330A /* VoiceKey.cpp */,
@ -3964,7 +3978,10 @@
1790B0EB09883BFD008A330A /* TrackArtist.h */,
1790B0ED09883BFD008A330A /* TrackPanel.h */,
1790B0EF09883BFD008A330A /* TrackPanelAx.h */,
5E74D2D91CC4427B00D88B0B /* TrackPanelCell.h */,
5E74D2DA1CC4427B00D88B0B /* TrackPanelCellIterator.h */,
2803C8B619F35AA000278526 /* TrackPanelListener.h */,
5E74D2D71CC4425D00D88B0B /* TrackPanelOverlay.h */,
284416391B82D6BC0000574D /* TranslatableStringArray.h */,
1790B0F309883BFD008A330A /* UndoManager.h */,
1790B0F609883BFD008A330A /* ViewInfo.h */,
@ -3973,6 +3990,7 @@
1790B0FC09883BFD008A330A /* WaveTrack.h */,
2844163A1B82D6BC0000574D /* WaveTrackLocation.h */,
28FC1AFA0A47762C00A188AE /* WrappedType.h */,
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */,
1790AFDC09883BFD008A330A /* blockfile */,
174D9025098C78AF00D5909F /* commands */,
1790AFFD09883BFD008A330A /* effects */,
@ -3981,6 +3999,7 @@
1841B4FD0E00AD3D00F386E9 /* ondemand */,
1790B0B509883BFD008A330A /* prefs */,
2897F6DB0AB3DB5A003C20C5 /* toolbars */,
5E74D2DB1CC4429700D88B0B /* tracks */,
1790B0FD09883BFD008A330A /* widgets */,
1790B10D09883BFD008A330A /* xml */,
);
@ -5516,6 +5535,27 @@
path = expat/lib;
sourceTree = "<group>";
};
5E74D2DB1CC4429700D88B0B /* tracks */ = {
isa = PBXGroup;
children = (
5E74D2DC1CC4429700D88B0B /* ui */,
);
path = tracks;
sourceTree = "<group>";
};
5E74D2DC1CC4429700D88B0B /* ui */ = {
isa = PBXGroup;
children = (
5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */,
5E74D2DE1CC4429700D88B0B /* EditCursorOverlay.h */,
5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */,
5E74D2E01CC4429700D88B0B /* PlayIndicatorOverlay.h */,
5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */,
5E74D2E21CC4429700D88B0B /* Scrubbing.h */,
);
path = ui;
sourceTree = "<group>";
};
ED05D0FF0E50AD5600CC4BD3 /* libscorealign */ = {
isa = PBXGroup;
children = (
@ -7289,6 +7329,7 @@
1790B14F09883BFD008A330A /* SoundTouchEffect.cpp in Sources */,
1790B15109883BFD008A330A /* StereoToMono.cpp in Sources */,
1790B15209883BFD008A330A /* ToneGen.cpp in Sources */,
5E74D2E31CC4429700D88B0B /* EditCursorOverlay.cpp in Sources */,
1790B15309883BFD008A330A /* TruncSilence.cpp in Sources */,
1790B15409883BFD008A330A /* TwoPassSimpleMono.cpp in Sources */,
1790B15809883BFD008A330A /* Wahwah.cpp in Sources */,
@ -7421,6 +7462,7 @@
1841B50B0E00AD6E00F386E9 /* ODManager.cpp in Sources */,
1841B50C0E00AD6E00F386E9 /* ODTask.cpp in Sources */,
1841B50D0E00AD6E00F386E9 /* ODTaskThread.cpp in Sources */,
5E74D2E51CC4429700D88B0B /* Scrubbing.cpp in Sources */,
1841B50E0E00AD6E00F386E9 /* ODWaveTrackTaskQueue.cpp in Sources */,
1841B5110E00AD8D00F386E9 /* ODPCMAliasBlockFile.cpp in Sources */,
2860BA240E0F0D8600A13878 /* SoundActivatedRecord.cpp in Sources */,
@ -7540,6 +7582,7 @@
ED920CAF15B19F61008CA12C /* ModulePrefs.cpp in Sources */,
EDD2431416934A6100D9DEC2 /* BassTreble.cpp in Sources */,
ED19449A1733F92800F4F5CA /* Reverb.cpp in Sources */,
5E74D2D81CC4425D00D88B0B /* TrackPanelOverlay.cpp in Sources */,
2849A42017F8BEC2005C653F /* KeyView.cpp in Sources */,
284FD04217FC72A50009A025 /* ScienFilter.cpp in Sources */,
284FD04517FC72EE0009A025 /* Biquad.cpp in Sources */,
@ -7559,6 +7602,7 @@
28001B3E1A0F0E5D007DD161 /* NumericTextCtrl.cpp in Sources */,
28001B4B1A0F0EB6007DD161 /* SpectralSelectionBar.cpp in Sources */,
28BB98051A15BE6800D1CC80 /* NoiseReduction.cpp in Sources */,
5E74D2E41CC4429700D88B0B /* PlayIndicatorOverlay.cpp in Sources */,
28D000A51A32920C00367B21 /* DeviceChange.cpp in Sources */,
28D8425C1AD8D69D00551353 /* SelectedRegion.cpp in Sources */,
2888A1631AE25F9A00E06FDC /* Diags.cpp in Sources */,

View File

@ -233,7 +233,11 @@ audacity_SOURCES = \
TrackPanel.h \
TrackPanelAx.cpp \
TrackPanelAx.h \
TrackPanelCell.h \
TrackPanelCellIterator.h \
TrackPanelListener.h \
TrackPanelOverlay.cpp \
TrackPanelOverlay.h \
TranslatableStringArray.h \
UndoManager.cpp \
UndoManager.h \
@ -523,6 +527,12 @@ audacity_SOURCES = \
toolbars/ToolsToolBar.h \
toolbars/TranscriptionToolBar.cpp \
toolbars/TranscriptionToolBar.h \
tracks/ui/EditCursorOverlay.cpp \
tracks/ui/EditCursorOverlay.h \
tracks/ui/PlayIndicatorOverlay.cpp \
tracks/ui/PlayIndicatorOverlay.h \
tracks/ui/Scrubbing.cpp \
tracks/ui/Scrubbing.h \
widgets/AButton.cpp \
widgets/AButton.h \
widgets/ASlider.cpp \

View File

@ -156,6 +156,10 @@ scroll information. It also has some status flags.
#include "toolbars/ToolsToolBar.h"
#include "toolbars/TranscriptionToolBar.h"
#include "tracks/ui/EditCursorOverlay.h"
#include "tracks/ui/PlayIndicatorOverlay.h"
#include "tracks/ui/Scrubbing.h"
#include "commands/ScriptCommandRelay.h"
#include "commands/CommandDirectory.h"
#include "commands/CommandTargets.h"
@ -924,6 +928,32 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
this,
mRuler);
mIndicatorOverlay = std::make_unique<PlayIndicatorOverlay>(this);
mCursorOverlay = std::make_unique<EditCursorOverlay>(this);
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
// This must follow construction of *mIndicatorOverlay, because it must
// attach its timer event handler later (so that its handler is invoked
// earlier)
mScrubOverlay = std::make_unique<ScrubbingOverlay>(this);
#else
mScrubOverlay = NULL;
#endif
// This must follow construction of *mScrubOverlay, because it must
// attach its timer event handler later (so that its handler is invoked
// earlier)
this->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(ViewInfo::OnTimer),
NULL,
&mViewInfo);
// Add the overlays, in the sequence in which they will be painted
mTrackPanel->AddOverlay(mIndicatorOverlay.get());
mTrackPanel->AddOverlay(mCursorOverlay.get());
mTrackPanel->AddOverlay(mScrubOverlay.get());
// LLL: When Audacity starts or becomes active after returning from
// another application, the first window that can accept focus
// will be given the focus even if we try to SetFocus(). By
@ -1051,6 +1081,12 @@ AudacityProject::~AudacityProject()
wxGetApp().GetRecentFiles()->RemoveMenu(mRecentFilesMenu);
}
if(mTrackPanel) {
mTrackPanel->RemoveOverlay(mScrubOverlay.get());
mTrackPanel->RemoveOverlay(mCursorOverlay.get());
mTrackPanel->RemoveOverlay(mIndicatorOverlay.get());
}
wxTheApp->Disconnect(EVT_AUDIOIO_CAPTURE,
wxCommandEventHandler(AudacityProject::OnCapture),
NULL,
@ -2339,6 +2375,11 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
#endif
}
this->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(ViewInfo::OnTimer),
NULL,
&mViewInfo);
Destroy();
mIsBeingDeleted = true;

View File

@ -62,6 +62,7 @@ class Tags;
class EffectPlugs;
class TrackPanel;
class TrackPanelOverlay;
class FreqWindow;
class ContrastDialog;
class Meter;
@ -171,9 +172,13 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
double GetRate() const { return mRate; }
bool ZoomInAvailable() const { return mViewInfo.ZoomInAvailable(); }
bool ZoomOutAvailable() const { return mViewInfo.ZoomOutAvailable(); }
double GetSel0() { return mViewInfo.selectedRegion.t0(); }
double GetSel1() { return mViewInfo.selectedRegion.t1(); }
const SelectedRegion &GetSelection() const { return mViewInfo.selectedRegion; }
SelectedRegion &GetSelection() { return mViewInfo.selectedRegion; }
double GetSel0() const { return mViewInfo.selectedRegion.t0(); }
double GetSel1() const { return mViewInfo.selectedRegion.t1(); }
const ZoomInfo &GetZoomInfo() const { return mViewInfo; }
const ViewInfo &GetViewInfo() const { return mViewInfo; }
ViewInfo &GetViewInfo() { return mViewInfo; }
Track *GetFirstVisible();
void UpdateFirstVisible();
@ -702,6 +707,10 @@ public:
// CommandManager needs to use private methods
friend class CommandManager;
// TrackPanelOverlay objects
std::unique_ptr<TrackPanelOverlay>
mIndicatorOverlay, mCursorOverlay, mScrubOverlay;
DECLARE_EVENT_TABLE()
};

View File

@ -155,6 +155,9 @@ is time to refresh some aspect of the screen.
#include "Audacity.h"
#include "Experimental.h"
#include "TrackPanel.h"
#include "TrackPanelCell.h"
#include "TrackPanelCellIterator.h"
#include "TrackPanelOverlay.h"
//#define DEBUG_DRAW_TIMING 1
// #define SPECTRAL_EDITING_ESC_KEY
@ -287,12 +290,6 @@ template < class A, class B, class DIST > bool within(A a, B b, DIST d)
return (a > b - d) && (a < b + d);
}
template < class LOW, class MID, class HIGH >
bool between_incexc(LOW l, MID m, HIGH h)
{
return (m >= l && m < h);
}
template < class CLIPPEE, class CLIPVAL >
void clip_top(CLIPPEE & clippee, CLIPVAL val)
{
@ -564,9 +561,6 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
mSnapLeft = -1;
mSnapRight = -1;
mLastCursorX = mNewCursorX = -1;
mLastIndicatorX = mNewIndicatorX = -1;
mCursorTime = -1.0;
mOldQPIndicatorPos = -1;
// Register for tracklist updates
@ -1023,11 +1017,9 @@ void TrackPanel::OnTimer(wxTimerEvent& )
const double playPos = gAudioIO->GetStreamTime();
// The sequence of the next two is important.
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
TimerUpdateScrubbing(playPos);
#endif
TimerUpdateIndicator(playPos);
DrawOverlays(false);
@ -1140,249 +1132,6 @@ double TrackPanel::GetScreenEndTime() const
return mViewInfo->PositionToTime(width, true);
}
void TrackPanel::TimerUpdateIndicator(double playPos)
{
if (!IsAudioActive())
mNewIndicatorX = -1;
else {
// Calculate the horizontal position of the indicator
AudacityProject *p = GetProject();
const bool
onScreen = playPos >= 0.0 &&
between_incexc(mViewInfo->h,
playPos,
GetScreenEndTime());
// This displays the audio time, too...
DisplaySelection();
// BG: Scroll screen if option is set
// msmeyer: But only if not playing looped or in one-second mode
if( mViewInfo->bUpdateTrackIndicator &&
p->mLastPlayMode != loopedPlay &&
p->mLastPlayMode != oneSecondPlay &&
playPos >= 0 &&
!onScreen &&
!gAudioIO->IsPaused() )
{
mListener->TP_ScrollWindow( playPos );
}
// Always update scrollbars even if not scrolling the window. This is
// important when NEW audio is recorded, because this can change the
// length of the project and therefore the appearance of the scrollbar.
MakeParentRedrawScrollbars();
mNewIndicatorX = mViewInfo->TimeToPosition(playPos, GetLeftOffset());
}
}
std::pair<wxRect, bool> TrackPanel::GetIndicatorRectangle()
{
wxRect rect(mLastIndicatorX, 0, 1, mBacking->GetHeight());
#if defined(__WXMAC__)
rect.Inflate(1, 0);
#endif
return std::make_pair(
rect,
mLastIndicatorX != mNewIndicatorX
);
}
void TrackPanel::UndrawIndicator(wxDC & dc)
{
// AS: The "indicator" is the little graphical mark shown in the ruler
// that indicates where the current play/record position is. (This also
// draws the moving vertical line.)
// Erase the old indicator.
if (mLastIndicatorX != -1)
{
int width;
GetTracksUsableArea(&width, NULL);
const bool
onScreen = between_incexc(GetLeftOffset(),
mLastIndicatorX,
GetLeftOffset() + width);
if (onScreen)
{
// LL: Keep from trying to blit outsize of the source DC. This results in a crash on
// OSX due to allocating memory using negative sizes and can be caused by resizing
// the project window while recording or playing.
int w = dc.GetSize().GetWidth();
if (mLastIndicatorX >= w) {
mLastIndicatorX = w - 1;
}
// Restore the old position from the backing DC.
#if defined(__WXMAC__)
// On OSX, if a HiDPI resolution is being used, the line will actually take up
// more than 1 pixel (even though it is drawn as 1), so we restore the surrounding
// pixels as well. (This is because the wxClientDC doesn't know about the scaling.)
dc.Blit(mLastIndicatorX - 1, 0, 3, mBacking->GetHeight(), &mBackingDC, mLastIndicatorX - 1, 0);
#else
dc.Blit(mLastIndicatorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastIndicatorX, 0);
#endif
}
mRuler->ClearIndicator();
}
}
void TrackPanel::DoDrawIndicator(wxDC & dc)
{
mLastIndicatorX = mNewIndicatorX;
if (mLastIndicatorX == -1)
return;
double pos = mViewInfo->PositionToTime(mLastIndicatorX, GetLeftOffset());
// Set play/record color
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
AColor::IndicatorColor( &dc, !rec);
mRuler->DrawIndicator( pos, rec );
// Ensure that we don't draw through the TrackInfo or vertical ruler.
wxRect clip = GetRect();
int leftCutoff = clip.x + GetLeftOffset();
int rightCutoff = clip.x + clip.width - kRightMargin;
if (!between_incexc(leftCutoff, mLastIndicatorX, rightCutoff))
{
return;
}
// Draw indicator in all visible tracks
VisibleTrackIterator iter( GetProject() );
for( Track *t = iter.First(); t; t = iter.Next() )
{
// Don't draw the indicator in label tracks
if( t->GetKind() == Track::Label )
{
continue;
}
// Convert virtual coordinate to physical
int y = t->GetY() - mViewInfo->vpos;
// Draw the NEW indicator in its new location
AColor::Line(dc,
mLastIndicatorX,
y + kTopMargin,
mLastIndicatorX,
// Minus one more because AColor::Line includes both endpoints
y + t->GetHeight() - kBottomMargin - 1);
}
}
#if 0
// now unused
/// This method draws the cursor things, both in the
/// ruler as seen at the top of the screen, but also in each of the
/// selected tracks.
/// These are the 'vertical lines' through waves, notes, and ruler.
void TrackPanel::DrawCursor()
{
wxClientDC dc( this );
DoDrawCursor( dc );
}
#endif
std::pair<wxRect, bool> TrackPanel::GetCursorRectangle()
{
if (!mViewInfo->selectedRegion.isPoint()) {
mCursorTime = -1.0;
mNewCursorX = -1;
}
else {
mCursorTime = mViewInfo->selectedRegion.t0();
mNewCursorX = mViewInfo->TimeToPosition(mCursorTime, GetLeftOffset());
}
wxRect rect(mLastCursorX, 0, 1, mBacking->GetHeight());
#if defined(__WXMAC__)
rect.Inflate(1, 0);
#endif
return std::make_pair(
rect,
mLastCursorX != mNewCursorX
);
}
void TrackPanel::UndrawCursor(wxDC & dc)
{
bool onScreen;
if( mLastCursorX != -1 )
{
int width;
GetTracksUsableArea(&width, NULL);
onScreen = between_incexc(GetLeftOffset(),
mLastCursorX,
GetLeftOffset() + width);
if( onScreen )
#if defined(__WXMAC__)
// On OSX, if a HiDPI resolution is being used, the line will actually take up
// more than 1 pixel (even though it is drawn as 1), so we restore the surrounding
// pixels as well. (This is because the wxClientDC doesn't know about the scaling.)
dc.Blit(mLastCursorX - 1, 0, 3, mBacking->GetHeight(), &mBackingDC, mLastCursorX - 1, 0);
#else
dc.Blit(mLastCursorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastCursorX, 0);
#endif
}
}
void TrackPanel::DoDrawCursor(wxDC & dc)
{
mLastCursorX = mNewCursorX;
if (mLastCursorX == -1)
return;
const bool
onScreen = between_incexc(mViewInfo->h,
mCursorTime,
GetScreenEndTime() );
if( !onScreen )
return;
AColor::CursorColor(&dc);
// Draw cursor in all selected tracks
VisibleTrackIterator iter( GetProject() );
for( Track *t = iter.First(); t; t = iter.Next() )
{
if( t->GetSelected() || mAx->IsFocused( t ) )
{
int y = t->GetY() - mViewInfo->vpos;
wxCoord top = y + kTopMargin;
// Minus one more because AColor::Line includes both endpoints
wxCoord bottom = y + t->GetHeight() - kBottomMargin - 1;
// MB: warp() is not needed here as far as I know, in fact it creates a bug. Removing it fixes that.
AColor::Line(dc, mLastCursorX, top, mLastCursorX, bottom); // <-- The whole point of this routine.
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if(MONO_WAVE_PAN(t)){
y = t->GetY(true) - mViewInfo->vpos + 1;
top = y + kTopInset;
bottom = y + t->GetHeight(true) - kTopInset;
AColor::Line( dc, mLastCursorX, top, mLastCursorX, bottom );
}
#endif
}
}
// AS: Ah, no, this is where we draw the blinky thing in the ruler.
mRuler->DrawCursor(mCursorTime);
DisplaySelection();
}
/// OnSize() is called when the panel is resized
void TrackPanel::OnSize(wxSizeEvent & /* event */)
{
@ -7890,80 +7639,81 @@ void TrackPanel::DrawOutsideOfTrack(Track * t, wxDC * dc, const wxRect & rect)
#endif
}
void TrackPanel::AddOverlay(TrackPanelOverlay *pOverlay)
{
mOverlays.push_back(pOverlay);
}
bool TrackPanel::RemoveOverlay(TrackPanelOverlay *pOverlay)
{
const size_t oldSize = mOverlays.size();
std::remove(mOverlays.begin(), mOverlays.end(), pOverlay);
return oldSize != mOverlays.size();
}
void TrackPanel::ClearOverlays()
{
mOverlays.clear();
}
void TrackPanel::DrawOverlays(bool repaint)
{
// Determine which overlays are outdated.
enum {
n_pairs =
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
3
#else
2
#endif
};
std::pair<wxRect, bool> pairs[n_pairs] = {
GetIndicatorRectangle(),
GetCursorRectangle(),
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
GetScrubSpeedRectangle(),
#endif
};
size_t n_pairs = mOverlays.size();
{
// Drawing now goes directly to the client area
wxClientDC dc(this);
std::vector< std::pair<wxRect, bool> > pairs;
pairs.reserve(n_pairs);
// See what requires redrawing. If repainting, all.
// If not, then whatever is outdated, and whatever will be damaged by
// undrawing.
// By redrawing only what needs it, we avoid flashing things like
// the cursor that are drawn with xor.
if (!repaint) {
bool done;
do {
done = true;
for (int ii = 0; ii < n_pairs; ++ii) {
for (int jj = ii + 1; jj < n_pairs; ++jj) {
if (pairs[ii].second != pairs[jj].second &&
pairs[ii].first.Intersects(pairs[jj].first)) {
done = false;
pairs[ii].second = pairs[jj].second = true;
}
// Find out the rectangles and outdatedness for each overlay
wxSize size(mBackingDC.GetSize());
for (const auto pOverlay : mOverlays)
pairs.push_back(pOverlay->GetRectangle(size));
// See what requires redrawing. If repainting, all.
// If not, then whatever is outdated, and whatever will be damaged by
// undrawing.
// By redrawing only what needs it, we avoid flashing things like
// the cursor that are drawn with invert.
if (!repaint) {
bool done;
do {
done = true;
for (size_t ii = 0; ii < n_pairs; ++ii) {
for (size_t jj = ii + 1; jj < n_pairs; ++jj) {
if (pairs[ii].second != pairs[jj].second &&
pairs[ii].first.Intersects(pairs[jj].first)) {
done = false;
pairs[ii].second = pairs[jj].second = true;
}
}
} while (!done);
}
} while (!done);
}
// Erase
bool done = true;
auto it2 = pairs.begin();
for (auto pOverlay : mOverlays) {
if (repaint || it2->second) {
done = false;
wxClientDC dc(this);
pOverlay->Erase(dc, mBackingDC);
}
++it2;
}
// Draw
if (!done) {
it2 = pairs.begin();
for (auto pOverlay : mOverlays) {
if (repaint || it2->second) {
wxClientDC dc(this);
TrackPanelCellIterator begin(this, true);
TrackPanelCellIterator end(this, false);
pOverlay->Draw(dc, begin, end);
}
++it2;
}
}
if (repaint || pairs[0].second) {
wxClientDC dc(this);
UndrawIndicator(dc);
}
if (repaint || pairs[1].second) {
wxClientDC dc(this);
UndrawCursor(dc);
}
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
if (repaint || pairs[2].second) {
wxClientDC dc(this);
UndrawScrubSpeed(dc);
}
#endif
if (repaint || pairs[0].second) {
wxClientDC dc(this);
DoDrawIndicator(dc);
}
if (repaint || pairs[1].second) {
wxClientDC dc(this);
DoDrawCursor(dc);
}
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
if (repaint || pairs[2].second) {
wxClientDC dc(this);
DoDrawScrubSpeed(dc);
}
#endif
}
/// Draw a three-level highlight gradient around the focused track.
@ -10036,6 +9786,46 @@ LWSlider * TrackInfo::PanSlider(WaveTrack *t, bool captured) const
return captured ? mPanCaptured : mPan;
}
TrackPanelCellIterator::TrackPanelCellIterator(TrackPanel *trackPanel, bool begin)
: mPanel(trackPanel)
, mIter(trackPanel->GetProject())
, mpCell(begin ? mIter.First() : NULL)
{
}
TrackPanelCellIterator &TrackPanelCellIterator::operator++ ()
{
mpCell = mIter.Next();
return *this;
}
TrackPanelCellIterator TrackPanelCellIterator::operator++ (int)
{
TrackPanelCellIterator copy(*this);
++ *this;
return copy;
}
auto TrackPanelCellIterator::operator* () const -> value_type
{
if (!mpCell)
return std::make_pair((Track*)nullptr, wxRect());
// Convert virtual coordinate to physical
int width;
mPanel->GetTracksUsableArea(&width, NULL);
int y = mpCell->GetY() - mPanel->GetViewInfo()->vpos;
return std::make_pair(
mpCell,
wxRect(
mPanel->GetLeftOffset(),
y + kTopMargin,
width,
mpCell->GetHeight() - (kTopMargin + kBottomMargin)
)
);
}
static TrackPanel * TrackPanelFactory(wxWindow * parent,
wxWindowID id,
const wxPoint & pos,

View File

@ -35,6 +35,7 @@ class wxRect;
class LabelTrack;
class SpectrumAnalyst;
class TrackPanel;
class TrackPanelOverlay;
class TrackArtist;
class Ruler;
class SnapManager;
@ -250,18 +251,6 @@ class AUDACITY_DLL_API TrackPanel final : public wxPanel {
virtual bool IsOverCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event);
virtual void HandleTrackSpecificMouseEvent(wxMouseEvent & event);
virtual void TimerUpdateIndicator(double playPos);
// Second member of pair indicates whether the indicator is out of date:
virtual std::pair<wxRect, bool> GetIndicatorRectangle();
virtual void UndrawIndicator(wxDC & dc);
/// draws the green line on the tracks to show playback position
virtual void DoDrawIndicator(wxDC & dc);
// Second member of pair indicates whether the cursor is out of date:
virtual std::pair<wxRect, bool> GetCursorRectangle();
virtual void UndrawCursor(wxDC & dc);
virtual void DoDrawCursor(wxDC & dc);
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
bool ShouldDrawScrubSpeed();
virtual void TimerUpdateScrubbing(double playPos);
@ -547,6 +536,15 @@ protected:
virtual void DrawOutsideOfTrack (Track *t, wxDC* dc, const wxRect & rect);
public:
// Register and unregister overlay objects.
// The sequence in which they were registered is the sequence in
// which they are painted.
// TrackPanel is not responsible for their memory management.
virtual void AddOverlay(TrackPanelOverlay *pOverlay);
// Returns true if the overlay was found
virtual bool RemoveOverlay(TrackPanelOverlay *pOverlay);
virtual void ClearOverlays();
// Erase and redraw things like the cursor, cheaply and directly to the
// client area, without full refresh.
virtual void DrawOverlays(bool repaint);
@ -597,14 +595,6 @@ protected:
TrackPanel *parent;
} mTimer;
// This stores the parts of the screen that get overwritten by the indicator
// and cursor
int mLastIndicatorX;
int mNewIndicatorX;
int mLastCursorX;
double mCursorTime;
int mNewCursorX;
// Quick-Play indicator postion
int mOldQPIndicatorPos;
@ -854,6 +844,11 @@ protected:
TrackPanelAx *mAx;
public:
TrackPanelAx &GetAx() { return *mAx; }
protected:
wxString mSoloPref;
// Keeps track of extra fractional vertical scroll steps
@ -867,6 +862,10 @@ protected:
public:
wxSize vrulerSize;
protected:
std::vector<TrackPanelOverlay*> mOverlays;
public:
DECLARE_EVENT_TABLE()
};

19
src/TrackPanelCell.h Normal file
View File

@ -0,0 +1,19 @@
/**********************************************************************
Audacity: A Digital Audio Editor
TrackPanelCell.h
Paul Licameli
**********************************************************************/
#ifndef __AUDACITY_TRACK_PANEL_CELL__
#define __AUDACITY_TRACK_PANEL_CELL__
// Future: TrackPanelCell will be generalized to a new abstract base class of Track
// and of other things.
class Track;
using TrackPanelCell = Track;
#endif

View File

@ -0,0 +1,52 @@
/**********************************************************************
Audacity: A Digital Audio Editor
TrackPanelCellIterator.h
Paul Licameli
**********************************************************************/
#ifndef __AUDACITY_TRACK_PANEL_CELL_ITERATOR__
#define __AUDACITY_TRACK_PANEL_CELL_ITERATOR__
#include "Track.h"
class Track;
typedef Track TrackPanelCell;
class TrackPanel;
// A class that allows iteration over the rectangles of visible cells.
class TrackPanelCellIterator
{
public:
TrackPanelCellIterator(TrackPanel *trackPanel, bool begin);
// implement the STL iterator idiom
TrackPanelCellIterator &operator++ ();
TrackPanelCellIterator operator++ (int);
friend inline bool operator==
(const TrackPanelCellIterator &lhs, const TrackPanelCellIterator &rhs)
{
return lhs.mpCell == rhs.mpCell;
}
using value_type = std::pair<TrackPanelCell*, wxRect>;
value_type operator * () const;
private:
TrackPanel *mPanel;
VisibleTrackIterator mIter;
TrackPanelCell *mpCell;
};
inline bool operator !=
(const TrackPanelCellIterator &lhs, const TrackPanelCellIterator &rhs)
{
return !(lhs == rhs);
}
#endif

40
src/TrackPanelOverlay.cpp Normal file
View File

@ -0,0 +1,40 @@
/**********************************************************************
Audacity: A Digital Audio Editor
TrackPanelOverlay.cpp
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#include "TrackPanelOverlay.h"
#include <wx/dc.h>
TrackPanelOverlay::~TrackPanelOverlay()
{
}
std::pair<wxRect, bool> TrackPanelOverlay::GetRectangle(wxSize size)
{
auto result = DoGetRectangle(size);
#ifdef __WXMAC__
// On OSX, if a HiDPI resolution is being used, a vertical line will actually take up
// more than 1 pixel (even though it is drawn as 1), so we restore the surrounding
// pixels as well. (This is because the wxClientDC doesn't know about the scaling.
result.first.Inflate(1, 0);
#endif
return result;
}
void TrackPanelOverlay::Erase(wxDC &dc, wxDC &src)
{
wxRect rect(dc.GetSize());
rect.Intersect(src.GetSize());
auto smallRect(GetRectangle(src.GetSize()).first);
rect.Intersect(smallRect);
if (!rect.IsEmpty())
dc.Blit(rect.x, rect.y, rect.width, rect.height,
&src, rect.x, rect.y);
}

43
src/TrackPanelOverlay.h Normal file
View File

@ -0,0 +1,43 @@
/**********************************************************************
Audacity: A Digital Audio Editor
TrackPanelOverlay.h
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#ifndef __AUDACITY_TRACK_PANEL_OVERLAY__
#define __AUDACITY_TRACK_PANEL_OVERLAY__
class TrackPanelCellIterator;
#include <utility>
class wxDC;
class wxRect;
class wxSize;
class TrackPanelOverlay
{
public:
virtual ~TrackPanelOverlay() = 0;
// nonvirtual wrapper
std::pair<wxRect, bool> GetRectangle(wxSize size);
// size passes the dimensions of the backing dc
// First member of pair is the rectangle that would be erased
// Second member of pair indicates whether the overlay is out of date
virtual std::pair<wxRect, bool> DoGetRectangle(wxSize size) = 0;
// Default implementation blits from backing store over GetRectangle().first
virtual void Erase(wxDC &dc, wxDC &src);
// Draw; dc.GetSize() tells you the total dimensions, and the iterators let you
// find the rectangles of tracks (or other sub-rectangles of the panel)
virtual void Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end) = 0;
};
#endif

View File

@ -13,6 +13,7 @@ Paul Licameli
#include <algorithm>
#include "AudioIO.h"
#include "Internat.h"
#include "prefs/GUISettings.h"
#include "Prefs.h"
@ -123,6 +124,7 @@ ViewInfo::ViewInfo(double start, double screenDuration, double pixelsPerSecond)
, scrollStep(16)
, bUpdateTrackIndicator(true)
, bScrollBeyondZero(false)
, mRecentStreamTime(-1.0)
{
UpdatePrefs();
}
@ -176,3 +178,9 @@ bool ViewInfo::ReadXMLAttribute(const wxChar *attr, const wxChar *value)
return false;
}
void ViewInfo::OnTimer(wxCommandEvent &event)
{
mRecentStreamTime = gAudioIO->GetStreamTime();
event.Skip();
}

View File

@ -12,6 +12,7 @@
#define __AUDACITY_VIEWINFO__
#include <vector>
#include <wx/event.h>
#include "SelectedRegion.h"
@ -131,10 +132,10 @@ public:
// Exclusive:
wxInt64 GetFisheyeRightBoundary(wxInt64 WXUNUSED(origin = 0)) const
{return 0;} // stub
};
class AUDACITY_DLL_API ViewInfo final : public ZoomInfo
class AUDACITY_DLL_API ViewInfo final
: public wxEvtHandler, public ZoomInfo
{
public:
ViewInfo(double start, double screenDuration, double pixelsPerSecond);
@ -180,8 +181,15 @@ public:
bool bScrollBeyondZero;
// During timer update, grab the volatile stream time just once, so that
// various other drawing code can use the exact same value.
double mRecentStreamTime;
void WriteXMLAttributes(XMLWriter &xmlFile);
bool ReadXMLAttribute(const wxChar *attr, const wxChar *value);
// Receive track panel timer notifications
void OnTimer(wxCommandEvent &event);
};
#endif

View File

@ -0,0 +1,118 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EditCursorOverlay.cpp
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#include "../../Audacity.h"
#include "EditCursorOverlay.h"
#include "../../Experimental.h"
#include "../../AColor.h"
#include "../../widgets/Ruler.h"
#include "../../Project.h"
//#include "../../TrackPanel.h"
#include "../../TrackPanelCell.h"
#include "../../TrackPanelCellIterator.h"
#include "../../TrackPanelAx.h"
#include "../../ViewInfo.h"
#include <wx/dc.h>
namespace {
template < class LOW, class MID, class HIGH >
bool between_incexc(LOW l, MID m, HIGH h)
{
return (m >= l && m < h);
}
}
EditCursorOverlay::EditCursorOverlay(AudacityProject *project)
: mProject(project)
, mLastCursorX(-1)
, mCursorTime(-1)
, mNewCursorX(-1)
{
}
EditCursorOverlay::~EditCursorOverlay()
{
}
std::pair<wxRect, bool> EditCursorOverlay::DoGetRectangle(wxSize size)
{
const SelectedRegion &selection = mProject->GetSelection();
if (!selection.isPoint()) {
mCursorTime = -1.0;
mNewCursorX = -1;
}
else {
mCursorTime = selection.t0();
mNewCursorX = mProject->GetZoomInfo().TimeToPosition
(mCursorTime, mProject->GetTrackPanel()->GetLeftOffset());
}
return std::make_pair(
mLastCursorX == -1
? wxRect()
: wxRect(mLastCursorX, 0, 1, size.GetHeight()),
mLastCursorX != mNewCursorX
);
}
void EditCursorOverlay::Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end)
{
mLastCursorX = mNewCursorX;
if (mLastCursorX == -1)
return;
const ZoomInfo &viewInfo = mProject->GetZoomInfo();
const bool
onScreen = between_incexc(viewInfo.h,
mCursorTime,
mProject->GetScreenEndTime());
if (!onScreen)
return;
AColor::CursorColor(&dc);
// Draw cursor in all selected tracks
for (; begin != end; ++begin)
{
TrackPanelCellIterator::value_type data(*begin);
Track *const pTrack = data.first;
if (!pTrack)
continue;
if (pTrack->GetSelected() ||
mProject->GetTrackPanel()->GetAx().IsFocused(pTrack))
{
const wxRect &rect = data.second;
// AColor::Line includes both endpoints so use GetBottom()
AColor::Line(dc, mLastCursorX, rect.GetTop(), mLastCursorX, rect.GetBottom()); // <-- The whole point of this routine.
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
if (MONO_WAVE_PAN(t)){
y = t->GetY(true) - mViewInfo->vpos + 1;
top = y + kTopInset;
bottom = y + t->GetHeight(true) - kTopInset;
AColor::Line(dc, mLastCursorX, top, mLastCursorX, bottom);
}
#endif
}
}
// AS: Ah, no, this is where we draw the blinky thing in the ruler.
mProject->GetRulerPanel()->DrawCursor(mCursorTime);
// This updates related displays such as numbers on the status bar
mProject->TP_DisplaySelection();
}

View File

@ -0,0 +1,36 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EditCursorOverlay.h
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#ifndef __AUDACITY_EDIT_CURSOR_OVERLAY__
#define __AUDACITY_EDIT_CURSOR_OVERLAY__
#include "../../TrackPanelOverlay.h"
class AudacityProject;
class EditCursorOverlay final : public TrackPanelOverlay
{
public:
EditCursorOverlay(AudacityProject *project);
virtual ~EditCursorOverlay();
private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end) override;
AudacityProject *mProject;
int mLastCursorX;
double mCursorTime;
int mNewCursorX;
};
#endif

View File

@ -0,0 +1,151 @@
/**********************************************************************
Audacity: A Digital Audio Editor
PlayIndicatorOverlay.cpp
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#include "PlayIndicatorOverlay.h"
#include "../../AColor.h"
#include "../../AudioIO.h"
#include "../../Project.h"
#include "../../TrackPanel.h"
#include "../../TrackPanelCell.h"
#include "../../TrackPanelCellIterator.h"
#include "../../widgets/Ruler.h"
#include <wx/dc.h>
#include <algorithm>
namespace {
template < class LOW, class MID, class HIGH >
bool between_incexc(LOW l, MID m, HIGH h)
{
return (m >= l && m < h);
}
}
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
: mProject(project)
, mLastIndicatorX(-1)
, mNewIndicatorX(-1)
{
mProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
PlayIndicatorOverlay::~PlayIndicatorOverlay()
{
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
std::pair<wxRect, bool> PlayIndicatorOverlay::DoGetRectangle(wxSize size)
{
wxRect rect(mLastIndicatorX, 0, 1, size.GetHeight());
return std::make_pair(
rect,
mLastIndicatorX != mNewIndicatorX
);
}
void PlayIndicatorOverlay::Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end)
{
mLastIndicatorX = mNewIndicatorX;
if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
return;
const ZoomInfo &viewInfo = mProject->GetZoomInfo();
TrackPanel *const trackPanel = mProject->GetTrackPanel();
double pos = viewInfo.PositionToTime(mLastIndicatorX, trackPanel->GetLeftOffset());
// Set play/record color
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
AColor::IndicatorColor(&dc, !rec);
mProject->GetRulerPanel()->DrawIndicator(pos, rec);
// Draw indicator in all visible tracks
for (; begin != end; ++begin)
{
TrackPanelCellIterator::value_type data(*begin);
Track *const pTrack = data.first;
if (!pTrack)
continue;
// Don't draw the indicator in label tracks
if (pTrack->GetKind() == Track::Label)
{
continue;
}
// Draw the NEW indicator in its NEW location
// AColor::Line includes both endpoints so use GetBottom()
const wxRect &rect = data.second;
AColor::Line(dc,
mLastIndicatorX,
rect.GetTop(),
mLastIndicatorX,
rect.GetBottom());
}
}
void PlayIndicatorOverlay::Erase(wxDC &dc, wxDC &src)
{
TrackPanelOverlay::Erase(dc, src);
mProject->GetRulerPanel()->ClearIndicator();
}
void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
{
// Let other listeners get the notification
event.Skip();
if (!mProject->IsAudioActive())
mNewIndicatorX = -1;
else {
ViewInfo &viewInfo = mProject->GetViewInfo();
// Calculate the horizontal position of the indicator
const double playPos = viewInfo.mRecentStreamTime;
const bool onScreen = playPos >= 0.0 &&
between_incexc(viewInfo.h,
playPos,
mProject->GetScreenEndTime());
// This displays the audio time, too...
mProject->TP_DisplaySelection();
// BG: Scroll screen if option is set
// msmeyer: But only if not playing looped or in one-second mode
if (viewInfo.bUpdateTrackIndicator &&
mProject->mLastPlayMode != loopedPlay &&
mProject->mLastPlayMode != oneSecondPlay &&
playPos >= 0 &&
!onScreen &&
!gAudioIO->IsPaused())
{
mProject->TP_ScrollWindow(playPos);
}
// Always update scrollbars even if not scrolling the window. This is
// important when NEW audio is recorded, because this can change the
// length of the project and therefore the appearance of the scrollbar.
mProject->TP_RedrawScrollbars();
mNewIndicatorX = viewInfo.TimeToPosition(playPos, mProject->GetTrackPanel()->GetLeftOffset());
}
}

View File

@ -0,0 +1,40 @@
/**********************************************************************
Audacity: A Digital Audio Editor
PlayIndicatorOverlay.h
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#ifndef __AUDACITY_PLAY_INDICATOR_OVERLAY__
#define __AUDACITY_PLAY_INDICATOR_OVERLAY__
#include "../../TrackPanelOverlay.h"
#include <wx/event.h>
class AudacityProject;
class PlayIndicatorOverlay final : public wxEvtHandler, public TrackPanelOverlay
{
public:
PlayIndicatorOverlay(AudacityProject *project);
virtual ~PlayIndicatorOverlay();
private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end) override;
void Erase(wxDC &dc, wxDC &src) override;
void OnTimer(wxCommandEvent &event);
AudacityProject *mProject;
int mLastIndicatorX;
int mNewIndicatorX;
};
#endif

View File

@ -0,0 +1,53 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Scrubbing.cpp
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#include "Scrubbing.h"
#include "../../Project.h"
#include "../../TrackPanel.h"
#include "../../TrackPanelCell.h"
#include "../../TrackPanelCellIterator.h"
#include <wx/dc.h>
ScrubbingOverlay::ScrubbingOverlay(AudacityProject *project)
: mProject(project)
{
mProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(ScrubbingOverlay::OnTimer),
NULL,
this);
}
ScrubbingOverlay::~ScrubbingOverlay()
{
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(ScrubbingOverlay::OnTimer),
NULL,
this);
}
std::pair<wxRect, bool> ScrubbingOverlay::DoGetRectangle(wxSize)
{
return std::make_pair(wxRect(), false);
}
void ScrubbingOverlay::Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end)
{
}
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
{
// Let other listeners get the notification
event.Skip();
// To do: move code here
}

36
src/tracks/ui/Scrubbing.h Normal file
View File

@ -0,0 +1,36 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Scrubbing.h
Paul Licameli split from TrackPanel.cpp
**********************************************************************/
#ifndef __AUDACITY_SCRUBBING__
#define __AUDACITY_SCRUBBING__
#include <wx/event.h>
#include "../../TrackPanelOverlay.h"
class AudacityProject;
class ScrubbingOverlay : public wxEvtHandler, public TrackPanelOverlay
{
public:
ScrubbingOverlay(AudacityProject *project);
virtual ~ScrubbingOverlay();
private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end) override;
void OnTimer(wxCommandEvent &event);
AudacityProject *mProject;
};
#endif

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -213,6 +213,10 @@
<ClCompile Include="..\..\..\src\TrackArtist.cpp" />
<ClCompile Include="..\..\..\src\TrackPanel.cpp" />
<ClCompile Include="..\..\..\src\TrackPanelAx.cpp" />
<ClCompile Include="..\..\..\src\TrackPanelOverlay.cpp" />
<ClCompile Include="..\..\..\src\tracks\ui\EditCursorOverlay.cpp" />
<ClCompile Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.cpp" />
<ClCompile Include="..\..\..\src\tracks\ui\Scrubbing.cpp" />
<ClCompile Include="..\..\..\src\UndoManager.cpp" />
<ClCompile Include="..\..\..\src\ViewInfo.cpp" />
<ClCompile Include="..\..\..\src\VoiceKey.cpp" />
@ -435,7 +439,13 @@
<ClInclude Include="..\..\..\src\SseMathFuncs.h" />
<ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBar.h" />
<ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBarListener.h" />
<ClInclude Include="..\..\..\src\TrackPanelCell.h" />
<ClInclude Include="..\..\..\src\TrackPanelCellIterator.h" />
<ClInclude Include="..\..\..\src\TrackPanelListener.h" />
<ClInclude Include="..\..\..\src\TrackPanelOverlay.h" />
<ClInclude Include="..\..\..\src\tracks\ui\EditCursorOverlay.h" />
<ClInclude Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.h" />
<ClInclude Include="..\..\..\src\tracks\ui\Scrubbing.h" />
<ClInclude Include="..\..\..\src\TranslatableStringArray.h" />
<ClInclude Include="..\..\..\src\WaveTrackLocation.h" />
<ClInclude Include="..\..\..\src\widgets\HelpSystem.h" />
@ -1097,4 +1107,4 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\ny.targets" />
</ImportGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
@ -69,6 +69,12 @@
<Filter Include="src\effects\VST">
<UniqueIdentifier>{99325e00-3930-4e03-a599-999f275db78e}</UniqueIdentifier>
</Filter>
<Filter Include="src\tracks">
<UniqueIdentifier>{7b403d1f-de11-43d5-becc-d9d118d06f18}</UniqueIdentifier>
</Filter>
<Filter Include="src\tracks\ui">
<UniqueIdentifier>{aa9627ea-e614-4704-bf68-4a347023569f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\AboutDialog.cpp">
@ -275,9 +281,6 @@
<ClCompile Include="..\..\..\src\TrackArtist.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\TrackPanel.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\TrackPanelAx.cpp">
<Filter>src</Filter>
</ClCompile>
@ -857,6 +860,21 @@
<ClCompile Include="..\..\..\src\RealFFTf48x.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\TrackPanelOverlay.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\tracks\ui\EditCursorOverlay.cpp">
<Filter>src\tracks\ui</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.cpp">
<Filter>src\tracks\ui</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\tracks\ui\Scrubbing.cpp">
<Filter>src\tracks\ui</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\TrackPanel.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\AboutDialog.h">
@ -1714,6 +1732,9 @@
<ClInclude Include="..\..\..\src\effects\VST\VSTControlMSW.h">
<Filter>src\effects\VST</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\TrackPanelOverlay.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\TranslatableStringArray.h">
<Filter>src</Filter>
</ClInclude>
@ -1732,6 +1753,21 @@
<ClInclude Include="..\..\..\src\RealFFTf48x.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\TrackPanelCell.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\tracks\ui\EditCursorOverlay.h">
<Filter>src\tracks\ui</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.h">
<Filter>src\tracks\ui</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\tracks\ui\Scrubbing.h">
<Filter>src\tracks\ui</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\TrackPanelCellIterator.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\..\audacity.ico">
@ -1952,4 +1988,4 @@
<Filter>plug-ins</Filter>
</copy>
</ItemGroup>
</Project>
</Project>