-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2805 from Paul-Licameli/Non-display-channel-group…
…-data Non display channel group data Move many things into ChannelGropuAttachments, so they are not duplicated between channels. This simplifies code that formerly had to maintain consistency of channels. There are fewer uses of TrackList::Channels and fewer iterations over all tracks when iteration over leaders only is enough. Remove some other calls to TrackList::Channels() that were needed only to count the channels. Also fixes an issue related to correctness of Mute and Solo settings when copying and pasting or duplicating MIDI or audio tracks. Also a new small library lib-playable-track to lift the mute and solo logic out of lib-track.
- Loading branch information
Showing
60 changed files
with
741 additions
and
753 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,7 @@ set( LIBRARIES | |
lib-lv2 | ||
lib-ladspa | ||
lib-audio-unit | ||
lib-playable-track | ||
) | ||
|
||
if ( ${_OPT}has_networking ) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#[[ | ||
Extends Track with subclasses defining the notions of mute and solo. | ||
]] | ||
|
||
set( SOURCES | ||
PlayableTrack.cpp | ||
PlayableTrack.h | ||
) | ||
set( LIBRARIES | ||
lib-track-interface | ||
) | ||
audacity_library( lib-playable-track "${SOURCES}" "${LIBRARIES}" | ||
"" "" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/*!******************************************************************** | ||
Audacity: A Digital Audio Editor | ||
PlayableTrack.cpp | ||
Dominic Mazzoni | ||
Paul Licameli split from Track.cpp | ||
*******************************************************************//** | ||
\class AudioTrack | ||
\brief A Track that can load/save audio data to/from XML. | ||
\class PlayableTrack | ||
\brief An AudioTrack that can be played and stopped. | ||
*//*******************************************************************/ | ||
#include "PlayableTrack.h" | ||
|
||
namespace { | ||
struct MuteAndSolo : ClientData::Cloneable<> { | ||
MuteAndSolo() = default; | ||
MuteAndSolo(const MuteAndSolo &); | ||
MuteAndSolo& operator=(const MuteAndSolo &) = delete; | ||
~MuteAndSolo() override; | ||
std::unique_ptr<ClientData::Cloneable<>> Clone() const override; | ||
|
||
static MuteAndSolo &Get(PlayableTrack &track); | ||
static const MuteAndSolo &Get(const PlayableTrack &track); | ||
|
||
bool GetMute() const; | ||
void SetMute(bool value); | ||
bool GetSolo() const; | ||
void SetSolo(bool value); | ||
|
||
private: | ||
//! Atomic because it may be read by worker threads in playback | ||
std::atomic<bool> mMute{ false }; | ||
//! Atomic because it may be read by worker threads in playback | ||
std::atomic<bool> mSolo{ false }; | ||
}; | ||
|
||
static const Track::ChannelGroupAttachments::RegisteredFactory | ||
muteAndSoloFactory{ [](auto &) { return std::make_unique<MuteAndSolo>(); } }; | ||
|
||
//! Copy can't be generated by default because of mutable members | ||
MuteAndSolo::MuteAndSolo(const MuteAndSolo &other) { | ||
SetMute(other.GetMute()); | ||
SetSolo(other.GetSolo()); | ||
} | ||
|
||
MuteAndSolo::~MuteAndSolo() = default; | ||
|
||
std::unique_ptr<ClientData::Cloneable<>> MuteAndSolo::Clone() const { | ||
return std::make_unique<MuteAndSolo>(*this); | ||
} | ||
|
||
MuteAndSolo &MuteAndSolo::Get(PlayableTrack &track) { | ||
return track.GetGroupData().Track::ChannelGroupAttachments | ||
::Get<MuteAndSolo>(muteAndSoloFactory); | ||
} | ||
|
||
const MuteAndSolo &MuteAndSolo::Get(const PlayableTrack &track) | ||
{ | ||
return Get(const_cast<PlayableTrack &>(track)); | ||
} | ||
|
||
bool MuteAndSolo::GetMute() const | ||
{ | ||
return mMute.load(std::memory_order_relaxed); | ||
} | ||
|
||
void MuteAndSolo::SetMute(bool value) | ||
{ | ||
mMute.store(value, std::memory_order_relaxed); | ||
} | ||
|
||
bool MuteAndSolo::GetSolo() const | ||
{ | ||
return mSolo.load(std::memory_order_relaxed); | ||
} | ||
|
||
void MuteAndSolo::SetSolo(bool value) | ||
{ | ||
mSolo.store(value, std::memory_order_relaxed); | ||
} | ||
} | ||
|
||
|
||
AudioTrack::AudioTrack() : Track{} | ||
{ | ||
} | ||
|
||
AudioTrack::AudioTrack(const Track &orig, ProtectedCreationArg &&a) | ||
: Track{ orig, std::move(a) } | ||
{ | ||
} | ||
|
||
PlayableTrack::PlayableTrack() : AudioTrack{} | ||
{ | ||
} | ||
|
||
PlayableTrack::PlayableTrack( | ||
const PlayableTrack &orig, ProtectedCreationArg &&a | ||
) : AudioTrack{ orig, std::move(a) } | ||
{ | ||
} | ||
|
||
void PlayableTrack::SetMute(bool m) | ||
{ | ||
if (DoGetMute() != m) { | ||
DoSetMute(m); | ||
Notify(true); | ||
} | ||
} | ||
|
||
void PlayableTrack::SetSolo(bool s) | ||
{ | ||
if (DoGetSolo() != s) { | ||
DoSetSolo(s); | ||
Notify(true); | ||
} | ||
} | ||
|
||
bool PlayableTrack::DoGetMute() const | ||
{ | ||
return MuteAndSolo::Get(*this).GetMute(); | ||
} | ||
|
||
void PlayableTrack::DoSetMute(bool value) | ||
{ | ||
MuteAndSolo::Get(*this).SetMute(value); | ||
} | ||
|
||
bool PlayableTrack::DoGetSolo() const | ||
{ | ||
return MuteAndSolo::Get(*this).GetSolo(); | ||
} | ||
|
||
void PlayableTrack::DoSetSolo(bool value) | ||
{ | ||
MuteAndSolo::Get(*this).SetSolo(value); | ||
} | ||
|
||
// Serialize, not with tags of its own, but as attributes within a tag. | ||
void PlayableTrack::WriteXMLAttributes(XMLWriter &xmlFile) const | ||
{ | ||
xmlFile.WriteAttr(wxT("mute"), DoGetMute()); | ||
xmlFile.WriteAttr(wxT("solo"), DoGetSolo()); | ||
AudioTrack::WriteXMLAttributes(xmlFile); | ||
} | ||
|
||
// Return true iff the attribute is recognized. | ||
bool PlayableTrack::HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &value) | ||
{ | ||
long nValue; | ||
|
||
if (attr == "mute" && value.TryGet(nValue)) { | ||
DoSetMute(nValue != 0); | ||
return true; | ||
} | ||
else if (attr == "solo" && value.TryGet(nValue)) { | ||
DoSetSolo(nValue != 0); | ||
return true; | ||
} | ||
|
||
return AudioTrack::HandleXMLAttribute(attr, value); | ||
} | ||
|
||
auto AudioTrack::ClassTypeInfo() -> const TypeInfo & | ||
{ | ||
static Track::TypeInfo info{ | ||
{ "audio", "audio", XO("Audio Track") }, | ||
false, &Track::ClassTypeInfo() }; | ||
return info; | ||
} | ||
|
||
auto PlayableTrack::ClassTypeInfo() -> const TypeInfo & | ||
{ | ||
static Track::TypeInfo info{ | ||
{ "playable", "playable", XO("Playable Track") }, | ||
false, &AudioTrack::ClassTypeInfo() }; | ||
return info; | ||
} | ||
|
||
EnumSetting<SoloBehavior> TracksBehaviorsSolo{ | ||
wxT("/GUI/Solo"), | ||
{ | ||
ByColumns, | ||
{ XO("Simple"), XO("Multi-track"), XO("None") }, | ||
{ wxT("Simple"), wxT("Multi"), wxT("None") } | ||
}, | ||
0, // "Simple" | ||
{ SoloBehaviorSimple, SoloBehaviorMulti, SoloBehaviorNone }, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/*!******************************************************************** | ||
Audacity: A Digital Audio Editor | ||
@file PlayableTrack.h | ||
@brief Extends Track with notions of mute and solo setting | ||
Dominic Mazzoni | ||
Paul Licameli split from Track.h | ||
**********************************************************************/ | ||
#ifndef __AUDACITY_PLAYABLE_TRACK__ | ||
#define __AUDACITY_PLAYABLE_TRACK__ | ||
|
||
#include "Prefs.h" | ||
#include "Track.h" | ||
|
||
//! Track subclass holding data representing sound (as notes, or samples, or ...) | ||
class PLAYABLE_TRACK_API AudioTrack /* not final */ : public Track | ||
{ | ||
public: | ||
AudioTrack(); | ||
AudioTrack(const Track &orig, ProtectedCreationArg &&a); | ||
|
||
static const TypeInfo &ClassTypeInfo(); | ||
|
||
// Serialize, not with tags of its own, but as attributes within a tag. | ||
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const {} | ||
|
||
// Return true iff the attribute is recognized. | ||
bool HandleXMLAttribute(const std::string_view & /*attr*/, const XMLAttributeValueView &/*value*/) | ||
{ return false; } | ||
}; | ||
|
||
ENUMERATE_TRACK_TYPE(AudioTrack); | ||
|
||
//! AudioTrack subclass that can also be audibly replayed by the program | ||
class PLAYABLE_TRACK_API PlayableTrack /* not final */ : public AudioTrack | ||
{ | ||
public: | ||
PlayableTrack(); | ||
PlayableTrack(const PlayableTrack &orig, ProtectedCreationArg&&); | ||
|
||
static const TypeInfo &ClassTypeInfo(); | ||
|
||
bool GetMute () const { return DoGetMute(); } | ||
bool GetSolo () const { return DoGetSolo(); } | ||
bool GetNotMute () const { return !DoGetMute(); } | ||
bool GetNotSolo () const { return !DoGetSolo(); } | ||
void SetMute (bool m); | ||
void SetSolo (bool s); | ||
|
||
// 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 std::string_view &attr, const XMLAttributeValueView &value); | ||
|
||
protected: | ||
bool DoGetMute() const; | ||
void DoSetMute(bool value); | ||
bool DoGetSolo() const; | ||
void DoSetSolo(bool value); | ||
}; | ||
|
||
ENUMERATE_TRACK_TYPE(PlayableTrack); | ||
|
||
enum SoloBehavior { | ||
SoloBehaviorSimple, | ||
SoloBehaviorMulti, | ||
SoloBehaviorNone, | ||
}; | ||
|
||
extern PLAYABLE_TRACK_API EnumSetting<SoloBehavior> TracksBehaviorsSolo; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.