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/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. :-) 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); 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; iAddCommand(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(); 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/src/TrackPanel.cpp b/src/TrackPanel.cpp index 36f035bca..05fcdf86a 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1468,6 +1468,22 @@ void TrackPanel::MakeParentResize() mListener->TP_HandleResize(); } +void TrackPanel::HandleEscapeKey() +{ + switch (mMouseCapture) + { + case IsZooming: + case IsVZooming: + SetCapturedTrack(NULL, IsUncaptured); + if (HasCapture()) + ReleaseMouse(); + Refresh(false); + return; + default: + return; + } +} + void TrackPanel::HandleAltKey(bool down) { mLastMouseEvent.m_altDown = down; @@ -5963,6 +5979,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 @@ -6126,7 +6147,8 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event) if (event.ButtonDown()) { SetFocus(); - CaptureMouse(); + if (!HasCapture()) + CaptureMouse(); } else if (event.ButtonUp()) { if (HasCapture()) 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); 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; 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; } 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) 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 + + +