Audacity  3.0.3
TrackUtilities.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  TrackUtilities.cpp
6 
7  Paul Licameli split from TrackMenus.cpp
8 
9  **********************************************************************/
10 
11 #include "TrackUtilities.h"
12 
13 #include "ProjectHistory.h"
14 #include "ProjectSettings.h"
15 #include "ProjectWindow.h"
16 #include "Track.h"
17 #include "TrackPanelAx.h"
18 #include "TrackPanel.h"
19 
20 namespace TrackUtilities {
21 
23 {
24  auto &tracks = TrackList::Get( project );
25  auto &trackPanel = TrackPanel::Get( project );
26 
27  std::vector<Track*> toRemove;
28  for (auto track : tracks.Selected())
29  toRemove.push_back(track);
30 
31  // Capture the track preceding the first removed track
32  Track *f{};
33  if (!toRemove.empty()) {
34  auto found = tracks.Find(toRemove[0]);
35  f = *--found;
36  }
37 
38  for (auto track : toRemove)
39  tracks.Remove(track);
40 
41  if (!f)
42  // try to use the last track
43  f = *tracks.Any().rbegin();
44  if (f) {
45  // Try to use the first track after the removal
46  auto found = tracks.FindLeader(f);
47  auto t = *++found;
48  if (t)
49  f = t;
50  }
51 
52  // If we actually have something left, then set focus and make sure it's seen
53  if (f) {
54  TrackFocus::Get(project).Set(f);
55  f->EnsureVisible();
56  }
57 
58  ProjectHistory::Get( project )
59  .PushState(XO("Removed audio track(s)"), XO("Remove Track"));
60 
61  trackPanel.UpdateViewIfNoTracks();
62 }
63 
64 void DoTrackMute(AudacityProject &project, Track *t, bool exclusive)
65 {
66  const auto &settings = ProjectSettings::Get( project );
67  auto &tracks = TrackList::Get( project );
68 
69  // Whatever t is, replace with lead channel
70  t = *tracks.FindLeader(t);
71 
72  // "exclusive" mute means mute the chosen track and unmute all others.
73  if (exclusive) {
74  for (auto leader : tracks.Leaders<PlayableTrack>()) {
75  const auto group = TrackList::Channels(leader);
76  bool chosen = (t == leader);
77  for (auto channel : group)
78  channel->SetMute( chosen ),
79  channel->SetSolo( false );
80  }
81  }
82  else {
83  // Normal click toggles this track.
84  auto pt = dynamic_cast<PlayableTrack *>( t );
85  if (!pt)
86  return;
87 
88  bool wasMute = pt->GetMute();
89  for (auto channel : TrackList::Channels(pt))
90  channel->SetMute( !wasMute );
91 
92  if (settings.IsSoloSimple() || settings.IsSoloNone())
93  {
94  // We also set a solo indicator if we have just one track / stereo pair playing.
95  // in a group of more than one playable tracks.
96  // otherwise clear solo on everything.
97 
98  auto range = tracks.Leaders<PlayableTrack>();
99  auto nPlayableTracks = range.size();
100  auto nPlaying = (range - &PlayableTrack::GetMute).size();
101 
102  for (auto track : tracks.Any<PlayableTrack>())
103  // will set both of a stereo pair
104  track->SetSolo( (nPlaying==1) && (nPlayableTracks > 1 ) && !track->GetMute() );
105  }
106  }
107  ProjectHistory::Get( project ).ModifyState(true);
108 
109  TrackFocus::Get( project ).UpdateAccessibility();
110 }
111 
112 void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive)
113 {
114  const auto &settings = ProjectSettings::Get( project );
115  auto &tracks = TrackList::Get( project );
116 
117  // Whatever t is, replace with lead channel
118  t = *tracks.FindLeader(t);
119 
120  const auto pt = dynamic_cast<PlayableTrack *>( t );
121  if (!pt)
122  return;
123  bool bWasSolo = pt->GetSolo();
124 
125  bool bSoloMultiple = !settings.IsSoloSimple() ^ exclusive;
126 
127  // Standard and Simple solo have opposite defaults:
128  // Standard - Behaves as individual buttons, shift=radio buttons
129  // Simple - Behaves as radio buttons, shift=individual
130  // In addition, Simple solo will mute/unmute tracks
131  // when in standard radio button mode.
132  if ( bSoloMultiple )
133  {
134  for (auto channel : TrackList::Channels(pt))
135  channel->SetSolo( !bWasSolo );
136  }
137  else
138  {
139  // Normal click solo this track only, mute everything else.
140  // OR unmute and unsolo everything.
141  for (auto leader : tracks.Leaders<PlayableTrack>()) {
142  const auto group = TrackList::Channels(leader);
143  bool chosen = (t == leader);
144  for (auto channel : group) {
145  if (chosen) {
146  channel->SetSolo( !bWasSolo );
147  if( settings.IsSoloSimple() )
148  channel->SetMute( false );
149  }
150  else {
151  channel->SetSolo( false );
152  if( settings.IsSoloSimple() )
153  channel->SetMute( !bWasSolo );
154  }
155  }
156  }
157  }
158  ProjectHistory::Get( project ).ModifyState(true);
159 
160  TrackFocus::Get( project ).UpdateAccessibility();
161 }
162 
163 void DoRemoveTrack(AudacityProject &project, Track * toRemove)
164 {
165  auto &tracks = TrackList::Get( project );
166  auto &trackFocus = TrackFocus::Get( project );
167  auto &window = ProjectWindow::Get( project );
168 
169  // If it was focused, then NEW focus is the next or, if
170  // unavailable, the previous track. (The NEW focus is set
171  // after the track has been removed.)
172  bool toRemoveWasFocused = trackFocus.Get() == toRemove;
173  Track* newFocus{};
174  if (toRemoveWasFocused) {
175  auto iterNext = tracks.FindLeader(toRemove), iterPrev = iterNext;
176  newFocus = *++iterNext;
177  if (!newFocus) {
178  newFocus = *--iterPrev;
179  }
180  }
181 
182  wxString name = toRemove->GetName();
183 
184  auto channels = TrackList::Channels(toRemove);
185  // Be careful to post-increment over positions that get erased!
186  auto &iter = channels.first;
187  while (iter != channels.end())
188  tracks.Remove( * iter++ );
189 
190  if (toRemoveWasFocused)
191  trackFocus.Set( newFocus );
192 
193  ProjectHistory::Get( project ).PushState(
194  XO("Removed track '%s.'").Format( name ),
195  XO("Track Remove"));
196 }
197 
199 (AudacityProject &project, Track* target, MoveChoice choice)
200 {
201  auto &tracks = TrackList::Get( project );
202 
203  TranslatableString longDesc, shortDesc;
204 
205  switch (choice)
206  {
207  case OnMoveTopID:
208  /* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
209  longDesc = XO("Moved '%s' to Top");
210  shortDesc = XO("Move Track to Top");
211 
212  // TODO: write TrackList::Rotate to do this in one step and avoid emitting
213  // an event for each swap
214  while (tracks.CanMoveUp(target))
215  tracks.Move(target, true);
216 
217  break;
218  case OnMoveBottomID:
219  /* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
220  longDesc = XO("Moved '%s' to Bottom");
221  shortDesc = XO("Move Track to Bottom");
222 
223  // TODO: write TrackList::Rotate to do this in one step and avoid emitting
224  // an event for each swap
225  while (tracks.CanMoveDown(target))
226  tracks.Move(target, false);
227 
228  break;
229  default:
230  bool bUp = (OnMoveUpID == choice);
231 
232  tracks.Move(target, bUp);
233  longDesc =
234  /* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
235  bUp? XO("Moved '%s' Up")
236  : XO("Moved '%s' Down");
237  shortDesc =
238  /* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
239  bUp? XO("Move Track Up")
240  : XO("Move Track Down");
241 
242  }
243 
244  longDesc.Format(target->GetName());
245 
246  ProjectHistory::Get( project ).PushState(longDesc, shortDesc);
247 }
248 
249 }
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
PlayableTrack::GetSolo
bool GetSolo() const
Definition: Track.h:861
PlayableTrack::GetMute
bool GetMute() const
Definition: Track.h:860
ClientData::Site::Find
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Definition: ClientData.h:333
Track::GetName
wxString GetName() const
Definition: Track.h:426
Track::EnsureVisible
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:100
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1484
Format
Abstract base class used in importing a file.
TrackPanel.h
TrackPanelAx.h
TrackPanel::Get
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:227
XO
#define XO(s)
Definition: Internat.h:31
ClientData::Site::size
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:251
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:44
ProjectSettings.h
ProjectWindow::Get
static ProjectWindow & Get(AudacityProject &project)
Definition: ProjectWindow.cpp:535
TrackUtilities::DoTrackSolo
void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive)
Definition: TrackUtilities.cpp:112
TrackUtilities::MoveChoice
MoveChoice
Definition: TrackUtilities.h:19
TrackUtilities.h
name
const TranslatableString name
Definition: Distortion.cpp:98
TrackUtilities::OnMoveTopID
@ OnMoveTopID
Definition: TrackUtilities.h:20
TrackFocus::Get
Track * Get()
Definition: TrackPanelAx.cpp:755
PlayableTrack
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:854
TrackUtilities::DoRemoveTracks
void DoRemoveTracks(AudacityProject &project)
Definition: TrackUtilities.cpp:22
ProjectHistory::PushState
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
Definition: ProjectHistory.cpp:90
TrackUtilities::DoRemoveTrack
void DoRemoveTrack(AudacityProject &project, Track *toRemove)
Definition: TrackUtilities.cpp:163
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
TrackUtilities::DoTrackMute
void DoTrackMute(AudacityProject &project, Track *t, bool exclusive)
Definition: TrackUtilities.cpp:64
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
TrackUtilities::OnMoveBottomID
@ OnMoveBottomID
Definition: TrackUtilities.h:20
ProjectHistory.h
TrackUtilities::OnMoveUpID
@ OnMoveUpID
Definition: TrackUtilities.h:20
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
TrackUtilities
Definition: TrackUtilities.cpp:20
ProjectWindow.h
TranslatableString::Format
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
Definition: TranslatableString.h:103
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
TrackUtilities::DoMoveTrack
void DoMoveTrack(AudacityProject &project, Track *target, MoveChoice choice)
Move a track up, down, to top or to bottom.
Definition: TrackUtilities.cpp:199
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26