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
+
+
+