45#define MAXPATHLEN MAX_PATH
54static constexpr size_t OPENMSX_W32_MIDI_SYSMES_MAXLEN = 4096;
61 std::array<char, MAXPATHLEN + 1> vfname;
62 std::array<char, MAXPNAMELEN> devname;
69static MemBuffer<vfn_midi> vfnt_midiout;
70static MemBuffer<vfn_midi> vfnt_midiin;
71static unsigned vfnt_midiout_num, vfnt_midiin_num;
73static MemBuffer<int> state_out;
74static MemBuffer<outbuf> buf_out;
77static std::array<char, OPENMSX_W32_MIDI_SYSMES_MAXLEN> inlongmes;
80static void w32_midiDevNameConv(
char *dst,
const char *src)
82 size_t len = strlen(src);
84 for (; i < len; ++i) {
85 if ((src[i] <
'0') || (src[i] >
'z') ||
86 ((src[i] >
'9') && (src[i] <
'A')) ||
87 ((src[i] >
'Z') && (src[i] <
'a'))) {
98static int w32_midiOutFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
100 for (
auto i :
xrange(vfnt_midiout_num)) {
101 if (!strcmp(vfnt_midiout[i].vfname.data(), vfn)) {
103 *dev = vfnt_midiout[i].devid;
113 vfnt_midiout_num = 0;
114 unsigned num = midiOutGetNumDevs();
117 state_out.resize(num + 1);
118 memset(state_out.data(), 0, (num + 1) *
sizeof(
int));
120 buf_out.resize(num + 1);
121 memset(buf_out.data(), 0, (num + 1) *
sizeof(outbuf));
123 vfnt_midiout.resize(num + 1);
126 auto OPENMSX_MIDI_MAPPER =
static_cast<UINT
>(-1);
128 if (midiOutGetDevCapsA(OPENMSX_MIDI_MAPPER, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
131 vfnt_midiout[0].devid = OPENMSX_MIDI_MAPPER;
132 w32_midiDevNameConv(vfnt_midiout[0].devname.data(), cap.szPname);
133 strncpy(vfnt_midiout[0].vfname.data(),
"midi-out",
MAXPATHLEN);
137 for (
auto i :
xrange(num)) {
138 if (midiOutGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
141 vfnt_midiout[i + 1].devid = i;
142 w32_midiDevNameConv(vfnt_midiout[i + 1].devname.data(), cap.szPname);
143 snprintf(vfnt_midiout[i + 1].vfname.data(),
MAXPATHLEN + 1,
"midi-out-%u", i);
149void w32_midiOutClean()
151 vfnt_midiout_num = 0;
155unsigned w32_midiOutGetVFNsNum()
157 return vfnt_midiout_num;
160std::string w32_midiOutGetVFN(
unsigned nmb)
162 assert(nmb < vfnt_midiout_num);
163 return vfnt_midiout[nmb].vfname.data();
166std::string w32_midiOutGetRDN(
unsigned nmb)
168 assert(nmb < vfnt_midiout_num);
169 return vfnt_midiout[nmb].devname.data();
173unsigned w32_midiOutOpen(
const char *vfn)
176 if (w32_midiOutFindDev(&idx, &devid,vfn)) {
179 if (midiOutOpen(std::bit_cast<HMIDIOUT*>(&vfnt_midiout[idx].handle), devid, 0, 0 ,0) != MMSYSERR_NOERROR) {
185int w32_midiOutClose(
unsigned idx)
187 midiOutReset(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle));
188 if (midiOutClose(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle)) == MMSYSERR_NOERROR) {
196static int w32_midiOutFlushExclusiveMsg(
unsigned idx)
201 buf_out[idx].header.dwFlags = 0;
202 if ((i = midiOutPrepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
203 throw FatalError(
"midiOutPrepareHeader() returned ", i);
205 if ((i = midiOutLongMsg(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
206 throw FatalError(
"midiOutLongMsg() returned ", i);
210 while (!(buf_out[idx].header.dwFlags & MHDR_DONE)) {
214 if ((i = midiOutUnprepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
215 throw FatalError(
"midiOutUnPrepareHeader() returned ", i);
220int w32_midiOutMsg(
size_t size,
const uint8_t* data,
unsigned idx)
222 if (size == 0)
return 0;
224 auto hMidiOut =
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle);
225 if (data[0] ==
one_of(0xF0, 0xF7)) {
226 if (size > OPENMSX_W32_MIDI_SYSMES_MAXLEN) {
229 auto& buf = buf_out[idx];
233 buf.header.lpData =
const_cast<LPSTR
>(
reinterpret_cast<LPCSTR
>(data));
234 buf.header.dwBufferLength = unsigned(size);
235 w32_midiOutFlushExclusiveMsg(idx);
237 DWORD midiMsg = 0x000000;
238 for (
unsigned i = 0; i <
size && i < 4; i++) {
239 midiMsg |= data[i] << (8 * i);
241 midiOutShortMsg(hMidiOut, midiMsg);
248static int w32_midiInFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
250 for (
auto i :
xrange(vfnt_midiin_num)) {
251 if (!strcmp(vfnt_midiin[i].vfname.data(), vfn)) {
253 *dev = vfnt_midiin[i].devid;
264 unsigned num = midiInGetNumDevs();
267 vfnt_midiin.resize(num + 1);
268 for (
auto i :
xrange(num)) {
270 if (midiInGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
273 vfnt_midiin[i].devid = i;
274 w32_midiDevNameConv(vfnt_midiin[i].devname.data(), cap.szPname);
275 snprintf(vfnt_midiin[i].vfname.data(),
MAXPATHLEN + 1,
"midi-in-%u", i);
281void w32_midiInClean()
287unsigned w32_midiInGetVFNsNum()
289 return vfnt_midiin_num;
292std::string w32_midiInGetVFN(
unsigned nmb)
294 assert(nmb < vfnt_midiin_num);
295 return vfnt_midiin[nmb].vfname.data();
298std::string w32_midiInGetRDN(
unsigned nmb)
300 assert(nmb < vfnt_midiin_num);
301 return vfnt_midiin[nmb].devname.data();
304unsigned w32_midiInOpen(
const char *vfn, DWORD thrdid)
307 if (w32_midiInFindDev(&idx, &devid, vfn)) {
310 if (midiInOpen(std::bit_cast<HMIDIIN*>(&vfnt_midiin[idx].handle), devid, thrdid, 0, CALLBACK_THREAD) != MMSYSERR_NOERROR) {
313 memset(&inhdr, 0,
sizeof(inhdr));
314 inhdr.lpData = inlongmes.data();
315 inhdr.dwBufferLength = OPENMSX_W32_MIDI_SYSMES_MAXLEN;
316 if (midiInPrepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
317 &inhdr,
sizeof(inhdr)) != MMSYSERR_NOERROR) {
320 if (midiInAddBuffer(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle), &inhdr,
sizeof(inhdr)) != MMSYSERR_NOERROR) {
323 if (midiInStart(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle)) != MMSYSERR_NOERROR) {
329int w32_midiInClose(
unsigned idx)
331 midiInStop(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
332 midiInReset(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
333 midiInUnprepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
334 &inhdr,
sizeof(inhdr));
335 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)