Audacity 3.2.0
TrackMenus.cpp
Go to the documentation of this file.
1#include "../CommonCommandFlags.h"
2#include "../LabelTrack.h"
3#include "../Menus.h"
4#include "MixAndRender.h"
5
6#include "Prefs.h"
7#include "Project.h"
8#include "ProjectAudioIO.h"
9#include "ProjectHistory.h"
10#include "ProjectRate.h"
11#include "../ProjectSettings.h"
12#include "PluginManager.h"
13#include "ProjectStatus.h"
14#include "../ProjectWindow.h"
15#include "../SelectUtilities.h"
16#include "ShuttleGui.h"
17#include "SyncLock.h"
18#include "../TrackPanelAx.h"
19#include "../TrackPanel.h"
20#include "../TrackUtilities.h"
21#include "UndoManager.h"
22#include "WaveClip.h"
23#include "ViewInfo.h"
24#include "WaveTrack.h"
25#include "../commands/CommandContext.h"
26#include "../commands/CommandManager.h"
27#include "../effects/EffectManager.h"
28#include "../effects/EffectUI.h"
29#include "QualitySettings.h"
30#include "../tracks/playabletrack/wavetrack/ui/WaveTrackControls.h"
31#include "../toolbars/ToolManager.h"
32#include "../widgets/ASlider.h"
33#include "AudacityMessageBox.h"
34#include "ProgressDialog.h"
35
36#include <wx/combobox.h>
37
38#ifdef EXPERIMENTAL_SCOREALIGN
39#include "../effects/ScoreAlignDialog.h"
40#include "audioreader.h"
41#include "scorealign.h"
42#include "scorealign-glue.h"
43#endif /* EXPERIMENTAL_SCOREALIGN */
44
45// private helper classes and functions
46namespace {
47
48void DoMixAndRender(AudacityProject &project, bool toNewTrack)
49{
51 auto &trackFactory = WaveTrackFactory::Get(project);
52 auto rate = ProjectRate::Get(project).GetRate();
53 auto defaultFormat = QualitySettings::SampleFormatChoice();
54 auto &trackPanel = TrackPanel::Get(project);
55 auto &window = ProjectWindow::Get(project);
56
57 auto trackRange = tracks.Selected<WaveTrack>();
58 auto newTracks = ::MixAndRender(trackRange.Filter<const WaveTrack>(),
59 Mixer::WarpOptions{ tracks.GetOwner() },
60 tracks.MakeUniqueTrackName(_("Mix")),
61 &trackFactory, rate, defaultFormat, 0.0, 0.0);
62
63 if (newTracks) {
64 // Remove originals, get stats on what tracks were mixed
65
66 // But before removing, determine the first track after the removal
67 auto last = *trackRange.rbegin();
68 auto insertionPoint = * ++ tracks.Find(last);
69
70 auto selectedCount = trackRange.size();
71 wxString firstName;
72 int firstColour = -1;
73 if (selectedCount > 0) {
74 firstName = (*trackRange.begin())->GetName();
75 firstColour = (*trackRange.begin())->GetWaveColorIndex();
76 }
77 if (!toNewTrack) {
78 // Beware iterator invalidation!
79 while (!trackRange.empty())
80 // Range iterates over leaders only
81 tracks.Remove(**trackRange.first++);
82 }
83
84 // Add new tracks
85 const bool stereo = newTracks->NChannels() > 1;
86 tracks.Append(std::move(*newTracks));
87 const auto pNewTrack = *tracks.Any<WaveTrack>().rbegin();
88
89 // If we're just rendering (not mixing), keep the track name the same
90 if (selectedCount == 1)
91 pNewTrack->SetName(firstName);
92
93 // Bug 2218, remember more things...
94 if (selectedCount >= 1) {
95 pNewTrack->SetSelected(!toNewTrack);
96 pNewTrack->SetWaveColorIndex(firstColour);
97 }
98
99 // Permute the tracks as needed
100 // The new track appears after the old tracks (or where the old tracks
101 // had been) so that they are in the same sync-lock group
102 if (insertionPoint) {
103 std::vector<Track *> arr;
104 arr.reserve(tracks.Size());
105 size_t iBegin = 0, ii = 0;
106 for (const auto pTrack : tracks) {
107 arr.push_back(pTrack);
108 if (pTrack == insertionPoint)
109 iBegin = ii;
110 ++ii;
111 }
112 const auto end = arr.end(),
113 mid = end - 1;
114 std::rotate(arr.begin() + iBegin, mid, end);
115 tracks.Permute(arr);
116 }
117
118 // Smart history/undo message
119 if (selectedCount==1) {
120 auto msg = XO("Rendered all audio in track '%s'").Format( firstName );
121 /* i18n-hint: Convert the audio into a more usable form, so apply
122 * panning and amplification and write to some external file.*/
123 ProjectHistory::Get( project ).PushState(msg, XO("Render"));
124 }
125 else {
126 auto msg = (stereo
127 ? XO("Mixed and rendered %d tracks into one new stereo track")
128 : XO("Mixed and rendered %d tracks into one new mono track")
129 )
130 .Format((int)selectedCount);
131 ProjectHistory::Get(project).PushState(msg, XO("Mix and Render"));
132 }
133
134 trackPanel.SetFocus();
135 TrackFocus::Get(project).Set(pNewTrack);
136 pNewTrack->EnsureVisible();
137 }
138}
139
140void DoPanTracks(AudacityProject &project, float PanValue)
141{
142 auto &tracks = TrackList::Get( project );
143 auto &window = ProjectWindow::Get( project );
144
145 // count selected wave tracks
146 const auto range = tracks.Any< WaveTrack >();
147 const auto selectedRange = range + &Track::IsSelected;
148 auto count = selectedRange.size();
149
150 // iter through them, all if none selected.
151 for (auto left : count == 0 ? range : selectedRange )
152 left->SetPan( PanValue );
153
154 auto flags = UndoPush::NONE;
156 /*i18n-hint: One or more audio tracks have been panned*/
157 .PushState(XO("Panned audio track(s)"), XO("Pan Track"), flags);
158 flags = flags | UndoPush::CONSOLIDATE;
159}
160
161enum {
167 // The next two are only in one subMenu, so more easily handled at the end.
171
172static const std::vector< ComponentInterfaceSymbol >
173&alignLabels() { static std::vector< ComponentInterfaceSymbol > symbols{
174 { wxT("StartToZero"), XXO("Start to &Zero") },
175 { wxT("StartToSelStart"), XXO("Start to &Cursor/Selection Start") },
176 { wxT("StartToSelEnd"), XXO("Start to Selection &End") },
177 { wxT("EndToSelStart"), XXO("End to Cu&rsor/Selection Start") },
178 { wxT("EndToSelEnd"), XXO("End to Selection En&d") },
179}; return symbols; }
180
181const size_t kAlignLabelsCount(){ return alignLabels().size(); }
182
183void DoAlign(AudacityProject &project, int index, bool moveSel)
184{
185 auto &tracks = TrackList::Get( project );
186 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
187 auto &window = ProjectWindow::Get( project );
188
189 TranslatableString action, shortAction;
190 double delta = 0.0;
191 double newPos = -1.0;
192
193 auto trackRange = tracks.Selected<AudioTrack>();
194
195 auto FindOffset =
196 [](const Track *pTrack) { return pTrack->GetStartTime(); };
197
198 auto firstTrackOffset = [&]{ return FindOffset( *trackRange.begin() ); };
199 auto minOffset = [&]{ return trackRange.min( FindOffset ); };
200 auto avgOffset = [&]{
201 return trackRange.sum( FindOffset ) /
202 std::max( size_t(1), trackRange.size() ); };
203
204 auto maxEndOffset = [&]{
205 return std::max(0.0, trackRange.max(&Track::GetEndTime)); };
206
207 switch(index) {
208 case kAlignStartZero:
209 delta = -minOffset();
210 action = moveSel
211 /* i18n-hint: In this and similar messages describing editing actions,
212 the starting or ending points of tracks are re-"aligned" to other
213 times, and the time selection may be "moved" too. The first
214 noun -- "start" in this example -- is the object of a verb (not of
215 an implied preposition "from"). */
216 ? XO("Aligned/Moved start to zero")
217 : XO("Aligned start to zero");
218 shortAction = moveSel
219 /* i18n-hint: This and similar messages give shorter descriptions of
220 the aligning and moving editing actions */
221 ? XO("Align/Move Start")
222 : XO("Align Start");
223 break;
225 delta = selectedRegion.t0() - minOffset();
226 action = moveSel
227 ? XO("Aligned/Moved start to cursor/selection start")
228 : XO("Aligned start to cursor/selection start");
229 shortAction = moveSel
230 ? XO("Align/Move Start")
231 : XO("Align Start");
232 break;
234 delta = selectedRegion.t1() - minOffset();
235 action = moveSel
236 ? XO("Aligned/Moved start to selection end")
237 : XO("Aligned start to selection end");
238 shortAction = moveSel
239 ? XO("Align/Move Start")
240 : XO("Align Start");
241 break;
243 delta = selectedRegion.t0() - maxEndOffset();
244 action = moveSel
245 ? XO("Aligned/Moved end to cursor/selection start")
246 : XO("Aligned end to cursor/selection start");
247 shortAction =
248 moveSel
249 ? XO("Align/Move End")
250 : XO("Align End");
251 break;
252 case kAlignEndSelEnd:
253 delta = selectedRegion.t1() - maxEndOffset();
254 action = moveSel
255 ? XO("Aligned/Moved end to selection end")
256 : XO("Aligned end to selection end");
257 shortAction =
258 moveSel
259 ? XO("Align/Move End")
260 : XO("Align End");
261 break;
262 // index set in alignLabelsNoSync
263 case kAlignEndToEnd:
264 newPos = firstTrackOffset();
265 action = moveSel
266 ? XO("Aligned/Moved end to end")
267 : XO("Aligned end to end");
268 shortAction =
269 moveSel
270 ? XO("Align/Move End to End")
271 : XO("Align End to End");
272 break;
273 case kAlignTogether:
274 newPos = avgOffset();
275 action = moveSel
276 ? XO("Aligned/Moved together")
277 : XO("Aligned together");
278 shortAction =
279 moveSel
280 ? XO("Align/Move Together")
281 : XO("Align Together");
282 }
283
284 if ((unsigned)index >= kAlignLabelsCount()) {
285 // This is an alignLabelsNoSync command.
286 for (auto t : tracks.Selected<AudioTrack>()) {
287 // This shifts different tracks in different ways, so no sync-lock
288 // move.
289 // Only align Wave and Note tracks end to end.
290 t->MoveTo(newPos);
291 if (index == kAlignEndToEnd)
292 newPos += (t->GetEndTime() - t->GetStartTime());
293 }
294 if (index == kAlignEndToEnd)
295 window.DoZoomFit();
296 }
297
298 if (delta != 0.0) {
299 // For a fixed-distance shift move sync-lock selected tracks also.
300 for (auto t : tracks.Any()
302 t->MoveTo(t->GetStartTime() + delta);
303 }
304
305 if (moveSel)
306 selectedRegion.move(delta);
307
308 ProjectHistory::Get( project ).PushState(action, shortAction);
309}
310
311#ifdef EXPERIMENTAL_SCOREALIGN
312
313#ifdef USE_MIDI
314static const ReservedCommandFlag&
315 NoteTracksSelectedFlag() { static ReservedCommandFlag flag{
316 [](const AudacityProject &project){
317 return !TrackList::Get( project ).Selected<const NoteTrack>().empty();
318 }
319 }; return flag; } //gsw
320#endif
321
322// rough relative amount of time to compute one
323// frame of audio or midi, or one cell of matrix, or one iteration
324// of smoothing, measured on a 1.9GHz Core 2 Duo in 32-bit mode
325// (see COLLECT_TIMING_DATA below)
326#define AUDIO_WORK_UNIT 0.004F
327#define MIDI_WORK_UNIT 0.0001F
328#define MATRIX_WORK_UNIT 0.000002F
329#define SMOOTHING_WORK_UNIT 0.000001F
330
331// Write timing data to a file; useful for calibrating AUDIO_WORK_UNIT,
332// MIDI_WORK_UNIT, MATRIX_WORK_UNIT, and SMOOTHING_WORK_UNIT coefficients
333// Data is written to timing-data.txt; look in
334// audacity-src/win/Release/modules/
335#define COLLECT_TIMING_DATA
336
337// Audacity Score Align Progress class -- progress reports come here
338class ASAProgress final : public SAProgress {
339 private:
340 float mTotalWork;
341 float mFrames[2];
342 long mTotalCells; // how many matrix cells?
343 long mCellCount; // how many cells so far?
344 long mPrevCellCount; // cell_count last reported with Update()
345 std::optional<ProgressDialog> mProgress;
346 #ifdef COLLECT_TIMING_DATA
347 FILE *mTimeFile;
348 wxDateTime mStartTime;
349 long iterations;
350 #endif
351
352 public:
353 ASAProgress() {
354 smoothing = false;
355 #ifdef COLLECT_TIMING_DATA
356 mTimeFile = fopen("timing-data.txt", "w");
357 #endif
358 }
359 ~ASAProgress() {
360 #ifdef COLLECT_TIMING_DATA
361 fclose(mTimeFile);
362 #endif
363 }
364 void set_phase(int i) override {
365 float work[2]; // chromagram computation work estimates
366 float work2, work3 = 0; // matrix and smoothing work estimates
367 SAProgress::set_phase(i);
368 #ifdef COLLECT_TIMING_DATA
369 long ms = 0;
370 wxDateTime now = wxDateTime::UNow();
371 wxFprintf(mTimeFile, "Phase %d begins at %s\n",
372 i, now.FormatTime());
373 if (i != 0)
374 ms = now.Subtract(mStartTime).GetMilliseconds().ToLong();
375 mStartTime = now;
376 #endif
377 if (i == 0) {
378 mCellCount = 0;
379 for (int j = 0; j < 2; j++) {
380 mFrames[j] = durations[j] / frame_period;
381 }
382 mTotalWork = 0;
383 for (int j = 0; j < 2; j++) {
384 work[j] =
385 (is_audio[j] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[j];
386 mTotalWork += work[j];
387 }
388 mTotalCells = mFrames[0] * mFrames[1];
389 work2 = mTotalCells * MATRIX_WORK_UNIT;
390 mTotalWork += work2;
391 // arbitrarily assume 60 iterations to fit smooth segments and
392 // per frame per iteration is SMOOTHING_WORK_UNIT
393 if (smoothing) {
394 work3 =
395 wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT * 40;
396 mTotalWork += work3;
397 }
398 #ifdef COLLECT_TIMING_DATA
399 wxFprintf(mTimeFile,
400 " mTotalWork (an estimate) = %g\n", mTotalWork);
401 wxFprintf(mTimeFile, " work0 = %g, frames %g, is_audio %d\n",
402 work[0], mFrames[0], is_audio[0]);
403 wxFprintf(mTimeFile, " work1 = %g, frames %g, is_audio %d\n",
404 work[1], mFrames[1], is_audio[1]);
405 wxFprintf(mTimeFile, "work2 = %g, work3 = %g\n", work2, work3);
406 #endif
407 mProgress.emplace(XO("Synchronize MIDI with Audio"),
408 XO("Synchronizing MIDI and Audio Tracks"));
409 } else if (i < 3) {
410 wxFprintf(mTimeFile,
411 "Phase %d took %d ms for %g frames, coefficient = %g s/frame\n",
412 i - 1, ms, mFrames[i - 1], (ms * 0.001) / mFrames[i - 1]);
413 } else if (i == 3) {
414 wxFprintf(mTimeFile,
415 "Phase 2 took %d ms for %d cells, coefficient = %g s/cell\n",
416 ms, mCellCount, (ms * 0.001) / mCellCount);
417 } else if (i == 4) {
418 wxFprintf(mTimeFile,
419 "Phase 3 took %d ms for %d iterations on %g frames, "
420 "coefficient = %g s per frame per iteration\n",
421 ms, iterations, wxMax(mFrames[0], mFrames[1]),
422 (ms * 0.001) / (wxMax(mFrames[0], mFrames[1]) * iterations));
423 }
424 }
425 bool set_feature_progress(float s) override {
426 float work;
427 if (phase == 0) {
428 float f = s / frame_period;
429 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
430 } else if (phase == 1) {
431 float f = s / frame_period;
432 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
433 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
434 }
435 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
436 return (updateResult == ProgressResult::Success);
437 }
438 bool set_matrix_progress(int cells) override {
439 mCellCount += cells;
440 float work =
441 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
442 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1];
443 work += mCellCount * MATRIX_WORK_UNIT;
444 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
445 return (updateResult == ProgressResult::Success);
446 }
447 bool set_smoothing_progress(int i) override {
448 iterations = i;
449 float work =
450 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
451 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1] +
452 MATRIX_WORK_UNIT * mFrames[0] * mFrames[1];
453 work += i * wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT;
454 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
455 return (updateResult == ProgressResult::Success);
456 }
457};
458
459
460long mixer_process(void *mixer, float **buffer, long n)
461{
462 Mixer *mix = (Mixer *) mixer;
463 long frame_count = mix->Process(std::max(0L, n));
464 *buffer = (float *) mix->GetBuffer();
465 return frame_count;
466}
467
468#endif // EXPERIMENTAL_SCOREALIGN
469
470enum{
473};
474
476{
477 auto GetTime = [](const Track &t) {
478 return t.TypeSwitch<double>(
479 [&](const WaveTrack &w) {
480 auto stime = w.GetEndTime();
481
482 int ndx;
483 for (ndx = 0; ndx < w.GetNumClips(); ndx++) {
484 const auto c = w.GetClipByIndex(ndx);
485 if (c->GetVisibleSampleCount() == 0)
486 continue;
487 stime = std::min(stime, c->GetPlayStartTime());
488 }
489 return stime;
490 },
491 [&](const LabelTrack& l) {
492 return l.GetStartTime();
493 }
494 );
495 };
496
497 std::vector<Track *> arr;
499 arr.reserve(tracks.Size());
500
501 // First find the permutation.
502 for (const auto pTrack : tracks) {
503 auto &track = *pTrack;
504 const auto size = arr.size();
505 size_t ndx = 0;
506 for (; ndx < size; ++ndx) {
507 Track &arrTrack = *arr[ndx];
508 if (flags & kAudacitySortByName) {
509 //do case insensitive sort - cmpNoCase returns less than zero if
510 // the string is 'less than' its argument
511 //also if we have case insensitive equality, then we need to sort
512 // by case as well
513 //We sort 'b' before 'B' accordingly. We uncharacteristically
514 // use greater than for the case sensitive
515 //compare because 'b' is greater than 'B' in ascii.
516 auto cmpValue = track.GetName().CmpNoCase(arrTrack.GetName());
517 if (cmpValue < 0 ||
518 (0 == cmpValue &&
519 track.GetName().CompareTo(arrTrack.GetName()) > 0))
520 break;
521 }
522 //sort by time otherwise
523 else if (flags & kAudacitySortByTime)
524 if (GetTime(track) < GetTime(arrTrack))
525 break;
526 }
527 arr.insert(arr.begin() + ndx, &track);
528 }
529
530 // Now apply the permutation
531 tracks.Permute(arr);
532}
533
535{
536 wxASSERT(wt);
537 float newValue = slider->Get();
538
539 wt->SetGain(newValue);
540
542 .PushState(XO("Adjusted gain"), XO("Gain"), UndoPush::CONSOLIDATE);
543
545}
546
548{
549 wxASSERT(wt);
550 float newValue = slider->Get();
551
552 wt->SetPan(newValue);
553
555 .PushState(XO("Adjusted Pan"), XO("Pan"), UndoPush::CONSOLIDATE);
556
558}
559
560}
561
562namespace {
563
564// Menu handler functions
565
566void OnStereoToMono(const CommandContext &context)
567{
569 EffectManager::Get().GetEffectByIdentifier(wxT("StereoToMono")),
570 context,
572}
573
574void OnMixAndRender(const CommandContext &context)
575{
576 auto &project = context.project;
577 DoMixAndRender(project, false);
578}
579
581{
582 auto &project = context.project;
583 DoMixAndRender(project, true);
584}
585
586void OnResample(const CommandContext &context)
587{
588 auto &project = context.project;
589 auto projectRate = ProjectRate::Get(project).GetRate();
591 auto &undoManager = UndoManager::Get(project);
592 auto &window = ProjectWindow::Get(project);
593
594 int newRate;
595
596 while (true) {
597 wxDialogWrapper dlg(&window, wxID_ANY, XO("Resample"));
598 ShuttleGui S(&dlg, eIsCreating);
599 wxString rate;
600 wxComboBox *cb;
601
602 rate.Printf(wxT("%ld"), lrint(projectRate));
603
604 wxArrayStringEx rates{
605 wxT("8000") ,
606 wxT("11025") ,
607 wxT("16000") ,
608 wxT("22050") ,
609 wxT("32000") ,
610 wxT("44100") ,
611 wxT("48000") ,
612 wxT("88200") ,
613 wxT("96000") ,
614 wxT("176400") ,
615 wxT("192000") ,
616 wxT("352800") ,
617 wxT("384000") ,
618 };
619
620 S.StartVerticalLay(true);
621 {
622 S.AddSpace(-1, 15);
623
624 S.StartHorizontalLay(wxCENTER, false);
625 {
626 cb = S.AddCombo(XXO("New sample rate (Hz):"),
627 rate,
628 rates);
629 }
630 S.EndHorizontalLay();
631
632 S.AddSpace(-1, 15);
633
634 S.AddStandardButtons();
635 }
636 S.EndVerticalLay();
637
638 dlg.Layout();
639 dlg.Fit();
640 dlg.Center();
641
642 if (dlg.ShowModal() != wxID_OK)
643 return; // user cancelled dialog
644
645 long lrate;
646 if (cb->GetValue().ToLong(&lrate) && lrate >= 1 && lrate <= 1000000) {
647 newRate = (int)lrate;
648 break;
649 }
650
652 XO("The entered value is invalid"),
653 XO("Error"),
654 wxICON_ERROR,
655 &window);
656 }
657
658 int ndx = 0;
659 auto flags = UndoPush::NONE;
660 for (auto wt : tracks.Selected<WaveTrack>()) {
661 auto msg = XO("Resampling track %d").Format(++ndx);
662
663 using namespace BasicUI;
664 auto progress = MakeProgress(XO("Resample"), msg);
665
666 // The resampling of a track may be stopped by the user. This might
667 // leave a track with multiple clips in a partially resampled state.
668 // But the thrown exception will cause rollback in the application
669 // level handler.
670
671 wt->Resample(newRate, progress.get());
672
673 // Each time a track is successfully, completely resampled,
674 // commit that to the undo stack. The second and later times,
675 // consolidate.
676
678 XO("Resampled audio track(s)"), XO("Resample Track"), flags);
679 flags = flags | UndoPush::CONSOLIDATE;
680 }
681
682 undoManager.StopConsolidating();
683
684 // Need to reset
685 window.FinishAutoScroll();
686}
687
688void OnRemoveTracks(const CommandContext &context)
689{
691}
692
693static void MuteTracks(const CommandContext &context, bool mute, bool selected)
694{
695 auto &project = context.project;
696 const auto &settings = ProjectSettings::Get( project );
697 auto &tracks = TrackList::Get( project );
698 auto &window = ProjectWindow::Get( project );
699
700 const auto solo = TracksBehaviorsSolo.ReadEnum();
701 const auto soloSimple = (solo == SoloBehaviorSimple);
702 const auto soloNone = (solo == SoloBehaviorNone);
703
704 auto iter = selected ? tracks.Selected<PlayableTrack>() : tracks.Any<PlayableTrack>();
705 for (auto pt : iter) {
706 pt->SetMute(mute);
707 if (soloSimple || soloNone)
708 pt->SetSolo(false);
709 }
710
712}
713
714void OnMuteAllTracks(const CommandContext &context)
715{
716 MuteTracks(context, true, false);
717}
718
720{
721 MuteTracks(context, false, false);
722}
723
725{
726 MuteTracks(context, true, true);
727}
728
730{
731 MuteTracks(context, false, true);
732}
733
734void OnPanLeft(const CommandContext &context)
735{
736 auto &project = context.project;
737 DoPanTracks( project, -1.0);
738}
739
740void OnPanRight(const CommandContext &context)
741{
742 auto &project = context.project;
743 DoPanTracks( project, 1.0);
744}
745
746void OnPanCenter(const CommandContext &context)
747{
748 auto &project = context.project;
749 DoPanTracks( project, 0.0);
750}
751
752void OnAlignNoSync(const CommandContext &context)
753{
754 auto &project = context.project;
755
757 context.index + kAlignLabelsCount(), false);
758}
759
760void OnAlign(const CommandContext &context)
761{
762 auto &project = context.project;
763
764 bool bMoveWith;
765 gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
766 DoAlign(project, context.index, bMoveWith);
767}
768
769/*
770// Now handled in OnAlign.
771void OnAlignMoveSel(int index)
772{
773 DoAlign(index, true);
774}
775*/
776
777void OnMoveSelectionWithTracks(const CommandContext &WXUNUSED(context) )
778{
779 bool bMoveWith;
780 gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
781 gPrefs->Write(wxT("/GUI/MoveSelectionWithTracks"), !bMoveWith);
782 gPrefs->Flush();
783
784}
785
786#ifdef EXPERIMENTAL_SCOREALIGN
787void OnScoreAlign(const CommandContext &context)
788{
789 auto &project = context.project;
790 auto &tracks = TrackList::Get( project );
791 const auto rate = ProjectSettings::Get( project ).GetRate();
792
793 int numWaveTracksSelected = 0;
794 int numNoteTracksSelected = 0;
795 int numOtherTracksSelected = 0;
796 double endTime = 0.0;
797
798 // Iterate through once to make sure that there is exactly
799 // one WaveTrack and one NoteTrack selected.
800 tracks.Selected().Visit(
801 [&](WaveTrack *wt) {
802 numWaveTracksSelected++;
803 endTime = endTime > wt->GetEndTime() ? endTime : wt->GetEndTime();
804 },
805 [&](NoteTrack *) {
806 numNoteTracksSelected++;
807 },
808 [&](Track*) {
809 numOtherTracksSelected++;
810 }
811 );
812
813 if(numWaveTracksSelected == 0 ||
814 numNoteTracksSelected != 1 ||
815 numOtherTracksSelected != 0){
817 XO("Please select at least one audio track and one MIDI track.") );
818 return;
819 }
820
821 // Creating the dialog also stores dialog into gScoreAlignDialog so
822 // that it can be deleted by CloseScoreAlignDialog() either here or
823 // if the program is quit by the user while the dialog is up.
824 ScoreAlignParams params;
825
826 // safe because the class maintains a global resource pointer
828
829 CloseScoreAlignDialog();
830
831 if (params.mStatus != wxID_OK) return;
832
833 // We're going to do it.
834 //pushing the state before the change is wrong (I think)
835 //PushState(XO("Sync MIDI with Audio"), XO("Sync MIDI with Audio"));
836 // Make a copy of the note track in case alignment is canceled or fails
837 auto holder = nt->Duplicate();
838 auto alignedNoteTrack = static_cast<NoteTrack*>(holder.get());
839 // Remove offset from NoteTrack because audio is
840 // mixed starting at zero and incorporating clip offsets.
841 if (alignedNoteTrack->GetOffset() < 0) {
842 // remove the negative offset data before alignment
843 nt->Clear(alignedNoteTrack->GetOffset(), 0);
844 } else if (alignedNoteTrack->GetOffset() > 0) {
845 alignedNoteTrack->Shift(alignedNoteTrack->GetOffset());
846 }
847 alignedNoteTrack->MoveTo(0);
848
849 WaveTrackConstArray waveTracks =
850 tracks->GetWaveTrackConstArray(true /* selectionOnly */);
851
852 int result;
853 {
854 Mixer mix(
855 waveTracks, // const WaveTrackConstArray &inputTracks
856 false, // mayThrow -- is this right?
858 0.0, // double startTime
859 endTime, // double stopTime
860 2, // int numOutChannels
861 44100u, // size_t outBufferSize
862 true, // bool outInterleaved
863 rate, // double outRate
864 floatSample, // sampleFormat outFormat
865 true, // bool highQuality = true
866 NULL); // MixerSpec *mixerSpec = NULL
867
868 ASAProgress progress;
869
870 // There's a lot of adjusting made to incorporate the note track offset into
871 // the note track while preserving the position of notes within beats and
872 // measures. For debugging, you can see just the pre-scorealign note track
873 // manipulation by setting SKIP_ACTUAL_SCORE_ALIGNMENT. You could then, for
874 // example, save the modified note track in ".gro" form to read the details.
875 //#define SKIP_ACTUAL_SCORE_ALIGNMENT 1
876#ifndef SKIP_ACTUAL_SCORE_ALIGNMENT
877 result = scorealign((void *) &mix, &mixer_process,
878 2 /* channels */, 44100.0 /* srate */, endTime,
879 &alignedNoteTrack->GetSeq(), &progress, params);
880#else
881 result = SA_SUCCESS;
882#endif
883 }
884
885 if (result == SA_SUCCESS) {
886 tracks->Replace(nt, holder);
888 XO("Alignment completed: MIDI from %.2f to %.2f secs, Audio from %.2f to %.2f secs.")
889 .Format(
890 params.mMidiStart, params.mMidiEnd,
891 params.mAudioStart, params.mAudioEnd) );
893 .PushState(XO("Sync MIDI with Audio"), XO("Sync MIDI with Audio"));
894 } else if (result == SA_TOOSHORT) {
896 XO(
897"Alignment error: input too short: MIDI from %.2f to %.2f secs, Audio from %.2f to %.2f secs.")
898 .Format(
899 params.mMidiStart, params.mMidiEnd,
900 params.mAudioStart, params.mAudioEnd) );
901 } else if (result == SA_CANCEL) {
902 // wrong way to recover...
903 //project.OnUndo(); // recover any changes to note track
904 return; // no message when user cancels alignment
905 } else {
906 //project.OnUndo(); // recover any changes to note track
907 AudacityMessageBox( XO("Internal error reported by alignment process.") );
908 }
909}
910#endif /* EXPERIMENTAL_SCOREALIGN */
911
912void OnSortTime(const CommandContext &context)
913{
914 auto &project = context.project;
916
918 .PushState(XO("Tracks sorted by time"), XO("Sort by Time"));
919}
920
921void OnSortName(const CommandContext &context)
922{
923 auto &project = context.project;
925
927 .PushState(XO("Tracks sorted by name"), XO("Sort by Name"));
928}
929
930void OnSyncLock(const CommandContext &context)
931{
932 auto &project = context.project;
933 auto &trackPanel = TrackPanel::Get( project );
934
936 gPrefs->Flush();
937
938 // Toolbar, project sync-lock handled within
940
941 trackPanel.Refresh(false);
942}
943
946void OnTrackPan(const CommandContext &context)
947{
948 auto &project = context.project;
949 auto &trackPanel = TrackPanel::Get( project );
950
951 const auto track = TrackFocus::Get( project ).Get();
952 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
953 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
954 if (slider->ShowDialog())
955 SetTrackPan(project, &wt, slider);
956 });
957}
958
959void OnTrackPanLeft(const CommandContext &context)
960{
961 auto &project = context.project;
962 auto &trackPanel = TrackPanel::Get( project );
963
964 const auto track = TrackFocus::Get( project ).Get();
965 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
966 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
967 slider->Decrease(1);
968 SetTrackPan(project, &wt, slider);
969 });
970}
971
972void OnTrackPanRight(const CommandContext &context)
973{
974 auto &project = context.project;
975 auto &trackPanel = TrackPanel::Get( project );
976
977 const auto track = TrackFocus::Get( project ).Get();
978 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
979 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
980 slider->Increase(1);
981 SetTrackPan(project, &wt, slider);
982 });
983}
984
985void OnTrackGain(const CommandContext &context)
986{
987 auto &project = context.project;
988 auto &trackPanel = TrackPanel::Get( project );
989
991 const auto track = TrackFocus::Get( project ).Get();
992 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
993 LWSlider *slider = WaveTrackControls::GainSlider( trackPanel, wt );
994 if (slider->ShowDialog())
995 SetTrackGain(project, &wt, slider);
996 });
997}
998
999void OnTrackGainInc(const CommandContext &context)
1000{
1001 auto &project = context.project;
1002 auto &trackPanel = TrackPanel::Get( project );
1003
1004 const auto track = TrackFocus::Get( project ).Get();
1005 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
1006 LWSlider *slider = WaveTrackControls::GainSlider( trackPanel, wt );
1007 slider->Increase(1);
1008 SetTrackGain(project, &wt, slider);
1009 });
1010}
1011
1012void OnTrackGainDec(const CommandContext &context)
1013{
1014 auto &project = context.project;
1015 auto &trackPanel = TrackPanel::Get( project );
1016
1017 const auto track = TrackFocus::Get( project ).Get();
1018 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
1019 LWSlider *slider = WaveTrackControls::GainSlider( trackPanel, wt );
1020 slider->Decrease(1);
1021 SetTrackGain(project, &wt, slider);
1022 });
1023}
1024
1025void OnTrackMenu(const CommandContext &context)
1026{
1027 auto &project = context.project;
1028 auto &trackPanel = TrackPanel::Get( project );
1029
1030 trackPanel.OnTrackMenu();
1031}
1032
1033void OnTrackMute(const CommandContext &context)
1034{
1035 auto &project = context.project;
1036
1037 // Use the temporary selection if it is specified, else the track focus
1038 auto track = context.temporarySelection.pTrack;
1039 if (!track)
1040 track = TrackFocus::Get( project ).Get();
1041
1042 if (track) track->TypeSwitch( [&](PlayableTrack &t) {
1044 });
1045}
1046
1047void OnTrackSolo(const CommandContext &context)
1048{
1049 auto &project = context.project;
1050
1051 const auto track = TrackFocus::Get( project ).Get();
1052 if (track) track->TypeSwitch( [&](PlayableTrack &t) {
1054 });
1055}
1056
1057void OnTrackClose(const CommandContext &context)
1058{
1059 auto &project = context.project;
1060 auto &trackPanel = TrackPanel::Get( project );
1061
1062 const auto t = TrackFocus::Get( project ).Get();
1063 if (!t)
1064 return;
1065
1066 auto isAudioActive = ProjectAudioIO::Get( project ).IsAudioActive();
1067
1068 if (isAudioActive)
1069 {
1071 XO("Can't delete track with active audio"));
1072 wxBell();
1073 return;
1074 }
1075
1077
1078 trackPanel.UpdateViewIfNoTracks();
1079 trackPanel.Refresh(false);
1080}
1081
1082void OnTrackMoveUp(const CommandContext &context)
1083{
1084 auto &project = context.project;
1085 auto &trackPanel = TrackPanel::Get( project );
1086 auto &tracks = TrackList::Get( project );
1087
1088 const auto focusedTrack = TrackFocus::Get( project ).Get();
1089 if (tracks.CanMoveUp(focusedTrack)) {
1091 trackPanel.Refresh(false);
1092 }
1093}
1094
1096{
1097 auto &project = context.project;
1098 auto &trackPanel = TrackPanel::Get( project );
1099 auto &tracks = TrackList::Get( project );
1100
1101 const auto focusedTrack = TrackFocus::Get( project ).Get();
1102 if (tracks.CanMoveDown(focusedTrack)) {
1104 trackPanel.Refresh(false);
1105 }
1106}
1107
1108void OnTrackMoveTop(const CommandContext &context)
1109{
1110 auto &project = context.project;
1111 auto &trackPanel = TrackPanel::Get( project );
1112 auto &tracks = TrackList::Get( project );
1113
1114 const auto focusedTrack = TrackFocus::Get( project ).Get();
1115 if (tracks.CanMoveUp(focusedTrack)) {
1117 trackPanel.Refresh(false);
1118 }
1119}
1120
1122{
1123 auto &project = context.project;
1124 auto &trackPanel = TrackPanel::Get( project );
1125 auto &tracks = TrackList::Get( project );
1126
1127 const auto focusedTrack = TrackFocus::Get( project ).Get();
1128 if (tracks.CanMoveDown(focusedTrack)) {
1130 trackPanel.Refresh(false);
1131 }
1132}
1133
1134// Menu definitions
1135
1136// Under /MenuBar
1137using namespace MenuTable;
1139{
1140 // Tracks Menu (formerly Project Menu)
1142
1143 static BaseItemSharedPtr menu{
1144 Menu( wxT("Tracks"), XXO("&Tracks"),
1145 Section( "Add",
1146 Menu( wxT("Add"), XXO("Add &New") )
1147 ),
1148
1150
1151 Section( "",
1152 Menu( wxT("Mix"), XXO("Mi&x"),
1153 // Delayed evaluation
1154 // Stereo to Mono is an oddball command that is also subject to control
1155 // by the plug-in manager, as if an effect. Decide whether to show or
1156 // hide it.
1158 const PluginID ID =
1159 EffectManager::Get().GetEffectByIdentifier(wxT("StereoToMono"));
1160 const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
1161 if (plug && plug->IsEnabled())
1162 return Command( wxT("Stereo to Mono"),
1163 XXO("Mix Stereo Down to &Mono"), OnStereoToMono,
1166 else
1167 return {};
1168 },
1169 Command( wxT("MixAndRender"), XXO("Mi&x and Render"),
1172 Command( wxT("MixAndRenderToNewTrack"),
1173 XXO("Mix and Render to Ne&w Track"),
1175 AudioIONotBusyFlag() | WaveTracksSelectedFlag(), wxT("Ctrl+Shift+M") )
1176 ),
1177
1178 Command( wxT("Resample"), XXO("&Resample..."), OnResample,
1180 ),
1181
1182 Section( "",
1183 Command( wxT("RemoveTracks"), XXO("Remo&ve Tracks"), OnRemoveTracks,
1185 ),
1186
1187 Section( "",
1188 Menu( wxT("Mute"), XXO("M&ute/Unmute"),
1189 Command( wxT("MuteAllTracks"), XXO("&Mute All Tracks"),
1190 OnMuteAllTracks, TracksExistFlag(), wxT("Ctrl+U") ),
1191 Command( wxT("UnmuteAllTracks"), XXO("&Unmute All Tracks"),
1192 OnUnmuteAllTracks, TracksExistFlag(), wxT("Ctrl+Shift+U") ),
1193 Command( wxT("MuteTracks"), XXO("Mut&e Tracks"),
1195 Command( wxT("UnmuteTracks"), XXO("U&nmute Tracks"),
1196 OnUnmuteSelectedTracks, EditableTracksSelectedFlag(), wxT("Ctrl+Alt+Shift+U") )
1197 ),
1198
1199 Menu( wxT("Pan"), XXO("&Pan"),
1200 // As Pan changes are not saved on Undo stack,
1201 // pan settings for all tracks
1202 // in the project could very easily be lost unless we
1203 // require the tracks to be selected.
1204 Command( wxT("PanLeft"), XXO("&Left"), OnPanLeft,
1206 Options{}.LongName( XO("Pan Left") ) ),
1207 Command( wxT("PanRight"), XXO("&Right"), OnPanRight,
1209 Options{}.LongName( XO("Pan Right") ) ),
1210 Command( wxT("PanCenter"), XXO("&Center"), OnPanCenter,
1212 Options{}.LongName( XO("Pan Center") ) )
1213 )
1214 ),
1215
1216 Section( "",
1217 Menu( wxT("Align"), XXO("&Align Tracks"), // XO("Just Move Tracks"),
1218 Section( "",
1219 // Mutual alignment of tracks independent of selection or zero
1220 CommandGroup(wxT("Align"),
1221 {
1222 { wxT("EndToEnd"), XXO("&Align End to End") },
1223 { wxT("Together"), XXO("Align &Together") },
1224 },
1226 ),
1227
1228 Section( "",
1229 // Alignment commands using selection or zero
1230 CommandGroup(wxT("Align"),
1231 alignLabels(),
1233 ),
1234
1235 Section( "",
1236 Command( wxT("MoveSelectionWithTracks"),
1237 XXO("&Move Selection with Tracks (on/off)"),
1240 Options{}.CheckTest( wxT("/GUI/MoveSelectionWithTracks"), false ) )
1241 )
1242 ),
1243
1244 #if 0
1245 // TODO: Can these labels be made clearer?
1246 // Do we need this sub-menu at all?
1247 Menu( wxT("MoveSelectionAndTracks"), XO("Move Sele&ction and Tracks"), {
1248 CommandGroup(wxT("AlignMove"), alignLabels(),
1249 OnAlignMoveSel, AudioIONotBusyFlag() | EditableTracksSelectedFlag()),
1250 } ),
1251 #endif
1252
1254
1255 #ifdef EXPERIMENTAL_SCOREALIGN
1256 Command( wxT("ScoreAlign"), XXO("Synchronize MIDI with Audio"),
1257 OnScoreAlign,
1258 AudioIONotBusyFlag() | NoteTracksSelectedFlag() | WaveTracksSelectedFlag() ),
1259 #endif // EXPERIMENTAL_SCOREALIGN
1260
1262
1263 Menu( wxT("Sort"), XXO("S&ort Tracks"),
1264 Command( wxT("SortByTime"), XXO("By &Start Time"), OnSortTime,
1266 Options{}.LongName( XO("Sort by Time") ) ),
1267 Command( wxT("SortByName"), XXO("By &Name"), OnSortName,
1269 Options{}.LongName( XO("Sort by Name") ) )
1270 )
1271
1273 ),
1274
1275 Section( "",
1276 Command( wxT("SyncLock"), XXO("Keep tracks synchronized (Sync &Lock)"),
1279 )
1280
1281 ) };
1282 return menu;
1283}
1284
1286 wxT(""),
1288};
1289
1291{
1293 static BaseItemSharedPtr menu{
1294 Menu( wxT("Track"), XXO("&Track"),
1295 Command( wxT("TrackPan"), XXO("Change P&an on Focused Track..."),
1296 OnTrackPan,
1297 TrackPanelHasFocus() | TracksExistFlag(), wxT("Shift+P") ),
1298 Command( wxT("TrackPanLeft"), XXO("Pan &Left on Focused Track"),
1300 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Left") ),
1301 Command( wxT("TrackPanRight"), XXO("Pan &Right on Focused Track"),
1303 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Right") ),
1304 Command( wxT("TrackGain"), XXO("Change Gai&n on Focused Track..."),
1306 TrackPanelHasFocus() | TracksExistFlag(), wxT("Shift+G") ),
1307 Command( wxT("TrackGainInc"), XXO("&Increase Gain on Focused Track"),
1309 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Up") ),
1310 Command( wxT("TrackGainDec"), XXO("&Decrease Gain on Focused Track"),
1312 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Down") ),
1313 Command( wxT("TrackMenu"), XXO("Op&en Menu on Focused Track..."),
1316 Options{ wxT("Shift+M") }.SkipKeyDown() ),
1317 Command( wxT("TrackMute"), XXO("M&ute/Unmute Focused Track"),
1319 TracksExistFlag() | TrackPanelHasFocus(), wxT("Shift+U") ),
1320 Command( wxT("TrackSolo"), XXO("&Solo/Unsolo Focused Track"),
1322 TracksExistFlag() | TrackPanelHasFocus(), wxT("Shift+S") ),
1323 Command( wxT("TrackClose"), XXO("&Close Focused Track"),
1326 wxT("Shift+C") ),
1327 Command( wxT("TrackMoveUp"), XXO("Move Focused Track U&p"),
1330 Command( wxT("TrackMoveDown"), XXO("Move Focused Track Do&wn"),
1333 Command( wxT("TrackMoveTop"), XXO("Move Focused Track to T&op"),
1336 Command( wxT("TrackMoveBottom"), XXO("Move Focused Track to &Bottom"),
1339 ) };
1340 return menu;
1341}
1342
1344 wxT("Optional/Extra/Part2"),
1346};
1347
1348}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
AttachedItem sAttachment1
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & StereoRequiredFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
const ReservedCommandFlag & TrackPanelHasFocus()
int min(int a, int b)
EffectDistortionSettings params
Definition: Distortion.cpp:77
wxString PluginID
Definition: EffectManager.h:30
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:10
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
TrackListHolder MixAndRender(const TrackIterRange< const WaveTrack > &trackRange, const Mixer::WarpOptions &warpOptions, const wxString &newTrackName, WaveTrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime)
Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effec...
EnumSetting< SoloBehavior > TracksBehaviorsSolo
@ SoloBehaviorSimple
Definition: PlayableTrack.h:70
@ SoloBehaviorNone
Definition: PlayableTrack.h:72
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
an object holding per-project preferred sample rate
constexpr sampleFormat floatSample
Definition: SampleFormat.h:43
@ eIsCreating
Definition: ShuttleGui.h:37
BoolSetting SyncLockTracks
Definition: SyncLock.cpp:173
const auto tracks
const auto project
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:83
static std::once_flag flag
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Track subclass holding data representing sound (as notes, or samples, or ...)
Definition: PlayableTrack.h:21
bool Toggle()
Write the negation of the previous value, and then return the current value.
Definition: Prefs.cpp:529
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:135
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Definition: Channel.cpp:124
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:251
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:309
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
static EffectManager & Get()
const PluginID & GetEffectByIdentifier(const CommandID &strTarget)
Abstract base class used in importing a file.
Lightweight version of ASlider. In other words it does not have a window permanently associated with ...
Definition: ASlider.h:64
void Decrease(float steps)
Definition: ASlider.cpp:1603
void Increase(float steps)
Definition: ASlider.cpp:1580
float Get(bool convert=true)
Definition: ASlider.cpp:1555
bool ShowDialog()
Definition: ASlider.cpp:1122
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
Functions for doing the mixdown of the tracks.
Definition: Mix.h:27
size_t Process(size_t maxSamples)
Definition: Mix.cpp:271
constSamplePtr GetBuffer()
Retrieve the main buffer or the interleaved buffer.
Definition: Mix.cpp:370
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:65
void Clear(double t0, double t1) override
Definition: NoteTrack.cpp:530
AudioTrack subclass that can also be audibly replayed by the program.
Definition: PlayableTrack.h:40
void SetMute(bool m)
bool IsEnabled() const
const PluginDescriptor * GetPlugin(const PluginID &ID) const
static PluginManager & Get()
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectSettings & Get(AudacityProject &project)
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
static ProjectWindow & Get(AudacityProject &project)
ScoreAlignDialog is \TODO.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:630
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
static void ModifyAllProjectToolbarMenus()
Track * Get()
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:123
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:86
bool IsSelected() const
Definition: Track.cpp:295
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:56
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1108
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:232
void RefreshTrack(Track *trk, bool refreshbacking=true)
Definition: TrackPanel.cpp:747
Holds a msgid for the translation catalog; may also bind format arguments.
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:219
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static LWSlider * PanSlider(CellularPanel &panel, const WaveTrack &wt)
static LWSlider * GainSlider(CellularPanel &panel, const WaveTrack &wt)
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:4079
A Track that contains audio waveform data.
Definition: WaveTrack.h:220
void SetPan(float newPan)
Definition: WaveTrack.cpp:923
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2717
void SetGain(float newGain)
Definition: WaveTrack.cpp:905
size_t NChannels() const override
May report more than one only when this is a leader track.
Definition: WaveTrack.cpp:620
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
#define lrint(dbl)
Definition: float_cast.h:169
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:289
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1144
constexpr auto Section
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
constexpr auto CommandGroup
constexpr auto Command
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
PROJECT_RATE_API sampleFormat SampleFormatChoice()
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:113
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:77
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:78
void DoTrackMute(AudacityProject &project, Track *t, bool exclusive)
void DoMoveTrack(AudacityProject &project, Track *target, MoveChoice choice)
Move a track up, down, to top or to bottom.
void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive)
void DoRemoveTrack(AudacityProject &project, Track *toRemove)
void DoRemoveTracks(AudacityProject &project)
void OnPanCenter(const CommandContext &context)
Definition: TrackMenus.cpp:746
void OnUnmuteSelectedTracks(const CommandContext &context)
Definition: TrackMenus.cpp:729
void OnTrackMoveBottom(const CommandContext &context)
void OnResample(const CommandContext &context)
Definition: TrackMenus.cpp:586
void OnMixAndRenderToNewTrack(const CommandContext &context)
Definition: TrackMenus.cpp:580
void OnTrackPan(const CommandContext &context)
Definition: TrackMenus.cpp:946
static const std::vector< ComponentInterfaceSymbol > & alignLabels()
Definition: TrackMenus.cpp:173
void OnSortName(const CommandContext &context)
Definition: TrackMenus.cpp:921
void OnPanRight(const CommandContext &context)
Definition: TrackMenus.cpp:740
void OnMixAndRender(const CommandContext &context)
Definition: TrackMenus.cpp:574
void OnMuteAllTracks(const CommandContext &context)
Definition: TrackMenus.cpp:714
void OnTrackMoveTop(const CommandContext &context)
void DoAlign(AudacityProject &project, int index, bool moveSel)
Definition: TrackMenus.cpp:183
void SetTrackGain(AudacityProject &project, WaveTrack *wt, LWSlider *slider)
Definition: TrackMenus.cpp:534
void OnTrackPanRight(const CommandContext &context)
Definition: TrackMenus.cpp:972
void OnUnmuteAllTracks(const CommandContext &context)
Definition: TrackMenus.cpp:719
void DoSortTracks(AudacityProject &project, int flags)
Definition: TrackMenus.cpp:475
void OnTrackMoveDown(const CommandContext &context)
void OnTrackGain(const CommandContext &context)
Definition: TrackMenus.cpp:985
void OnRemoveTracks(const CommandContext &context)
Definition: TrackMenus.cpp:688
void OnTrackMute(const CommandContext &context)
void OnTrackMenu(const CommandContext &context)
void OnTrackSolo(const CommandContext &context)
void OnTrackGainDec(const CommandContext &context)
void OnPanLeft(const CommandContext &context)
Definition: TrackMenus.cpp:734
void DoPanTracks(AudacityProject &project, float PanValue)
Definition: TrackMenus.cpp:140
void DoMixAndRender(AudacityProject &project, bool toNewTrack)
Definition: TrackMenus.cpp:48
void OnMuteSelectedTracks(const CommandContext &context)
Definition: TrackMenus.cpp:724
void OnTrackGainInc(const CommandContext &context)
Definition: TrackMenus.cpp:999
void OnMoveSelectionWithTracks(const CommandContext &WXUNUSED(context))
Definition: TrackMenus.cpp:777
void SetTrackPan(AudacityProject &project, WaveTrack *wt, LWSlider *slider)
Definition: TrackMenus.cpp:547
static void MuteTracks(const CommandContext &context, bool mute, bool selected)
Definition: TrackMenus.cpp:693
void OnSyncLock(const CommandContext &context)
Definition: TrackMenus.cpp:930
void OnAlignNoSync(const CommandContext &context)
Definition: TrackMenus.cpp:752
void OnTrackMoveUp(const CommandContext &context)
void OnTrackClose(const CommandContext &context)
void OnAlign(const CommandContext &context)
Definition: TrackMenus.cpp:760
void OnStereoToMono(const CommandContext &context)
Definition: TrackMenus.cpp:566
void OnSortTime(const CommandContext &context)
Definition: TrackMenus.cpp:912
void OnTrackPanLeft(const CommandContext &context)
Definition: TrackMenus.cpp:959
Options && CheckTest(const CheckFn &fn) &&
Options && LongName(const TranslatableString &value) &&
Immutable structure is an argument to Mixer's constructor.
Definition: MixerOptions.h:56