Audacity 3.2.0
TransportMenus.cpp
Go to the documentation of this file.
1#include "AudioIO.h"
2#include "../CommonCommandFlags.h"
3#include "DeviceManager.h"
4#include "../LabelTrack.h"
5#include "../Menus.h"
6#include "Prefs.h"
7#include "Project.h"
8#include "ProjectAudioIO.h"
9#include "../ProjectAudioManager.h"
10#include "ProjectHistory.h"
11#include "../ProjectSettings.h"
12#include "../ProjectWindows.h"
13#include "../ProjectWindow.h"
14#include "../SelectUtilities.h"
15#include "../SoundActivatedRecord.h"
16#include "../TrackPanelAx.h"
17#include "../TrackPanel.h"
18#include "../TransportUtilities.h"
19#include "UndoManager.h"
20#include "../prefs/RecordingPrefs.h"
21#include "../prefs/TracksPrefs.h"
22#include "WaveTrack.h"
23#include "ViewInfo.h"
24#include "../commands/CommandContext.h"
25#include "../commands/CommandManager.h"
26#include "../toolbars/ControlToolBar.h"
27#include "../toolbars/ToolManager.h"
28#include "AudacityMessageBox.h"
29#include "BasicUI.h"
30#include "ProgressDialog.h"
31
32#include <thread>
33#include <float.h>
34#include <wx/app.h>
35
36// private helper classes and functions
37namespace {
38
39// TODO: Should all these functions which involve
40// the toolbar actually move into ControlToolBar?
41
47{
48 auto &toolbar = ControlToolBar::Get( project );
49 wxCommandEvent evt;
50
51 // If this project is playing, stop playing
52 auto gAudioIO = AudioIOBase::Get();
53 if (gAudioIO->IsStreamActive(
55 )) {
56 // Make momentary changes of button appearances
57 toolbar.SetPlay(false); //Pops
58 toolbar.SetStop(); //Pushes stop down
59 toolbar.OnStop(evt);
60
61 using namespace std::chrono;
62 std::this_thread::sleep_for(100ms);
63 }
64
65 // If it didn't stop playing quickly, or if some other
66 // project is playing, return
67 if (gAudioIO->IsBusy())
68 return false;
69
70 return true;
71}
72
73void DoMoveToLabel(AudacityProject &project, bool next)
74{
75 auto &tracks = TrackList::Get( project );
76 auto &trackFocus = TrackFocus::Get( project );
77 auto &window = ProjectWindow::Get( project );
78 auto &projectAudioManager = ProjectAudioManager::Get(project);
79
80 // Find the number of label tracks, and ptr to last track found
81 auto trackRange = tracks.Any<LabelTrack>();
82 auto lt = *trackRange.rbegin();
83 auto nLabelTrack = trackRange.size();
84
85 if (nLabelTrack == 0 ) {
86 trackFocus.MessageForScreenReader(XO("no label track"));
87 }
88 else if (nLabelTrack > 1) {
89 // find first label track, if any, starting at the focused track
90 lt =
91 *tracks.Find(trackFocus.Get()).Filter<LabelTrack>();
92 if (!lt)
93 trackFocus.MessageForScreenReader(
94 XO("no label track at or below focused track"));
95 }
96
97 // If there is a single label track, or there is a label track at or below
98 // the focused track
99 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
100 if (lt) {
101 int i;
102 if (next)
103 i = lt->FindNextLabel(selectedRegion);
104 else
105 i = lt->FindPrevLabel(selectedRegion);
106
107 if (i >= 0) {
108 const LabelStruct* label = lt->GetLabel(i);
109 bool newDefault = projectAudioManager.Looping();
110 if (ProjectAudioIO::Get( project ).IsAudioActive()) {
112 selectedRegion = label->selectedRegion;
113 window.RedrawProject();
114 TransportUtilities::DoStartPlaying(project, newDefault);
115 }
116 else {
117 selectedRegion = label->selectedRegion;
118 window.ScrollIntoView(selectedRegion.t0());
119 window.RedrawProject();
120 }
121 /* i18n-hint:
122 String is replaced by the name of a label,
123 first number gives the position of that label in a sequence
124 of labels,
125 and the last number is the total number of labels in the sequence.
126 */
127 auto message = XO("%s %d of %d")
128 .Format( label->title, i + 1, lt->GetNumLabels() );
129 trackFocus.MessageForScreenReader(message);
130 }
131 else {
132 trackFocus.MessageForScreenReader(XO("no labels in label track"));
133 }
134 }
135}
136
138{
139 auto &playRegion = ViewInfo::Get(project).playRegion;
140 return playRegion.Active();
141}
142
143}
144
145// Strings for menu items and also for dialog titles
146/* i18n-hint Sets a starting point for looping play */
147static const auto SetLoopInTitle = XXO("Set Loop &In");
148/* i18n-hint Sets an ending point for looping play */
149static const auto SetLoopOutTitle = XXO("Set Loop &Out");
150
151// Menu handler functions
152
153namespace {
154
155// This plays (once, with fixed bounds) OR Stops audio. It's a toggle.
156// The default binding for Shift+SPACE.
158{
160 return;
162}
163
165{
167}
168
169// This plays (looping, maybe adjusting the loop) OR Stops audio. It's a toggle.
170// The default binding for SPACE
172{
173 auto &project = context.project;
175 return;
176
177 if( !MakeReadyToPlay(project) )
178 return;
179
180 // Now play in a loop
181 // Will automatically set mLastPlayMode
183}
184
185void OnPause(const CommandContext &context)
186{
188}
189
190void OnRecord(const CommandContext &context)
191{
192 TransportUtilities::RecordAndWait(context, false);
193}
194
195// If first choice is record same track 2nd choice is record NEW track
196// and vice versa.
198{
200}
201
202#ifdef EXPERIMENTAL_PUNCH_AND_ROLL
203void OnPunchAndRoll(const CommandContext &context)
204{
205 AudacityProject &project = context.project;
206 auto &viewInfo = ViewInfo::Get( project );
207
208 static const auto url =
209 wxT("Punch_and_Roll_Record#Using_Punch_and_Roll_Record");
210
211 auto gAudioIO = AudioIO::Get();
212 if (gAudioIO->IsBusy())
213 return;
214
215 // Ignore all but left edge of the selection.
216 viewInfo.selectedRegion.collapseToT0();
217 double t1 = std::max(0.0, viewInfo.selectedRegion.t1());
218
219 // Checking the selected tracks: making sure they all have the same rate
220 const auto selectedTracks{ GetPropertiesOfSelected(project) };
221 const int rateOfSelected{ selectedTracks.rateOfSelected };
222 const bool allSameRate{ selectedTracks.allSameRate };
223
224 if (!allSameRate) {
225 AudacityMessageBox(XO("The tracks selected "
226 "for recording must all have the same sampling rate"),
227 XO("Mismatched Sampling Rates"),
228 wxICON_ERROR | wxCENTRE);
229
230 return;
231 }
232
233 // Decide which tracks to record in.
234 auto tracks =
235 ProjectAudioManager::ChooseExistingRecordingTracks(project, true, rateOfSelected);
236 if (tracks.empty()) {
237 auto recordingChannels =
238 std::max(0, AudioIORecordChannels.Read());
239 auto message =
240 (recordingChannels == 1)
241 ? XO("Please select in a mono track.")
242 : (recordingChannels == 2)
243 ? XO("Please select in a stereo track or two mono tracks.")
244 : XO("Please select at least %d channels.").Format( recordingChannels );
246 XO("Error"), message, url);
247 return;
248 }
249
250 // Delete the portion of the target tracks right of the selection, but first,
251 // remember a part of the deletion for crossfading with the new recording.
252 // We may also adjust the starting point leftward if it is too close to the
253 // end of the track, so that at least some nonzero crossfade data can be
254 // taken.
255 PRCrossfadeData crossfadeData;
256 const double crossFadeDuration = std::max(0.0,
258 / 1000.0
259 );
260
261 // The test for t1 == 0.0 stops punch and roll deleting everything where the
262 // selection is at zero. There wouldn't be any cued audio to play in
263 // that case, so a normal record, not a punch and roll, is called for.
264 bool error = (t1 == 0.0);
265
266 double newt1 = t1;
267 for (const auto &wt : tracks) {
268 auto rate = wt->GetRate();
269 sampleCount testSample(floor(t1 * rate));
270 auto intervals = wt->GetIntervals();
271 auto pred = [rate](sampleCount testSample){ return
272 [rate, testSample](const Track::Interval &interval){
273 auto start = floor(interval.Start() * rate + 0.5);
274 auto end = floor(interval.End() * rate + 0.5);
275 auto ts = testSample.as_double();
276 return ts >= start && ts < end;
277 };
278 };
279 auto begin = intervals.begin(), end = intervals.end(),
280 iter = std::find_if(begin, end, pred(testSample));
281 if (iter == end)
282 // Bug 1890 (an enhancement request)
283 // Try again, a little to the left.
284 // Subtract 10 to allow a selection exactly at or slightly after the
285 // end time
286 iter = std::find_if(begin, end, pred(testSample - 10));
287 if (iter == end)
288 error = true;
289 else {
290 // May adjust t1 left
291 // Let's ignore the possibility of a clip even shorter than the
292 // crossfade duration!
293 newt1 = std::min(newt1, iter->End() - crossFadeDuration);
294 }
295 }
296
297 if (error) {
298 auto message = XO("Please select a time within a clip.");
300 *ProjectFramePlacement(&project), XO("Error"), message, url);
301 return;
302 }
303
304 t1 = newt1;
305 for (const auto &wt : tracks) {
306 const auto endTime = wt->GetEndTime();
307 const auto duration =
308 std::max(0.0, std::min(crossFadeDuration, endTime - t1));
309 const size_t getLen = floor(duration * wt->GetRate());
310 std::vector<float> data(getLen);
311 if (getLen > 0) {
312 float *const samples = data.data();
313 const sampleCount pos = wt->TimeToLongSamples(t1);
314 wt->GetFloats(samples, pos, getLen);
315 }
316 crossfadeData.push_back(std::move(data));
317 }
318
319 // Change tracks only after passing the error checks above
320 for (const auto &wt : tracks) {
321 wt->Clear(t1, wt->GetEndTime());
322 }
323
324 // Choose the tracks for playback.
325 TransportTracks transportTracks;
326 const auto duplex = ProjectAudioManager::UseDuplex();
327 if (duplex)
328 // play all
329 transportTracks = TransportTracks{
330 TrackList::Get( project ), false, true };
331 else
332 // play recording tracks only
333 std::copy(tracks.begin(), tracks.end(),
334 std::back_inserter(transportTracks.playbackTracks));
335
336 // Unlike with the usual recording, a track may be chosen both for playback
337 // and recording.
338 transportTracks.captureTracks = std::move(tracks);
339
340 // Try to start recording
341 auto options = ProjectAudioIO::GetDefaultOptions(project);
342 options.rate = rateOfSelected;
343 options.preRoll = std::max(0L,
345 options.pCrossfadeData = &crossfadeData;
346 bool success = ProjectAudioManager::Get( project ).DoRecord(project,
347 transportTracks,
348 t1, DBL_MAX,
349 false, // altAppearance
350 options);
351
352 if (success)
353 // Undo state will get pushed elsewhere, when record finishes
354 ;
355 else
356 // Roll back the deletions
358}
359#endif
360
362{
364}
365
367{
369}
370
372{
373 auto &project = context.project;
374 auto &playRegion = ViewInfo::Get(project).playRegion;
375 if (!playRegion.Active())
378 true, false, SetLoopInTitle.Stripped());
379}
380
381
383{
384 auto &project = context.project;
385 auto &playRegion = ViewInfo::Get(project).playRegion;
386 if (!playRegion.Active())
389 false, false, SetLoopOutTitle.Stripped());
390}
391
393{
395}
396
397void OnRescanDevices(const CommandContext &WXUNUSED(context) )
398{
400}
401
403{
404 AudacityProject &project = context.project;
405
406 SoundActivatedRecordDialog dialog( &GetProjectFrame( project ) /* parent */ );
407 dialog.ShowModal();
408}
409
410void OnToggleSoundActivated(const CommandContext &WXUNUSED(context) )
411{
413 gPrefs->Flush();
415}
416
417void OnTogglePlayRecording(const CommandContext &WXUNUSED(context) )
418{
419 bool Duplex;
420#ifdef EXPERIMENTAL_DA
421 gPrefs->Read(wxT("/AudioIO/Duplex"), &Duplex, false);
422#else
423 gPrefs->Read(wxT("/AudioIO/Duplex"), &Duplex, true);
424#endif
425 gPrefs->Write(wxT("/AudioIO/Duplex"), !Duplex);
426 gPrefs->Flush();
428}
429
430void OnToggleSWPlaythrough(const CommandContext &WXUNUSED(context) )
431{
432 bool SWPlaythrough;
433 gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &SWPlaythrough, false);
434 gPrefs->Write(wxT("/AudioIO/SWPlaythrough"), !SWPlaythrough);
435 gPrefs->Flush();
437}
438
439#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
440void OnToggleAutomatedInputLevelAdjustment(
441 const CommandContext &WXUNUSED(context) )
442{
443 bool AVEnabled;
444 gPrefs->Read(
445 wxT("/AudioIO/AutomatedInputLevelAdjustment"), &AVEnabled, false);
446 gPrefs->Write(wxT("/AudioIO/AutomatedInputLevelAdjustment"), !AVEnabled);
447 gPrefs->Flush();
449}
450#endif
451
452void OnStop(const CommandContext &context)
453{
455}
456
457void OnPlayOneSecond(const CommandContext &context)
458{
459 auto &project = context.project;
460 if( !MakeReadyToPlay(project) )
461 return;
462
463 auto &trackPanel = TrackPanel::Get( project );
464 auto options = ProjectAudioIO::GetDefaultOptions(project);
465
466 double pos = trackPanel.GetMostRecentXPos();
468 context, SelectedRegion(pos - 0.5, pos + 0.5),
469 options, PlayMode::oneSecondPlay);
470}
471
480{
481 auto &project = context.project;
482
483 if( !MakeReadyToPlay(project) )
484 return;
485
486 auto &trackPanel = TrackPanel::Get( project );
487 auto &viewInfo = ViewInfo::Get( project );
488 const auto &selectedRegion = viewInfo.selectedRegion;
489
490 double pos = trackPanel.GetMostRecentXPos();
491
492 double t0,t1;
493 // check region between pointer and the nearest selection edge
494 if (fabs(pos - selectedRegion.t0()) <
495 fabs(pos - selectedRegion.t1())) {
496 t0 = t1 = selectedRegion.t0();
497 } else {
498 t0 = t1 = selectedRegion.t1();
499 }
500 if( pos < t1)
501 t0=pos;
502 else
503 t1=pos;
504
505 // JKC: oneSecondPlay mode disables auto scrolling
506 // On balance I think we should always do this in this function
507 // since you are typically interested in the sound EXACTLY
508 // where the cursor is.
509 // TODO: have 'playing attributes' such as 'with_autoscroll'
510 // rather than modes, since that's how we're now using the modes.
511
512 // An alternative, commented out below, is to disable autoscroll
513 // only when playing a short region, less than or equal to a second.
514// mLastPlayMode = ((t1-t0) > 1.0) ? normalPlay : oneSecondPlay;
515
516 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
517
519 context, SelectedRegion(t0, t1),
520 playOptions, PlayMode::oneSecondPlay);
521}
522
523// The next 4 functions provide a limited version of the
524// functionality of OnPlayToSelection() for keyboard users
525
527{
528 auto &project = context.project;
529
530 if( !MakeReadyToPlay(project) )
531 return;
532
533 auto &viewInfo = ViewInfo::Get( project );
534 const auto &selectedRegion = viewInfo.selectedRegion;
535
536 double t0 = selectedRegion.t0();
537 double beforeLen;
538 gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
539
540 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
541
543 context, SelectedRegion(t0 - beforeLen, t0),
544 playOptions, PlayMode::oneSecondPlay);
545}
546
548{
549 auto &project = context.project;
550
551 if( !MakeReadyToPlay(project) )
552 return;
553
554 auto &viewInfo = ViewInfo::Get( project );
555 const auto &selectedRegion = viewInfo.selectedRegion;
556
557 double t0 = selectedRegion.t0();
558 double t1 = selectedRegion.t1();
559 double afterLen;
560 gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
561
562 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
563
564 if ( t1 - t0 > 0.0 && t1 - t0 < afterLen )
566 context, SelectedRegion(t0, t1),
567 playOptions, PlayMode::oneSecondPlay);
568 else
570 context, SelectedRegion(t0, t0 + afterLen),
571 playOptions, PlayMode::oneSecondPlay);
572}
573
575{
576 auto &project = context.project;
577
578 if( !MakeReadyToPlay(project) )
579 return;
580
581 auto &viewInfo = ViewInfo::Get( project );
582 const auto &selectedRegion = viewInfo.selectedRegion;
583
584 double t0 = selectedRegion.t0();
585 double t1 = selectedRegion.t1();
586 double beforeLen;
587 gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
588
589 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
590
591 if ( t1 - t0 > 0.0 && t1 - t0 < beforeLen )
593 context, SelectedRegion(t0, t1),
594 playOptions, PlayMode::oneSecondPlay);
595 else
597 context, SelectedRegion(t1 - beforeLen, t1),
598 playOptions, PlayMode::oneSecondPlay);
599}
600
602{
603 auto &project = context.project;
604
605 if( !MakeReadyToPlay(project) )
606 return;
607
608 auto &viewInfo = ViewInfo::Get( project );
609 const auto &selectedRegion = viewInfo.selectedRegion;
610
611 double t1 = selectedRegion.t1();
612 double afterLen;
613 gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
614
615 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
616
618 context, SelectedRegion(t1, t1 + afterLen),
619 playOptions, PlayMode::oneSecondPlay);
620}
621
623(const CommandContext &context)
624{
625 auto &project = context.project;
626
627 if (!MakeReadyToPlay(project))
628 return;
629
630 auto &viewInfo = ViewInfo::Get( project );
631 const auto &selectedRegion = viewInfo.selectedRegion;
632
633 double t0 = selectedRegion.t0();
634 double t1 = selectedRegion.t1();
635 double beforeLen;
636 gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
637 double afterLen;
638 gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
639
640 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
641
642 if ( t1 - t0 > 0.0 && t1 - t0 < afterLen )
644 context, SelectedRegion(t0 - beforeLen, t1),
645 playOptions, PlayMode::oneSecondPlay);
646 else
648 context, SelectedRegion(t0 - beforeLen, t0 + afterLen),
649 playOptions, PlayMode::oneSecondPlay);
650}
651
653(const CommandContext &context)
654{
655 auto &project = context.project;
656
657 if (!MakeReadyToPlay(project))
658 return;
659
660 auto &viewInfo = ViewInfo::Get( project );
661 const auto &selectedRegion = viewInfo.selectedRegion;
662
663 double t0 = selectedRegion.t0();
664 double t1 = selectedRegion.t1();
665 double beforeLen;
666 gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
667 double afterLen;
668 gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
669
670 auto playOptions = ProjectAudioIO::GetDefaultOptions(project);
671
672 if ( t1 - t0 > 0.0 && t1 - t0 < beforeLen )
674 context, SelectedRegion(t0, t1 + afterLen),
675 playOptions, PlayMode::oneSecondPlay);
676 else
678 context, SelectedRegion(t1 - beforeLen, t1 + afterLen),
679 playOptions, PlayMode::oneSecondPlay);
680}
681
683{
684 auto &project = context.project;
685
686 if ( !MakeReadyToPlay(project) )
687 return;
688
689 // Play with cut preview
691}
692
694{
695 auto &project = context.project;
696 DoMoveToLabel(project, false);
697}
698
700{
701 auto &project = context.project;
702 DoMoveToLabel(project, true);
703}
704
705#if 0
706// Legacy handlers, not used as of version 2.3.0
707void OnStopSelect(const CommandContext &context)
708{
709 auto &project = context.project;
710 auto &history = ProjectHistory::Get( project );
711 auto &viewInfo = project.GetViewInfo();
712 auto &selectedRegion = viewInfo.selectedRegion;
713
714 auto gAudioIO = AudioIOBase::Get();
715 if (gAudioIO->IsStreamActive()) {
716 selectedRegion.setT0(gAudioIO->GetStreamTime(), false);
717 ProjectAudioManager::Get( project ).Stop();
718 history.ModifyState(false); // without bWantsAutoSave
719 }
720}
721#endif
722
723// Menu definitions
724
725// Under /MenuBar
726using namespace MenuTable;
728{
730
732
733 static BaseItemSharedPtr menu{
734 /* i18n-hint: 'Transport' is the name given to the set of controls that
735 play, record, pause etc. */
736 Menu( wxT("Transport"), XXO("Tra&nsport"),
737 Section( "Basic",
738 Menu( wxT("Play"), XXO("Pl&aying"),
739 /* i18n-hint: (verb) Start or Stop audio playback*/
740 Command( wxT("DefaultPlayStop"), XXO("Pl&ay/Stop"), OnPlayDefaultOrStop,
741 CanStopAudioStreamFlag(), wxT("Space") ),
742 Command( wxT("PlayStopSelect"), XXO("Play/Stop and &Set Cursor"),
744 Command( wxT("OncePlayStop"), XXO("Play &Once/Stop"), OnPlayOnceOrStop,
745 CanStopAudioStreamFlag(), wxT("Shift+Space") ),
746 Command( wxT("Pause"), XXO("&Pause"), OnPause,
748 ),
749
750 Menu( wxT("Record"), XXO("&Recording"),
751 /* i18n-hint: (verb)*/
752 Command( wxT("Record1stChoice"), XXO("&Record"), OnRecord,
753 CanStopFlags, wxT("R") ),
754
755 // The OnRecord2ndChoice function is: if normal record records beside,
756 // it records below, if normal record records below, it records beside.
757 // TODO: Do 'the right thing' with other options like TimerRecord.
758 // Delayed evaluation in case gPrefs is not yet defined
759 [](const AudacityProject&)
760 { return Command( wxT("Record2ndChoice"),
761 // Our first choice is bound to R (by default)
762 // and gets the prime position.
763 // We supply the name for the 'other one' here.
764 // It should be bound to Shift+R
765 (gPrefs->ReadBool("/GUI/PreferNewTrackRecord", false)
766 ? XXO("&Append Record") : XXO("Record &New Track")),
768 wxT("Shift+R")
769 ); },
770
771 #ifdef EXPERIMENTAL_PUNCH_AND_ROLL
772 Command( wxT("PunchAndRoll"), XXO("Punch and Rol&l Record"),
773 OnPunchAndRoll,
774 WaveTracksExistFlag() | AudioIONotBusyFlag(), wxT("Shift+D") ),
775 #endif
776
777 // JKC: I decided to duplicate this between play and record,
778 // rather than put it at the top level.
779 // CommandManger::AddItem can now cope with simple duplicated items.
780 // PRL: caution, this is a duplicated command name!
781 Command( wxT("Pause"), XXO("&Pause"), OnPause,
783 )
784 ),
785
786 Section( "Other",
787 Section( "",
788 Menu( wxT("PlayRegion"), XXO("&Looping"),
789 Command( wxT("TogglePlayRegion"), LoopToggleText,
791 Options(L"L").CheckTest([](const AudacityProject& project){
792 return IsLoopingEnabled(project);
793 } )),
794 Command( wxT("ClearPlayRegion"), XXO("&Clear Loop"),
795 OnClearPlayRegion, AlwaysEnabledFlag, L"Shift+Alt+L" ),
796 Command( wxT("SetPlayRegionToSelection"),
797 XXO("&Set Loop to Selection"),
799 L"Shift+L" ),
800 Command( wxT("SetPlayRegionIn"),
803 Command( wxT("SetPlayRegionOut"),
806 )
807 ),
808
809 Command( wxT("RescanDevices"), XXO("R&escan Audio Devices"),
811
812 Menu( wxT("Options"), XXO("Transport &Options"),
813 Section( "Part1",
814 // Sound Activated recording options
815 Command( wxT("SoundActivationLevel"),
816 XXO("Sound Activation Le&vel..."), OnSoundActivated,
818 Command( wxT("SoundActivation"),
819 XXO("Sound A&ctivated Recording (on/off)"),
823 ),
824
825 Section( "Part2",
826 Command( wxT("Overdub"), XXO("&Overdub (on/off)"),
829 Options{}.CheckTest( wxT("/AudioIO/Duplex"),
830#ifdef EXPERIMENTAL_DA
831 false
832#else
833 true
834#endif
835 ) ),
836 Command( wxT("SWPlaythrough"), XXO("So&ftware Playthrough (on/off)"),
839 Options{}.CheckTest( wxT("/AudioIO/SWPlaythrough"), false ) )
840
841
842 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
843 ,
844 Command( wxT("AutomatedInputLevelAdjustmentOnOff"),
845 XXO("A&utomated Recording Level Adjustment (on/off)"),
846 OnToggleAutomatedInputLevelAdjustment,
849 wxT("/AudioIO/AutomatedInputLevelAdjustment"), false ) )
850 #endif
851 )
852 )
853 )
854 ) };
855 return menu;
856}
857
859 wxT(""),
861};
862
864{
865 static BaseItemSharedPtr menu{
866 Menu( wxT("Transport"), XXO("T&ransport"),
867 // PlayStop is already in the menus.
868 /* i18n-hint: (verb) Start playing audio*/
869 Command( wxT("Play"), XXO("Pl&ay Once"), OnPlayOnceOrStop,
871 /* i18n-hint: (verb) Stop playing audio*/
872 Command( wxT("Stop"), XXO("Sto&p"), OnStop,
874 Command( wxT("PlayOneSec"), XXO("Play &One Second"), OnPlayOneSecond,
875 CaptureNotBusyFlag(), wxT("1") ),
876 Command( wxT("PlayToSelection"), XXO("Play to &Selection"),
878 CaptureNotBusyFlag(), wxT("B") ),
879 Command( wxT("PlayBeforeSelectionStart"),
880 XXO("Play &Before Selection Start"), OnPlayBeforeSelectionStart,
881 CaptureNotBusyFlag(), wxT("Shift+F5") ),
882 Command( wxT("PlayAfterSelectionStart"),
883 XXO("Play Af&ter Selection Start"), OnPlayAfterSelectionStart,
884 CaptureNotBusyFlag(), wxT("Shift+F6") ),
885 Command( wxT("PlayBeforeSelectionEnd"),
886 XXO("Play Be&fore Selection End"), OnPlayBeforeSelectionEnd,
887 CaptureNotBusyFlag(), wxT("Shift+F7") ),
888 Command( wxT("PlayAfterSelectionEnd"),
889 XXO("Play Aft&er Selection End"), OnPlayAfterSelectionEnd,
890 CaptureNotBusyFlag(), wxT("Shift+F8") ),
891 Command( wxT("PlayBeforeAndAfterSelectionStart"),
892 XXO("Play Before a&nd After Selection Start"),
894 wxT("Ctrl+Shift+F5") ),
895 Command( wxT("PlayBeforeAndAfterSelectionEnd"),
896 XXO("Play Before an&d After Selection End"),
898 wxT("Ctrl+Shift+F7") ),
899 Command( wxT("PlayCutPreview"), XXO("Play C&ut Preview"),
901 CaptureNotBusyFlag(), wxT("C") )
902 ) };
903 return menu;
904}
905
907 wxT("Optional/Extra/Part1"),
909};
910
912{
914 static BaseItemSharedPtr items{
915 Items(wxT("MoveToLabel"),
916 Command(wxT("MoveToPrevLabel"), XXO("Move to Pre&vious Label"),
918 CaptureNotBusyFlag() | TrackPanelHasFocus(), wxT("Alt+Left")),
919 Command(wxT("MoveToNextLabel"), XXO("Move to Ne&xt Label"),
921 CaptureNotBusyFlag() | TrackPanelHasFocus(), wxT("Alt+Right"))
922 ) };
923 return items;
924}
925
927 { wxT("Optional/Extra/Part1/Select"), { OrderingHint::End, {} } },
929};
930
931}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3333
IntSetting AudioIORecordChannels
std::vector< std::vector< float > > PRCrossfadeData
Definition: AudioIOBase.h:36
Toolkit-neutral facade for basic user interface services.
AttachedItem sAttachment1
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & CaptureNotBusyFlag()
const ReservedCommandFlag & AudioIOBusyFlag()
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & TrackPanelHasFocus()
int min(int a, int b)
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
FileConfig * gPrefs
Definition: Prefs.cpp:70
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
Definition: Project.cpp:129
const ReservedCommandFlag & CanStopAudioStreamFlag()
PropertiesOfSelected GetPropertiesOfSelected(const AudacityProject &proj)
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
#define AUDIO_PRE_ROLL_KEY
#define DEFAULT_PRE_ROLL_SECONDS
#define DEFAULT_ROLL_CROSSFADE_MS
#define AUDIO_ROLL_CROSSFADE_KEY
TranslatableString label
Definition: TagsEditor.cpp:164
static const auto SetLoopInTitle
static const auto SetLoopOutTitle
const TranslatableString LoopToggleText
Definition: ViewInfo.cpp:227
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:91
static AudioIO * Get()
Definition: AudioIO.cpp:147
bool Toggle()
Write the negation of the previous value, and then return the current value.
Definition: Prefs.cpp:514
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:251
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
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
static ControlToolBar & Get(AudacityProject &project)
static DeviceManager * Instance()
Gets the singleton instance.
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:29
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
int GetNumLabels() const
Definition: LabelTrack.cpp:934
int FindPrevLabel(const SelectedRegion &currentSelection)
const LabelStruct * GetLabel(int index) const
Definition: LabelTrack.cpp:939
int FindNextLabel(const SelectedRegion &currentSelection)
bool Active() const
Definition: ViewInfo.h:124
int GetAudioIOToken() const
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static ProjectAudioIO & Get(AudacityProject &project)
void Stop(bool stopStream=true)
static WritableSampleTrackArray ChooseExistingRecordingTracks(AudacityProject &proj, bool selectedOnly, double targetRate=RATE_NOT_SELECTED)
static ProjectAudioManager & Get(AudacityProject &project)
bool DoPlayStopSelect(bool click, bool shift)
bool DoRecord(AudacityProject &project, const TransportTracks &transportTracks, double t0, double t1, bool altAppearance, const AudioIOStartStreamOptions &options)
static ProjectHistory & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
Defines a selected portion of a project.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:200
Configures sound activated recording.
static void ModifyAllProjectToolbarMenus()
Track * Get()
A start and an end time, and mutative access to optional extra information.
Definition: Track.h:206
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:487
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:231
PlayRegion playRegion
Definition: ViewInfo.h:220
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:219
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:259
std::unique_ptr< MenuItem > Menu(const Identifier &internalName, const TranslatableString &title, Args &&... args)
std::unique_ptr< MenuPart > Section(const Identifier &internalName, Args &&... args)
std::unique_ptr< MenuItems > Items(const Identifier &internalName, Args &&... args)
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
void SetPlayRegionToSelection(AudacityProject &project)
void ActivatePlayRegion(AudacityProject &project)
void OnSetRegion(AudacityProject &project, bool left, bool selection, const TranslatableString &dialogTitle)
Adjust left or right of selection or play region.
void ClearPlayRegion(AudacityProject &project)
void TogglePlayRegion(AudacityProject &project)
void OnPlayToSelection(const CommandContext &context)
void OnSetPlayRegionToSelection(const CommandContext &context)
void OnTogglePlayRecording(const CommandContext &WXUNUSED(context))
void OnMoveToNextLabel(const CommandContext &context)
void OnPlayBeforeAndAfterSelectionEnd(const CommandContext &context)
void OnSetPlayRegionIn(const CommandContext &context)
void OnToggleSWPlaythrough(const CommandContext &WXUNUSED(context))
bool MakeReadyToPlay(AudacityProject &project)
void OnMoveToPrevLabel(const CommandContext &context)
void OnPlayAfterSelectionStart(const CommandContext &context)
void OnSoundActivated(const CommandContext &context)
void OnPlayBeforeSelectionEnd(const CommandContext &context)
void OnToggleSoundActivated(const CommandContext &WXUNUSED(context))
void OnSetPlayRegionOut(const CommandContext &context)
void OnRecord(const CommandContext &context)
void DoMoveToLabel(AudacityProject &project, bool next)
void OnRecord2ndChoice(const CommandContext &context)
void OnPause(const CommandContext &context)
void OnPlayAfterSelectionEnd(const CommandContext &context)
void OnPlayBeforeAndAfterSelectionStart(const CommandContext &context)
void OnPlayDefaultOrStop(const CommandContext &context)
void OnRescanDevices(const CommandContext &WXUNUSED(context))
void OnPlayStopSelect(const CommandContext &context)
void OnTogglePlayRegion(const CommandContext &context)
void OnPlayCutPreview(const CommandContext &context)
void OnStop(const CommandContext &context)
void OnPlayOneSecond(const CommandContext &context)
void OnPlayOnceOrStop(const CommandContext &context)
void OnClearPlayRegion(const CommandContext &context)
void OnPlayBeforeSelectionStart(const CommandContext &context)
bool IsLoopingEnabled(const AudacityProject &project)
Options && CheckTest(const CheckFn &fn) &&
WritableSampleTrackArray captureTracks
Definition: AudioIO.h:88
SampleTrackConstArray playbackTracks
Definition: AudioIO.h:87
static void PlayPlayRegionAndWait(const CommandContext &context, const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode mode)
static bool DoStopPlaying(const CommandContext &context)
static void PlayCurrentRegionAndWait(const CommandContext &context, bool newDefault=false, bool cutpreview=false)
static void RecordAndWait(const CommandContext &context, bool altAppearance)
static void DoStartPlaying(const CommandContext &context, bool newDefault=false)