Audacity 3.2.0
DeviceToolBar.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 DeviceToolBar.cpp
6
7 Dominic Mazzoni
8
9*******************************************************************//*******************************************************************/
15
16
17
18#include "DeviceToolBar.h"
19#include "ToolManager.h"
20
21#include <thread>
22
23// For compilers that support precompilation, includes "wx/wx.h".
24#include <wx/wxprec.h>
25
26#include <wx/setup.h> // for wxUSE_* macros
27
28#ifndef WX_PRECOMP
29#include <wx/app.h>
30#include <wx/choice.h>
31#include <wx/settings.h>
32#include <wx/sizer.h>
33#include <wx/statbmp.h>
34#include <wx/stattext.h>
35#include <wx/tooltip.h>
36#endif
37
38#include "../TrackPanel.h"
39
40#include "AColor.h"
41#include "AllThemeResources.h"
42#include "AudioIOBase.h"
43#include "ImageManipulation.h"
44#include "../KeyboardCapture.h"
45#include "Prefs.h"
46#include "Project.h"
47#include "ShuttleGui.h"
48#include "../widgets/Grabber.h"
49#include "DeviceManager.h"
50#include "AudacityMessageBox.h"
51
52#if wxUSE_ACCESSIBILITY
53#include "WindowAccessible.h"
54#endif
55
57
61
62BEGIN_EVENT_TABLE(DeviceToolBar, ToolBar)
63 EVT_CHOICE(wxID_ANY, DeviceToolBar::OnChoice)
64 EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, DeviceToolBar::OnCaptureKey)
66
68{
69 static int value = wxNewId();
70 return value;
71}
72
74{
75 return wxT("Device");
76}
77
78//Standard constructor
80: ToolBar( project, XO("Device"), ID(), true )
81{
84}
85
87{
88}
89
91{
92 return false;
93}
94
96{
97 auto &toolManager = ToolManager::Get( project );
98 return *static_cast<DeviceToolBar*>(toolManager.GetToolBar(ID()));
99}
100
102{
103 return Get( const_cast<AudacityProject&>( project )) ;
104}
105
106void DeviceToolBar::Create(wxWindow *parent)
107{
108 ToolBar::Create(parent);
109
110 // Simulate a size event to set initial meter placement/size
111 wxSizeEvent event(GetSize(), GetId());
112 event.SetEventObject(this);
113 GetEventHandler()->ProcessEvent(event);
114}
115
117{
118 mInput = NULL;
119 mOutput = NULL;
120 mInputChannels = NULL;
121 mHost = NULL;
122}
123
125{
126 SetBackgroundColour( theTheme.Colour( clrMedium ) );
128
129 // Hosts
130 mHost = safenew wxChoice(this,
131 wxID_ANY,
132 wxDefaultPosition,
133 wxDefaultSize);
134#if wxUSE_ACCESSIBILITY
135 // so that name can be set on a standard control
136 mHost->SetAccessible(safenew WindowAccessible(mHost));
137#endif
138 Add(mHost, 15, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 1);
139
140 // Input device
142 wxID_ANY,
143 theTheme.Bitmap(bmpMic)), 0, wxALIGN_CENTER_VERTICAL);
144 mInput = safenew wxChoice(this,
145 wxID_ANY,
146 wxDefaultPosition,
147 wxDefaultSize);
148#if wxUSE_ACCESSIBILITY
149 // so that name can be set on a standard control
150 mInput->SetAccessible(safenew WindowAccessible(mInput));
151#endif
152 Add(mInput, 30, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 1);
153
154 // Input channels
155 mInputChannels = safenew wxChoice(this,
156 wxID_ANY,
157 wxDefaultPosition,
158 wxDefaultSize);
159#if wxUSE_ACCESSIBILITY
160 // so that name can be set on a standard control
162#endif
163 Add(mInputChannels, 20, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 1);
164
165 // Output device
167 wxID_ANY,
168 theTheme.Bitmap(bmpSpeaker)), 0, wxALIGN_CENTER_VERTICAL);
169 mOutput = safenew wxChoice(this,
170 wxID_ANY,
171 wxDefaultPosition,
172 wxDefaultSize);
173#if wxUSE_ACCESSIBILITY
174 // so that name can be set on a standard control
175 mOutput->SetAccessible(safenew WindowAccessible(mOutput));
176#endif
177 Add(mOutput, 30, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 1);
178
179#if defined(__WXGTK3__)
180 // Nothing special
181#elif defined(__WXGTK__)
182 // Scale the font to fit inside (hopefully)
183 wxFont font = mHost->GetFont();
184 font.Scale((double) toolbarSingle / mHost->GetSize().GetHeight());
185
186 // Set it
187 mHost->SetFont(font);
188 mInput->SetFont(font);
189 mInputChannels->SetFont(font);
190 mOutput->SetFont(font);
191#endif
192
193 mHost->Bind(wxEVT_SET_FOCUS,
195 this);
196 mHost->Bind(wxEVT_KILL_FOCUS,
198 this);
199 mOutput->Bind(wxEVT_SET_FOCUS,
201 this);
202 mOutput->Bind(wxEVT_KILL_FOCUS,
204 this);
205 mInput->Bind(wxEVT_SET_FOCUS,
207 this);
208 mInput->Bind(wxEVT_KILL_FOCUS,
210 this);
211 mInputChannels->Bind(wxEVT_SET_FOCUS,
213 this);
214 mInputChannels->Bind(wxEVT_KILL_FOCUS,
216 this);
217
218 SetNames();
219
220 RefillCombos();
221}
222
223void DeviceToolBar::OnFocus(wxFocusEvent &event)
224{
225 KeyboardCapture::OnFocus( *this, event );
226}
227
228void DeviceToolBar::OnCaptureKey(wxCommandEvent &event)
229{
230 wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
231 int keyCode = kevent->GetKeyCode();
232
233 // Pass UP/DOWN/LEFT/RIGHT through for input/output choice
234 if (FindFocus() == mInput && (keyCode == WXK_LEFT || keyCode == WXK_RIGHT
235 || keyCode == WXK_UP || keyCode == WXK_DOWN)) {
236 return;
237 }
238
239 if (FindFocus() == mOutput && (keyCode == WXK_LEFT || keyCode == WXK_RIGHT
240 || keyCode == WXK_UP || keyCode == WXK_DOWN)) {
241 return;
242 }
243 event.Skip();
244
245 return;
246}
247
249{
250 wxString desc;
251 const std::vector<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
252 const std::vector<DeviceSourceMap> &outMaps = DeviceManager::Instance()->GetOutputDeviceMaps();
253
254
255 int hostSelectionIndex = mHost->GetSelection();
256 wxString oldHost = hostSelectionIndex >= 0 ? mHost->GetString(hostSelectionIndex) :
257 wxString{};
258 auto hostName = AudioIOHost.Read();
259
260 // if the prefs host name doesn't match the one displayed, it changed
261 // in another project's DeviceToolBar, so we need to repopulate everything.
262 if (oldHost != hostName)
264
265 auto devName = AudioIORecordingDevice.Read();
266 auto sourceName = AudioIORecordingSource.Read();
267 if (sourceName.empty())
268 desc = devName;
269 else
270 desc = devName + wxT(": ") + sourceName;
271
272 if (mInput->GetStringSelection() != desc &&
273 mInput->FindString(desc) != wxNOT_FOUND) {
274 mInput->SetStringSelection(desc);
276 } else if (mInput->GetStringSelection() != desc && mInput->GetCount()) {
277 for (size_t i = 0; i < inMaps.size(); i++) {
278 if (inMaps[i].hostString == hostName &&
279 MakeDeviceSourceString(&inMaps[i]) == mInput->GetString(0)) {
280 // use the default. It should exist but check just in case, falling back on the 0 index.
281 DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultInputDevice(inMaps[i].hostIndex);
282 if (defaultMap) {
283 mInput->SetStringSelection(MakeDeviceSourceString(defaultMap));
284 SetDevices(defaultMap, NULL);
285 } else {
286 //use the first item (0th index) if we have no familiar devices
287 mInput->SetSelection(0);
288 SetDevices(&inMaps[i], NULL);
289 }
290 break;
291 }
292 }
293 }
294
295 devName = AudioIOPlaybackDevice.Read();
296 sourceName = AudioIOPlaybackSource.Read();
297 if (sourceName.empty())
298 desc = devName;
299 else
300 desc = devName + wxT(": ") + sourceName;
301
302 if (mOutput->GetStringSelection() != desc &&
303 mOutput->FindString(desc) != wxNOT_FOUND) {
304 mOutput->SetStringSelection(desc);
305 } else if (mOutput->GetStringSelection() != desc &&
306 mOutput->GetCount()) {
307 for (size_t i = 0; i < outMaps.size(); i++) {
308 if (outMaps[i].hostString == hostName &&
309 MakeDeviceSourceString(&outMaps[i]) == mOutput->GetString(0)) {
310 // use the default. It should exist but check just in case, falling back on the 0 index.
311 DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultOutputDevice(outMaps[i].hostIndex);
312 if (defaultMap) {
313 mOutput->SetStringSelection(MakeDeviceSourceString(defaultMap));
314 SetDevices(NULL, defaultMap);
315 } else {
316 //use the first item (0th index) if we have no familiar devices
317 mOutput->SetSelection(0);
318 SetDevices(NULL, &outMaps[i]);
319 }
320 break;
321 }
322 }
323 }
324
325 long oldChannels;
326 oldChannels = mInputChannels->GetSelection() + 1;
327 auto newChannels = AudioIORecordChannels.ReadWithDefault(0);
328 if (newChannels > 0 && oldChannels != newChannels)
329 mInputChannels->SetSelection(newChannels - 1);
330
331 if (!hostName.empty() && mHost->GetStringSelection() != hostName)
332 mHost->SetStringSelection(hostName);
333
335
336 // Set label to pull in language change
337 SetLabel(XO("Device"));
338
339 // Give base class a chance
341
342 Layout();
343 Refresh();
344}
345
347{
348 if (id == DeviceToolbarPrefsID())
349 UpdatePrefs();
351}
352
353
355{
356 auto gAudioIO = AudioIOBase::Get();
357 if (gAudioIO) {
358 // we allow changes when monitoring, but not when recording
359 bool audioStreamActive = gAudioIO->IsStreamActive() && !gAudioIO->IsMonitoring();
360
361 // Here we should relinquish focus
362 if (audioStreamActive) {
363 wxWindow *focus = wxWindow::FindFocus();
364 if (focus == mHost || focus == mInput || focus == mOutput || focus == mInputChannels)
365 TrackPanel::Get( mProject ).SetFocus();
366 }
367
368 mHost->Enable(!audioStreamActive);
369 mInput->Enable(!audioStreamActive);
370 mOutput->Enable(!audioStreamActive);
371 mInputChannels->Enable(!audioStreamActive);
372 }
373}
374
376{
377 /* i18n-hint: (noun) It's the device used for playback.*/
378 mOutput->SetName(_("Playback Device"));
379 /* i18n-hint: (noun) It's the device used for recording.*/
380 mInput->SetName(_("Recording Device"));
381 mHost->SetName(_("Audio Host"));
382 mInputChannels->SetName(_("Recording Channels"));
383}
384
386{
387#if wxUSE_TOOLTIPS
388 SetNames();
389 mOutput->SetToolTip(mOutput->GetName() + wxT(" - ") + mOutput->GetStringSelection());
390 mInput->SetToolTip(mInput->GetName() + wxT(" - ") + mInput->GetStringSelection());
391 mHost->SetToolTip(mHost->GetName() + wxT(" - ") + mHost->GetStringSelection());
392 mInputChannels->SetToolTip(mInputChannels->GetName() + wxT(" - ") + mInputChannels->GetStringSelection());
393#endif
394}
395
397{
398 FillHosts();
401 // make the device display selection reflect the prefs if they exist
402 UpdatePrefs();
403}
404
406{
407 const std::vector<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
408 const std::vector<DeviceSourceMap> &outMaps = DeviceManager::Instance()->GetOutputDeviceMaps();
409
410 wxArrayString hosts;
411
412 // go over our lists add the host to the list if it isn't there yet
413
414 for (auto & device : inMaps) {
415 if (!make_iterator_range(hosts).contains(device.hostString)) {
416 hosts.push_back(device.hostString);
417 }
418 }
419
420 for (auto & device : outMaps) {
421 if (!make_iterator_range(hosts).contains(device.hostString)) {
422 hosts.push_back(device.hostString);
423 }
424 }
425
426 mHost->Clear();
427 mHost->Append(hosts);
428
429 if (hosts.size() == 0) {
430 mHost->Enable(false);
431 }
432
433 mHost->SetMinSize(wxSize(50, wxDefaultCoord));
434}
435
437{
438 const std::vector<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
439 const std::vector<DeviceSourceMap> &outMaps = DeviceManager::Instance()->GetOutputDeviceMaps();
440
441 //read what is in the prefs
442 auto host = AudioIOHost.Read();
443 int foundHostIndex = -1;
444
445 // if the host is not in the hosts combo then we rescanned.
446 // set it to blank so we search for another host.
447 if (mHost->FindString(host) == wxNOT_FOUND) {
448 host = wxT("");
449 }
450
451 for (auto & device : outMaps) {
452 if (device.hostString == host) {
453 foundHostIndex = device.hostIndex;
454 break;
455 }
456 }
457
458 if (foundHostIndex == -1) {
459 for (auto & device : inMaps) {
460 if (device.hostString == host) {
461 foundHostIndex = device.hostIndex;
462 break;
463 }
464 }
465 }
466
467 // If no host was found based on the prefs device host, load the first available one
468 if (foundHostIndex == -1) {
469 if (outMaps.size()) {
470 foundHostIndex = outMaps[0].hostIndex;
471 }
472 else if (inMaps.size()) {
473 foundHostIndex = inMaps[0].hostIndex;
474 }
475 }
476
477 // Make sure in/out are clear in case no host was found
478 mInput->Clear();
479 mOutput->Clear();
480
481 // If we still have no host it means no devices, in which case do nothing.
482 if (foundHostIndex == -1) {
483 return;
484 }
485
486 // Repopulate the Input/Output device list available to the user
487 for (auto & device : inMaps) {
488 if (foundHostIndex == device.hostIndex) {
489 mInput->Append(MakeDeviceSourceString(&device));
490 if (host.empty()) {
491 host = device.hostString;
492 AudioIOHost.Write(host);
493 mHost->SetStringSelection(host);
494 }
495 }
496 }
497 mInput->Enable(mInput->GetCount() ? true : false);
498
499 mInput->SetMinSize(wxSize(50, wxDefaultCoord));
500
501 for (auto & device : outMaps) {
502 if (foundHostIndex == device.hostIndex) {
503 mOutput->Append(MakeDeviceSourceString(&device));
504 if (host.empty()) {
505 host = device.hostString;
506 AudioIOHost.Write(host);
507 gPrefs->Flush();
508 mHost->SetStringSelection(host);
509 }
510 }
511 }
512 mOutput->Enable(mOutput->GetCount() ? true : false);
513
514 mOutput->SetMinSize(wxSize(50, wxDefaultCoord));
515
516 // The setting of the Device is left up to OnChoice
517}
518
520{
521 const std::vector<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
522 auto host = AudioIOHost.Read();
523 auto device = AudioIORecordingDevice.Read();
524 auto source = AudioIORecordingSource.Read();
525 long newChannels;
526
527 auto oldChannels = AudioIORecordChannels.Read();
528 mInputChannels->Clear();
529 for (auto & dev: inMaps) {
530 if (source == dev.sourceString &&
531 device == dev.deviceString &&
532 host == dev.hostString) {
533
534 // add one selection for each channel of this source
535 for (size_t j = 0; j < (unsigned int) dev.numChannels; j++) {
536 wxString name;
537
538 if (j == 0) {
539 name = _("1 (Mono) Recording Channel");
540 }
541 else if (j == 1) {
542 name = _("2 (Stereo) Recording Channels");
543 }
544 else {
545 name = wxString::Format(wxT("%d"), (int) j + 1);
546 }
547 mInputChannels->Append(name);
548 }
549 newChannels = dev.numChannels;
550 if (oldChannels <= newChannels && oldChannels >= 1) {
551 newChannels = oldChannels;
552 }
553 if (newChannels >= 1) {
554 mInputChannels->SetSelection(newChannels - 1);
555 }
556 AudioIORecordChannels.Write(newChannels);
557 break;
558 }
559 }
560 mInputChannels->Enable(mInputChannels->GetCount() ? true : false);
561
562 mInputChannels->SetMinSize(wxSize(50, wxDefaultCoord));
563}
564
566{
567 // Hosts may have disappeared or appeared so a complete repopulate is needed.
569 RefillCombos();
570}
571
572//return 1 if host changed, 0 otherwise.
574{
575 int hostSelectionIndex;
576 hostSelectionIndex = mHost->GetSelection();
577
578 auto oldHost = AudioIOHost.Read();
579 wxString newHost = hostSelectionIndex >= 0 ? mHost->GetString(hostSelectionIndex) :
580 oldHost;
581
582 if (oldHost == newHost)
583 return 0;
584
585 //change the host and switch to correct devices.
586 AudioIOHost.Write(newHost);
587 gPrefs->Flush();
588
589 // populate the devices
591
592 return 1;
593}
594
596{
597 if (in) {
600 if (in->totalSources >= 1)
602 else
604 gPrefs->Flush();
605
607 }
608
609 if (out) {
611 if (out->totalSources >= 1) {
613 } else {
615 }
616 gPrefs->Flush();
617 }
618}
619
621{
622 int newIndex = -1;
623 wxChoice *combo = isInput ? mInput :mOutput;
624 size_t i;
625
626 int selectionIndex = combo->GetSelection();
627 auto host = AudioIOHost.Read();
628 const std::vector<DeviceSourceMap> &maps = isInput ? DeviceManager::Instance()->GetInputDeviceMaps()
630
631 // Find device indices for input and output
632 if (selectionIndex >= 0 ) {
633 wxString newDevice = combo->GetStringSelection();
634 for (i = 0; i < maps.size(); ++i) {
635 wxString name;
636 name = MakeDeviceSourceString(&maps[i]);
637 if (name == newDevice && maps[i].hostString == host) {
638 newIndex = i;
639 }
640 }
641 }
642
643 if (newIndex < 0) {
644 wxLogDebug(wxT("DeviceToolBar::OnChoice(): couldn't find device indices"));
645 return;
646 }
647
648 SetDevices(isInput ? &maps[newIndex] : NULL,
649 isInput ? NULL : &maps[newIndex]);
650}
651
652void DeviceToolBar::OnChoice(wxCommandEvent &event)
653{
654 wxObject *eventObject = event.GetEventObject();
655 //if we've changed hosts, we've handled the device switching already.
656 if (eventObject == mHost) {
657 ChangeHost();
658 } else if (eventObject == mInputChannels) {
659 int channelsSelectionIndex = mInputChannels->GetSelection();
660 if (channelsSelectionIndex >= 0)
661 AudioIORecordChannels.Write(channelsSelectionIndex + 1);
662 } else if (eventObject == mInput) {
663 ChangeDevice(true);
664 }
665 else if (eventObject == mOutput) {
666 ChangeDevice(false);
667 }
668
669 auto gAudioIO = AudioIOBase::Get();
670 if (gAudioIO) {
671 // We cannot have gotten here if gAudioIO->IsAudioTokenActive(),
672 // per the setting of AudioIONotBusyFlag and AudioIOBusyFlag in
673 // AudacityProject::GetUpdateFlags().
674 // However, we can have an invalid audio token (so IsAudioTokenActive()
675 // is false), but be monitoring.
676 // If monitoring, have to stop the stream, so HandleDeviceChange() can work.
677 // We could disable the Preferences command while monitoring, i.e.,
678 // set AudioIONotBusyFlag/AudioIOBusyFlag according to monitoring, as well.
679 // Instead allow it because unlike recording, for example, monitoring
680 // is not clearly something that should prohibit changing device.
681 // TODO: We *could* be smarter in this method and call HandleDeviceChange()
682 // only when the device choices actually changed. True of lots of prefs!
683 // As is, we always stop monitoring before handling the device change.
684 if (gAudioIO->IsMonitoring())
685 {
686 gAudioIO->StopStream();
687 while (gAudioIO->IsBusy()) {
688 using namespace std::chrono;
689 std::this_thread::sleep_for(100ms);
690 }
691 }
692 gAudioIO->HandleDeviceChange();
693 }
694
696}
697
699{
700 ShowComboDialog(mInput, XO("Select Recording Device"));
701}
703{
704 ShowComboDialog(mOutput, XO("Select Playback Device"));
705}
707{
708 ShowComboDialog(mHost, XO("Select Audio Host"));
709}
711{
712 ShowComboDialog(mInputChannels, XO("Select Recording Channels"));
713}
714
716{
717 if (!combo || combo->GetCount() == 0) {
718 AudacityMessageBox( XO("Device information is not available.") );
719 return;
720 }
721
722#if USE_PORTMIXER
723 wxArrayStringEx inputSources = combo->GetStrings();
724
725 wxDialogWrapper dlg(nullptr, wxID_ANY, title);
726 dlg.SetName();
727 ShuttleGui S(&dlg, eIsCreating);
728 wxChoice *c;
729
730 S.StartVerticalLay(true);
731 {
732 S.StartHorizontalLay(wxCENTER, false);
733 {
734 c = S.AddChoice( Verbatim( combo->GetName() ),
735 transform_container<TranslatableStrings>( inputSources, Verbatim ),
736 combo->GetSelection());
737 c->SetMinSize(c->GetBestSize());
738 }
739 S.EndHorizontalLay();
740 }
741 S.EndVerticalLay();
742 S.AddStandardButtons();
743
744 dlg.GetSizer()->SetSizeHints(&dlg);
745 dlg.Center();
746
747 if (dlg.ShowModal() == wxID_OK)
748 {
749 wxCommandEvent dummyEvent;
750 dummyEvent.SetEventObject(combo);
751 // SetSelection() doesn't send an event, so we call OnChoice explicitly
752 combo->SetSelection(c->GetSelection());
753 OnChoice(dummyEvent);
754 }
755#endif
756}
757
761};
762
763namespace {
765 /* i18n-hint: Clicking this menu item shows the toolbar
766 that manages devices */
767 DeviceToolBar::ID(), wxT("ShowDeviceTB"), XXO("&Device Toolbar")
768};
769}
770
771
772// Define some related menu items
773#include "CommandContext.h"
774#include "../CommonCommandFlags.h"
775
776namespace {
777void OnInputDevice(const CommandContext &context)
778{
779 auto &project = context.project;
780 auto &tb = DeviceToolBar::Get( project );
781 tb.ShowInputDialog();
782}
783
784void OnOutputDevice(const CommandContext &context)
785{
786 auto &project = context.project;
787 auto &tb = DeviceToolBar::Get( project );
788 tb.ShowOutputDialog();
789}
790
791void OnInputChannels(const CommandContext &context)
792{
793 auto &project = context.project;
794 auto &tb = DeviceToolBar::Get( project );
795 tb.ShowChannelsDialog();
796}
797
798void OnAudioHost(const CommandContext &context)
799{
800 auto &project = context.project;
801 auto &tb = DeviceToolBar::Get( project );
802 tb.ShowHostDialog();
803}
804
805// Menu definitions
806
807using namespace MenuRegistry;
808// Under /MenuBar/Optional/Extra/Part1
810{
811 static auto menu = std::shared_ptr{
812 Menu( wxT("Device"), XXO("De&vice"),
813 Command( wxT("InputDevice"), XXO("Change &Recording Device..."),
815 AudioIONotBusyFlag(), wxT("Shift+I") ),
816 Command( wxT("OutputDevice"), XXO("Change &Playback Device..."),
818 AudioIONotBusyFlag(), wxT("Shift+O") ),
819 Command( wxT("AudioHost"), XXO("Change Audio &Host..."), OnAudioHost,
820 AudioIONotBusyFlag(), wxT("Shift+H") ),
821 Command( wxT("InputChannels"), XXO("Change Recording Cha&nnels..."),
823 AudioIONotBusyFlag(), wxT("Shift+N") )
824 ) };
825 return menu;
826}
827
829 Placement{ wxT("Optional/Extra/Part1"), { OrderingHint::End } }
830};
831
832}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
StringSetting AudioIORecordingSource
StringSetting AudioIOPlaybackSource
StringSetting AudioIOPlaybackDevice
StringSetting AudioIORecordingDevice
StringSetting AudioIOHost
IntSetting AudioIORecordingSourceIndex
IntSetting AudioIORecordChannels
END_EVENT_TABLE()
AttachedItem sAttachment2
const ReservedCommandFlag & AudioIONotBusyFlag()
DeviceChangeMessage
Definition: DeviceChange.h:16
wxString MakeDeviceSourceString(const DeviceSourceMap *map)
int DeviceToolbarPrefsID()
Methods for DeviceToolBar.
IMPLEMENT_CLASS(DeviceToolBar, ToolBar)
static RegisteredToolbarFactory factory
const TranslatableString name
Definition: Distortion.cpp:76
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:89
#define safenew
Definition: MemoryX.h:10
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:448
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
@ eIsCreating
Definition: ShuttleGui.h:37
const auto project
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
#define toolbarSingle
Definition: ToolBar.h:59
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
A widget for bitmaps which ignores the erase event for flicker-free use.
Definition: Grabber.h:155
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:93
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
DeviceSourceMap * GetDefaultInputDevice(int hostIndex)
const std::vector< DeviceSourceMap > & GetInputDeviceMaps()
const std::vector< DeviceSourceMap > & GetOutputDeviceMaps()
static DeviceManager * Instance()
Gets the singleton instance.
DeviceSourceMap * GetDefaultOutputDevice(int hostIndex)
A toobar to allow easier changing of input and output devices .
Definition: DeviceToolBar.h:27
wxChoice * mOutput
Definition: DeviceToolBar.h:80
void FillInputChannels()
void ShowOutputDialog()
void Populate() override
void ShowChannelsDialog()
void OnCaptureKey(wxCommandEvent &event)
void SetDevices(const DeviceSourceMap *in, const DeviceSourceMap *out)
void RegenerateTooltips() override
wxChoice * mHost
Definition: DeviceToolBar.h:82
wxChoice * mInputChannels
Definition: DeviceToolBar.h:81
void EnableDisableButtons() override
void OnFocus(wxFocusEvent &event)
void ShowComboDialog(wxChoice *combo, const TranslatableString &title)
Observer::Subscription mSubscription
Definition: DeviceToolBar.h:84
void ChangeDevice(bool isInput)
bool ShownByDefault() const override
Whether the toolbar should be shown by default. Default implementation returns true.
void UpdateSelectedPrefs(int) override
void FillHostDevices()
static DeviceToolBar & Get(AudacityProject &project)
void ShowInputDialog()
static Identifier ID()
wxChoice * mInput
Definition: DeviceToolBar.h:79
void OnRescannedDevices(DeviceChangeMessage)
DeviceToolBar(AudacityProject &project)
virtual ~DeviceToolBar()
void UpdatePrefs() override
void Create(wxWindow *parent) override
void OnChoice(wxCommandEvent &event)
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
Definition: Prefs.cpp:99
virtual void UpdateSelectedPrefs(int id)
Definition: Prefs.cpp:129
Generates classes whose instances register items at construction.
Definition: Registry.h:388
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:257
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:211
bool Reset()
Reset to the default value.
Definition: Prefs.h:282
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:205
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:630
wxColour & Colour(int iIndex)
wxBitmap & Bitmap(int iIndex)
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed.
Definition: ToolBar.h:74
AudacityProject & mProject
Definition: ToolBar.h:248
void Add(wxWindow *window, int proportion=0, int flag=wxALIGN_TOP, int border=0, wxObject *userData=NULL)
Definition: ToolBar.cpp:709
void SetLabel(const wxString &label) override
Definition: ToolBar.cpp:408
void UpdatePrefs() override
Definition: ToolBar.cpp:622
virtual void Create(wxWindow *parent)
Definition: ToolBar.cpp:492
wxWindowPtr< ToolBar > Holder
Definition: ToolBar.h:78
static ToolManager & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:233
Holds a msgid for the translation catalog; may also bind format arguments.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
virtual bool Flush() noexcept=0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
void SetName(const TranslatableString &title)
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:373
void OnFocus(wxWindow &window, wxFocusEvent &event)
a function useful to implement a focus event handler The window releases the keyboard if the event is...
constexpr auto Command
Definition: MenuRegistry.h:456
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
Definition: MenuRegistry.h:445
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
void OnInputDevice(const CommandContext &context)
void OnInputChannels(const CommandContext &context)
void OnAudioHost(const CommandContext &context)
void OnOutputDevice(const CommandContext &context)
const TranslatableString desc
Definition: ExportPCM.cpp:51
wxString sourceString
Definition: DeviceManager.h:34
wxString deviceString
Definition: DeviceManager.h:35