From 6510b859f336d4b8264974a55cc8f7cf3612f4e2 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 9 Sep 2020 07:35:58 -0400 Subject: [PATCH] Define new virtual functions Track::GetIntervals (const and non-const) --- src/LabelTrack.cpp | 22 +++++++++++++++++ src/LabelTrack.h | 7 ++++++ src/NoteTrack.cpp | 14 +++++++++++ src/NoteTrack.h | 3 +++ src/Track.cpp | 12 +++++++++ src/Track.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++ src/WaveTrack.cpp | 21 ++++++++++++++++ src/WaveTrack.h | 14 +++++++++++ 8 files changed, 154 insertions(+) diff --git a/src/LabelTrack.cpp b/src/LabelTrack.cpp index 0992b3b9d..de304be82 100644 --- a/src/LabelTrack.cpp +++ b/src/LabelTrack.cpp @@ -84,6 +84,28 @@ LabelTrack::LabelTrack(const LabelTrack &orig) : } } +template< typename Container > +static Container MakeIntervals(const LabelArray &labels) +{ + Container result; + size_t ii = 0; + for (const auto &label : labels) + result.emplace_back( + label.getT0(), label.getT1(), + std::make_unique( ii++ ) ); + return result; +} + +auto LabelTrack::GetIntervals() const -> ConstIntervals +{ + return MakeIntervals(mLabels); +} + +auto LabelTrack::GetIntervals() -> Intervals +{ + return MakeIntervals(mLabels); +} + void LabelTrack::SetLabel( size_t iLabel, const LabelStruct &newLabel ) { if( iLabel >= mLabels.size() ) { diff --git a/src/LabelTrack.h b/src/LabelTrack.h index 98f334f02..09cdd78a0 100644 --- a/src/LabelTrack.h +++ b/src/LabelTrack.h @@ -155,6 +155,13 @@ public: int FindNextLabel(const SelectedRegion& currentSelection); int FindPrevLabel(const SelectedRegion& currentSelection); + struct IntervalData final : Track::IntervalData { + size_t index; + explicit IntervalData(size_t index) : index{index} {}; + }; + ConstIntervals GetIntervals() const override; + Intervals GetIntervals() override; + public: void SortLabels(); diff --git a/src/NoteTrack.cpp b/src/NoteTrack.cpp index 4e113903f..789a1ff8e 100644 --- a/src/NoteTrack.cpp +++ b/src/NoteTrack.cpp @@ -683,6 +683,20 @@ QuantizedTimeAndBeat NoteTrack::NearestBeatTime( double time ) const return { seq_time + GetOffset(), beat }; } +auto NoteTrack::GetIntervals() const -> ConstIntervals +{ + ConstIntervals results; + results.emplace_back( GetStartTime(), GetEndTime() ); + return results; +} + +auto NoteTrack::GetIntervals() -> Intervals +{ + Intervals results; + results.emplace_back( GetStartTime(), GetEndTime() ); + return results; +} + void NoteTrack::AddToDuration( double delta ) { auto &seq = GetSeq(); diff --git a/src/NoteTrack.h b/src/NoteTrack.h index 91295ce81..f1cf21658 100644 --- a/src/NoteTrack.h +++ b/src/NoteTrack.h @@ -185,6 +185,9 @@ public: mVisibleChannels = CHANNEL_BIT(c); } + ConstIntervals GetIntervals() const override; + Intervals GetIntervals() override; + private: TrackKind GetKind() const override { return TrackKind::Note; } diff --git a/src/Track.cpp b/src/Track.cpp index 0caaed327..1f9a14869 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -1224,6 +1224,16 @@ std::shared_ptr Track::SubstituteOriginalTrack() const return SharedPointer(); } +auto Track::GetIntervals() const -> ConstIntervals +{ + return {}; +} + +auto Track::GetIntervals() -> Intervals +{ + return {}; +} + // Serialize, not with tags of its own, but as attributes within a tag. void Track::WriteCommonXMLAttributes( XMLWriter &xmlFile, bool includeNameAndSelected) const @@ -1269,6 +1279,8 @@ void Track::AdjustPositions() } } +TrackIntervalData::~TrackIntervalData() = default; + bool TrackList::HasPendingTracks() const { if ( !mPendingUpdates.empty() ) diff --git a/src/Track.h b/src/Track.h index d8637ddf6..15a7eff57 100644 --- a/src/Track.h +++ b/src/Track.h @@ -181,6 +181,50 @@ private: long mValue; }; +//! Optional extra information about an interval, appropriate to a subtype of Track +struct TrackIntervalData { + virtual ~TrackIntervalData(); +}; + +//! A start and an end time, and non-mutative access to optional extra information +/*! @invariant `Start() <= End()` */ +class ConstTrackInterval { +public: + + /*! @pre `start <= end` */ + ConstTrackInterval( double start, double end, + std::unique_ptr pExtra = {} ) + : start{ start }, end{ end }, pExtra{ std::move( pExtra ) } + { + wxASSERT( start <= end ); + } + + ConstTrackInterval( ConstTrackInterval&& ) = default; + ConstTrackInterval &operator=( ConstTrackInterval&& ) = default; + + double Start() const { return start; } + double End() const { return end; } + const TrackIntervalData *Extra() const { return pExtra.get(); } + +private: + double start, end; +protected: + // TODO C++17: use std::any instead + std::unique_ptr< TrackIntervalData > pExtra; +}; + +//! A start and an end time, and mutative access to optional extra information +/*! @invariant `Start() <= End()` */ +class TrackInterval : public ConstTrackInterval { +public: + using ConstTrackInterval::ConstTrackInterval; + + TrackInterval(TrackInterval&&) = default; + TrackInterval &operator= (TrackInterval&&) = default; + + TrackIntervalData *Extra() const { return pExtra.get(); } +}; + //! Template generated base class for Track lets it host opaque UI related objects using AttachedTrackObjects = ClientData::Site< Track, ClientData::Base, ClientData::SkipCopying, std::shared_ptr @@ -268,6 +312,23 @@ class AUDACITY_DLL_API Track /* not final */ // original; else return this track std::shared_ptr SubstituteOriginalTrack() const; + using IntervalData = TrackIntervalData; + using Interval = TrackInterval; + using Intervals = std::vector< Interval >; + using ConstInterval = ConstTrackInterval; + using ConstIntervals = std::vector< ConstInterval >; + + //! Report times on the track where important intervals begin and end, for UI to snap to + /*! + Some intervals may be empty, and no ordering of the intervals is assumed. + */ + virtual ConstIntervals GetIntervals() const; + + /*! @copydoc GetIntervals() + This overload exposes the extra data of the intervals as non-const + */ + virtual Intervals GetIntervals(); + public: mutable wxSize vrulerSize; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 18b48c7d3..d86a4960d 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -323,6 +323,27 @@ int WaveTrack::ZeroLevelYCoordinate(wxRect rect) const (int)((mDisplayMax / (mDisplayMax - mDisplayMin)) * rect.height); } +template< typename Container > +static Container MakeIntervals(const std::vector &clips) +{ + Container result; + for (const auto &clip: clips) { + result.emplace_back( clip->GetStartTime(), clip->GetEndTime(), + std::make_unique( clip ) ); + } + return result; +} + +auto WaveTrack::GetIntervals() const -> ConstIntervals +{ + return MakeIntervals( mClips ); +} + +auto WaveTrack::GetIntervals() -> Intervals +{ + return MakeIntervals( mClips ); +} + Track::Holder WaveTrack::Clone() const { return std::make_shared( *this ); diff --git a/src/WaveTrack.h b/src/WaveTrack.h index a209ca02d..4ac2a45b5 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -523,6 +523,20 @@ private: // bottom and top. Maybe that is out of bounds. int ZeroLevelYCoordinate(wxRect rect) const; + class IntervalData final : public Track::IntervalData { + public: + explicit IntervalData( const std::shared_ptr &pClip ) + : pClip{ pClip } + {} + std::shared_ptr GetClip() const { return pClip; } + std::shared_ptr &GetClip() { return pClip; } + private: + std::shared_ptr pClip; + }; + + ConstIntervals GetIntervals() const override; + Intervals GetIntervals() override; + protected: // // Protected variables