From 26771b6db95ba66edbb98c5392c3c7c3ee519ddd Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 21 Apr 2016 11:14:41 -0400 Subject: [PATCH] Add transport menu items for scrubbing and seeking... ... This includes new always-seeking modes unlike scrubbing which can switch to seeking and back according to the left mouse button state. The reason for this is that visually impaired users should not be required to click with the mouse in the track panel window to signal seeking. But mouse movements can still control scrubbing, because we poll the global mouse position in the timer, not relying on events from any window object. --- src/Menus.cpp | 41 +++++++++++++++++++++++++++++++++++++ src/Menus.h | 5 +++++ src/TrackPanel.cpp | 1 + src/tracks/ui/Scrubbing.cpp | 23 +++++++++++++-------- src/tracks/ui/Scrubbing.h | 10 ++++++--- 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/Menus.cpp b/src/Menus.cpp index 0aa3ef6e1..0d899e84d 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -818,6 +818,17 @@ void AudacityProject::CreateMenusAndCommands() c->AddItem(wxT("PlayLooped"), _("&Loop Play"), FN(OnPlayLooped), wxT("Shift+Space"), WaveTracksExistFlag | AudioIONotBusyFlag | CanStopAudioStreamFlag, WaveTracksExistFlag | AudioIONotBusyFlag | CanStopAudioStreamFlag); + + // Scrubbing sub-menu + { + c->BeginSubMenu(_("Scru&bbing")); + c->AddItem(wxT("Scrub"), _("&Scrub"), FN(OnScrub)); + c->AddItem(wxT("ScrollScrub"), _("Sc&rolling Scrub"), FN(OnScrollScrub)); + c->AddItem(wxT("Seek"), _("See&k"), FN(OnSeek)); + c->AddItem(wxT("ScrollSeek"), _("Scrollin&g Seek"), FN(OnScrollSeek)); + c->EndSubMenu(); + } + c->AddItem(wxT("Pause"), _("&Pause"), FN(OnPause), wxT("P"), c->GetDefaultFlags() | AudioStreamNotScrubbingFlag, c->GetDefaultMask() | AudioStreamNotScrubbingFlag); @@ -2253,6 +2264,36 @@ void AudacityProject::OnPlayCutPreview() GetControlToolBar()->PlayCurrentRegion(false, true); } +namespace { + inline void DoScrub(AudacityProject *project, bool scroll, bool seek) + { + auto tp = project->GetTrackPanel(); + wxCoord xx = tp->ScreenToClient(::wxGetMouseState().GetPosition()).x; + wxMouseEvent evt; + project->GetScrubber().MarkScrubStart(evt, scroll, seek); + } +} + +void AudacityProject::OnScrub() +{ + DoScrub(this, false, false); +} + +void AudacityProject::OnScrollScrub() +{ + DoScrub(this, true, false); +} + +void AudacityProject::OnSeek() +{ + DoScrub(this, false, true); +} + +void AudacityProject::OnScrollSeek() +{ + DoScrub(this, true, true); +} + void AudacityProject::OnPlayStop() { ControlToolBar *toolbar = GetControlToolBar(); diff --git a/src/Menus.h b/src/Menus.h index f8cc32084..e1e6d897b 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -88,6 +88,11 @@ void OnPlayBeforeAndAfterSelectionEnd(); void OnPlayLooped(); void OnPlayCutPreview(); +void OnScrub(); +void OnScrollScrub(); +void OnSeek(); +void OnScrollSeek(); + // Wave track control void OnTrackPan(); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 8edd93fc4..58390de57 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1962,6 +1962,7 @@ void TrackPanel::SelectionHandleClick(wxMouseEvent & event, #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL , event.LeftDClick() #endif + , false ); return; } diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index 30a5d7a6c..77529673e 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -34,11 +34,6 @@ enum { }; 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) @@ -144,6 +139,7 @@ void Scrubber::MarkScrubStart( #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL , bool smoothScrolling #endif + , bool alwaysSeeking ) { const wxCoord xx = event.m_x; @@ -154,6 +150,7 @@ void Scrubber::MarkScrubStart( #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL mSmoothScrollingScrub = smoothScrolling; #endif + mAlwaysSeeking = alwaysSeeking; mScrubStartPosition = xx; mScrubStartClockTimeMillis = ::wxGetLocalTimeMillis(); @@ -202,10 +199,12 @@ bool Scrubber::MaybeStartScrubbing(const wxMouseEvent &event) 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 = + if (!mAlwaysSeeking) { + // 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; @@ -488,7 +487,7 @@ void ScrubbingOverlay::OnTimer(wxCommandEvent &event) ::wxGetMousePosition(&xx, &yy); trackPanel->ScreenToClient(&xx, &yy); - const bool seeking = PollIsSeeking(); + const bool seeking = scrubber.PollIsSeeking(); // Find the text const double maxScrubSpeed = GetScrubber().GetMaxScrubSpeed(); @@ -543,4 +542,10 @@ Scrubber &ScrubbingOverlay::GetScrubber() { return mProject->GetScrubber(); } + +bool Scrubber::PollIsSeeking() +{ + return mAlwaysSeeking || ::wxGetMouseState().LeftIsDown(); +} + #endif diff --git a/src/tracks/ui/Scrubbing.h b/src/tracks/ui/Scrubbing.h index 715509bdf..2edd2cdd0 100644 --- a/src/tracks/ui/Scrubbing.h +++ b/src/tracks/ui/Scrubbing.h @@ -31,6 +31,8 @@ public: #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL , bool smoothScrolling #endif + , bool alwaysSeeking // if false, can switch seeking or scrubbing + // by mouse button state ); // Returns true iff the event should be considered consumed by this: bool MaybeStartScrubbing(const wxMouseEvent &event); @@ -55,6 +57,10 @@ public: void HandleScrollWheel(int steps); void SetSeeking() { mScrubSeekPress = true; } + bool PollIsSeeking(); + +private: + void OnActivateOrDeactivateApp(wxActivateEvent & event); private: int mScrubToken; @@ -65,14 +71,12 @@ private: double mMaxScrubSpeed; bool mScrubSeekPress; bool mSmoothScrollingScrub; + bool mAlwaysSeeking{}; #ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL int mLogMaxScrubSpeed; #endif -private: - void OnActivateOrDeactivateApp(wxActivateEvent & event); - AudacityProject *mProject; };