diff --git a/mac/Build.txt b/mac/Build.txt index b546ba0e1..b968bec45 100644 --- a/mac/Build.txt +++ b/mac/Build.txt @@ -4,7 +4,10 @@ to extract the 10.6 SDK from an earlier version of Xcode. In the instructions below, Xcode 4.3.3 (for the 10.6 SDK) and Xcode 5.1.1 will be used. Xcode 6.1.1, 6.3, 6.4.1, and 7.1 -have been verified to work as well. +have also been verified to work. Xcode 7.2 and later require a +custom build setting to accept the 10.6 SDK, or to edit +src\MemoryX.h in the Audacity code. See this topic: +http://forum.audacityteam.org/viewtopic.php?p=303835#p303835 . 1) Download Xcode 5.1.1 or greater and install it to /Applications. 2) Download Xcode 4.3.3 (it includes the 10.6 and 10.7 SDK's despite diff --git a/src/Track.cpp b/src/Track.cpp index c21347ec5..3ed80cdef 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -878,7 +878,9 @@ Track *TrackList::Add(std::unique_ptr &&t) // Make instantiations for the linker to find template Track *TrackList::Add(std::unique_ptr &&); +#if defined(USE_MIDI) template Track *TrackList::Add(std::unique_ptr &&); +#endif template Track *TrackList::Add(std::unique_ptr &&); template Track *TrackList::Add(std::unique_ptr &&); diff --git a/src/effects/TruncSilence.cpp b/src/effects/TruncSilence.cpp index e47e08616..8133b57af 100644 --- a/src/effects/TruncSilence.cpp +++ b/src/effects/TruncSilence.cpp @@ -283,7 +283,7 @@ bool EffectTruncSilence::ProcessIndependently() if (track2->GetKind() == Track::Wave && !(track2 == track || track2 == link) && track2->GetSelected()) { - ::wxMessageBox(_("When truncating independently, there may only be one selected audio track in each sync-lock group.")); + ::wxMessageBox(_("When truncating independently, there may only be one selected audio track in each Sync-Locked Track Group.")); return false; } } diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 1474b436b..1524260df 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -2109,8 +2109,11 @@ bool AdornedRulerPanel::IsWithinMarker(int mousePosX, double markerTime) void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) { // Disable mouse actions on Timeline while recording. - if (mIsRecording) + if (mIsRecording) { + if (HasCapture()) + ReleaseMouse(); return; + } const bool inScrubZone = // only if scrubbing is allowed now @@ -2121,17 +2124,14 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) const bool changeInScrubZone = (inScrubZone != mPrevInScrubZone); mPrevInScrubZone = inScrubZone; - double t0 = mTracks->GetStartTime(); - double t1 = mTracks->GetEndTime(); - double sel0 = mProject->GetSel0(); - double sel1 = mProject->GetSel1(); - wxCoord xx = evt.GetX(); wxCoord mousePosX = xx; UpdateQuickPlayPos(mousePosX); + HandleSnapping(); // If not looping, restrict selection to end of project if (!inScrubZone && !evt.ShiftDown()) { + const double t1 = mTracks->GetEndTime(); mQuickPlayPos = std::min(t1, mQuickPlayPos); } @@ -2201,11 +2201,6 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) mPlayRegionLock = mProject->IsPlayRegionLocked(); } - bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); - bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); - bool isWithinClick = (mLeftDownClick >= 0) && IsWithinMarker(mousePosX, mLeftDownClick); - bool canDragSel = !mPlayRegionLock && mPlayRegionDragsSelection; - // Handle entering and leaving of the bar, or movement from // one portion (quick play or scrub) to the other if (evt.Leaving() || (changeInScrubZone && inScrubZone)) { @@ -2244,7 +2239,10 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) if (!mQuickPlayEnabled) return; - if (isWithinStart || isWithinEnd) { + bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); + bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); + + if (isWithinStart || isWithinEnd) { if (!mIsWE) { SetCursor(mCursorSizeWE); mIsWE = true; @@ -2257,53 +2255,68 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) } } - HandleSnapping(); + if (evt.LeftDown()) { + HandleQPClick(evt, mousePosX); + HandleQPDrag(evt, mousePosX); + } + else if (evt.LeftIsDown()) + HandleQPDrag(evt, mousePosX); + else if (evt.LeftUp()) + HandleQPRelease(evt); mQuickPlayInd = true; wxClientDC dc(this); DrawQuickPlayIndicator(&dc); +} - if (evt.LeftDown()) - { - // Temporarily unlock locked play region - if (mPlayRegionLock && evt.LeftDown()) { - //mPlayRegionLock = true; - mProject->OnUnlockPlayRegion(); - } - - mLeftDownClick = mQuickPlayPos; - isWithinClick = IsWithinMarker(mousePosX, mLeftDownClick); - - if (isWithinStart || isWithinEnd) { - // If Quick-Play is playing from a point, we need to treat it as a click - // not as dragging. - if (mOldPlayRegionStart == mOldPlayRegionEnd) - mMouseEventState = mesSelectingPlayRegionClick; - // otherwise check which marker is nearer - else { - // Don't compare times, compare positions. - //if (fabs(mQuickPlayPos - mPlayRegionStart) < fabs(mQuickPlayPos - mPlayRegionEnd)) - if (abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionStart)) < - abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionEnd))) - mMouseEventState = mesDraggingPlayRegionStart; - else - mMouseEventState = mesDraggingPlayRegionEnd; - } - } - else { - // Clicked but not yet dragging - mMouseEventState = mesSelectingPlayRegionClick; - } - - // Check if we are dragging BEFORE CaptureMouse. - if (mMouseEventState != mesNone) - SetCursor(mCursorSizeWE); - CaptureMouse(); +void AdornedRulerPanel::HandleQPClick(wxMouseEvent &evt, wxCoord mousePosX) +{ + // Temporarily unlock locked play region + if (mPlayRegionLock && evt.LeftDown()) { + //mPlayRegionLock = true; + mProject->OnUnlockPlayRegion(); } - if (evt.LeftIsDown()) { - switch (mMouseEventState) - { + mLeftDownClick = mQuickPlayPos; + bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); + bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); + + if (isWithinStart || isWithinEnd) { + // If Quick-Play is playing from a point, we need to treat it as a click + // not as dragging. + if (mOldPlayRegionStart == mOldPlayRegionEnd) + mMouseEventState = mesSelectingPlayRegionClick; + // otherwise check which marker is nearer + else { + // Don't compare times, compare positions. + //if (fabs(mQuickPlayPos - mPlayRegionStart) < fabs(mQuickPlayPos - mPlayRegionEnd)) + if (abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionStart)) < + abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionEnd))) + mMouseEventState = mesDraggingPlayRegionStart; + else + mMouseEventState = mesDraggingPlayRegionEnd; + } + } + else { + // Clicked but not yet dragging + mMouseEventState = mesSelectingPlayRegionClick; + } + + // Check if we are dragging BEFORE CaptureMouse. + if (mMouseEventState != mesNone) + SetCursor(mCursorSizeWE); + CaptureMouse(); +} + +void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX) +{ + bool isWithinClick = (mLeftDownClick >= 0) && IsWithinMarker(mousePosX, mLeftDownClick); + bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); + bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); + bool canDragSel = !mPlayRegionLock && mPlayRegionDragsSelection; + + switch (mMouseEventState) + { case mesNone: // If close to either end of play region, snap to closest if (isWithinStart || isWithinEnd) { @@ -2351,7 +2364,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) break; case mesSelectingPlayRegionClick: - // Don't start dragging until mouse is beyond tollerance of initial click. + // Don't start dragging until mouse is beyond tolerance of initial click. if (isWithinClick || mLeftDownClick == -1) { DrawQuickPlayIndicator(NULL); @@ -2382,109 +2395,113 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) DragSelection(); } break; - } - Refresh(); - Update(); + } + Refresh(); + Update(); +} + +void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt) +{ + HideQuickPlayIndicator(); + + if (HasCapture()) + ReleaseMouse(); + + if (mPlayRegionEnd < mPlayRegionStart) { + // Swap values to ensure mPlayRegionStart < mPlayRegionEnd + double tmp = mPlayRegionStart; + mPlayRegionStart = mPlayRegionEnd; + mPlayRegionEnd = tmp; } - if (evt.LeftUp()) - { - HideQuickPlayIndicator(); + const double t0 = mTracks->GetStartTime(); + const double t1 = mTracks->GetEndTime(); + const double sel0 = mProject->GetSel0(); + const double sel1 = mProject->GetSel1(); - if (HasCapture()) - ReleaseMouse(); - - if (mPlayRegionEnd < mPlayRegionStart) { - // Swap values to ensure mPlayRegionStart < mPlayRegionEnd - double tmp = mPlayRegionStart; - mPlayRegionStart = mPlayRegionEnd; - mPlayRegionEnd = tmp; - } - - // We want some audio in the selection, but we allow a dragged - // region to include selected white-space and space before audio start. - if (evt.ShiftDown() && (mPlayRegionStart == mPlayRegionEnd)) { - // Looping the selection or project. - // Disable if track selection is in white-space beyond end of tracks and - // play position is outside of track contents. - if (((sel1 < t0) || (sel0 > t1)) && - ((mPlayRegionStart < t0) || (mPlayRegionStart > t1))) { - ClearPlayRegion(); - } - } - // Disable if beyond end. - else if (mPlayRegionStart >= t1) { - ClearPlayRegion(); - } - // Disable if empty selection before start. - // (allow Quick-Play region to include 'pre-roll' white space) - else if (((mPlayRegionEnd - mPlayRegionStart) > 0.0) && (mPlayRegionEnd < t0)) { + // We want some audio in the selection, but we allow a dragged + // region to include selected white-space and space before audio start. + if (evt.ShiftDown() && (mPlayRegionStart == mPlayRegionEnd)) { + // Looping the selection or project. + // Disable if track selection is in white-space beyond end of tracks and + // play position is outside of track contents. + if (((sel1 < t0) || (sel0 > t1)) && + ((mPlayRegionStart < t0) || (mPlayRegionStart > t1))) { ClearPlayRegion(); } + } + // Disable if beyond end. + else if (mPlayRegionStart >= t1) { + ClearPlayRegion(); + } + // Disable if empty selection before start. + // (allow Quick-Play region to include 'pre-roll' white space) + else if (((mPlayRegionEnd - mPlayRegionStart) > 0.0) && (mPlayRegionEnd < t0)) { + ClearPlayRegion(); + } - // Start / Restart playback on left click. - bool startPlaying = (mPlayRegionStart >= 0); + // Start / Restart playback on left click. + bool startPlaying = (mPlayRegionStart >= 0); - if (startPlaying) { - ControlToolBar* ctb = mProject->GetControlToolBar(); - ctb->StopPlaying(); + if (startPlaying) { + ControlToolBar* ctb = mProject->GetControlToolBar(); + ctb->StopPlaying(); - bool loopEnabled = true; - double start, end; + bool loopEnabled = true; + double start, end; - if ((mPlayRegionEnd - mPlayRegionStart == 0.0) && evt.ShiftDown()) { - // Loop play a point will loop either a selection or the project. - if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) { - // we are in a selection, so use the selection - start = sel0; - end = sel1; - } // not in a selection, so use the project - else { - start = t0; - end = t1; - } - } + if ((mPlayRegionEnd - mPlayRegionStart == 0.0) && evt.ShiftDown()) { + // Loop play a point will loop either a selection or the project. + if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) { + // we are in a selection, so use the selection + start = sel0; + end = sel1; + } // not in a selection, so use the project else { - start = mPlayRegionStart; - end = mPlayRegionEnd; + start = t0; + end = t1; } - // Looping a tiny selection may freeze, so just play it once. - loopEnabled = ((end - start) > 0.001)? true : false; - - AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions()); - options.playLooped = (loopEnabled && evt.ShiftDown()); - - if (!evt.ControlDown()) - options.pStartTime = &mPlayRegionStart; - else - options.timeTrack = NULL; - - ControlToolBar::PlayAppearance appearance = - evt.ControlDown() ? ControlToolBar::PlayAppearance::CutPreview - : loopEnabled ? ControlToolBar::PlayAppearance::Looped - : ControlToolBar::PlayAppearance::Straight; - ctb->PlayPlayRegion((SelectedRegion(start, end)), - options, PlayMode::normalPlay, - appearance, - false, - true); - - mPlayRegionStart = start; - mPlayRegionEnd = end; - Refresh(); } - - mMouseEventState = mesNone; - mIsDragging = false; - mLeftDownClick = -1; - - if (mPlayRegionLock) { - // Restore Locked Play region - SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd); - mProject->OnLockPlayRegion(); - // and release local lock - mPlayRegionLock = false; + else { + start = mPlayRegionStart; + end = mPlayRegionEnd; } + // Looping a tiny selection may freeze, so just play it once. + loopEnabled = ((end - start) > 0.001)? true : false; + + AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions()); + options.playLooped = (loopEnabled && evt.ShiftDown()); + + if (!evt.ControlDown()) + options.pStartTime = &mPlayRegionStart; + else + options.timeTrack = NULL; + + ControlToolBar::PlayAppearance appearance = + evt.ControlDown() ? ControlToolBar::PlayAppearance::CutPreview + : options.playLooped ? ControlToolBar::PlayAppearance::Looped + : ControlToolBar::PlayAppearance::Straight; + ctb->PlayPlayRegion((SelectedRegion(start, end)), + options, PlayMode::normalPlay, + appearance, + false, + true); + + mPlayRegionStart = start; + mPlayRegionEnd = end; + Refresh(); + } + + mMouseEventState = mesNone; + mIsDragging = false; + mLeftDownClick = -1; + + if (mPlayRegionLock) { + // Restore Locked Play region + SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd); + mProject->OnLockPlayRegion(); + // and release local lock + mPlayRegionLock = false; } } @@ -2704,8 +2721,8 @@ void AdornedRulerPanel::DoDrawPlayRegion(wxDC * dc) if (start >= 0) { - int x1 = Time2Pos(start) + 1; - int x2 = Time2Pos(end); + const int x1 = Time2Pos(start) + 1; + const int x2 = Time2Pos(end); int y = mInner.y - TopMargin + mInner.height/2; bool isLocked = mProject->IsPlayRegionLocked(); @@ -2746,7 +2763,7 @@ void AdornedRulerPanel::DoDrawPlayRegion(wxDC * dc) r.x = x1 + PLAY_REGION_TRIANGLE_SIZE; r.y = y - PLAY_REGION_RECT_HEIGHT/2 + PLAY_REGION_GLOBAL_OFFSET_Y; - r.width = x2-x1 - PLAY_REGION_TRIANGLE_SIZE*2; + r.width = std::max(0, x2-x1 - PLAY_REGION_TRIANGLE_SIZE*2); r.height = PLAY_REGION_RECT_HEIGHT; dc->DrawRectangle(r); } @@ -2762,8 +2779,8 @@ void AdornedRulerPanel::DoDrawBorder(wxDC * dc) if (mShowScrubbing) { // Let's distinguish the scrubbing area by using the same gray as for // selected track control panel. - AColor::Medium(&mBackDC, true); - mBackDC.DrawRectangle(mScrubZone); + AColor::Medium(dc, true); + dc->DrawRectangle(mScrubZone); } wxRect r = mOuter; diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 085f9ff3d..fcde62ea9 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -321,6 +321,9 @@ private: void OnSize(wxSizeEvent &evt); void UpdateRects(); void OnMouseEvents(wxMouseEvent &evt); + void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX); + void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX); + void HandleQPRelease(wxMouseEvent &event); enum class StatusChoice { EnteringQP, diff --git a/src/wxFileNameWrapper.h b/src/wxFileNameWrapper.h index e39815bfc..ffaaeae2a 100644 --- a/src/wxFileNameWrapper.h +++ b/src/wxFileNameWrapper.h @@ -28,6 +28,8 @@ public: void swap(wxFileNameWrapper &that) { if (this != &that) { +#if 0 + // Awful hack number 1 makes gcc 5 choke enum : size_t { Size = sizeof(*this) }; // Do it bitwise. // std::aligned_storage::type buffer; @@ -35,6 +37,32 @@ public: memcpy(&buffer, this, Size); memcpy(this, &that, Size); memcpy(&that, &buffer, Size); +#else + // Awful hack number 2 relies on knowing the class layout + // This is the less evil one but watch out for redefinition of the base class + struct Contents + { + void swap(Contents &that) { + m_volume.swap(that.m_volume); + m_dirs.swap(that.m_dirs); + m_name.swap(that.m_name); + m_ext.swap(that.m_ext); + std::swap(m_relative, that.m_relative); + std::swap(m_hasExt, that.m_hasExt); + std::swap(m_dontFollowLinks, that.m_dontFollowLinks); + }; + + wxString m_volume; + wxArrayString m_dirs; + wxString m_name, m_ext; + bool m_relative; + bool m_hasExt; + bool m_dontFollowLinks; + }; + + reinterpret_cast(this)->swap + (*reinterpret_cast(&that)); +#endif } }