Audacity  2.2.2
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 #include "../Audacity.h"
27 #include "../Experimental.h"
28 #ifdef EXPERIMENTAL_MIDI_OUT
29 
30 #include <wx/defs.h>
31 
32 #include <wx/choice.h>
33 #include <wx/intl.h>
34 
35 #include "../../lib-src/portmidi/pm_common/portmidi.h"
36 
37 #include "../AudioIO.h"
38 #include "../Internat.h"
39 #include "../Prefs.h"
40 #include "../Project.h"
41 #include "../ShuttleGui.h"
42 #include "../widgets/ErrorDialog.h"
43 
44 #include "MidiIOPrefs.h"
45 
46 enum {
47  HostID = 10000,
48  PlayID,
49  RecordID,
51 };
52 
53 BEGIN_EVENT_TABLE(MidiIOPrefs, PrefsPanel)
54  EVT_CHOICE(HostID, MidiIOPrefs::OnHost)
55 // EVT_CHOICE(RecordID, MidiIOPrefs::OnDevice)
57 
58 MidiIOPrefs::MidiIOPrefs(wxWindow * parent, wxWindowID winid)
59 /* i18n-hint: untranslatable acronym for "Musical Instrument Device Interface" */
60 : PrefsPanel(parent, winid, _("MIDI Devices"))
61 {
62  Populate();
63 }
64 
65 MidiIOPrefs::~MidiIOPrefs()
66 {
67 }
68 
69 void MidiIOPrefs::Populate()
70 {
71  // First any pre-processing for constructing the GUI.
72  GetNamesAndLabels();
73 
74  // Get current setting for devices
75  mPlayDevice = gPrefs->Read(wxT("/MidiIO/PlaybackDevice"), wxT(""));
76 #ifdef EXPERIMENTAL_MIDI_IN
77  mRecordDevice = gPrefs->Read(wxT("/MidiIO/RecordingDevice"), wxT(""));
78 #endif
79 // mRecordChannels = gPrefs->Read(wxT("/MidiIO/RecordChannels"), 2L);
80 
81  //------------------------- Main section --------------------
82  // Now construct the GUI itself.
83  // Use 'eIsCreatingFromPrefs' so that the GUI is
84  // initialised with values from gPrefs.
86  PopulateOrExchange(S);
87  // ----------------------- End of main section --------------
88 
89  wxCommandEvent e;
90  OnHost(e);
91 }
92 
97 void MidiIOPrefs::GetNamesAndLabels() {
98  // Gather list of hosts. Only added hosts that have devices attached.
99  Pm_Terminate(); // close and open to refresh device lists
100  Pm_Initialize();
101  int nDevices = Pm_CountDevices();
102  for (int i = 0; i < nDevices; i++) {
103  const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
104  if (info->output || info->input) { //should always happen
105  wxString name = wxSafeConvertMB2WX(info->interf);
106  if (mHostNames.Index(name) == wxNOT_FOUND) {
107  mHostNames.Add(name);
108  mHostLabels.Add(name);
109  }
110  }
111  }
112 }
113 
114 void MidiIOPrefs::PopulateOrExchange( ShuttleGui & S ) {
115  wxArrayString empty;
116 
117  S.SetBorder(2);
118  S.StartScroller();
119 
120  S.StartStatic(_("Interface"));
121  {
122  S.StartMultiColumn(2);
123  {
124  S.Id(HostID);
125  /* i18n-hint: (noun) */
126  mHost = S.TieChoice(_("&Host:"),
127  wxT("/MidiIO/Host"),
128  wxT(""),
129  mHostNames,
130  mHostLabels);
131 
132  S.AddPrompt(_("Using: PortMidi"));
133  }
134  S.EndMultiColumn();
135  }
136  S.EndStatic();
137 
138  S.StartStatic(_("Playback"));
139  {
140  S.StartMultiColumn(2);
141  {
142  S.Id(PlayID);
143  mPlay = S.AddChoice(_("&Device:"),
144  wxEmptyString,
145  &empty);
146  int latency = gPrefs->Read(wxT("/MidiIO/OutputLatency"),
148  mLatency = S.TieNumericTextBox(_("MIDI Synth L&atency (ms):"),
149  wxT("/MidiIO/SynthLatency"),
150  latency, 3);
151  }
152  S.EndMultiColumn();
153  }
154  S.EndStatic();
155 #ifdef EXPERIMENTAL_MIDI_IN
156  S.StartStatic(_("Recording"));
157  {
158  S.StartMultiColumn(2);
159  {
160  S.Id(RecordID);
161  mRecord = S.AddChoice(_("De&vice:"),
162  wxEmptyString,
163  &empty);
164 
165  S.Id(ChannelsID);
166  /*
167  mChannels = S.AddChoice(_("&Channels:"),
168  wxEmptyString,
169  &empty);
170  */
171  }
172  S.EndMultiColumn();
173  }
174  S.EndStatic();
175 #endif
176  S.EndScroller();
177 
178 }
179 
180 void MidiIOPrefs::OnHost(wxCommandEvent & WXUNUSED(e))
181 {
182  wxString itemAtIndex;
183  int index = mHost->GetCurrentSelection();
184  if (index >= 0 && index < (int)mHostNames.Count())
185  itemAtIndex = mHostNames.Item(index);
186  int nDevices = Pm_CountDevices();
187 
188  if (nDevices == 0) {
189  mHost->Clear();
190  mHost->Append(_("No MIDI interfaces"), (void *) NULL);
191  mHost->SetSelection(0);
192  }
193 
194  mPlay->Clear();
195 #ifdef EXPERIMENTAL_MIDI_IN
196  mRecord->Clear();
197 #endif
198 
199  wxArrayString playnames;
200  wxArrayString recordnames;
201 
202  for (int i = 0; i < nDevices; i++) {
203  const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
204  wxString interf = wxSafeConvertMB2WX(info->interf);
205  if (itemAtIndex.IsSameAs(interf)) {
206  wxString name = wxSafeConvertMB2WX(info->name);
207  wxString device = wxString::Format(wxT("%s: %s"),
208  interf,
209  name);
210  int index;
211 
212  if (info->output) {
213  playnames.Add(name);
214  index = mPlay->Append(name, (void *) info);
215  if (device == mPlayDevice) {
216  mPlay->SetSelection(index);
217  }
218  }
219 #ifdef EXPERIMENTAL_MIDI_IN
220  if (info->input) {
221  recordnames.Add(name);
222  index = mRecord->Append(name, (void *) info);
223  if (device == mRecordDevice) {
224  mRecord->SetSelection(index);
225  }
226  }
227 #endif
228  }
229  }
230 
231  if (mPlay->GetCount() == 0) {
232  playnames.Add(_("No devices found"));
233  mPlay->Append(playnames[0], (void *) NULL);
234  }
235 #ifdef EXPERIMENTAL_MIDI_IN
236  if (mRecord->GetCount() == 0) {
237  recordnames.Add(_("No devices found"));
238  mRecord->Append(recordnames[0], (void *) NULL);
239  }
240 #endif
241  if (mPlay->GetCount() && mPlay->GetSelection() == wxNOT_FOUND) {
242  mPlay->SetSelection(0);
243  }
244 #ifdef EXPERIMENTAL_MIDI_IN
245  if (mRecord->GetCount() && mRecord->GetSelection() == wxNOT_FOUND) {
246  mRecord->SetSelection(0);
247  }
248 #endif
249  ShuttleGui S(this, eIsCreating);
250  S.SetSizeHints(mPlay, playnames);
251 #ifdef EXPERIMENTAL_MIDI_IN
252  S.SetSizeHints(mRecord, recordnames);
253 #endif
254 // OnDevice(e);
255 }
256 
257 bool MidiIOPrefs::Commit()
258 {
259  ShuttleGui S(this, eIsSavingToPrefs);
260  PopulateOrExchange(S);
261 
262  const PmDeviceInfo *info;
263 
264  info = (const PmDeviceInfo *) mPlay->GetClientData(mPlay->GetSelection());
265  if (info) {
266  gPrefs->Write(wxT("/MidiIO/PlaybackDevice"),
267  wxString::Format(wxT("%s: %s"),
268  wxString(wxSafeConvertMB2WX(info->interf)),
269  wxString(wxSafeConvertMB2WX(info->name))));
270  }
271 #ifdef EXPERIMENTAL_MIDI_IN
272  info = (const PmDeviceInfo *) mRecord->GetClientData(mRecord->GetSelection());
273  if (info) {
274  gPrefs->Write(wxT("/MidiIO/RecordingDevice"),
275  wxString::Format(wxT("%s: %s"),
276  wxString(wxSafeConvertMB2WX(info->interf)),
277  wxString(wxSafeConvertMB2WX(info->name))));
278  }
279 #endif
280  return gPrefs->Flush();
281 }
282 
283 bool MidiIOPrefs::Validate()
284 {
285  long latency;
286  if (!mLatency->GetValue().ToLong(&latency)) {
287  AudacityMessageBox(_("The MIDI Synthesizer Latency must be an integer"));
288  return false;
289  }
290  return true;
291 }
292 
293 wxString MidiIOPrefs::HelpPageName()
294 {
295  return "MIDI_Devices_Preferences";
296 }
297 
298 PrefsPanel *MidiIOPrefsFactory::operator () (wxWindow *parent, wxWindowID winid)
299 {
300  wxASSERT(parent); // to justify safenew
301  return safenew MidiIOPrefs(parent, winid);
302 }
303 
304 #endif
wxChoice * TieChoice(const wxString &Prompt, WrappedType &WrappedRef, const wxArrayString *pChoices)
void SetSizeHints(int minX, int minY)
Used to modify an already placed Window.
Definition: ShuttleGui.cpp:194
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
void EndMultiColumn()
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
void EndScroller()
Definition: ShuttleGui.cpp:828
#define safenew
Definition: Audacity.h:230
void AddPrompt(const wxString &Prompt)
Right aligned text string.
Definition: ShuttleGui.cpp:239
wxScrolledWindow * StartScroller(int iStyle=0)
Definition: ShuttleGui.cpp:795
#define DEFAULT_SYNTH_LATENCY
Definition: AudioIO.h:82
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:371
ShuttleGui & Id(int id)
wxTextCtrl * TieNumericTextBox(const wxString &Prompt, WrappedType &WrappedRef, const int nChars)
A PrefsPanel used to select recording and playback devices and other settings.
Used within the PrefsDialog, classes derived from this class include AudioIOPrefs, BatchPrefs, DirectoriesPrefs, FileFormatPrefs, GUIPrefs, KeyConfigPrefs, MousePrefs, QualityPrefs, SpectrumPrefs and ThemePrefs.
Definition: PrefsPanel.h:45
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
const wxChar * name
Definition: Distortion.cpp:94
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:763
END_EVENT_TABLE()
void SetBorder(int Border)
Definition: ShuttleGui.h:286