2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
Track.h
|
|
|
|
|
|
|
|
Dominic Mazzoni
|
|
|
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#ifndef __AUDACITY_TRACK__
|
|
|
|
#define __AUDACITY_TRACK__
|
|
|
|
|
|
|
|
#include "Audacity.h"
|
|
|
|
|
2016-03-07 06:29:26 +00:00
|
|
|
#include "MemoryX.h"
|
2016-02-26 23:10:45 +00:00
|
|
|
#include <vector>
|
2016-03-01 23:31:51 +00:00
|
|
|
#include <list>
|
2017-08-24 18:31:51 +00:00
|
|
|
#include <functional>
|
2010-01-23 19:44:49 +00:00
|
|
|
#include <wx/dynarray.h>
|
|
|
|
#include <wx/event.h>
|
|
|
|
#include <wx/gdicmn.h>
|
|
|
|
#include <wx/longlong.h>
|
|
|
|
#include <wx/string.h>
|
|
|
|
|
|
|
|
#include "Experimental.h"
|
|
|
|
#include "SampleFormat.h"
|
2015-07-07 03:12:16 +00:00
|
|
|
#include "tracks/ui/CommonTrackPanelCell.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "xml/XMLTagHandler.h"
|
|
|
|
|
|
|
|
#ifdef __WXMSW__
|
|
|
|
#pragma warning(disable:4284)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class wxTextFile;
|
|
|
|
class DirManager;
|
2015-08-24 01:25:01 +00:00
|
|
|
class Track;
|
2010-01-23 19:44:49 +00:00
|
|
|
class LabelTrack;
|
|
|
|
class TimeTrack;
|
2015-07-07 03:12:16 +00:00
|
|
|
class TrackControls;
|
|
|
|
class TrackVRulerControls;
|
2017-06-26 20:13:56 +00:00
|
|
|
class TrackPanelResizerCell;
|
2010-01-23 19:44:49 +00:00
|
|
|
class WaveTrack;
|
2016-04-09 19:10:05 +00:00
|
|
|
class NoteTrack;
|
2010-01-23 19:44:49 +00:00
|
|
|
class AudacityProject;
|
2016-01-26 22:37:16 +00:00
|
|
|
class ZoomInfo;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
Changed lifetime management of UIHandle objects, no singletons...
... Rather, construct them during hit tests (also capturing more state sooner
rather than at Click time, and adding some accessors for later use)
This also fixes bug 1677 by other means and avoids similar problems.
A cell may be implemented to re-use a previously hit handle object, not yet
clicked, in a later hit test, by remembering a weak pointer, but TrackPanel
holds the strong pointers that determine when the object is destroyed.
And the objects will surely be destroyed after drag-release, or ESC key.
For now they are also destroyed whenever not dragging, and hit-testing is
re-invoked; that will be changed later, so that the re-use mentioned above
becomes effective, but still they will be destroyed when the pointer moves
from one cell to another.
2017-07-05 20:45:55 +00:00
|
|
|
class SelectHandle;
|
|
|
|
class TimeShiftHandle;
|
|
|
|
|
2015-08-24 01:25:01 +00:00
|
|
|
WX_DEFINE_USER_EXPORTED_ARRAY(Track*, TrackArray, class AUDACITY_DLL_API);
|
2017-08-24 15:44:36 +00:00
|
|
|
using WaveTrackArray = std::vector < std::shared_ptr< WaveTrack > > ;
|
|
|
|
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
|
|
|
|
using NoteTrackArray = std::vector < std::shared_ptr < NoteTrack > >;
|
2016-04-09 19:10:05 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
#if defined(USE_MIDI)
|
|
|
|
class NoteTrack;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class TrackList;
|
2016-03-01 23:31:51 +00:00
|
|
|
|
2017-06-22 23:25:46 +00:00
|
|
|
using ListOfTracks = std::list< std::shared_ptr< Track > >;
|
2016-03-13 15:08:21 +00:00
|
|
|
|
2016-03-01 23:31:51 +00:00
|
|
|
using TrackNodePointer = ListOfTracks::iterator;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-07-07 03:12:16 +00:00
|
|
|
class ViewInfo;
|
|
|
|
|
2018-01-11 00:28:16 +00:00
|
|
|
// This is an in-session identifier of track objects across undo states
|
|
|
|
// It does not persist between sessions
|
|
|
|
// Default constructed value is not equal to the id of any track that has ever
|
|
|
|
// been added to a TrackList, or (directly or transitively) copied from such
|
2017-08-24 18:31:51 +00:00
|
|
|
// (A pending additional track that is not yet applied is not considered added)
|
2018-01-11 00:28:16 +00:00
|
|
|
// TrackIds are assigned uniquely across projects
|
|
|
|
class TrackId
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TrackId() : mValue(-1) {}
|
|
|
|
explicit TrackId (long value) : mValue(value) {}
|
|
|
|
|
|
|
|
bool operator == (const TrackId &other) const
|
|
|
|
{ return mValue == other.mValue; }
|
|
|
|
|
|
|
|
bool operator != (const TrackId &other) const
|
|
|
|
{ return mValue != other.mValue; }
|
|
|
|
|
|
|
|
// Define this in case you want to key a std::map on TrackId
|
|
|
|
// The operator does not mean anything else
|
|
|
|
bool operator < (const TrackId &other) const
|
|
|
|
{ return mValue < other.mValue; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
long mValue;
|
|
|
|
};
|
|
|
|
|
2015-07-07 03:12:16 +00:00
|
|
|
class AUDACITY_DLL_API Track /* not final */
|
|
|
|
: public CommonTrackPanelCell, public XMLTagHandler
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2016-03-01 23:31:51 +00:00
|
|
|
friend class TrackList;
|
|
|
|
friend class TrackListIterator;
|
|
|
|
friend class SyncLockedTracksIterator;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// To be TrackDisplay
|
2018-01-11 00:28:16 +00:00
|
|
|
private:
|
|
|
|
TrackId mId;
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
protected:
|
2017-07-10 15:48:11 +00:00
|
|
|
std::weak_ptr<TrackList> mList;
|
2016-03-01 23:31:51 +00:00
|
|
|
TrackNodePointer mNode{};
|
2010-01-23 19:44:49 +00:00
|
|
|
int mIndex;
|
|
|
|
int mY;
|
|
|
|
int mHeight;
|
|
|
|
wxString mName;
|
|
|
|
wxString mDefaultName;
|
|
|
|
|
|
|
|
bool mSelected;
|
|
|
|
|
|
|
|
bool mLinked;
|
|
|
|
bool mMinimized;
|
|
|
|
|
2018-01-11 00:28:16 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
TrackId GetId() const { return mId; }
|
|
|
|
private:
|
|
|
|
void SetId( TrackId id ) { mId = id; }
|
2010-01-23 19:44:49 +00:00
|
|
|
public:
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2017-06-23 00:29:32 +00:00
|
|
|
// Given a bare pointer, find a shared_ptr. But this is not possible for
|
2017-07-10 15:48:11 +00:00
|
|
|
// a track not owned by any project, so the result can be null.
|
2017-06-23 00:29:32 +00:00
|
|
|
template<typename Subclass = Track>
|
|
|
|
inline static std::shared_ptr<Subclass> Pointer( Track *t )
|
|
|
|
{
|
2017-07-10 15:48:11 +00:00
|
|
|
if (t) {
|
|
|
|
auto pList = t->mList.lock();
|
|
|
|
if (pList)
|
|
|
|
return std::static_pointer_cast<Subclass>(*t->mNode);
|
|
|
|
}
|
2017-06-23 00:29:32 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Subclass = const Track>
|
|
|
|
inline static std::shared_ptr<Subclass> Pointer( const Track *t )
|
|
|
|
{
|
2017-07-10 15:48:11 +00:00
|
|
|
if (t) {
|
|
|
|
auto pList = t->mList.lock();
|
|
|
|
if (pList) {
|
|
|
|
std::shared_ptr<const Track> p{ *t->mNode };
|
|
|
|
// Let you change the type, but not cast away the const
|
|
|
|
return std::static_pointer_cast<Subclass>(p);
|
|
|
|
}
|
2017-06-23 00:29:32 +00:00
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2017-06-19 19:02:45 +00:00
|
|
|
// Cause certain overriding tool modes (Zoom; future ones?) to behave
|
|
|
|
// uniformly in all tracks, disregarding track contents.
|
|
|
|
// Do not further override this...
|
2017-06-29 14:34:57 +00:00
|
|
|
std::vector<UIHandlePtr> HitTest
|
2017-06-29 03:21:20 +00:00
|
|
|
(const TrackPanelMouseState &, const AudacityProject *pProject)
|
2017-07-13 01:23:08 +00:00
|
|
|
final override;
|
2017-06-19 19:02:45 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
// Rather override this for subclasses:
|
2017-06-29 14:34:57 +00:00
|
|
|
virtual std::vector<UIHandlePtr> DetailedHitTest
|
2017-06-29 03:21:20 +00:00
|
|
|
(const TrackPanelMouseState &,
|
2017-06-19 19:02:45 +00:00
|
|
|
const AudacityProject *pProject, int currentTool, bool bMultiTool)
|
|
|
|
= 0;
|
|
|
|
|
|
|
|
mutable wxSize vrulerSize;
|
2015-07-07 03:12:16 +00:00
|
|
|
|
|
|
|
// Return another, associated TrackPanelCell object that implements the
|
|
|
|
// drop-down, close and minimize buttons, etc.
|
2017-06-23 21:33:45 +00:00
|
|
|
std::shared_ptr<TrackPanelCell> GetTrackControl();
|
2015-07-07 03:12:16 +00:00
|
|
|
|
|
|
|
// Return another, associated TrackPanelCell object that implements the
|
|
|
|
// mouse actions for the vertical ruler
|
2017-06-23 21:33:45 +00:00
|
|
|
std::shared_ptr<TrackPanelCell> GetVRulerControl();
|
2015-07-07 03:12:16 +00:00
|
|
|
|
2017-06-26 20:13:56 +00:00
|
|
|
// Return another, associated TrackPanelCell object that implements the
|
|
|
|
// click and drag to resize
|
|
|
|
std::shared_ptr<TrackPanelCell> GetResizer();
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
// This just returns a constant and can be overriden by subclasses
|
|
|
|
// to specify a different height for the case that the track is minimized.
|
|
|
|
virtual int GetMinimizedHeight() const;
|
2017-02-22 19:23:35 +00:00
|
|
|
int GetActualHeight() const { return mHeight; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
int GetIndex() const;
|
|
|
|
void SetIndex(int index);
|
2018-01-12 01:57:37 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
int GetY() const;
|
2018-01-12 01:57:37 +00:00
|
|
|
private:
|
|
|
|
// Always maintain a strictly contiguous layout of tracks.
|
|
|
|
// So client code is not permitted to modify this attribute directly.
|
2010-01-23 19:44:49 +00:00
|
|
|
void SetY(int y);
|
2018-01-12 01:57:37 +00:00
|
|
|
// No need yet to make this virtual
|
|
|
|
void DoSetY(int y);
|
|
|
|
public:
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
int GetHeight() const;
|
2018-01-12 01:57:37 +00:00
|
|
|
void SetHeight(int h);
|
|
|
|
protected:
|
|
|
|
virtual void DoSetHeight(int h);
|
|
|
|
public:
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
bool GetMinimized() const;
|
2018-01-12 01:57:37 +00:00
|
|
|
void SetMinimized(bool isMinimized);
|
|
|
|
protected:
|
|
|
|
virtual void DoSetMinimized(bool isMinimized);
|
|
|
|
public:
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
Track *GetLink() const;
|
|
|
|
|
2016-03-01 23:31:51 +00:00
|
|
|
private:
|
|
|
|
TrackNodePointer GetNode() const;
|
2017-07-10 15:48:11 +00:00
|
|
|
void SetOwner
|
|
|
|
(const std::weak_ptr<TrackList> &list, TrackNodePointer node);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Keep in Track
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int mChannel;
|
|
|
|
double mOffset;
|
|
|
|
|
2016-08-13 04:38:31 +00:00
|
|
|
mutable std::shared_ptr<DirManager> mDirManager;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
LeftChannel = 0,
|
|
|
|
RightChannel = 1,
|
|
|
|
MonoChannel = 2
|
|
|
|
};
|
|
|
|
|
2010-02-13 02:16:47 +00:00
|
|
|
enum TrackKindEnum
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
None,
|
|
|
|
Wave,
|
|
|
|
#if defined(USE_MIDI)
|
|
|
|
Note,
|
|
|
|
#endif
|
|
|
|
Label,
|
|
|
|
Time,
|
|
|
|
All
|
2010-02-13 02:16:47 +00:00
|
|
|
};
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2017-06-07 01:40:58 +00:00
|
|
|
enum : unsigned { DefaultHeight = 150 };
|
|
|
|
|
2016-08-13 04:38:31 +00:00
|
|
|
Track(const std::shared_ptr<DirManager> &projDirManager);
|
2010-01-23 19:44:49 +00:00
|
|
|
Track(const Track &orig);
|
|
|
|
|
|
|
|
virtual ~ Track();
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
void Init(const Track &orig);
|
2016-03-02 19:37:47 +00:00
|
|
|
|
|
|
|
using Holder = std::unique_ptr<Track>;
|
|
|
|
virtual Holder Duplicate() const = 0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2011-04-26 21:19:59 +00:00
|
|
|
// Called when this track is merged to stereo with another, and should
|
2010-01-23 19:44:49 +00:00
|
|
|
// take on some paramaters of its partner.
|
|
|
|
virtual void Merge(const Track &orig);
|
|
|
|
|
|
|
|
wxString GetName() const { return mName; }
|
2016-02-23 02:18:11 +00:00
|
|
|
void SetName( const wxString &n ) { mName = n; }
|
2010-01-23 19:44:49 +00:00
|
|
|
wxString GetDefaultName() const { return mDefaultName; }
|
2016-02-23 02:18:11 +00:00
|
|
|
void SetDefaultName( const wxString &n ) { mDefaultName = n; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
bool GetSelected() const { return mSelected; }
|
2018-01-15 02:36:33 +00:00
|
|
|
virtual void SetSelected(bool s);
|
2018-01-12 01:57:37 +00:00
|
|
|
|
|
|
|
bool GetLinked () const { return mLinked; }
|
2013-03-10 16:31:07 +00:00
|
|
|
void SetLinked (bool l);
|
2018-01-12 01:57:37 +00:00
|
|
|
private:
|
|
|
|
// No need yet to make this virtual
|
|
|
|
void DoSetLinked(bool l);
|
|
|
|
public:
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2017-04-02 22:07:13 +00:00
|
|
|
virtual int GetChannel() const { return mChannel;};
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual double GetOffset() const = 0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
void Offset(double t) { SetOffset(GetOffset() + t); }
|
|
|
|
virtual void SetOffset (double o) { mOffset = o; }
|
|
|
|
|
|
|
|
void SetChannel(int c) { mChannel = c; }
|
2017-04-23 11:58:11 +00:00
|
|
|
virtual void SetPan( float ){ ;}
|
2017-04-02 22:07:13 +00:00
|
|
|
virtual void SetPanFromChannelType(){ ;};
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// AS: Note that the dirManager is mutable. This is
|
|
|
|
// mostly to support "Duplicate" of const objects,
|
|
|
|
// but in general, mucking with the dir manager is
|
|
|
|
// separate from the Track.
|
2016-08-13 04:38:31 +00:00
|
|
|
const std::shared_ptr<DirManager> &GetDirManager() const { return mDirManager; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2017-03-31 18:54:55 +00:00
|
|
|
// Create a NEW track and modify this track
|
|
|
|
// Return non-NULL or else throw
|
2017-11-19 03:18:49 +00:00
|
|
|
// May assume precondition: t0 <= t1
|
2017-03-31 18:54:55 +00:00
|
|
|
virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
|
2016-03-02 20:36:44 +00:00
|
|
|
|
2017-03-31 18:54:55 +00:00
|
|
|
// Create a NEW track and don't modify this track
|
|
|
|
// Return non-NULL or else throw
|
2016-11-26 13:48:08 +00:00
|
|
|
// Note that subclasses may want to distinguish tracks stored in a clipboard
|
|
|
|
// from those stored in a project
|
2017-11-19 03:18:49 +00:00
|
|
|
// May assume precondition: t0 <= t1
|
2016-11-26 13:48:08 +00:00
|
|
|
virtual Holder Copy
|
2017-03-31 18:54:55 +00:00
|
|
|
(double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
|
2016-03-02 20:36:44 +00:00
|
|
|
|
2017-11-19 03:18:49 +00:00
|
|
|
// May assume precondition: t0 <= t1
|
2017-03-23 15:10:14 +00:00
|
|
|
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
|
2016-03-02 20:36:44 +00:00
|
|
|
|
2017-03-23 15:10:14 +00:00
|
|
|
virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2010-08-11 22:47:26 +00:00
|
|
|
// This can be used to adjust a sync-lock selected track when the selection
|
2010-02-16 20:50:38 +00:00
|
|
|
// is replaced by one of a different length.
|
2017-03-23 15:10:14 +00:00
|
|
|
virtual void SyncLockAdjust(double oldT1, double newT1);
|
2010-02-16 20:50:38 +00:00
|
|
|
|
2017-11-19 03:18:49 +00:00
|
|
|
// May assume precondition: t0 <= t1
|
2017-03-23 15:10:14 +00:00
|
|
|
virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
|
2017-11-19 03:18:49 +00:00
|
|
|
|
|
|
|
// May assume precondition: t0 <= t1
|
2017-03-23 15:10:14 +00:00
|
|
|
virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
virtual int GetKind() const { return None; }
|
|
|
|
|
2016-02-24 06:06:47 +00:00
|
|
|
// XMLTagHandler callback methods -- NEW virtual for writing
|
2017-02-22 19:23:35 +00:00
|
|
|
virtual void WriteXML(XMLWriter &xmlFile) const = 0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Returns true if an error was encountered while trying to
|
|
|
|
// open the track from XML
|
|
|
|
virtual bool GetErrorOpening() { return false; }
|
|
|
|
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual double GetStartTime() const = 0;
|
|
|
|
virtual double GetEndTime() const = 0;
|
2010-02-12 16:05:02 +00:00
|
|
|
|
2012-08-20 20:26:42 +00:00
|
|
|
// Checks if sync-lock is on and any track in its sync-lock group is selected.
|
2015-04-19 11:27:33 +00:00
|
|
|
bool IsSyncLockSelected() const;
|
2015-07-07 03:12:16 +00:00
|
|
|
|
|
|
|
protected:
|
2017-06-27 18:12:23 +00:00
|
|
|
std::shared_ptr<Track> FindTrack() override;
|
2017-06-23 21:33:45 +00:00
|
|
|
|
|
|
|
// These are called to create controls on demand:
|
|
|
|
virtual std::shared_ptr<TrackControls> GetControls() = 0;
|
|
|
|
virtual std::shared_ptr<TrackVRulerControls> GetVRulerControls() = 0;
|
|
|
|
|
|
|
|
// These hold the controls:
|
|
|
|
std::shared_ptr<TrackControls> mpControls;
|
|
|
|
std::shared_ptr<TrackVRulerControls> mpVRulerContols;
|
2017-06-26 20:13:56 +00:00
|
|
|
std::shared_ptr<TrackPanelResizerCell> mpResizer;
|
Changed lifetime management of UIHandle objects, no singletons...
... Rather, construct them during hit tests (also capturing more state sooner
rather than at Click time, and adding some accessors for later use)
This also fixes bug 1677 by other means and avoids similar problems.
A cell may be implemented to re-use a previously hit handle object, not yet
clicked, in a later hit test, by remembering a weak pointer, but TrackPanel
holds the strong pointers that determine when the object is destroyed.
And the objects will surely be destroyed after drag-release, or ESC key.
For now they are also destroyed whenever not dragging, and hit-testing is
re-invoked; that will be changed later, so that the re-use mentioned above
becomes effective, but still they will be destroyed when the pointer moves
from one cell to another.
2017-07-05 20:45:55 +00:00
|
|
|
|
|
|
|
std::weak_ptr<SelectHandle> mSelectHandle;
|
|
|
|
std::weak_ptr<TimeShiftHandle> mTimeShiftHandle;
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
2017-05-23 17:06:50 +00:00
|
|
|
class AUDACITY_DLL_API AudioTrack /* not final */ : public Track
|
2017-01-08 08:36:12 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioTrack(const std::shared_ptr<DirManager> &projDirManager)
|
|
|
|
: Track{ projDirManager } {}
|
|
|
|
AudioTrack(const Track &orig) : Track{ orig } {}
|
2017-03-30 20:00:27 +00:00
|
|
|
|
|
|
|
// Serialize, not with tags of its own, but as attributes within a tag.
|
2017-12-08 11:26:09 +00:00
|
|
|
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const {}
|
2017-03-30 20:00:27 +00:00
|
|
|
|
|
|
|
// Return true iff the attribute is recognized.
|
|
|
|
bool HandleXMLAttribute(const wxChar * /*attr*/, const wxChar * /*value*/)
|
|
|
|
{ return false; }
|
2017-01-08 08:36:12 +00:00
|
|
|
};
|
|
|
|
|
2017-05-23 17:06:50 +00:00
|
|
|
class AUDACITY_DLL_API PlayableTrack /* not final */ : public AudioTrack
|
2017-01-08 08:36:12 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
PlayableTrack(const std::shared_ptr<DirManager> &projDirManager)
|
|
|
|
: AudioTrack{ projDirManager } {}
|
|
|
|
PlayableTrack(const Track &orig) : AudioTrack{ orig } {}
|
2017-03-29 15:25:05 +00:00
|
|
|
|
|
|
|
bool GetMute () const { return mMute; }
|
|
|
|
bool GetSolo () const { return mSolo; }
|
|
|
|
void SetMute (bool m) { mMute = m; }
|
|
|
|
void SetSolo (bool s) { mSolo = s; }
|
|
|
|
|
|
|
|
void Init( const PlayableTrack &init );
|
|
|
|
void Merge( const Track &init ) override;
|
|
|
|
|
2017-03-30 20:00:27 +00:00
|
|
|
// Serialize, not with tags of its own, but as attributes within a tag.
|
|
|
|
void WriteXMLAttributes(XMLWriter &xmlFile) const;
|
|
|
|
|
|
|
|
// Return true iff the attribute is recognized.
|
|
|
|
bool HandleXMLAttribute(const wxChar *attr, const wxChar *value);
|
|
|
|
|
2017-03-29 15:25:05 +00:00
|
|
|
protected:
|
|
|
|
bool mMute { false };
|
|
|
|
bool mSolo { false };
|
2017-01-08 08:36:12 +00:00
|
|
|
};
|
|
|
|
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API TrackListIterator /* not final */
|
2018-01-14 19:01:04 +00:00
|
|
|
: public std::iterator< std::forward_iterator_tag, Track *const >
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-01-14 19:01:04 +00:00
|
|
|
// The default-constructed value can serve as the end iterator for
|
|
|
|
// traversal over any track list.
|
|
|
|
TrackListIterator() {}
|
|
|
|
explicit TrackListIterator(TrackList * val);
|
|
|
|
explicit TrackListIterator(TrackList * val, TrackNodePointer p);
|
|
|
|
TrackListIterator(const TrackListIterator&) = default;
|
|
|
|
TrackListIterator& operator=(const TrackListIterator&) = default;
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual ~TrackListIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Iterate functions
|
2018-01-14 19:01:04 +00:00
|
|
|
virtual Track *First(TrackList * val = nullptr);
|
2010-01-23 19:44:49 +00:00
|
|
|
virtual Track *StartWith(Track * val);
|
|
|
|
virtual Track *Next(bool skiplinked = false);
|
|
|
|
virtual Track *Prev(bool skiplinked = false);
|
|
|
|
virtual Track *Last(bool skiplinked = false);
|
|
|
|
|
2016-03-13 15:08:21 +00:00
|
|
|
Track *RemoveCurrent(); // deletes track, returns next
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2018-01-14 19:01:04 +00:00
|
|
|
// Provide minimal STL forward-iterator idiom:
|
|
|
|
|
|
|
|
// unlike Next, this is non-mutating.
|
|
|
|
// An end iterator may be safely dereferenced, returning nullptr.
|
|
|
|
Track *operator * () const;
|
|
|
|
|
|
|
|
TrackListIterator &operator++ () { (void) Next(); return *this; }
|
2018-01-14 21:55:49 +00:00
|
|
|
TrackListIterator operator++ (int)
|
|
|
|
{ auto copy = *this; operator++(); return copy; }
|
2018-01-14 19:01:04 +00:00
|
|
|
|
|
|
|
bool operator == (const TrackListIterator &other) const;
|
|
|
|
bool operator != (const TrackListIterator &other) const
|
|
|
|
{ return !(*this == other); }
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
protected:
|
2016-03-14 15:18:32 +00:00
|
|
|
friend TrackList;
|
|
|
|
|
2018-01-14 19:01:04 +00:00
|
|
|
TrackList *l {};
|
2016-03-01 23:31:51 +00:00
|
|
|
TrackNodePointer cur{};
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
2016-02-08 20:59:50 +00:00
|
|
|
class AUDACITY_DLL_API TrackListConstIterator
|
2018-01-14 19:01:04 +00:00
|
|
|
: public std::iterator< std::forward_iterator_tag, const Track *const >
|
2016-02-08 20:59:50 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-01-14 19:01:04 +00:00
|
|
|
// The default-constructed value can serve as the end iterator for
|
|
|
|
// traversal over any track list.
|
|
|
|
TrackListConstIterator() {}
|
|
|
|
explicit TrackListConstIterator(
|
|
|
|
const TrackList * val, TrackNodePointer p)
|
|
|
|
: mIter(const_cast<TrackList*>(val), p)
|
|
|
|
{}
|
|
|
|
explicit TrackListConstIterator(
|
|
|
|
const TrackList * val)
|
2018-01-14 14:24:21 +00:00
|
|
|
: mIter(const_cast<TrackList*>(val))
|
2016-02-08 20:59:50 +00:00
|
|
|
{}
|
2018-01-14 19:01:04 +00:00
|
|
|
TrackListConstIterator(const TrackListConstIterator&) = default;
|
|
|
|
TrackListConstIterator& operator=(const TrackListConstIterator&) = default;
|
2016-02-08 20:59:50 +00:00
|
|
|
~TrackListConstIterator() {}
|
|
|
|
|
|
|
|
// Iterate functions
|
|
|
|
const Track *First(const TrackList * val = NULL)
|
|
|
|
{ return mIter.First(const_cast<TrackList*>(val)); }
|
|
|
|
const Track *StartWith(const Track * val)
|
|
|
|
{ return mIter.StartWith(const_cast<Track*>(val)); }
|
|
|
|
const Track *Next(bool skiplinked = false)
|
|
|
|
{ return mIter.Next(skiplinked); }
|
|
|
|
const Track *Prev(bool skiplinked = false)
|
|
|
|
{ return mIter.Prev(skiplinked); }
|
|
|
|
const Track *Last(bool skiplinked = false)
|
|
|
|
{ return mIter.Last(skiplinked); }
|
|
|
|
|
2018-01-14 19:01:04 +00:00
|
|
|
// Provide minimal STL forward-iterator idiom:
|
|
|
|
|
|
|
|
// unlike Next, this is non-mutating.
|
|
|
|
// An end iterator may be safely dereferenced, returning nullptr.
|
|
|
|
const Track *operator * () const { return *mIter; }
|
|
|
|
|
|
|
|
TrackListConstIterator &operator++ () { (void) Next(); return *this; }
|
2018-01-14 21:55:49 +00:00
|
|
|
TrackListConstIterator operator++ (int)
|
|
|
|
{ auto copy = *this; operator++(); return copy; }
|
2018-01-14 19:01:04 +00:00
|
|
|
|
|
|
|
bool operator == (const TrackListConstIterator &other) const
|
|
|
|
{ return mIter == other.mIter; }
|
|
|
|
bool operator != (const TrackListConstIterator &other) const
|
|
|
|
{ return !(*this == other); }
|
|
|
|
|
2016-02-08 20:59:50 +00:00
|
|
|
private:
|
|
|
|
TrackListIterator mIter;
|
|
|
|
};
|
|
|
|
|
2011-04-18 06:30:07 +00:00
|
|
|
// TrackListCondIterator (base class for iterators that iterate over all tracks)
|
|
|
|
// that meet a condition)
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API TrackListCondIterator /* not final */ : public TrackListIterator
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
TrackListCondIterator(TrackList *val = NULL)
|
2015-03-28 18:46:40 +00:00
|
|
|
: TrackListIterator(val) {}
|
|
|
|
virtual ~TrackListCondIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Iteration functions
|
2016-02-24 06:06:47 +00:00
|
|
|
Track *First(TrackList *val = NULL) override;
|
|
|
|
Track *StartWith(Track *val) override;
|
|
|
|
Track *Next(bool skiplinked = false) override;
|
|
|
|
Track *Prev(bool skiplinked = false) override;
|
|
|
|
Track *Last(bool skiplinked = false) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2018-01-15 02:36:33 +00:00
|
|
|
protected:
|
2016-02-24 06:06:47 +00:00
|
|
|
// NEW virtual
|
2010-01-23 19:44:49 +00:00
|
|
|
virtual bool Condition(Track *t) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// TrackListOfKindIterator
|
|
|
|
//
|
|
|
|
// Based on TrackListIterator and returns only tracks of the specified type.
|
|
|
|
//
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API TrackListOfKindIterator /* not final */ : public TrackListCondIterator
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
TrackListOfKindIterator(int kind, TrackList * val = NULL);
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual ~TrackListOfKindIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
protected:
|
2016-02-24 06:06:47 +00:00
|
|
|
virtual bool Condition(Track *t) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int kind;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// SelectedTrackListOfKindIterator
|
|
|
|
//
|
|
|
|
// Based on TrackListOfKindIterator and returns only tracks selected.
|
|
|
|
//
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API SelectedTrackListOfKindIterator final : public TrackListOfKindIterator
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
2015-03-28 18:46:40 +00:00
|
|
|
SelectedTrackListOfKindIterator(int kind, TrackList * val = NULL) : TrackListOfKindIterator(kind, val) {}
|
|
|
|
virtual ~SelectedTrackListOfKindIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
protected:
|
2016-02-24 06:06:47 +00:00
|
|
|
bool Condition(Track *t) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// VisibleTrackIterator
|
|
|
|
//
|
|
|
|
// Based on TrackListIterator returns only the currently visible tracks.
|
|
|
|
//
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API VisibleTrackIterator final : public TrackListCondIterator
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
VisibleTrackIterator(AudacityProject *project);
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual ~VisibleTrackIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
protected:
|
2016-02-24 06:06:47 +00:00
|
|
|
bool Condition(Track *t) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
AudacityProject *mProject;
|
|
|
|
wxRect mPanelRect;
|
|
|
|
};
|
|
|
|
|
2010-08-11 23:56:50 +00:00
|
|
|
|
2014-06-03 20:30:19 +00:00
|
|
|
// SyncLockedTracksIterator returns only tracks belonging to the sync-locked tracks
|
2010-01-23 19:44:49 +00:00
|
|
|
// in which the starting track is a member.
|
2016-02-24 06:06:39 +00:00
|
|
|
class AUDACITY_DLL_API SyncLockedTracksIterator final : public TrackListIterator
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
public:
|
2010-08-11 23:56:50 +00:00
|
|
|
SyncLockedTracksIterator(TrackList * val);
|
2015-03-28 18:46:40 +00:00
|
|
|
virtual ~SyncLockedTracksIterator() {}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Iterate functions
|
2016-02-23 19:06:36 +00:00
|
|
|
Track *StartWith(Track *member) override;
|
|
|
|
Track *Next(bool skiplinked = false) override;
|
|
|
|
Track *Prev(bool skiplinked = false) override;
|
|
|
|
Track *Last(bool skiplinked = false) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
private:
|
2016-11-04 04:10:21 +00:00
|
|
|
bool IsGoodNextTrack(const Track *t) const;
|
2010-02-12 16:05:02 +00:00
|
|
|
bool mInLabelSection;
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** \brief TrackList is a flat linked list of tracks supporting Add, Remove,
|
|
|
|
* Clear, and Contains, plus serialization of the list of tracks.
|
|
|
|
*/
|
|
|
|
|
2017-11-04 17:33:11 +00:00
|
|
|
struct TrackListEvent : public wxCommandEvent
|
|
|
|
{
|
|
|
|
TrackListEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
|
|
|
|
: wxCommandEvent{ commandType, winid } {}
|
|
|
|
|
|
|
|
TrackListEvent( const TrackListEvent& ) = default;
|
|
|
|
|
|
|
|
wxEvent *Clone() const override { return new TrackListEvent(*this); }
|
|
|
|
|
|
|
|
std::weak_ptr<Track> mpTrack;
|
|
|
|
};
|
|
|
|
|
2017-06-26 17:40:19 +00:00
|
|
|
// Posted when tracks are reordered but otherwise unchanged.
|
|
|
|
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_PERMUTED, -1);
|
|
|
|
|
2017-06-25 05:33:31 +00:00
|
|
|
// Posted when some track was added or changed its height.
|
2017-11-04 17:33:11 +00:00
|
|
|
// Cast to TrackListEvent and examine mpTrack to retrieve it.
|
2017-06-25 05:33:31 +00:00
|
|
|
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZING, -1);
|
|
|
|
|
|
|
|
// Posted when a track has been deleted from a tracklist.
|
2017-06-01 18:19:52 +00:00
|
|
|
// Also posted when one track replaces another
|
2017-06-25 05:33:31 +00:00
|
|
|
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_DELETION, -1);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-03-13 15:08:21 +00:00
|
|
|
class TrackList final : public wxEvtHandler, public ListOfTracks
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2016-12-17 15:05:15 +00:00
|
|
|
// privatize this, make you use Swap instead:
|
|
|
|
using ListOfTracks::swap;
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
// Create an empty TrackList
|
2016-03-13 14:34:44 +00:00
|
|
|
TrackList();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2017-07-15 01:47:47 +00:00
|
|
|
TrackList(const TrackList &that) = delete;
|
2018-01-15 02:27:41 +00:00
|
|
|
TrackList(TrackList &&that) = delete;
|
2017-07-15 01:47:47 +00:00
|
|
|
|
2017-07-15 02:30:02 +00:00
|
|
|
void clear() = delete;
|
|
|
|
|
2017-07-15 01:47:47 +00:00
|
|
|
public:
|
|
|
|
// Create an empty TrackList
|
|
|
|
static std::shared_ptr<TrackList> Create();
|
|
|
|
|
2018-01-15 02:27:41 +00:00
|
|
|
// Allow copy -- a deep copy that duplicates all tracks
|
|
|
|
TrackList &operator= (const TrackList &that);
|
|
|
|
|
|
|
|
// Allow move
|
|
|
|
TrackList& operator= (TrackList&&);
|
|
|
|
|
2016-03-07 11:43:42 +00:00
|
|
|
// Move is defined in terms of Swap
|
|
|
|
void Swap(TrackList &that);
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
// Destructor
|
|
|
|
virtual ~TrackList();
|
|
|
|
|
2018-01-14 19:01:04 +00:00
|
|
|
// Hide the inherited begin() and end()
|
|
|
|
using iterator = TrackListIterator;
|
|
|
|
using const_iterator = TrackListConstIterator;
|
|
|
|
using value_type = Track *;
|
|
|
|
iterator begin() { return iterator{ this, ListOfTracks::begin() }; }
|
|
|
|
iterator end() { return {}; }
|
|
|
|
const_iterator begin() const { return const_iterator{ this }; }
|
|
|
|
const_iterator end() const { return {}; }
|
|
|
|
const_iterator cbegin() const { return begin(); }
|
|
|
|
const_iterator cend() const { return end(); }
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
friend class Track;
|
|
|
|
friend class TrackListIterator;
|
2016-03-01 23:31:51 +00:00
|
|
|
friend class SyncLockedTracksIterator;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-03-01 22:34:45 +00:00
|
|
|
/// For use in sorting: assume each iterator points into this list, no duplications
|
|
|
|
void Permute(const std::vector<TrackNodePointer> &permutation);
|
|
|
|
|
2018-01-11 00:28:16 +00:00
|
|
|
Track *FindById( TrackId id );
|
|
|
|
|
|
|
|
/// Add a Track, giving it a fresh id
|
2016-03-13 15:08:21 +00:00
|
|
|
template<typename TrackKind>
|
|
|
|
Track *Add(std::unique_ptr<TrackKind> &&t);
|
2018-01-11 00:28:16 +00:00
|
|
|
|
|
|
|
/// Add a Track, giving it a fresh id
|
2016-03-13 15:08:21 +00:00
|
|
|
template<typename TrackKind>
|
|
|
|
Track *AddToHead(std::unique_ptr<TrackKind> &&t);
|
|
|
|
|
2018-01-11 00:28:16 +00:00
|
|
|
/// Add a Track, giving it a fresh id
|
2016-03-13 15:08:21 +00:00
|
|
|
template<typename TrackKind>
|
|
|
|
Track *Add(std::shared_ptr<TrackKind> &&t);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-03-13 15:08:21 +00:00
|
|
|
/// Replace first track with second track, give back a holder
|
2018-01-11 00:28:16 +00:00
|
|
|
/// Give the replacement the same id as the replaced
|
2018-01-14 19:01:04 +00:00
|
|
|
ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2014-06-03 20:30:19 +00:00
|
|
|
/// Remove this Track or all children of this TrackList.
|
2016-03-01 23:31:51 +00:00
|
|
|
/// Return an iterator to what followed the removed track.
|
2016-03-01 21:28:59 +00:00
|
|
|
TrackNodePointer Remove(Track *t);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
/// Make the list empty
|
2016-06-28 03:38:42 +00:00
|
|
|
void Clear(bool sendEvent = true);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
/** Select a track, and if it is linked to another track, select it, too. */
|
|
|
|
void Select(Track * t, bool selected = true);
|
|
|
|
|
|
|
|
Track *GetPrev(Track * t, bool linked = false) const;
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2011-04-17 23:54:30 +00:00
|
|
|
/** Return a track in the list that comes after Track t
|
|
|
|
* @param t a track in the list
|
|
|
|
* @param linked if true, skips over linked tracks, if false returns the next track even if it is a linked track
|
|
|
|
**/
|
2010-01-23 19:44:49 +00:00
|
|
|
Track *GetNext(Track * t, bool linked = false) const;
|
|
|
|
int GetGroupHeight(Track * t) const;
|
|
|
|
|
|
|
|
bool CanMoveUp(Track * t) const;
|
|
|
|
bool CanMoveDown(Track * t) const;
|
|
|
|
|
|
|
|
bool MoveUp(Track * t);
|
|
|
|
bool MoveDown(Track * t);
|
|
|
|
bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
|
|
|
|
|
|
|
|
TimeTrack *GetTimeTrack();
|
2016-02-26 23:10:45 +00:00
|
|
|
const TimeTrack *GetTimeTrack() const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
/** \brief Find out how many channels this track list mixes to
|
|
|
|
*
|
2014-06-03 20:30:19 +00:00
|
|
|
* This is used in exports of the tracks to work out whether to export in
|
2010-01-23 19:44:49 +00:00
|
|
|
* Mono, Stereo etc. @param selectionOnly Whether to consider the entire track
|
|
|
|
* list or only the selected members of it
|
|
|
|
*/
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned GetNumExportChannels(bool selectionOnly) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-02-26 23:10:45 +00:00
|
|
|
WaveTrackArray GetWaveTrackArray(bool selectionOnly, bool includeMuted = true);
|
|
|
|
WaveTrackConstArray GetWaveTrackConstArray(bool selectionOnly, bool includeMuted = true) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
#if defined(USE_MIDI)
|
|
|
|
NoteTrackArray GetNoteTrackArray(bool selectionOnly);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/// Mainly a test function. Uses a linear search, so could be slow.
|
2016-05-22 03:19:09 +00:00
|
|
|
bool Contains(const Track * t) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2017-06-28 04:31:18 +00:00
|
|
|
// Return non-null only if the weak pointer is not, and the track is
|
|
|
|
// owned by this list; constant time.
|
|
|
|
template <typename Subclass>
|
|
|
|
std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
|
|
|
|
{
|
|
|
|
auto pTrack = wTrack.lock();
|
2017-07-10 15:53:23 +00:00
|
|
|
if (pTrack) {
|
|
|
|
auto pList = pTrack->mList.lock();
|
|
|
|
if (pTrack && this == pList.get())
|
|
|
|
return pTrack;
|
|
|
|
}
|
2017-06-28 04:31:18 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-01-14 21:55:49 +00:00
|
|
|
bool empty() const;
|
|
|
|
size_t size() const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
double GetStartTime() const;
|
|
|
|
double GetEndTime() const;
|
|
|
|
|
|
|
|
double GetMinOffset() const;
|
|
|
|
int GetHeight() const;
|
|
|
|
|
2014-06-03 20:30:19 +00:00
|
|
|
#if LEGACY_PROJECT_FILE_SUPPORT
|
2010-01-23 19:44:49 +00:00
|
|
|
// File I/O
|
2016-02-24 06:06:47 +00:00
|
|
|
bool Load(wxTextFile * in, DirManager * dirManager) override;
|
|
|
|
bool Save(wxTextFile * out, bool overwrite) override;
|
2010-01-23 19:44:49 +00:00
|
|
|
#endif
|
|
|
|
|
2016-03-01 23:31:51 +00:00
|
|
|
private:
|
|
|
|
bool isNull(TrackNodePointer p) const
|
2017-08-24 18:31:51 +00:00
|
|
|
{ return p == ListOfTracks::end()
|
|
|
|
|| p == mPendingUpdates.end(); }
|
2018-01-13 01:17:30 +00:00
|
|
|
TrackNodePointer getEnd() const
|
|
|
|
{ return const_cast<TrackList*>(this)->ListOfTracks::end(); }
|
|
|
|
TrackNodePointer getBegin() const
|
|
|
|
{ return const_cast<TrackList*>(this)->ListOfTracks::begin(); }
|
|
|
|
|
|
|
|
// Move an iterator to the next node, if any; else stay at end
|
|
|
|
TrackNodePointer getNext(TrackNodePointer p) const
|
|
|
|
{
|
|
|
|
if ( isNull(p) )
|
|
|
|
return p;
|
|
|
|
auto q = p;
|
|
|
|
return ++q;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move an iterator to the previous node, if any; else wrap to end
|
|
|
|
TrackNodePointer getPrev(TrackNodePointer p) const
|
|
|
|
{
|
|
|
|
if (p == this->ListOfTracks::begin())
|
|
|
|
return getEnd();
|
|
|
|
else {
|
|
|
|
auto q = p;
|
|
|
|
return --q;
|
|
|
|
}
|
|
|
|
}
|
2016-03-01 23:31:51 +00:00
|
|
|
|
2018-01-15 02:27:41 +00:00
|
|
|
void DoAssign(const TrackList &that);
|
|
|
|
|
2016-03-01 23:31:51 +00:00
|
|
|
void RecalcPositions(TrackNodePointer node);
|
2017-06-26 17:40:19 +00:00
|
|
|
void PermutationEvent();
|
2017-06-25 05:33:31 +00:00
|
|
|
void DeletionEvent();
|
|
|
|
void ResizingEvent(TrackNodePointer node);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-03-01 23:31:51 +00:00
|
|
|
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
|
2017-07-10 15:48:11 +00:00
|
|
|
|
|
|
|
std::weak_ptr<TrackList> mSelf;
|
2018-01-11 00:28:16 +00:00
|
|
|
|
|
|
|
// Nondecreasing during the session.
|
|
|
|
// Nonpersistent.
|
|
|
|
// Used to assign ids to added tracks.
|
|
|
|
static long sCounter;
|
2017-08-24 18:31:51 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
using Updater = std::function< void(Track &dest, const Track &src) >;
|
|
|
|
// Start a deferred update of the project.
|
|
|
|
// The return value is a duplicate of the given track.
|
|
|
|
// While ApplyPendingTracks or ClearPendingTracks is not yet called,
|
|
|
|
// there may be other direct changes to the project that push undo history.
|
|
|
|
// Meanwhile the returned object can accumulate other changes for a deferred
|
|
|
|
// push, and temporarily shadow the actual project track for display purposes.
|
|
|
|
// The Updater function, if not null, merges state (from the actual project
|
|
|
|
// into the pending track) which is not meant to be overridden by the
|
|
|
|
// accumulated pending changes.
|
|
|
|
// To keep the display consistent, the Y and Height values, minimized state,
|
|
|
|
// and Linked state must be copied, and this will be done even if the
|
|
|
|
// Updater does not do it.
|
|
|
|
// Pending track will have the same TrackId as the actual.
|
|
|
|
// Pending changed tracks will not occur in iterations.
|
|
|
|
std::shared_ptr<Track> RegisterPendingChangedTrack(
|
|
|
|
Updater updater,
|
|
|
|
Track *src
|
|
|
|
);
|
|
|
|
|
|
|
|
// Like the previous, but for a NEW track, not a replacement track. Caller
|
|
|
|
// supplies the track, and there are no updates.
|
|
|
|
// Pending track will have an unassigned TrackId.
|
|
|
|
// Pending changed tracks WILL occur in iterations, always after actual
|
|
|
|
// tracks, and in the sequence that they were added. They can be
|
|
|
|
// distinguished from actual tracks by TrackId.
|
|
|
|
void RegisterPendingNewTrack( const std::shared_ptr<Track> &pTrack );
|
|
|
|
|
|
|
|
// Invoke the updaters of pending tracks. Pass any exceptions from the
|
|
|
|
// updater functions.
|
|
|
|
void UpdatePendingTracks();
|
|
|
|
|
|
|
|
// Forget pending track additions and changes;
|
|
|
|
// if requested, give back the pending added tracks.
|
|
|
|
void ClearPendingTracks( ListOfTracks *pAdded = nullptr );
|
|
|
|
|
|
|
|
// Change the state of the project.
|
|
|
|
// Strong guarantee for project state in case of exceptions.
|
|
|
|
// Will always clear the pending updates.
|
|
|
|
// Return true if the state of the track list really did change.
|
|
|
|
bool ApplyPendingTracks();
|
|
|
|
|
|
|
|
// Find anything registered with RegisterPendingChangedTrack and not yet
|
|
|
|
// cleared or applied
|
|
|
|
std::shared_ptr<Track> FindPendingChangedTrack(TrackId id) const;
|
|
|
|
|
|
|
|
bool HasPendingTracks() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Need to put pending tracks into a list so that GetLink() works
|
|
|
|
ListOfTracks mPendingUpdates;
|
|
|
|
// This is in correspondence with mPendingUpdates
|
|
|
|
std::vector< Updater > mUpdaters;
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class AUDACITY_DLL_API TrackFactory
|
|
|
|
{
|
|
|
|
private:
|
2016-08-13 04:38:31 +00:00
|
|
|
TrackFactory(const std::shared_ptr<DirManager> &dirManager, const ZoomInfo *zoomInfo):
|
2010-01-23 19:44:49 +00:00
|
|
|
mDirManager(dirManager)
|
2016-01-26 22:37:16 +00:00
|
|
|
, mZoomInfo(zoomInfo)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-08-13 04:38:31 +00:00
|
|
|
const std::shared_ptr<DirManager> mDirManager;
|
2016-01-26 22:37:16 +00:00
|
|
|
const ZoomInfo *const mZoomInfo;
|
2010-01-23 19:44:49 +00:00
|
|
|
friend class AudacityProject;
|
|
|
|
friend class BenchmarkDialog;
|
|
|
|
|
|
|
|
public:
|
|
|
|
// These methods are defined in WaveTrack.cpp, NoteTrack.cpp,
|
|
|
|
// LabelTrack.cpp, and TimeTrack.cpp respectively
|
2017-02-22 19:23:35 +00:00
|
|
|
std::unique_ptr<WaveTrack> DuplicateWaveTrack(const WaveTrack &orig);
|
2016-03-02 19:59:31 +00:00
|
|
|
std::unique_ptr<WaveTrack> NewWaveTrack(sampleFormat format = (sampleFormat)0,
|
2010-01-23 19:44:49 +00:00
|
|
|
double rate = 0);
|
2016-03-02 19:59:31 +00:00
|
|
|
std::unique_ptr<LabelTrack> NewLabelTrack();
|
|
|
|
std::unique_ptr<TimeTrack> NewTimeTrack();
|
2010-01-23 19:44:49 +00:00
|
|
|
#if defined(USE_MIDI)
|
2016-03-02 19:59:31 +00:00
|
|
|
std::unique_ptr<NoteTrack> NewNoteTrack();
|
2010-01-23 19:44:49 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|