Audacity 3.2.0
MidiIOPrefs.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 MidiIOPrefs.cpp
6
7 Joshua Haberman
8 Dominic Mazzoni
9 James Crook
10
11*******************************************************************//********************************************************************/
25
26
27#include "MidiIOPrefs.h"
28
29#include <wx/defs.h>
30
31#include <wx/choice.h>
32#include <wx/textctrl.h>
33
34#include <portmidi.h>
35
36#include "NoteTrack.h"
37#include "Prefs.h"
38#include "ShuttleGui.h"
39#include "AudacityMessageBox.h"
40
41enum {
42 HostID = 10000,
46};
47
48BEGIN_EVENT_TABLE(MidiIOPrefs, PrefsPanel)
49 EVT_CHOICE(HostID, MidiIOPrefs::OnHost)
50// EVT_CHOICE(RecordID, MidiIOPrefs::OnDevice)
52
53MidiIOPrefs::MidiIOPrefs(wxWindow * parent, wxWindowID winid)
54/* i18n-hint: untranslatable acronym for "Musical Instrument Device Interface" */
55: PrefsPanel(parent, winid, XO("MIDI Devices"))
56{
57 Populate();
58}
59
61{
62}
63
65{
67}
68
70{
71 return XO("Preferences for MidiIO");
72}
73
75{
76 return "MIDI_Devices_Preferences";
77}
78
80{
81 // First any pre-processing for constructing the GUI.
83
84 // Get current setting for devices
86#ifdef EXPERIMENTAL_MIDI_IN
87 mRecordDevice = MIDIRecordingDevice.Read();
88#endif
89// mRecordChannels = gPrefs->Read(wxT("/MidiIO/RecordChannels"), 2L);
90
91 //------------------------- Main section --------------------
92 // Now construct the GUI itself.
93 // Use 'eIsCreatingFromPrefs' so that the GUI is
94 // initialised with values from gPrefs.
97 // ----------------------- End of main section --------------
98
99 wxCommandEvent e;
100 OnHost(e);
101}
102
108 // Gather list of hosts. Only added hosts that have devices attached.
109 Pm_Terminate(); // close and open to refresh device lists
110 Pm_Initialize();
111 int nDevices = Pm_CountDevices();
112 for (int i = 0; i < nDevices; i++) {
113 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
114 if (info->output || info->input) { //should always happen
115 wxString name = wxSafeConvertMB2WX(info->interf);
117 .contains( Verbatim( name ) )) {
118 mHostNames.push_back( Verbatim( name ) );
119 mHostLabels.push_back(name);
120 }
121 }
122 }
123
124 if (nDevices == 0) {
125 mHostNames.push_back(XO("No MIDI interfaces"));
126 mHostLabels.push_back(wxT("No MIDI interfaces"));
127 }
128}
129
131{
132 ChoiceSetting Setting{ L"/MidiIO/Host",
134 };
135
136 S.SetBorder(2);
137 S.StartScroller();
138
139 /* i18n-hint Software interface to MIDI */
140 S.StartStatic(XC("Interface", "MIDI"));
141 {
142 S.StartMultiColumn(2);
143 {
144 S.Id(HostID);
145 /* i18n-hint: (noun) */
146 mHost = S.TieChoice(XXO("&Host:"), Setting);
147
148 S.AddPrompt(XXO("Using: PortMidi"));
149 }
150 S.EndMultiColumn();
151 }
152 S.EndStatic();
153
154 S.StartStatic(XO("Playback"));
155 {
156 S.StartMultiColumn(2);
157 {
158 S.Id(PlayID);
159 mPlay = S.AddChoice(XXO("&Device:"),
160 {} );
161 mLatency = S.TieIntegerTextBox(XXO("MIDI Synth L&atency (ms):"),
163 }
164 S.EndMultiColumn();
165 }
166 S.EndStatic();
167#ifdef EXPERIMENTAL_MIDI_IN
168 S.StartStatic(XO("Recording"));
169 {
170 S.StartMultiColumn(2);
171 {
172 S.Id(RecordID);
173 mRecord = S.AddChoice(XO("De&vice:"),
174 {} );
175
176 S.Id(ChannelsID);
177 /*
178 mChannels = S.AddChoice(XO("&Channels:"),
179 wxEmptyString,
180 {} );
181 */
182 }
183 S.EndMultiColumn();
184 }
185 S.EndStatic();
186#endif
187 S.EndScroller();
188
189}
190
191void MidiIOPrefs::OnHost(wxCommandEvent & WXUNUSED(e))
192{
193 wxString itemAtIndex;
194 int index = mHost->GetCurrentSelection();
195 if (index >= 0 && index < (int)mHostNames.size())
196 itemAtIndex = mHostLabels[index];
197 int nDevices = Pm_CountDevices();
198
199 mPlay->Clear();
200#ifdef EXPERIMENTAL_MIDI_IN
201 mRecord->Clear();
202#endif
203
204 wxArrayStringEx playnames;
205 wxArrayStringEx recordnames;
206
207 for (int i = 0; i < nDevices; i++) {
208 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
209 wxString interf = wxSafeConvertMB2WX(info->interf);
210 if (itemAtIndex == interf) {
211 wxString name = wxSafeConvertMB2WX(info->name);
212 wxString device = wxString::Format(wxT("%s: %s"),
213 interf,
214 name);
215 if (info->output) {
216 playnames.push_back(name);
217 index = mPlay->Append(name, (void *) info);
218 if (device == mPlayDevice) {
219 mPlay->SetSelection(index);
220 }
221 }
222#ifdef EXPERIMENTAL_MIDI_IN
223 if (info->input) {
224 recordnames.push_back(name);
225 index = mRecord->Append(name, (void *) info);
226 if (device == mRecordDevice) {
227 mRecord->SetSelection(index);
228 }
229 }
230#endif
231 }
232 }
233
234 if (mPlay->GetCount() == 0) {
235 playnames.push_back(_("No devices found"));
236 mPlay->Append(playnames[0], (void *) NULL);
237 }
238#ifdef EXPERIMENTAL_MIDI_IN
239 if (mRecord->GetCount() == 0) {
240 recordnames.push_back(_("No devices found"));
241 mRecord->Append(recordnames[0], (void *) NULL);
242 }
243#endif
244 if (mPlay->GetCount() && mPlay->GetSelection() == wxNOT_FOUND) {
245 mPlay->SetSelection(0);
246 }
247#ifdef EXPERIMENTAL_MIDI_IN
248 if (mRecord->GetCount() && mRecord->GetSelection() == wxNOT_FOUND) {
249 mRecord->SetSelection(0);
250 }
251#endif
252 ShuttleGui::SetMinSize(mPlay, playnames);
253#ifdef EXPERIMENTAL_MIDI_IN
254 ShuttleGui::SetMinSize(mRecord, recordnames);
255#endif
256// OnDevice(e);
257}
258
260{
263
264 const PmDeviceInfo *info;
265
266 info = (const PmDeviceInfo *) mPlay->GetClientData(mPlay->GetSelection());
267 if (info) {
269 wxString::Format(wxT("%s: %s"),
270 wxString(wxSafeConvertMB2WX(info->interf)),
271 wxString(wxSafeConvertMB2WX(info->name))));
272 }
273#ifdef EXPERIMENTAL_MIDI_IN
274 info = (const PmDeviceInfo *) mRecord->GetClientData(mRecord->GetSelection());
275 if (info) {
276 MidiRecordingDevice.Write(
277 wxString::Format(wxT("%s: %s"),
278 wxString(wxSafeConvertMB2WX(info->interf)),
279 wxString(wxSafeConvertMB2WX(info->name))));
280 }
281#endif
283 return gPrefs->Flush();
284}
285
287{
288 long latency;
289 if (!mLatency->GetValue().ToLong(&latency)) {
291"The MIDI Synthesizer Latency must be an integer") );
292 return false;
293 }
294 return true;
295}
296
297namespace{
299 [](wxWindow *parent, wxWindowID winid, AudacityProject *)
300 {
301 wxASSERT(parent); // to justify safenew
302 return safenew MidiIOPrefs(parent, winid);
303 },
304 false,
305 // Register with an explicit ordering hint because this one is
306 // only conditionally compiled
307 { "", { Registry::OrderingHint::After, "Recording" } }
308};
309}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
END_EVENT_TABLE()
const TranslatableString name
Definition: Distortion.cpp:76
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define XC(s, c)
Definition: Internat.h:37
#define _(s)
Definition: Internat.h:73
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: IteratorX.h:210
#define safenew
Definition: MemoryX.h:9
@ ChannelsID
Definition: MidiIOPrefs.cpp:45
@ PlayID
Definition: MidiIOPrefs.cpp:43
@ HostID
Definition: MidiIOPrefs.cpp:42
@ RecordID
Definition: MidiIOPrefs.cpp:44
#define MIDI_IO_PREFS_PLUGIN_SYMBOL
Definition: MidiIOPrefs.h:23
IntSetting MIDISynthLatency_ms
Definition: NoteTrack.cpp:985
StringSetting MIDIRecordingDevice
Definition: NoteTrack.cpp:984
StringSetting MIDIPlaybackDevice
Definition: NoteTrack.cpp:983
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
ByColumns_t ByColumns
Definition: Prefs.cpp:515
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:46
@ eIsSavingToPrefs
Definition: ShuttleGui.h:47
#define S(N)
Definition: ToChars.cpp:64
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
A PrefsPanel used to select recording and playback devices and other settings.
Definition: MidiIOPrefs.h:26
TranslatableString GetDescription() const override
Definition: MidiIOPrefs.cpp:69
wxArrayStringEx mHostLabels
Definition: MidiIOPrefs.h:46
wxTextCtrl * mLatency
Definition: MidiIOPrefs.h:56
wxChoice * mHost
Definition: MidiIOPrefs.h:54
TranslatableStrings mHostNames
Definition: MidiIOPrefs.h:45
void OnHost(wxCommandEvent &e)
virtual ~MidiIOPrefs()
Definition: MidiIOPrefs.cpp:60
wxString mPlayDevice
Definition: MidiIOPrefs.h:48
void Populate()
Definition: MidiIOPrefs.cpp:79
void PopulateOrExchange(ShuttleGui &S) override
bool Commit() override
wxChoice * mPlay
Definition: MidiIOPrefs.h:55
ComponentInterfaceSymbol GetSymbol() const override
Definition: MidiIOPrefs.cpp:64
void GetNamesAndLabels()
bool Validate() override
ManualPageID HelpPageName() override
If not empty string, the Help button is added below the panel.
Definition: MidiIOPrefs.cpp:74
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
Definition: PrefsPanel.h:51
Definition: Prefs.h:178
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:259
void Invalidate() override
Definition: Prefs.h:289
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
static void SetMinSize(wxWindow *window, const TranslatableStrings &items)
Holds a msgid for the translation catalog; may also bind format arguments.
virtual bool Flush() noexcept=0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
PrefsPanel::Registration sAttachment