17
17
// the project at cecilios@users.sourceforge.net
19
19
//---------------------------------------------------------------------------------------
21
#include "lenmus_midi_server.h"
23
#include <wx/wxprec.h>
21
#include "lenmus_midi_server.h"
23
#include <wx/wxprec.h>
30
30
//=======================================================================================
31
// MidiServer implementation
31
// MidiServer implementation
32
32
//=======================================================================================
33
MidiServer::MidiServer(ApplicationScope& appScope)
34
: m_appScope(appScope)
39
m_pMidiSystem = wxMidiSystem::GetInstance();
40
LoadUserPreferences();
43
//---------------------------------------------------------------------------------------
44
MidiServer::~MidiServer()
56
//---------------------------------------------------------------------------------------
57
void MidiServer::LoadUserPreferences()
59
//load settings form user congiguration data or default values
61
wxConfigBase* pPrefs = m_appScope.get_preferences();
63
pPrefs->Read(_T("/Midi/IsSet"), &m_fMidiSet, false );
65
m_nOutDevId = (int)pPrefs->Read(_T("/Midi/OutDevice"), (long)0); // 0 based. So this is device 1
66
m_nVoiceChannel = (int)pPrefs->Read(_T("/Midi/VoiceChannel"), (long)0); // 0 based. So this is channel 1
67
m_nVoiceInstr = (int)pPrefs->Read(_T("/Midi/VoiceInstr"), (long)0); // 0 based. So this is instrument 1 (grand piano)
69
m_nMtrChannel = (int)pPrefs->Read(_T("/Midi/MtrChannel"), 9); // 0 based. So this is channel 10
70
m_nMtrInstr = (int)pPrefs->Read(_T("/Midi/MtrInstr"), (long)0); // 0 based. So this is instrument 1 (grand piano)
71
m_nMtrTone1 = (int)pPrefs->Read(_T("/Midi/MtrTone1"), 60L); // 60-High bongo
72
m_nMtrTone2 = (int)pPrefs->Read(_T("/Midi/MtrTone2"), 61L); // 61-low bongo
74
m_nInDevId = (int)pPrefs->Read(_T("/Midi/InDevice"), (long)0); // 0 based. So this is device 1
76
m_nDefaultVoiceChannel = m_nVoiceChannel;
77
m_nDefaultVoiceInstr = m_nVoiceInstr;
79
//sanity checks in case configuration file is corrupted
80
if (m_nVoiceChannel < 0 || m_nVoiceChannel > 15) m_nVoiceChannel = 0;
81
if (m_nVoiceInstr < 0 || m_nVoiceInstr > 255) m_nVoiceInstr = 0;
82
if (m_nMtrChannel < 0 || m_nMtrChannel > 15) m_nMtrChannel = 9;
83
if (m_nMtrInstr < 0 || m_nMtrInstr > 255) m_nMtrInstr = 0;
84
if (m_nMtrTone1 < 0 || m_nMtrTone1 > 255) m_nMtrTone1 = 60;
85
if (m_nMtrTone2 < 0 || m_nMtrTone2 > 255) m_nMtrTone2 = 61;
88
//---------------------------------------------------------------------------------------
89
void MidiServer::SaveUserPreferences()
91
//save settings in user congiguration data
93
wxConfigBase* pPrefs = m_appScope.get_preferences();
95
pPrefs->Write(_T("/Midi/IsSet"), m_fMidiSet );
96
pPrefs->Write(_T("/Midi/InDevice"), (long)m_nInDevId );
97
pPrefs->Write(_T("/Midi/OutDevice"), (long)m_nOutDevId );
98
pPrefs->Write(_T("/Midi/VoiceChannel"), (long)m_nVoiceChannel );
99
pPrefs->Write(_T("/Midi/VoiceInstr"), (long)m_nVoiceInstr );
100
pPrefs->Write(_T("/Midi/MtrChannel"), (long)m_nMtrChannel );
101
pPrefs->Write(_T("/Midi/MtrInstr"), (long)m_nMtrInstr );
102
pPrefs->Write(_T("/Midi/MtrTone1"), (long)m_nMtrTone1 );
103
pPrefs->Write(_T("/Midi/MtrTone2"), (long)m_nMtrTone2 );
105
m_nDefaultVoiceChannel = m_nVoiceChannel;
106
m_nDefaultVoiceInstr = m_nVoiceInstr;
109
//---------------------------------------------------------------------------------------
110
void MidiServer::SetUpCurrentConfig()
112
//int nInDev = m_nInDevId; //save current Id
113
m_nInDevId = -1; //mark as 'not set yet'
115
int nOutDev = m_nOutDevId; //save current Id
116
m_nOutDevId = -1; //mark as 'not set yet'
117
SetUpMidiOut(nOutDev, m_nVoiceChannel, m_nVoiceInstr);
120
//---------------------------------------------------------------------------------------
121
void MidiServer::SetOutDevice(int nOutDevId)
125
//if out device Id has changed close current device and open the new one
126
if (!m_pMidiOut || (m_nOutDevId != nOutDevId))
128
//close current device
131
nErr = m_pMidiOut->Close();
134
//TODO better error reporting
137
wxMessageBox( wxString::Format(
138
_T("Error %d in Open: %s \n")
139
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
146
m_nOutDevId = nOutDevId;
147
if (m_nOutDevId != -1)
149
m_pMidiOut = new wxMidiOutDevice(m_nOutDevId);
150
// open output device
151
nErr = m_pMidiOut->Open(0, NULL); // 0 latency, no driver user info
152
//TODO better error reporting
155
wxLogMessage(_T("Error %d opening Midi device"));
156
//wxMessageBox( wxString::Format(
157
// _T("Error %d in Open: %s \n"),
158
// nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
166
//---------------------------------------------------------------------------------------
167
void MidiServer::SetInDevice(int nInDevId)
171
//if in device Id has changed close current device and open the new one
172
if (!m_pMidiIn || (m_nInDevId != nInDevId))
174
//close current device
177
nErr = m_pMidiIn->Close();
180
//TODO better error reporting
183
wxMessageBox( wxString::Format(
184
_T("Error %d in Open: %s \n"),
185
nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
192
m_nInDevId = nInDevId;
193
if (m_nInDevId != -1)
195
m_pMidiIn = new wxMidiInDevice(m_nInDevId);
197
nErr = m_pMidiIn->Open(NULL); // 0 latency, no driver user info
198
//TODO better error reporting
201
wxMessageBox( wxString::Format(
202
_T("Error %d in Open: %s \n")
203
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
211
//---------------------------------------------------------------------------------------
212
void MidiServer::SetUpMidiOut(int nOutDevId, int nChannel, int nInstrument)
214
//open the new out device
215
SetOutDevice(nOutDevId);
218
VoiceChange(nChannel, nInstrument);
221
//---------------------------------------------------------------------------------------
222
void MidiServer::VoiceChange(int nChannel, int nInstrument)
224
//save new channel and instrument
225
m_nVoiceChannel = nChannel;
226
m_nVoiceInstr = nInstrument;
231
wxMidiError nErr = m_pMidiOut->ProgramChange(m_nVoiceChannel, m_nVoiceInstr);
232
//TODO error reporting eLocalError
235
wxMessageBox( wxString::Format(
236
_T("Error %d in ProgramChange:\n%s")
237
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
244
//---------------------------------------------------------------------------------------
245
void MidiServer::SetMetronomeTones(int nTone1, int nTone2)
247
m_nMtrTone1 = nTone1;
248
m_nMtrTone2 = nTone2;
251
//---------------------------------------------------------------------------------------
252
void MidiServer::TestOut()
254
if (!m_pMidiOut) return;
257
int scale[] = { 60, 62, 64, 65, 67, 69, 71, 72 };
260
for (int i = 0; i < SCALE_SIZE; i++)
262
m_pMidiOut->NoteOn(m_nVoiceChannel, scale[i], 100);
263
::wxMilliSleep(200); // wait 200ms
264
m_pMidiOut->NoteOff(m_nVoiceChannel, scale[i], 100);
268
//---------------------------------------------------------------------------------------
269
int MidiServer::CountDevices()
271
return m_pMidiSystem->CountDevices();
33
MidiServer::MidiServer(ApplicationScope& appScope)
34
: m_appScope(appScope)
39
m_pMidiSystem = wxMidiSystem::GetInstance();
40
LoadUserPreferences();
43
//---------------------------------------------------------------------------------------
44
MidiServer::~MidiServer()
56
//---------------------------------------------------------------------------------------
57
void MidiServer::LoadUserPreferences()
59
//load settings form user congiguration data or default values
61
wxConfigBase* pPrefs = m_appScope.get_preferences();
63
pPrefs->Read(_T("/Midi/IsSet"), &m_fMidiSet, false );
65
m_nOutDevId = (int)pPrefs->Read(_T("/Midi/OutDevice"), (long)0); // 0 based. So this is device 1
66
m_nVoiceChannel = (int)pPrefs->Read(_T("/Midi/VoiceChannel"), (long)0); // 0 based. So this is channel 1
67
m_nVoiceInstr = (int)pPrefs->Read(_T("/Midi/VoiceInstr"), (long)0); // 0 based. So this is instrument 1 (grand piano)
69
m_nMtrChannel = (int)pPrefs->Read(_T("/Midi/MtrChannel"), 9); // 0 based. So this is channel 10
70
m_nMtrInstr = (int)pPrefs->Read(_T("/Midi/MtrInstr"), (long)0); // 0 based. So this is instrument 1 (grand piano)
71
m_nMtrTone1 = (int)pPrefs->Read(_T("/Midi/MtrTone1"), 60L); // 60-High bongo
72
m_nMtrTone2 = (int)pPrefs->Read(_T("/Midi/MtrTone2"), 61L); // 61-low bongo
74
m_nInDevId = (int)pPrefs->Read(_T("/Midi/InDevice"), (long)0); // 0 based. So this is device 1
76
m_nDefaultVoiceChannel = m_nVoiceChannel;
77
m_nDefaultVoiceInstr = m_nVoiceInstr;
79
//sanity checks in case configuration file is corrupted
80
if (m_nVoiceChannel < 0 || m_nVoiceChannel > 15) m_nVoiceChannel = 0;
81
if (m_nVoiceInstr < 0 || m_nVoiceInstr > 255) m_nVoiceInstr = 0;
82
if (m_nMtrChannel < 0 || m_nMtrChannel > 15) m_nMtrChannel = 9;
83
if (m_nMtrInstr < 0 || m_nMtrInstr > 255) m_nMtrInstr = 0;
84
if (m_nMtrTone1 < 0 || m_nMtrTone1 > 255) m_nMtrTone1 = 60;
85
if (m_nMtrTone2 < 0 || m_nMtrTone2 > 255) m_nMtrTone2 = 61;
88
//---------------------------------------------------------------------------------------
89
void MidiServer::SaveUserPreferences()
91
//save settings in user congiguration data
93
wxConfigBase* pPrefs = m_appScope.get_preferences();
95
pPrefs->Write(_T("/Midi/IsSet"), m_fMidiSet );
96
pPrefs->Write(_T("/Midi/InDevice"), (long)m_nInDevId );
97
pPrefs->Write(_T("/Midi/OutDevice"), (long)m_nOutDevId );
98
pPrefs->Write(_T("/Midi/VoiceChannel"), (long)m_nVoiceChannel );
99
pPrefs->Write(_T("/Midi/VoiceInstr"), (long)m_nVoiceInstr );
100
pPrefs->Write(_T("/Midi/MtrChannel"), (long)m_nMtrChannel );
101
pPrefs->Write(_T("/Midi/MtrInstr"), (long)m_nMtrInstr );
102
pPrefs->Write(_T("/Midi/MtrTone1"), (long)m_nMtrTone1 );
103
pPrefs->Write(_T("/Midi/MtrTone2"), (long)m_nMtrTone2 );
105
m_nDefaultVoiceChannel = m_nVoiceChannel;
106
m_nDefaultVoiceInstr = m_nVoiceInstr;
111
//---------------------------------------------------------------------------------------
112
void MidiServer::SetUpCurrentConfig()
114
//int nInDev = m_nInDevId; //save current Id
115
m_nInDevId = -1; //mark as 'not set yet'
117
int nOutDev = m_nOutDevId; //save current Id
118
m_nOutDevId = -1; //mark as 'not set yet'
119
SetUpMidiOut(nOutDev, m_nVoiceChannel, m_nVoiceInstr);
122
//---------------------------------------------------------------------------------------
123
void MidiServer::SetOutDevice(int nOutDevId)
127
//if out device Id has changed close current device and open the new one
128
if (!m_pMidiOut || (m_nOutDevId != nOutDevId))
130
//close current device
133
nErr = m_pMidiOut->Close();
136
//TODO better error reporting
139
wxMessageBox( wxString::Format(
140
_T("Error %d in Open: %s \n")
141
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
148
wxLogMessage(_T("[MidiServer::SetOutDevice] Setting out Midi device: %d"), nOutDevId);
149
m_nOutDevId = nOutDevId;
150
if (m_nOutDevId != -1)
154
m_pMidiOut = new wxMidiOutDevice(m_nOutDevId);
155
nErr = m_pMidiOut->Open(0, NULL); // 0 latency, no driver user info
157
catch(...) //handle all exceptions
159
wxLogMessage(_T("[MidiServer::SetOutDevice] Crash opening Midi device"));
162
//TODO better error reporting
165
wxLogMessage(_T("[MidiServer::SetOutDevice] Error %d opening Midi device"), nErr);
166
//wxMessageBox( wxString::Format(
167
// _T("Error %d in Open: %s \n"),
168
// nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
173
wxLogMessage(_T("[MidiServer::SetOutDevice] Midi out device correctly set."));
178
//---------------------------------------------------------------------------------------
179
void MidiServer::SetInDevice(int nInDevId)
183
//if in device Id has changed close current device and open the new one
184
if (!m_pMidiIn || (m_nInDevId != nInDevId))
186
//close current device
189
nErr = m_pMidiIn->Close();
192
//TODO better error reporting
195
wxMessageBox( wxString::Format(
196
_T("Error %d in Open: %s \n"),
197
nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
204
m_nInDevId = nInDevId;
205
if (m_nInDevId != -1)
207
m_pMidiIn = new wxMidiInDevice(m_nInDevId);
209
nErr = m_pMidiIn->Open(NULL); // 0 latency, no driver user info
210
//TODO better error reporting
213
wxMessageBox( wxString::Format(
214
_T("Error %d in Open: %s \n")
215
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
223
//---------------------------------------------------------------------------------------
224
void MidiServer::SetUpMidiOut(int nOutDevId, int nChannel, int nInstrument)
226
//open the new out device
227
SetOutDevice(nOutDevId);
230
VoiceChange(nChannel, nInstrument);
233
//---------------------------------------------------------------------------------------
234
void MidiServer::VoiceChange(int nChannel, int nInstrument)
236
//save new channel and instrument
237
m_nVoiceChannel = nChannel;
238
m_nVoiceInstr = nInstrument;
243
wxMidiError nErr = m_pMidiOut->ProgramChange(m_nVoiceChannel, m_nVoiceInstr);
244
//TODO error reporting eLocalError
247
wxMessageBox( wxString::Format(
248
_T("Error %d in ProgramChange:\n%s")
249
, nErr, m_pMidiSystem->GetErrorText(nErr).c_str() ));
256
//---------------------------------------------------------------------------------------
257
void MidiServer::SetMetronomeTones(int nTone1, int nTone2)
259
m_nMtrTone1 = nTone1;
260
m_nMtrTone2 = nTone2;
263
//---------------------------------------------------------------------------------------
264
void MidiServer::TestOut()
266
if (!m_pMidiOut) return;
269
int scale[] = { 60, 62, 64, 65, 67, 69, 71, 72 };
272
for (int i = 0; i < SCALE_SIZE; i++)
274
m_pMidiOut->NoteOn(m_nVoiceChannel, scale[i], 100);
275
::wxMilliSleep(200); // wait 200ms
276
m_pMidiOut->NoteOff(m_nVoiceChannel, scale[i], 100);
280
//---------------------------------------------------------------------------------------
281
int MidiServer::CountDevices()
283
return m_pMidiSystem->CountDevices();
275
287
} //namespace lenmus