mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-03 17:19:43 +02:00
TrackPanel.cpp cleanup: Move code for scrubbing and some of drawing out...
... Specifically there are "overlays" for play indicator, cursor, scrubbing speed text, and quick play indicator, which now use a common abstract class interface. Also moved details of handling timer events elsewhere. Made a class Scrubber with most of the details. Still there are several places where TrackPanel must check for scrubbing and call to Scrubber. Too many places.
This commit is contained in:
commit
408f1ecad2
@ -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 */,
|
||||
|
@ -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 \
|
||||
|
@ -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,33 @@ 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);
|
||||
mScrubber = std::make_unique<Scrubber>(this);
|
||||
#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());
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
mTrackPanel->AddOverlay(mScrubOverlay.get());
|
||||
#endif
|
||||
|
||||
// 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 +1082,14 @@ AudacityProject::~AudacityProject()
|
||||
wxGetApp().GetRecentFiles()->RemoveMenu(mRecentFilesMenu);
|
||||
}
|
||||
|
||||
if(mTrackPanel) {
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
mTrackPanel->RemoveOverlay(mScrubOverlay.get());
|
||||
#endif
|
||||
mTrackPanel->RemoveOverlay(mCursorOverlay.get());
|
||||
mTrackPanel->RemoveOverlay(mIndicatorOverlay.get());
|
||||
}
|
||||
|
||||
wxTheApp->Disconnect(EVT_AUDIOIO_CAPTURE,
|
||||
wxCommandEventHandler(AudacityProject::OnCapture),
|
||||
NULL,
|
||||
@ -2339,6 +2378,11 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
|
||||
#endif
|
||||
}
|
||||
|
||||
this->Disconnect(EVT_TRACK_PANEL_TIMER,
|
||||
wxCommandEventHandler(ViewInfo::OnTimer),
|
||||
NULL,
|
||||
&mViewInfo);
|
||||
|
||||
Destroy();
|
||||
|
||||
mIsBeingDeleted = true;
|
||||
|
@ -62,6 +62,7 @@ class Tags;
|
||||
class EffectPlugs;
|
||||
|
||||
class TrackPanel;
|
||||
class TrackPanelOverlay;
|
||||
class FreqWindow;
|
||||
class ContrastDialog;
|
||||
class Meter;
|
||||
@ -72,6 +73,7 @@ class DeviceToolBar;
|
||||
class EditToolBar;
|
||||
class MeterToolBar;
|
||||
class MixerToolBar;
|
||||
class Scrubber;
|
||||
class SelectionBar;
|
||||
class SpectralSelectionBar;
|
||||
class Toolbar;
|
||||
@ -171,9 +173,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 +708,18 @@ public:
|
||||
// CommandManager needs to use private methods
|
||||
friend class CommandManager;
|
||||
|
||||
// TrackPanelOverlay objects
|
||||
std::unique_ptr<TrackPanelOverlay>
|
||||
mIndicatorOverlay, mCursorOverlay;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
std::unique_ptr<TrackPanelOverlay> mScrubOverlay;
|
||||
std::unique_ptr<Scrubber> mScrubber;
|
||||
public:
|
||||
Scrubber &GetScrubber() { return *mScrubber; }
|
||||
const Scrubber &GetScrubber() const { return *mScrubber; }
|
||||
#endif
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
1043
src/TrackPanel.cpp
1043
src/TrackPanel.cpp
File diff suppressed because it is too large
Load Diff
104
src/TrackPanel.h
104
src/TrackPanel.h
@ -35,6 +35,7 @@ class wxRect;
|
||||
class LabelTrack;
|
||||
class SpectrumAnalyst;
|
||||
class TrackPanel;
|
||||
class TrackPanelOverlay;
|
||||
class TrackArtist;
|
||||
class Ruler;
|
||||
class SnapManager;
|
||||
@ -73,6 +74,11 @@ enum class UndoPush : unsigned char;
|
||||
|
||||
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACK_PANEL_TIMER, -1);
|
||||
|
||||
enum {
|
||||
kTimerInterval = 50, // milliseconds
|
||||
kOneSecondCountdown = 1000 / kTimerInterval,
|
||||
};
|
||||
|
||||
class AUDACITY_DLL_API TrackInfo
|
||||
{
|
||||
public:
|
||||
@ -160,7 +166,6 @@ class AUDACITY_DLL_API TrackPanel final : public wxPanel {
|
||||
|
||||
virtual void OnSetFocus(wxFocusEvent & event);
|
||||
virtual void OnKillFocus(wxFocusEvent & event);
|
||||
virtual void OnActivateOrDeactivateApp(wxActivateEvent & event);
|
||||
|
||||
virtual void OnContextMenu(wxContextMenuEvent & event);
|
||||
|
||||
@ -224,8 +229,6 @@ class AUDACITY_DLL_API TrackPanel final : public wxPanel {
|
||||
virtual void UpdateTrackVRuler(Track *t);
|
||||
virtual void UpdateVRulerSize();
|
||||
|
||||
virtual void DrawQuickPlayIndicator(int x, bool snapped = false);
|
||||
|
||||
// Returns the time corresponding to the pixel column one past the track area
|
||||
// (ignoring any fisheye)
|
||||
virtual double GetScreenEndTime() const;
|
||||
@ -250,27 +253,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);
|
||||
// Second member of pair indicates whether the cursor is out of date:
|
||||
virtual std::pair<wxRect, bool> GetScrubSpeedRectangle();
|
||||
virtual void UndrawScrubSpeed(wxDC & dc);
|
||||
virtual void DoDrawScrubSpeed(wxDC & dc);
|
||||
#endif
|
||||
|
||||
virtual void ScrollDuringDrag();
|
||||
|
||||
// Working out where to dispatch the event to.
|
||||
@ -310,31 +292,7 @@ class AUDACITY_DLL_API TrackPanel final : public wxPanel {
|
||||
virtual void HandleSelect(wxMouseEvent & event);
|
||||
virtual void SelectionHandleDrag(wxMouseEvent &event, Track *pTrack);
|
||||
|
||||
// Made obsolete by scrubbing:
|
||||
#ifndef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
void StartOrJumpPlayback(wxMouseEvent &event);
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
double FindScrubSpeed(double timeAtMouse) const;
|
||||
double FindSeekSpeed(double timeAtMouse) const;
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
static bool PollIsSeeking();
|
||||
bool IsScrubbing();
|
||||
void MarkScrubStart(
|
||||
wxCoord xx
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
, bool smoothScrolling
|
||||
#endif
|
||||
);
|
||||
bool MaybeStartScrubbing(wxMouseEvent &event);
|
||||
bool ContinueScrubbing(wxCoord position, bool hasFocus, bool seek);
|
||||
public:
|
||||
bool StopScrubbing();
|
||||
protected:
|
||||
#endif
|
||||
|
||||
virtual void SelectionHandleClick(wxMouseEvent &event,
|
||||
Track* pTrack, wxRect rect);
|
||||
@ -547,6 +505,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,17 +564,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;
|
||||
|
||||
int mTimeCount;
|
||||
|
||||
wxMemoryDC mBackingDC;
|
||||
@ -798,27 +754,6 @@ protected:
|
||||
int mMoveDownThreshold;
|
||||
int mRearrangeCount;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
int mScrubToken;
|
||||
wxLongLong mScrubStartClockTimeMillis;
|
||||
wxCoord mScrubStartPosition;
|
||||
double mMaxScrubSpeed;
|
||||
int mScrubSpeedDisplayCountdown;
|
||||
bool mScrubHasFocus;
|
||||
bool mScrubSeekPress;
|
||||
|
||||
wxRect mLastScrubRect, mNextScrubRect;
|
||||
wxString mLastScrubSpeedText, mNextScrubSpeedText;
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
bool mSmoothScrollingScrub;
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
int mLogMaxScrubSpeed;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<wxCursor>
|
||||
mArrowCursor, mPencilCursor, mSelectCursor,
|
||||
mResizeCursor, mSlideCursor, mEnvelopeCursor, // doubles as the center frequency cursor
|
||||
@ -854,6 +789,11 @@ protected:
|
||||
|
||||
TrackPanelAx *mAx;
|
||||
|
||||
public:
|
||||
TrackPanelAx &GetAx() { return *mAx; }
|
||||
|
||||
protected:
|
||||
|
||||
wxString mSoloPref;
|
||||
|
||||
// Keeps track of extra fractional vertical scroll steps
|
||||
@ -867,6 +807,10 @@ protected:
|
||||
public:
|
||||
wxSize vrulerSize;
|
||||
|
||||
protected:
|
||||
std::vector<TrackPanelOverlay*> mOverlays;
|
||||
|
||||
public:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
19
src/TrackPanelCell.h
Normal file
19
src/TrackPanelCell.h
Normal 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
|
52
src/TrackPanelCellIterator.h
Normal file
52
src/TrackPanelCellIterator.h
Normal 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
40
src/TrackPanelOverlay.cpp
Normal 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
43
src/TrackPanelOverlay.h
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -52,13 +52,15 @@
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../ImageManipulation.h"
|
||||
#include "../Project.h"
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
#include "../TrackPanel.h"
|
||||
#endif
|
||||
#include "../Theme.h"
|
||||
#include "../widgets/AButton.h"
|
||||
|
||||
#include "../Experimental.h"
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
#include "../tracks/ui/Scrubbing.h"
|
||||
#endif
|
||||
|
||||
#include "../widgets/AButton.h"
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(ToolsToolBar, ToolBar);
|
||||
|
||||
@ -219,13 +221,9 @@ void ToolsToolBar::SetCurrentTool(int tool, bool show)
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
if (tool != selectTool) {
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (p) {
|
||||
TrackPanel *tp = p->GetTrackPanel();
|
||||
if (tp) {
|
||||
tp->StopScrubbing();
|
||||
}
|
||||
}
|
||||
AudacityProject *const p = GetActiveProject();
|
||||
if (p)
|
||||
p->GetScrubber().StopScrubbing();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -294,13 +292,9 @@ void ToolsToolBar::OnTool(wxCommandEvent & evt)
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
if (0 != mCurrentTool) {
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (p) {
|
||||
TrackPanel *tp = p->GetTrackPanel();
|
||||
if (tp) {
|
||||
tp->StopScrubbing();
|
||||
}
|
||||
}
|
||||
AudacityProject *const p = GetActiveProject();
|
||||
if (p)
|
||||
p->GetScrubber().StopScrubbing();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
118
src/tracks/ui/EditCursorOverlay.cpp
Normal file
118
src/tracks/ui/EditCursorOverlay.cpp
Normal 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();
|
||||
}
|
36
src/tracks/ui/EditCursorOverlay.h
Normal file
36
src/tracks/ui/EditCursorOverlay.h
Normal 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
|
151
src/tracks/ui/PlayIndicatorOverlay.cpp
Normal file
151
src/tracks/ui/PlayIndicatorOverlay.cpp
Normal 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());
|
||||
}
|
||||
}
|
40
src/tracks/ui/PlayIndicatorOverlay.h
Normal file
40
src/tracks/ui/PlayIndicatorOverlay.h
Normal 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
|
534
src/tracks/ui/Scrubbing.cpp
Normal file
534
src/tracks/ui/Scrubbing.cpp
Normal file
@ -0,0 +1,534 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
Scrubbing.cpp
|
||||
|
||||
Paul Licameli split from TrackPanel.cpp
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "Scrubbing.h"
|
||||
#include "../../Experimental.h"
|
||||
|
||||
#include "../../AudioIO.h"
|
||||
#include "../../Project.h"
|
||||
#include "../../TrackPanel.h"
|
||||
#include "../../TrackPanelCell.h"
|
||||
#include "../../TrackPanelCellIterator.h"
|
||||
#include "../../toolbars/ControlToolBar.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <wx/dc.h>
|
||||
|
||||
enum {
|
||||
// PRL:
|
||||
// Mouse must move at least this far to distinguish ctrl-drag to scrub
|
||||
// from ctrl-click for playback.
|
||||
SCRUBBING_PIXEL_TOLERANCE = 10,
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
ScrubSpeedStepsPerOctave = 4,
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace {
|
||||
bool PollIsSeeking()
|
||||
{
|
||||
return ::wxGetMouseState().LeftIsDown();
|
||||
}
|
||||
|
||||
double FindScrubbingSpeed(const ViewInfo &viewInfo, double maxScrubSpeed, double screen, double timeAtMouse)
|
||||
{
|
||||
// Map a time (which was mapped from a mouse position)
|
||||
// to a speed.
|
||||
// Map times to positive and negative speeds,
|
||||
// with the time at the midline of the screen mapping to 0,
|
||||
// and the extremes to the maximum scrub speed.
|
||||
|
||||
// Width of visible track area, in time terms:
|
||||
const double origin = viewInfo.h + screen / 2.0;
|
||||
|
||||
// There are various snapping zones that are this fraction of screen:
|
||||
const double snap = 0.05;
|
||||
|
||||
// By shrinking denom a bit, we make margins left and right
|
||||
// that snap to maximum and negative maximum speeds.
|
||||
const double factor = 1.0 - (snap * 2);
|
||||
const double denom = factor * screen / 2.0;
|
||||
double fraction = std::min(1.0, fabs(timeAtMouse - origin) / denom);
|
||||
|
||||
// Snap to 1.0 and -1.0
|
||||
const double unity = 1.0 / maxScrubSpeed;
|
||||
const double tolerance = snap / factor;
|
||||
// Make speeds near 1 available too by remapping fractions outside
|
||||
// this snap zone
|
||||
if (fraction <= unity - tolerance)
|
||||
fraction *= unity / (unity - tolerance);
|
||||
else if (fraction < unity + tolerance)
|
||||
fraction = unity;
|
||||
else
|
||||
fraction = unity + (fraction - (unity + tolerance)) *
|
||||
(1.0 - unity) / (1.0 - (unity + tolerance));
|
||||
|
||||
double result = fraction * maxScrubSpeed;
|
||||
if (timeAtMouse < origin)
|
||||
result *= -1.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
double FindSeekSpeed(const ViewInfo &viewInfo, double maxScrubSpeed, double screen, double timeAtMouse)
|
||||
{
|
||||
// Map a time (which was mapped from a mouse position)
|
||||
// to a signed skip speed: a multiplier of the stutter duration,
|
||||
// by which to advance the play position.
|
||||
// (The stutter will play at unit speed.)
|
||||
|
||||
// Times near the midline of the screen map to skip-less play,
|
||||
// and the extremes to a value proportional to maximum scrub speed.
|
||||
|
||||
// If the maximum scrubbing speed defaults to 1.0 when you begin to scroll-scrub,
|
||||
// the extreme skipping for scroll-seek needs to be larger to be useful.
|
||||
static const double ARBITRARY_MULTIPLIER = 10.0;
|
||||
const double extreme = std::max(1.0, maxScrubSpeed * ARBITRARY_MULTIPLIER);
|
||||
|
||||
// Width of visible track area, in time terms:
|
||||
const double halfScreen = screen / 2.0;
|
||||
const double origin = viewInfo.h + halfScreen;
|
||||
|
||||
// The snapping zone is this fraction of screen, on each side of the
|
||||
// center line:
|
||||
const double snap = 0.05;
|
||||
const double fraction =
|
||||
std::max(snap, std::min(1.0, fabs(timeAtMouse - origin) / halfScreen));
|
||||
|
||||
double result = 1.0 + ((fraction - snap) / (1.0 - snap)) * (extreme - 1.0);
|
||||
if (timeAtMouse < origin)
|
||||
result *= -1.0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Scrubber::Scrubber(AudacityProject *project)
|
||||
: mScrubToken(-1)
|
||||
, mScrubStartClockTimeMillis(-1)
|
||||
, mScrubHasFocus(false)
|
||||
, mScrubSpeedDisplayCountdown(0)
|
||||
, mScrubStartPosition(-1)
|
||||
, mMaxScrubSpeed(-1.0)
|
||||
, mScrubSeekPress(false)
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
, mSmoothScrollingScrub(false)
|
||||
, mLogMaxScrubSpeed(0)
|
||||
#endif
|
||||
|
||||
, mProject(project)
|
||||
{
|
||||
if (wxTheApp)
|
||||
wxTheApp->Connect
|
||||
(wxEVT_ACTIVATE_APP,
|
||||
wxActivateEventHandler(Scrubber::OnActivateOrDeactivateApp), NULL, this);
|
||||
}
|
||||
|
||||
Scrubber::~Scrubber()
|
||||
{
|
||||
if (wxTheApp)
|
||||
wxTheApp->Disconnect
|
||||
(wxEVT_ACTIVATE_APP,
|
||||
wxActivateEventHandler(Scrubber::OnActivateOrDeactivateApp), NULL, this);
|
||||
}
|
||||
|
||||
void Scrubber::MarkScrubStart(
|
||||
wxCoord xx
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
, bool smoothScrolling
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Don't actually start scrubbing, but collect some information
|
||||
// needed for the decision to start scrubbing later when handling
|
||||
// drag events.
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
mSmoothScrollingScrub = smoothScrolling;
|
||||
#endif
|
||||
mScrubStartPosition = xx;
|
||||
mScrubStartClockTimeMillis = ::wxGetLocalTimeMillis();
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
||||
bool Scrubber::MaybeStartScrubbing(const wxMouseEvent &event)
|
||||
{
|
||||
if (mScrubStartPosition < 0)
|
||||
return false;
|
||||
if (IsScrubbing())
|
||||
return false;
|
||||
else {
|
||||
const bool busy = gAudioIO->IsBusy();
|
||||
if (busy && gAudioIO->GetNumCaptureChannels() > 0) {
|
||||
// Do not stop recording, and don't try to start scrubbing after
|
||||
// recording stops
|
||||
mScrubStartPosition = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCoord position = event.m_x;
|
||||
if (abs(mScrubStartPosition - position) >= SCRUBBING_PIXEL_TOLERANCE) {
|
||||
const ViewInfo &viewInfo = mProject->GetViewInfo();
|
||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||
ControlToolBar * const ctb = mProject->GetControlToolBar();
|
||||
double maxTime = mProject->GetTracks()->GetEndTime();
|
||||
const int leftOffset = trackPanel->GetLeftOffset();
|
||||
double time0 = std::min(maxTime,
|
||||
viewInfo.PositionToTime(mScrubStartPosition, leftOffset)
|
||||
);
|
||||
double time1 = std::min(maxTime,
|
||||
viewInfo.PositionToTime(position, leftOffset)
|
||||
);
|
||||
if (time1 != time0)
|
||||
{
|
||||
if (busy)
|
||||
ctb->StopPlaying();
|
||||
|
||||
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
||||
options.timeTrack = NULL;
|
||||
options.scrubDelay = (kTimerInterval / 1000.0);
|
||||
options.scrubStartClockTimeMillis = mScrubStartClockTimeMillis;
|
||||
options.minScrubStutter = 0.2;
|
||||
#if 0
|
||||
// Take the starting speed limit from the transcription toolbar,
|
||||
// but it may be varied during the scrub.
|
||||
mMaxScrubSpeed = options.maxScrubSpeed =
|
||||
p->GetTranscriptionToolBar()->GetPlaySpeed();
|
||||
#else
|
||||
// That idea seems unpopular... just make it one
|
||||
mMaxScrubSpeed = options.maxScrubSpeed = 1.0;
|
||||
#endif
|
||||
options.maxScrubTime = mProject->GetTracks()->GetEndTime();
|
||||
const bool cutPreview = false;
|
||||
const bool backwards = time1 < time0;
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
static const double maxScrubSpeedBase =
|
||||
pow(2.0, 1.0 / ScrubSpeedStepsPerOctave);
|
||||
mLogMaxScrubSpeed = floor(0.5 +
|
||||
log(mMaxScrubSpeed) / log(maxScrubSpeedBase)
|
||||
);
|
||||
#endif
|
||||
mScrubSpeedDisplayCountdown = 0;
|
||||
mScrubToken =
|
||||
ctb->PlayPlayRegion(SelectedRegion(time0, time1), options, cutPreview, backwards);
|
||||
}
|
||||
}
|
||||
else
|
||||
// Wait to test again
|
||||
mScrubStartClockTimeMillis = ::wxGetLocalTimeMillis();
|
||||
|
||||
if (IsScrubbing())
|
||||
mScrubHasFocus = true;
|
||||
|
||||
// Return true whether we started scrub, or are still waiting to decide.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Scrubber::ContinueScrubbing()
|
||||
{
|
||||
// Thus scrubbing relies mostly on periodic polling of mouse and keys,
|
||||
// not event notifications. But there are a few event handlers that
|
||||
// leave messages for this routine, in mScrubSeekPress and in mScrubHasFocus.
|
||||
|
||||
// Seek only when the pointer is in the panel. Else, scrub.
|
||||
const wxMouseState state(::wxGetMouseState());
|
||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||
const wxPoint position = trackPanel->ScreenToClient(state.GetPosition());
|
||||
const bool inPanel = trackPanel->GetRect().Contains(position);
|
||||
const bool seek = inPanel && (mScrubSeekPress || PollIsSeeking());
|
||||
// When we don't have focus, enqueue silent scrubs until we regain focus.
|
||||
bool result = false;
|
||||
if (!mScrubHasFocus)
|
||||
result = gAudioIO->EnqueueScrubBySignedSpeed(0, mMaxScrubSpeed, false);
|
||||
else {
|
||||
const double time = mProject->GetViewInfo().PositionToTime(position.x, trackPanel->GetLeftOffset());
|
||||
|
||||
if (seek)
|
||||
// Cause OnTimer() to suppress the speed display
|
||||
mScrubSpeedDisplayCountdown = 1;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub) {
|
||||
const double speed = FindScrubSpeed(seek, time);
|
||||
result = gAudioIO->EnqueueScrubBySignedSpeed(speed, mMaxScrubSpeed, seek);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
result = gAudioIO->EnqueueScrubByPosition
|
||||
(time, seek ? 1.0 : mMaxScrubSpeed, seek);
|
||||
}
|
||||
|
||||
if (result)
|
||||
mScrubSeekPress = false;
|
||||
// else, if seek requested, try again at a later time when we might
|
||||
// enqueue a long enough stutter
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (mScrubSpeedDisplayCountdown > 0)
|
||||
--mScrubSpeedDisplayCountdown;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub) {
|
||||
// Pan the view, so that we center the play indicator.
|
||||
|
||||
ViewInfo &viewInfo = mProject->GetViewInfo();
|
||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||
const int posX = viewInfo.TimeToPosition(viewInfo.mRecentStreamTime);
|
||||
int width;
|
||||
trackPanel->GetTracksUsableArea(&width, NULL);
|
||||
const int deltaX = posX - width / 2;
|
||||
viewInfo.h =
|
||||
viewInfo.OffsetTimeByPixels(viewInfo.h, deltaX, true);
|
||||
if (!viewInfo.bScrollBeyondZero)
|
||||
// Can't scroll too far left
|
||||
viewInfo.h = std::max(0.0, viewInfo.h);
|
||||
trackPanel->Refresh(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Scrubber::StopScrubbing()
|
||||
{
|
||||
if (IsScrubbing())
|
||||
{
|
||||
if (gAudioIO->IsBusy()) {
|
||||
ControlToolBar *const ctb = mProject->GetControlToolBar();
|
||||
ctb->StopPlaying();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Scrubber::IsScrubbing() const
|
||||
{
|
||||
if (mScrubToken <= 0)
|
||||
return false;
|
||||
else if (mScrubToken == mProject->GetAudioIOToken())
|
||||
return true;
|
||||
else {
|
||||
const_cast<Scrubber&>(*this).mScrubToken = -1;
|
||||
const_cast<Scrubber&>(*this).mScrubStartPosition = -1;
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
const_cast<Scrubber&>(*this).mSmoothScrollingScrub = false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Scrubber::ShouldDrawScrubSpeed()
|
||||
{
|
||||
return IsScrubbing() &&
|
||||
mScrubHasFocus && (
|
||||
// Draw for (non-scroll) scrub, sometimes, but never for seek
|
||||
(!PollIsSeeking() && mScrubSpeedDisplayCountdown > 0)
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
// Draw always for scroll-scrub and for scroll-seek
|
||||
|| mSmoothScrollingScrub
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
double Scrubber::FindScrubSpeed(bool seeking, double time) const
|
||||
{
|
||||
ViewInfo &viewInfo = mProject->GetViewInfo();
|
||||
const double screen = mProject->GetScreenEndTime() - viewInfo.h;
|
||||
return (seeking ? FindSeekSpeed : FindScrubbingSpeed)
|
||||
(viewInfo, mMaxScrubSpeed, screen, time);
|
||||
}
|
||||
|
||||
void Scrubber::HandleScrollWheel(int steps)
|
||||
{
|
||||
const int newLogMaxScrubSpeed = mLogMaxScrubSpeed + steps;
|
||||
static const double maxScrubSpeedBase =
|
||||
pow(2.0, 1.0 / ScrubSpeedStepsPerOctave);
|
||||
double newSpeed = pow(maxScrubSpeedBase, newLogMaxScrubSpeed);
|
||||
if (newSpeed >= AudioIO::GetMinScrubSpeed() &&
|
||||
newSpeed <= AudioIO::GetMaxScrubSpeed()) {
|
||||
mLogMaxScrubSpeed = newLogMaxScrubSpeed;
|
||||
mMaxScrubSpeed = newSpeed;
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (!mSmoothScrollingScrub)
|
||||
#endif
|
||||
// Show the speed for one second
|
||||
mScrubSpeedDisplayCountdown = kOneSecondCountdown + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Scrubber::OnActivateOrDeactivateApp(wxActivateEvent &event)
|
||||
{
|
||||
if (event.GetActive())
|
||||
mScrubHasFocus = IsScrubbing();
|
||||
else
|
||||
mScrubHasFocus = false;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// class ScrubbingOverlay is responsible for drawing the speed numbers
|
||||
|
||||
ScrubbingOverlay::ScrubbingOverlay(AudacityProject *project)
|
||||
: mProject(project)
|
||||
, mLastScrubRect()
|
||||
, mNextScrubRect()
|
||||
, mLastScrubSpeedText()
|
||||
, mNextScrubSpeedText()
|
||||
{
|
||||
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)
|
||||
{
|
||||
wxRect rect(mLastScrubRect);
|
||||
const bool outdated =
|
||||
(mLastScrubRect != mNextScrubRect) ||
|
||||
(!mLastScrubRect.IsEmpty() && !GetScrubber().ShouldDrawScrubSpeed()) ||
|
||||
(mLastScrubSpeedText != mNextScrubSpeedText);
|
||||
return std::make_pair(
|
||||
rect,
|
||||
outdated
|
||||
);
|
||||
}
|
||||
|
||||
void ScrubbingOverlay::Draw
|
||||
(wxDC &dc, TrackPanelCellIterator, TrackPanelCellIterator)
|
||||
{
|
||||
mLastScrubRect = mNextScrubRect;
|
||||
mLastScrubSpeedText = mNextScrubSpeedText;
|
||||
|
||||
Scrubber &scrubber = GetScrubber();
|
||||
if (!scrubber.ShouldDrawScrubSpeed())
|
||||
return;
|
||||
|
||||
static const wxFont labelFont(24, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
dc.SetFont(labelFont);
|
||||
|
||||
// These two colors were previously saturated red and green. However
|
||||
// we have a rule to try to only use red for reserved purposes of
|
||||
// (a) Recording
|
||||
// (b) Error alerts
|
||||
// So they were changed to 'orange' and 'lime'.
|
||||
static const wxColour clrNoScroll(215, 162, 0), clrScroll(0, 204, 153);
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (scrubber.IsScrollScrubbing())
|
||||
dc.SetTextForeground(clrScroll);
|
||||
else
|
||||
#endif
|
||||
dc.SetTextForeground(clrNoScroll);
|
||||
|
||||
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
|
||||
}
|
||||
|
||||
|
||||
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
|
||||
{
|
||||
// Let other listeners get the notification
|
||||
event.Skip();
|
||||
|
||||
Scrubber &scrubber = GetScrubber();
|
||||
if (!GetScrubber().IsScrubbing()) {
|
||||
mNextScrubRect = wxRect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Call ContinueScrubbing() here in the timer handler
|
||||
// rather than in SelectionHandleDrag()
|
||||
// so that even without drag events, we can instruct the play head to
|
||||
// keep approaching the mouse cursor, when its maximum speed is limited.
|
||||
scrubber.ContinueScrubbing();
|
||||
|
||||
if (!scrubber.ShouldDrawScrubSpeed()) {
|
||||
mNextScrubRect = wxRect();
|
||||
}
|
||||
else {
|
||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||
int panelWidth, panelHeight;
|
||||
trackPanel->GetSize(&panelWidth, &panelHeight);
|
||||
|
||||
// Where's the mouse?
|
||||
int xx, yy;
|
||||
::wxGetMousePosition(&xx, &yy);
|
||||
trackPanel->ScreenToClient(&xx, &yy);
|
||||
|
||||
const bool seeking = PollIsSeeking();
|
||||
|
||||
// Find the text
|
||||
const double maxScrubSpeed = GetScrubber().GetMaxScrubSpeed();
|
||||
const double speed =
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
scrubber.IsScrollScrubbing()
|
||||
? scrubber.FindScrubSpeed
|
||||
(seeking, mProject->GetViewInfo().PositionToTime(xx, trackPanel->GetLeftOffset()))
|
||||
:
|
||||
#endif
|
||||
maxScrubSpeed;
|
||||
|
||||
const wxChar *format =
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
scrubber.IsScrollScrubbing()
|
||||
? seeking
|
||||
? wxT("%+.2fX")
|
||||
: wxT("%+.2f")
|
||||
:
|
||||
#endif
|
||||
wxT("%.2f");
|
||||
|
||||
mNextScrubSpeedText = wxString::Format(format, speed);
|
||||
|
||||
// Find the origin for drawing text
|
||||
wxCoord width, height;
|
||||
{
|
||||
wxClientDC dc(trackPanel);
|
||||
static const wxFont labelFont(24, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
dc.SetFont(labelFont);
|
||||
dc.GetTextExtent(mNextScrubSpeedText, &width, &height);
|
||||
}
|
||||
xx = std::max(0, std::min(panelWidth - width, xx - width / 2));
|
||||
|
||||
// Put the text above the cursor, if it fits.
|
||||
enum { offset = 20 };
|
||||
yy -= height + offset;
|
||||
if (yy < 0)
|
||||
yy += height + 2 * offset;
|
||||
yy = std::max(0, std::min(panelHeight - height, yy));
|
||||
|
||||
mNextScrubRect = wxRect(xx, yy, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
const Scrubber &ScrubbingOverlay::GetScrubber() const
|
||||
{
|
||||
return mProject->GetScrubber();
|
||||
}
|
||||
|
||||
Scrubber &ScrubbingOverlay::GetScrubber()
|
||||
{
|
||||
return mProject->GetScrubber();
|
||||
}
|
||||
#endif
|
95
src/tracks/ui/Scrubbing.h
Normal file
95
src/tracks/ui/Scrubbing.h
Normal file
@ -0,0 +1,95 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
Scrubbing.h
|
||||
|
||||
Paul Licameli split from TrackPanel.cpp
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_SCRUBBING__
|
||||
#define __AUDACITY_SCRUBBING__
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/longlong.h>
|
||||
|
||||
#include "../../Experimental.h"
|
||||
#include "../../TrackPanelOverlay.h"
|
||||
|
||||
class AudacityProject;
|
||||
|
||||
// Scrub state object
|
||||
class Scrubber : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
Scrubber(AudacityProject *project);
|
||||
~Scrubber();
|
||||
|
||||
void MarkScrubStart(
|
||||
wxCoord xx
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
, bool smoothScrolling
|
||||
#endif
|
||||
);
|
||||
// Returns true iff the event should be considered consumed by this:
|
||||
bool MaybeStartScrubbing(const wxMouseEvent &event);
|
||||
void ContinueScrubbing();
|
||||
bool StopScrubbing();
|
||||
|
||||
bool IsScrubbing() const;
|
||||
bool IsScrollScrubbing() const // If true, implies IsScrubbing()
|
||||
{ return mSmoothScrollingScrub; }
|
||||
|
||||
bool ShouldDrawScrubSpeed();
|
||||
double FindScrubSpeed(bool seeking, double time) const;
|
||||
double GetMaxScrubSpeed() const { return mMaxScrubSpeed; }
|
||||
|
||||
void HandleScrollWheel(int steps);
|
||||
|
||||
void SetSeeking() { mScrubSeekPress = true; }
|
||||
|
||||
private:
|
||||
int mScrubToken;
|
||||
wxLongLong mScrubStartClockTimeMillis;
|
||||
bool mScrubHasFocus;
|
||||
int mScrubSpeedDisplayCountdown;
|
||||
wxCoord mScrubStartPosition;
|
||||
double mMaxScrubSpeed;
|
||||
bool mScrubSeekPress;
|
||||
bool mSmoothScrollingScrub;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||
int mLogMaxScrubSpeed;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void OnActivateOrDeactivateApp(wxActivateEvent & event);
|
||||
|
||||
AudacityProject *mProject;
|
||||
};
|
||||
|
||||
// Specialist in drawing the scrub speed, and listening for certain events
|
||||
class ScrubbingOverlay final : 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);
|
||||
|
||||
const Scrubber &GetScrubber() const;
|
||||
Scrubber &GetScrubber();
|
||||
|
||||
AudacityProject *mProject;
|
||||
|
||||
wxRect mLastScrubRect, mNextScrubRect;
|
||||
wxString mLastScrubSpeedText, mNextScrubSpeedText;
|
||||
};
|
||||
|
||||
#endif
|
@ -66,6 +66,7 @@ array of Ruler::Label.
|
||||
#include <wx/menuitem.h>
|
||||
#include <wx/tooltip.h>
|
||||
|
||||
#include "../AColor.h"
|
||||
#include "../AudioIO.h"
|
||||
#include "../Internat.h"
|
||||
#include "../Project.h"
|
||||
@ -75,6 +76,8 @@ array of Ruler::Label.
|
||||
#include "../Experimental.h"
|
||||
#include "../TimeTrack.h"
|
||||
#include "../TrackPanel.h"
|
||||
#include "../TrackPanelCellIterator.h"
|
||||
#include "../TrackPanelOverlay.h"
|
||||
#include "../Menus.h"
|
||||
#include "../NumberScale.h"
|
||||
#include "../Prefs.h"
|
||||
@ -1643,6 +1646,91 @@ void RulerPanel::DoSetSize(int x, int y,
|
||||
ruler.SetBounds(0, 0, w-1, h-1);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
QuickPlayIndicatorOverlay.
|
||||
Graphical helper for AdornedRulerPanel.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
class QuickPlayIndicatorOverlay final : public TrackPanelOverlay
|
||||
{
|
||||
public:
|
||||
QuickPlayIndicatorOverlay(AudacityProject *project)
|
||||
: mProject(project)
|
||||
, mOldQPIndicatorPos(-1)
|
||||
, mNewQPIndicatorPos(-1)
|
||||
, mOldQPIndicatorSnapped(false)
|
||||
, mNewQPIndicatorSnapped(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~QuickPlayIndicatorOverlay()
|
||||
{
|
||||
}
|
||||
|
||||
void Update(int x, bool snapped = false)
|
||||
{
|
||||
mNewQPIndicatorPos = x;
|
||||
mNewQPIndicatorSnapped = snapped;
|
||||
|
||||
// Not strictly needed, but this reduces the lag in updating
|
||||
// track panel causing momentary mismatch between the triangle
|
||||
// in the ruler and the white line.
|
||||
|
||||
mProject->GetTrackPanel()->DrawOverlays(false);
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
|
||||
void Draw
|
||||
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end) override;
|
||||
|
||||
AudacityProject *mProject;
|
||||
int mOldQPIndicatorPos;
|
||||
int mNewQPIndicatorPos;
|
||||
bool mOldQPIndicatorSnapped;
|
||||
bool mNewQPIndicatorSnapped;
|
||||
};
|
||||
|
||||
std::pair<wxRect, bool> QuickPlayIndicatorOverlay::DoGetRectangle(wxSize size)
|
||||
{
|
||||
wxRect rect(mOldQPIndicatorPos, 0, 1, size.GetHeight());
|
||||
return std::make_pair(
|
||||
rect,
|
||||
(mOldQPIndicatorPos != mNewQPIndicatorPos ||
|
||||
mOldQPIndicatorSnapped != mNewQPIndicatorSnapped)
|
||||
);
|
||||
}
|
||||
|
||||
void QuickPlayIndicatorOverlay::Draw
|
||||
(wxDC &dc, TrackPanelCellIterator begin, TrackPanelCellIterator end)
|
||||
{
|
||||
mOldQPIndicatorPos = mNewQPIndicatorPos;
|
||||
mOldQPIndicatorSnapped = mNewQPIndicatorSnapped;
|
||||
|
||||
if (mOldQPIndicatorPos >= 0) {
|
||||
mOldQPIndicatorSnapped ? AColor::SnapGuidePen(&dc) : AColor::Light(&dc, false);
|
||||
|
||||
// Draw indicator in all visible tracks
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
TrackPanelCellIterator::value_type data(*begin);
|
||||
Track *const pTrack = dynamic_cast<Track*>(data.first);
|
||||
if (!pTrack)
|
||||
continue;
|
||||
const wxRect &rect = data.second;
|
||||
|
||||
// Draw the NEW indicator in its NEW location
|
||||
AColor::Line(dc,
|
||||
mOldQPIndicatorPos,
|
||||
rect.GetTop(),
|
||||
mOldQPIndicatorPos,
|
||||
rect.GetBottom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
Implementation of AdornedRulerPanel.
|
||||
@ -2525,6 +2613,16 @@ void AdornedRulerPanel::DoDrawIndicator(wxDC * dc)
|
||||
dc->DrawPolygon( 3, tri );
|
||||
}
|
||||
|
||||
QuickPlayIndicatorOverlay *AdornedRulerPanel::GetOverlay()
|
||||
{
|
||||
if (!mOverlay) {
|
||||
TrackPanel *tp = mProject->GetTrackPanel();
|
||||
mOverlay = std::make_unique<QuickPlayIndicatorOverlay>(mProject);
|
||||
tp->AddOverlay(mOverlay.get());
|
||||
}
|
||||
return mOverlay.get();
|
||||
}
|
||||
|
||||
// Draws the vertical line and green triangle indicating the Quick Play cursor position.
|
||||
void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc)
|
||||
{
|
||||
@ -2532,7 +2630,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc)
|
||||
|
||||
double latestEnd = std::max(mTracks->GetEndTime(), mProject->GetSel1());
|
||||
if (dc == NULL || (mQuickPlayPos >= latestEnd)) {
|
||||
tp->DrawQuickPlayIndicator(-1);
|
||||
GetOverlay()->Update(-1);
|
||||
mLastQuickPlayX = -1;
|
||||
return;
|
||||
}
|
||||
@ -2564,7 +2662,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc)
|
||||
AColor::IndicatorColor( dc, true);
|
||||
dc->DrawPolygon( 3, tri, x );
|
||||
|
||||
tp->DrawQuickPlayIndicator(x, mIsSnapped);
|
||||
GetOverlay()->Update(x, mIsSnapped);
|
||||
}
|
||||
|
||||
void AdornedRulerPanel::SetPlayRegion(double playRegionStart,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef __AUDACITY_RULER__
|
||||
#define __AUDACITY_RULER__
|
||||
|
||||
#include "../MemoryX.h"
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/dcmemory.h>
|
||||
@ -269,6 +270,8 @@ private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class QuickPlayIndicatorOverlay;
|
||||
|
||||
// This is an Audacity Specific ruler panel which additionally
|
||||
// has border, selection markers, play marker.
|
||||
// Once TrackPanel uses wxSizers, we will derive it from some
|
||||
@ -320,6 +323,7 @@ private:
|
||||
void DoDrawCursor(wxDC * dc);
|
||||
void DoDrawSelection(wxDC * dc);
|
||||
void DoDrawIndicator(wxDC * dc);
|
||||
QuickPlayIndicatorOverlay *GetOverlay();
|
||||
void DrawQuickPlayIndicator(wxDC * dc /*NULL to DELETE old only*/);
|
||||
void DoDrawPlayRegion(wxDC * dc);
|
||||
|
||||
@ -398,6 +402,8 @@ private:
|
||||
int mLastMouseX; // Pixel position
|
||||
bool mIsDragging;
|
||||
|
||||
std::unique_ptr<QuickPlayIndicatorOverlay> mOverlay;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user