From 36dd49ff50cff55b4ae140602cb5831f0092044b Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Wed, 8 Apr 2015 14:57:32 -0400 Subject: [PATCH 01/12] Really fix linux compilation! --- src/effects/Generator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/effects/Generator.cpp b/src/effects/Generator.cpp index 821da99bd..f1d97900a 100644 --- a/src/effects/Generator.cpp +++ b/src/effects/Generator.cpp @@ -19,6 +19,8 @@ #include "Generator.h" #include "TimeWarper.h" +#include + bool Generator::Process() { if (mDuration < 0.0) From 44fc5b9f4df801f8051608d813d4b00095b1f7fc Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Wed, 8 Apr 2015 11:58:39 -0400 Subject: [PATCH 02/12] Bug859 - Play indicator incorrect for very short loop plays (< 15 ms) --- src/AudioIO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 9fd579009..e9ed18079 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -3888,7 +3888,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, } // Wrap to start if looping - if (gAudioIO->mPlayLooped && gAudioIO->mTime >= gAudioIO->mT1) + while (gAudioIO->mPlayLooped && gAudioIO->mTime >= gAudioIO->mT1) { // LL: This is not exactly right, but I'm at my wits end trying to // figure it out. Feel free to fix it. :-) From 01c346fe915e24ee6876f5a1e37a34852def1bbb Mon Sep 17 00:00:00 2001 From: Chris Diamand Date: Wed, 8 Apr 2015 22:52:24 +0100 Subject: [PATCH 03/12] Don't capture the mouse if it's already captured. Otherwise the following assertion gets triggered: ../src/common/wincmn.cpp(3271): assert "!wxMouseCapture::IsInCaptureStack(this)" failed in CaptureMouse(): Recapturing the mouse in the same window? Based on the fix provided for an identical assertion triggered elsewhere, described here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765779 --- src/TrackPanel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 36f035bca..ec92c5e11 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -6126,7 +6126,8 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event) if (event.ButtonDown()) { SetFocus(); - CaptureMouse(); + if (!HasCapture()) + CaptureMouse(); } else if (event.ButtonUp()) { if (HasCapture()) From fe8d3535d8feb212f04bc3750a0aed77ea72f1c0 Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Wed, 8 Apr 2015 12:09:30 -0400 Subject: [PATCH 04/12] Bug819 - Paste should not change clipboard contents when sample formats differ --- src/WaveClip.cpp | 43 +++++++++++++++++++------------------------ src/WaveClip.h | 10 +++++----- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 4e4d0c185..0543d08ec 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -26,6 +26,7 @@ drawing). Cache's the Spectrogram frequency samples. *//*******************************************************************/ #include +#include #include #include @@ -311,7 +312,7 @@ WaveClip::WaveClip(DirManager *projDirManager, sampleFormat format, int rate) mIsPlaceholder = false; } -WaveClip::WaveClip(WaveClip& orig, DirManager *projDirManager) +WaveClip::WaveClip(const WaveClip& orig, DirManager *projDirManager) { // essentially a copy constructor - but you must pass in the // current project's DirManager, because we might be copying @@ -1221,34 +1222,34 @@ bool WaveClip::CreateFromCopy(double t0, double t1, WaveClip* other) return true; } -bool WaveClip::Paste(double t0, WaveClip* other) +bool WaveClip::Paste(double t0, const WaveClip* other) { - WaveClip* pastedClip; + const bool clipNeedsResampling = other->mRate != mRate; + const bool clipNeedsNewFormat = + other->mSequence->GetSampleFormat() != mSequence->GetSampleFormat(); + std::auto_ptr newClip; + const WaveClip* pastedClip; - bool clipNeedsResampling = other->mRate != mRate; - - if (clipNeedsResampling) + if (clipNeedsResampling || clipNeedsNewFormat) { - // The other clip's rate is different to our's, so resample - pastedClip = new WaveClip(*other, mSequence->GetDirManager()); - if (!pastedClip->Resample(mRate)) - { - delete pastedClip; - return false; - } + newClip.reset(new WaveClip(*other, mSequence->GetDirManager())); + if (clipNeedsResampling) + // The other clip's rate is different from ours, so resample + if (!newClip->Resample(mRate)) + return false; + if (clipNeedsNewFormat) + // Force sample formats to match. + newClip->ConvertToSampleFormat(mSequence->GetSampleFormat()); + pastedClip = newClip.get(); } else { - // No resampling needed, just use original clip without making a copy + // No resampling or format change needed, just use original clip without making a copy pastedClip = other; } sampleCount s0; TimeToSamplesClip(t0, &s0); - // Force sample formats to match. - if (pastedClip->mSequence->GetSampleFormat() != mSequence->GetSampleFormat()) - pastedClip->ConvertToSampleFormat(mSequence->GetSampleFormat()); - bool result = false; if (mSequence->Paste(s0, pastedClip->mSequence)) { @@ -1270,12 +1271,6 @@ bool WaveClip::Paste(double t0, WaveClip* other) result = true; } - if (clipNeedsResampling) - { - // Clip was constructed as a copy, so delete it - delete pastedClip; - } - return result; } diff --git a/src/WaveClip.h b/src/WaveClip.h index 22c2c8383..6a296291e 100644 --- a/src/WaveClip.h +++ b/src/WaveClip.h @@ -69,7 +69,7 @@ private: WaveClip(const WaveClip&) { wxFAIL_MSG(wxT("It is an error to copy a WaveClip without specifying the DirManager.")); - }; + } WaveClip& operator=(const WaveClip& orig) { WaveClip bogus(orig); @@ -83,7 +83,7 @@ public: // essentially a copy constructor - but you must pass in the // current project's DirManager, because we might be copying // from one project to another - WaveClip(WaveClip& orig, DirManager *projDirManager); + WaveClip(const WaveClip& orig, DirManager *projDirManager); virtual ~WaveClip(); @@ -179,7 +179,7 @@ public: bool ClearAndAddCutLine(double t0, double t1); /// Paste data from other clip, resampling it if not equal rate - bool Paste(double t0, WaveClip* other); + bool Paste(double t0, const WaveClip* other); /** Insert silence - note that this is an efficient operation for large * amounts of silence */ @@ -232,8 +232,8 @@ public: SpecPxCache *mSpecPxCache; // AWD, Oct 2009: for pasting whitespace at the end of selection - bool GetIsPlaceholder() { return mIsPlaceholder; }; - void SetIsPlaceholder(bool val) { mIsPlaceholder = val; }; + bool GetIsPlaceholder() const { return mIsPlaceholder; } + void SetIsPlaceholder(bool val) { mIsPlaceholder = val; } protected: wxRect mDisplayRect; From 291a465a76bad382b81472d11300855d90d0f31a Mon Sep 17 00:00:00 2001 From: James Crook Date: Thu, 9 Apr 2015 20:41:21 +0100 Subject: [PATCH 05/12] Build Revision Info Added Travis now overwrites RevisionIdent.h to place a commit reference into the Build Info of the AboutDialog I also added .opensdf to .gitignore. --- .gitignore | 3 ++ .travis.yml | 2 ++ src/AboutDialog.cpp | 4 +++ src/RevisionIdent.h | 28 +++++++++++++++++++ win/Projects/Audacity/Audacity.vcxproj | 1 + .../Audacity/Audacity.vcxproj.filters | 15 ++++------ 6 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 src/RevisionIdent.h diff --git a/.gitignore b/.gitignore index 2e7c7a485..3da21734f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ *.log *.tlog *.ipch +*.opensdf # Precompiled Headers *.gch @@ -40,3 +41,5 @@ *.out *.app win/resetPrefs.txt +src/RevisionIdent.h + diff --git a/.travis.yml b/.travis.yml index 38a024927..2a6024293 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ before_install: - sudo apt-get update -qq - sudo apt-get install -y libwxgtk2.8-dev + - git show -s --format="wxT(\"%h of %cd\")" + - git show -s --format="wxT(\"%h of %cd\")" > ./src/RevisionIdent.h language: cpp compiler: - gcc diff --git a/src/AboutDialog.cpp b/src/AboutDialog.cpp index 4f8410f46..830d10822 100644 --- a/src/AboutDialog.cpp +++ b/src/AboutDialog.cpp @@ -549,6 +549,10 @@ void AboutDialog::PopulateInformationPage( ShuttleGui & S ) // Current date AddBuildinfoRow(&informationStr, _("Program build date: "), __TDATE__); + AddBuildinfoRow(&informationStr, _("Commit Id:"), +#include "RevisionIdent.h" +); + #ifdef __WXDEBUG__ AddBuildinfoRow(&informationStr, _("Build type:"), _("Debug build")); #else diff --git a/src/RevisionIdent.h b/src/RevisionIdent.h new file mode 100644 index 000000000..a0bee9b61 --- /dev/null +++ b/src/RevisionIdent.h @@ -0,0 +1,28 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + Audacity(R) is copyright (c) 1999-2015 Audacity Team. + License: GPL v2. See License.txt. + + RevisionIdent.h + + +********************************************************************//*! + +\file RevisionIdent.h + + This entire file will be replaced by the revision identifier string + based on the branch SHA when the automated build system builds + Audacity. That striing will look something like: + + "7f2e839 of + Thu Apr 9 20:03:11 2015 +0100" + +*//********************************************************************/ + +// The string below is what you get if +// the build system does not replace this file. + +wxT("No revision identifier was provided") + diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 26d6ff45c..9b0f6ff83 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -529,6 +529,7 @@ + diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index f7e26c35c..196d32cfe 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -1670,6 +1670,9 @@ src + + src + @@ -1684,15 +1687,6 @@ - - nyquist - - - nyquist - - - nyquist - @@ -1812,6 +1806,9 @@ nyquist + + + From 903fcb1fc20798bae3a45b7a2c9a5e4031f44261 Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Thu, 9 Apr 2015 15:41:32 -0400 Subject: [PATCH 06/12] ESC key can abort certain dragging actions For now, let it abort vertical scale zoom (any mouse button in any tool, in the vertical ruler) and horizontal zoom (any mouse button in the zoom tool or right mouse button in the multi tool, in the wave display) Should any other drags be escapable too? Time shifting? That would need some more work to restore initial state. --- src/TrackPanel.cpp | 20 ++++++++++++++++++++ src/TrackPanel.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index ec92c5e11..36e0364c6 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1468,6 +1468,21 @@ void TrackPanel::MakeParentResize() mListener->TP_HandleResize(); } +void TrackPanel::HandleEscapeKey() +{ + switch (mMouseCapture) + { + case IsZooming: + case IsVZooming: + SetCapturedTrack(NULL, IsUncaptured); + if (HasCapture()) + ReleaseCapture(); + return; + default: + return; + } +} + void TrackPanel::HandleAltKey(bool down) { mLastMouseEvent.m_altDown = down; @@ -5963,6 +5978,11 @@ void TrackPanel::OnKeyDown(wxKeyEvent & event) { Track *t = GetFocusedTrack(); + if (event.GetKeyCode() == WXK_ESCAPE) { + HandleEscapeKey(); + return; + } + #ifdef EXPERIMENTAL_SPECTRAL_EDITING #ifdef SPECTRAL_EDITING_ESC_KEY // Test for pinning and unpinning of the center frequency diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 7bd95b8fc..5c637d64c 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -208,6 +208,7 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel { //virtual void SetSelectionFormat(int iformat) //virtual void SetSnapTo(int snapto) + void HandleEscapeKey(); virtual void HandleAltKey(bool down); virtual void HandleShiftKey(bool down); virtual void HandleControlKey(bool down); From f80db283b59a87f110b492d0f0bf202848b4b5d8 Mon Sep 17 00:00:00 2001 From: James Crook Date: Thu, 9 Apr 2015 23:43:28 +0100 Subject: [PATCH 07/12] Use ReleaseMouse not ReleaseCapture Change made to fix broken build under Linux. --- src/TrackPanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 36e0364c6..d610ec0b8 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1476,7 +1476,7 @@ void TrackPanel::HandleEscapeKey() case IsVZooming: SetCapturedTrack(NULL, IsUncaptured); if (HasCapture()) - ReleaseCapture(); + ReleaseMouse(); return; default: return; From a583fafbb7df33f3f4c1b7e695b1e124e2cbed7e Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Thu, 9 Apr 2015 19:09:33 -0400 Subject: [PATCH 08/12] Fix a memory leak This branch of the function is never reached because of checks in class EffectRepair, but anyway. --- src/InterpolateAudio.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/InterpolateAudio.cpp b/src/InterpolateAudio.cpp index ce2ec2e92..173b07d32 100644 --- a/src/InterpolateAudio.cpp +++ b/src/InterpolateAudio.cpp @@ -103,6 +103,7 @@ void InterpolateAudio(float *buffer, int len, InterpolateAudio(buffer2, len, len-numBad, numBad); for(i=0; i Date: Thu, 9 Apr 2015 19:21:39 -0400 Subject: [PATCH 09/12] Bug 828 (partial) - Don't divide by zero in Contrast dialog --- src/WaveTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 6cc29b7a0..07324e147 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -1734,7 +1734,7 @@ bool WaveTrack::GetRMS(float *rms, double t0, double t1) } } } - *rms = sqrt(sumsq/length); + *rms = length > 0.0 ? sqrt(sumsq / length) : 0.0; return result; } From fe12fce270cf485723eeb9e9f985655c530c5433 Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Thu, 9 Apr 2015 19:49:01 -0400 Subject: [PATCH 10/12] Bug830 - Paste should not destroy envelope information in the clipboard --- src/Envelope.cpp | 37 +++++++++++++++++-------------------- src/Envelope.h | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/Envelope.cpp b/src/Envelope.cpp index 12e99a946..a5658f047 100644 --- a/src/Envelope.cpp +++ b/src/Envelope.cpp @@ -656,14 +656,14 @@ void Envelope::CollapseRegion(double t0, double t1) // envelope point applies to the first sample, but the t=tracklen // envelope point applies one-past the last actual sample. // Rather than going to a .5-offset-index, we special case the framing. -void Envelope::Paste(double t0, Envelope *e) +void Envelope::Paste(double t0, const Envelope *e) { - bool pointsAdded = false; + const bool wasEmpty = (this->mEnv.Count() == 0); -// JC: The old analysis of cases and the resulting code here is way more complex than needed. -// TODO: simplify the analysis and simplify the code. + // JC: The old analysis of cases and the resulting code here is way more complex than needed. + // TODO: simplify the analysis and simplify the code. - if (e->mEnv.Count() == 0 && this->mEnv.Count() == 0 && e->mDefaultValue == this->mDefaultValue) + if (e->mEnv.Count() == 0 && wasEmpty && e->mDefaultValue == this->mDefaultValue) { // msmeyer: The envelope is empty and has the same default value, so // there is nothing that must be inserted, just return. This avoids @@ -672,16 +672,6 @@ void Envelope::Paste(double t0, Envelope *e) mTrackLen += e->mTrackLen; return; } - if (this->mEnv.Count() != 0) - { - // inserting a clip with a possibly empty envelope into one with an envelope - // so add end points to e, in case they are not there - double leftval = e->GetValue(0+e->mOffset); - double rightval = e->GetValue(e->mTrackLen+e->mOffset); - e->Insert(0, leftval); - e->Insert(e->mTrackLen, rightval); - pointsAdded = true; // we need to delete them later so's not to corrupt 'e' for later use - } t0 = wxMin(t0 - mOffset, mTrackLen); // t0 now has origin of zero double deltat = e->mTrackLen; @@ -834,17 +824,24 @@ Old analysis of cases: } // Copy points from inside the selection + + if (!wasEmpty) { + // Add end points in case they are not not in e. + // If they are in e, no harm, because the repeated Insert + // calls for the start and end times will have no effect. + const double leftval = e->GetValue(0 + e->mOffset); + const double rightval = e->GetValue(e->mTrackLen + e->mOffset); + Insert(t0, leftval); + Insert(t0 + e->mTrackLen, rightval); + } + len = e->mEnv.Count(); for (i = 0; i < len; i++) - pos=Insert(t0 + e->mEnv[i]->GetT(), e->mEnv[i]->GetVal()); + Insert(t0 + e->mEnv[i]->GetT(), e->mEnv[i]->GetVal()); /* if(len != 0) for (i = 0; i < mEnv.Count(); i++) wxLogDebug(wxT("Fixed i %d when %.18f val %f"),i,mEnv[i]->GetT(),mEnv[i]->GetVal()); */ - - if(pointsAdded) - while(e->mEnv.Count() != 0) - e->Delete(0); // they were not there when we entered this } // Deletes 'unneeded' points, starting from the left. diff --git a/src/Envelope.h b/src/Envelope.h index 691985199..1a33abc0f 100644 --- a/src/Envelope.h +++ b/src/Envelope.h @@ -140,7 +140,7 @@ class Envelope : public XMLTagHandler { // Handling Cut/Copy/Paste events void CollapseRegion(double t0, double t1); void CopyFrom(const Envelope * e, double t0, double t1); - void Paste(double t0, Envelope *e); + void Paste(double t0, const Envelope *e); void InsertSpace(double t0, double tlen); void RemoveUnneededPoints(double time = -1, double tolerence = 0.001); From 82fe9a162cc22bbf9e859283ffe9ba5eaa4fa806 Mon Sep 17 00:00:00 2001 From: Paul-Licameli Date: Thu, 9 Apr 2015 22:26:34 -0400 Subject: [PATCH 11/12] Refresh display after ESC aborts a drag, as James suggested. Otherwise zoom lines did not disappear if you hit ESC while the cursor is outside the main window. --- src/TrackPanel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index d610ec0b8..05fcdf86a 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1477,6 +1477,7 @@ void TrackPanel::HandleEscapeKey() SetCapturedTrack(NULL, IsUncaptured); if (HasCapture()) ReleaseMouse(); + Refresh(false); return; default: return; From c6455312aa7bb56ead561121578447d62b19b483 Mon Sep 17 00:00:00 2001 From: David Bailes Date: Fri, 10 Apr 2015 14:53:48 +0100 Subject: [PATCH 12/12] provide a limited version of functionality of AudacityProject::OnPlayToSelection() for keyboard users --- src/Menus.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Menus.h | 4 +++ 2 files changed, 76 insertions(+) diff --git a/src/Menus.cpp b/src/Menus.cpp index 19dbebdfa..4fa931a30 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -1214,6 +1214,10 @@ void AudacityProject::CreateMenusAndCommands() AudioIOBusyFlag); c->AddCommand(wxT("PlayOneSec"), _("Play One Second"), FN(OnPlayOneSecond), wxT("1")); c->AddCommand(wxT("PlayToSelection"),_("Play To Selection"), FN(OnPlayToSelection), wxT("B")); + c->AddCommand(wxT("PlayBeforeSelectionStart"),_("Play Before Selection Start"), FN(OnPlayBeforeSelectionStart), wxT("Shift+F5")); + c->AddCommand(wxT("PlayAfterSelectionStart"),_("Play After Selection Start"), FN(OnPlayAfterSelectionStart), wxT("Shift+F6")); + c->AddCommand(wxT("PlayBeforeSelectionEnd"),_("Play Before Selection End"), FN(OnPlayBeforeSelectionEnd), wxT("Shift+F7")); + c->AddCommand(wxT("PlayAfterSelectionEnd"),_("Play After Selection End"), FN(OnPlayAfterSelectionEnd), wxT("Shift+F8")); c->AddCommand(wxT("PlayCutPreview"), _("Play Cut Preview"), FN(OnPlayCutPreview), wxT("C")); c->AddCommand(wxT("SelStart"), _("Selection to Start"), FN(OnSelToStart), wxT("Shift+Home")); @@ -2252,6 +2256,74 @@ void AudacityProject::OnPlayToSelection() GetControlToolBar()->PlayPlayRegion(t0, t1); } +// The next 4 functions provide a limited version of the +// functionality of OnPlayToSelection() for keyboard users + +void AudacityProject::OnPlayBeforeSelectionStart() +{ + if( !MakeReadyToPlay() ) + return; + + double t0 = mViewInfo.selectedRegion.t0(); + double beforeLen; + gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0); + + mLastPlayMode = oneSecondPlay; // this disables auto scrolling, as in OnPlayToSelection() + + GetControlToolBar()->PlayPlayRegion(t0 - beforeLen, t0); +} + +void AudacityProject::OnPlayAfterSelectionStart() +{ + if( !MakeReadyToPlay() ) + return; + + double t0 = mViewInfo.selectedRegion.t0(); + double t1 = mViewInfo.selectedRegion.t1(); + double afterLen; + gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0); + + mLastPlayMode = oneSecondPlay; // this disables auto scrolling, as in OnPlayToSelection() + + if ( t1 - t0 > 0.0 && t1 - t0 < afterLen ) + GetControlToolBar()->PlayPlayRegion(t0, t1); + else + GetControlToolBar()->PlayPlayRegion(t0, t0 + afterLen); +} + +void AudacityProject::OnPlayBeforeSelectionEnd() +{ + if( !MakeReadyToPlay() ) + return; + + double t0 = mViewInfo.selectedRegion.t0(); + double t1 = mViewInfo.selectedRegion.t1(); + double beforeLen; + gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 1.0); + + mLastPlayMode = oneSecondPlay; // this disables auto scrolling, as in OnPlayToSelection() + + if ( t1 - t0 > 0.0 && t1 - t0 < beforeLen ) + GetControlToolBar()->PlayPlayRegion(t0, t1); + else + GetControlToolBar()->PlayPlayRegion(t1 - beforeLen, t1); +} + + +void AudacityProject::OnPlayAfterSelectionEnd() +{ + if( !MakeReadyToPlay() ) + return; + + double t1 = mViewInfo.selectedRegion.t1(); + double afterLen; + gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0); + + mLastPlayMode = oneSecondPlay; // this disables auto scrolling, as in OnPlayToSelection() + + GetControlToolBar()->PlayPlayRegion(t1, t1 + afterLen); +} + void AudacityProject::OnPlayLooped() { if( !MakeReadyToPlay(true) ) diff --git a/src/Menus.h b/src/Menus.h index b3d792410..c84ea9e9a 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -93,6 +93,10 @@ void OnPlayStop(); void OnPlayStopSelect(); void OnPlayOneSecond(); void OnPlayToSelection(); +void OnPlayBeforeSelectionStart(); +void OnPlayAfterSelectionStart(); +void OnPlayBeforeSelectionEnd(); +void OnPlayAfterSelectionEnd(); void OnPlayLooped(); void OnPlayCutPreview();