41 #define MAXPATHLEN MAX_PATH
52 #define OPENMSX_W32_MIDI_SYSMES_MAXLEN 4096
60 char devname[MAXPNAMELEN];
67 static MemBuffer<vfn_midi> vfnt_midiout;
68 static MemBuffer<vfn_midi> vfnt_midiin;
69 static unsigned vfnt_midiout_num, vfnt_midiin_num;
71 static MemBuffer<int> state_out;
72 static MemBuffer<outbuf> buf_out;
75 static char inlongmes[OPENMSX_W32_MIDI_SYSMES_MAXLEN];
78 static void w32_midiDevNameConv(
char *dst,
char *src)
80 size_t len = strlen(src);
82 for (; i < len; ++i) {
83 if ((src[i] <
'0') || (src[i] >
'z') ||
84 ((src[i] >
'9') && (src[i] <
'A')) ||
85 ((src[i] >
'Z') && (src[i] <
'a'))) {
96 static int w32_midiOutFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
98 for (
auto i :
xrange(vfnt_midiout_num)) {
99 if (!strcmp(vfnt_midiout[i].vfname, vfn)) {
101 *dev = vfnt_midiout[i].devid;
109 int w32_midiOutInit()
111 vfnt_midiout_num = 0;
112 unsigned num = midiOutGetNumDevs();
115 state_out.resize(num + 1);
116 memset(state_out.data(), 0, (num + 1) *
sizeof(
int));
118 buf_out.resize(num + 1);
119 memset(buf_out.data(), 0, (num + 1) *
sizeof(outbuf));
121 vfnt_midiout.resize(num + 1);
124 UINT OPENMSX_MIDI_MAPPER =
static_cast<UINT
>(-1);
126 if (midiOutGetDevCapsA(OPENMSX_MIDI_MAPPER, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
129 vfnt_midiout[0].devid = OPENMSX_MIDI_MAPPER;
130 w32_midiDevNameConv(vfnt_midiout[0].devname, cap.szPname);
131 strncpy(vfnt_midiout[0].vfname,
"midi-out",
MAXPATHLEN + 1);
134 for (
auto i :
xrange(num)) {
135 if (midiOutGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
138 vfnt_midiout[i + 1].devid = i;
139 w32_midiDevNameConv(vfnt_midiout[i + 1].devname, cap.szPname);
140 snprintf(vfnt_midiout[i + 1].vfname,
MAXPATHLEN + 1,
"midi-out-%u", i);
146 void w32_midiOutClean()
148 vfnt_midiout_num = 0;
152 unsigned w32_midiOutGetVFNsNum()
154 return vfnt_midiout_num;
157 string w32_midiOutGetVFN(
unsigned nmb)
159 assert(nmb < vfnt_midiout_num);
160 return vfnt_midiout[nmb].vfname;
163 string w32_midiOutGetRDN(
unsigned nmb)
165 assert(nmb < vfnt_midiout_num);
166 return vfnt_midiout[nmb].devname;
170 unsigned w32_midiOutOpen(
const char *vfn)
173 if (w32_midiOutFindDev(&idx, &devid,vfn)) {
176 if (midiOutOpen(
reinterpret_cast<HMIDIOUT*
>(&vfnt_midiout[idx].handle), devid, 0, 0 ,0) != MMSYSERR_NOERROR) {
182 int w32_midiOutClose(
unsigned idx)
184 midiOutReset(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle));
185 if (midiOutClose(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle)) == MMSYSERR_NOERROR) {
193 static int w32_midiOutFlushExclusiveMsg(
unsigned idx)
198 buf_out[idx].header.dwFlags = 0;
199 if ((i = midiOutPrepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
200 throw FatalError(
"midiOutPrepareHeader() returned ", i);
202 if ((i = midiOutLongMsg(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
203 throw FatalError(
"midiOutLongMsg() returned ", i);
207 while (!(buf_out[idx].header.dwFlags & MHDR_DONE)) {
211 if ((i = midiOutUnprepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
212 throw FatalError(
"midiOutUnPrepareHeader() returned ", i);
217 int w32_midiOutMsg(
size_t size,
const uint8_t* data,
unsigned idx)
219 if (
size == 0)
return 0;
221 HMIDIOUT hMidiOut =
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle);
222 if (data[0] ==
one_of(0xF0, 0xF7)) {
223 if (
size > OPENMSX_W32_MIDI_SYSMES_MAXLEN) {
226 auto& buf = buf_out[idx];
230 buf.header.lpData =
const_cast<LPSTR
>(
reinterpret_cast<LPCSTR
>(data));
231 buf.header.dwBufferLength = unsigned(
size);
232 w32_midiOutFlushExclusiveMsg(idx);
234 DWORD midiMsg = 0x000000;
235 for (
unsigned i = 0; i <
size && i < 4; i++) {
236 midiMsg |= data[i] << (8 * i);
238 midiOutShortMsg(hMidiOut, midiMsg);
245 static int w32_midiInFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
247 for (
auto i :
xrange(vfnt_midiin_num)) {
248 if (!strcmp(vfnt_midiin[i].vfname, vfn)) {
250 *dev = vfnt_midiin[i].devid;
261 unsigned num = midiInGetNumDevs();
264 vfnt_midiin.resize(num + 1);
265 for (
auto i :
xrange(num)) {
267 if (midiInGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
270 vfnt_midiin[i].devid = i;
271 w32_midiDevNameConv(vfnt_midiin[i].devname, cap.szPname);
272 snprintf(vfnt_midiin[i].vfname,
MAXPATHLEN + 1,
"midi-in-%u", i);
278 void w32_midiInClean()
284 unsigned w32_midiInGetVFNsNum()
286 return vfnt_midiin_num;
289 string w32_midiInGetVFN(
unsigned nmb)
291 assert(nmb < vfnt_midiin_num);
292 return vfnt_midiin[nmb].vfname;
295 string w32_midiInGetRDN(
unsigned nmb)
297 assert(nmb < vfnt_midiin_num);
298 return vfnt_midiin[nmb].devname;
301 unsigned w32_midiInOpen(
const char *vfn, DWORD thrdid)
304 if (w32_midiInFindDev(&idx, &devid, vfn)) {
307 if (midiInOpen(
reinterpret_cast<HMIDIIN*
>(&vfnt_midiin[idx].handle), devid, thrdid, 0, CALLBACK_THREAD) != MMSYSERR_NOERROR) {
310 memset(&inhdr, 0,
sizeof(inhdr));
311 inhdr.lpData = inlongmes;
312 inhdr.dwBufferLength = OPENMSX_W32_MIDI_SYSMES_MAXLEN;
313 if (midiInPrepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
314 static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr)) != MMSYSERR_NOERROR) {
317 if (midiInAddBuffer(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr)) != MMSYSERR_NOERROR) {
320 if (midiInStart(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle)) != MMSYSERR_NOERROR) {
326 int w32_midiInClose(
unsigned idx)
328 midiInStop(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
329 midiInReset(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
330 midiInUnprepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
331 static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr));
332 if (midiInClose(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle)) == MMSYSERR_NOERROR) {
This file implemented 3 utility functions:
size_t size(std::string_view utf8)
constexpr auto xrange(T e)