41#define MAXPATHLEN MAX_PATH
50#define OPENMSX_W32_MIDI_SYSMES_MAXLEN 4096
58 char devname[MAXPNAMELEN];
65static MemBuffer<vfn_midi> vfnt_midiout;
66static MemBuffer<vfn_midi> vfnt_midiin;
67static unsigned vfnt_midiout_num, vfnt_midiin_num;
69static MemBuffer<int> state_out;
70static MemBuffer<outbuf> buf_out;
73static char inlongmes[OPENMSX_W32_MIDI_SYSMES_MAXLEN];
76static void w32_midiDevNameConv(
char *dst,
char *src)
78 size_t len = strlen(src);
80 for (; i < len; ++i) {
81 if ((src[i] <
'0') || (src[i] >
'z') ||
82 ((src[i] >
'9') && (src[i] <
'A')) ||
83 ((src[i] >
'Z') && (src[i] <
'a'))) {
94static int w32_midiOutFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
96 for (
auto i :
xrange(vfnt_midiout_num)) {
97 if (!strcmp(vfnt_midiout[i].vfname, vfn)) {
99 *dev = vfnt_midiout[i].devid;
109 vfnt_midiout_num = 0;
110 unsigned num = midiOutGetNumDevs();
113 state_out.resize(num + 1);
114 memset(state_out.data(), 0, (num + 1) *
sizeof(
int));
116 buf_out.resize(num + 1);
117 memset(buf_out.data(), 0, (num + 1) *
sizeof(outbuf));
119 vfnt_midiout.resize(num + 1);
122 UINT OPENMSX_MIDI_MAPPER =
static_cast<UINT
>(-1);
124 if (midiOutGetDevCapsA(OPENMSX_MIDI_MAPPER, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
127 vfnt_midiout[0].devid = OPENMSX_MIDI_MAPPER;
128 w32_midiDevNameConv(vfnt_midiout[0].devname, cap.szPname);
129 strncpy(vfnt_midiout[0].vfname,
"midi-out",
MAXPATHLEN + 1);
132 for (
auto i :
xrange(num)) {
133 if (midiOutGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
136 vfnt_midiout[i + 1].devid = i;
137 w32_midiDevNameConv(vfnt_midiout[i + 1].devname, cap.szPname);
138 snprintf(vfnt_midiout[i + 1].vfname,
MAXPATHLEN + 1,
"midi-out-%u", i);
144void w32_midiOutClean()
146 vfnt_midiout_num = 0;
150unsigned w32_midiOutGetVFNsNum()
152 return vfnt_midiout_num;
155std::string w32_midiOutGetVFN(
unsigned nmb)
157 assert(nmb < vfnt_midiout_num);
158 return vfnt_midiout[nmb].vfname;
161std::string w32_midiOutGetRDN(
unsigned nmb)
163 assert(nmb < vfnt_midiout_num);
164 return vfnt_midiout[nmb].devname;
168unsigned w32_midiOutOpen(
const char *vfn)
171 if (w32_midiOutFindDev(&idx, &devid,vfn)) {
174 if (midiOutOpen(
reinterpret_cast<HMIDIOUT*
>(&vfnt_midiout[idx].handle), devid, 0, 0 ,0) != MMSYSERR_NOERROR) {
180int w32_midiOutClose(
unsigned idx)
182 midiOutReset(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle));
183 if (midiOutClose(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle)) == MMSYSERR_NOERROR) {
191static int w32_midiOutFlushExclusiveMsg(
unsigned idx)
196 buf_out[idx].header.dwFlags = 0;
197 if ((i = midiOutPrepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
198 throw FatalError(
"midiOutPrepareHeader() returned ", i);
200 if ((i = midiOutLongMsg(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
201 throw FatalError(
"midiOutLongMsg() returned ", i);
205 while (!(buf_out[idx].header.dwFlags & MHDR_DONE)) {
209 if ((i = midiOutUnprepareHeader(
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle), &buf_out[idx].header,
sizeof(buf_out[idx].header))) != MMSYSERR_NOERROR) {
210 throw FatalError(
"midiOutUnPrepareHeader() returned ", i);
215int w32_midiOutMsg(
size_t size,
const uint8_t* data,
unsigned idx)
217 if (
size == 0)
return 0;
219 HMIDIOUT hMidiOut =
reinterpret_cast<HMIDIOUT
>(vfnt_midiout[idx].handle);
220 if (data[0] ==
one_of(0xF0, 0xF7)) {
221 if (
size > OPENMSX_W32_MIDI_SYSMES_MAXLEN) {
224 auto& buf = buf_out[idx];
228 buf.header.lpData =
const_cast<LPSTR
>(
reinterpret_cast<LPCSTR
>(data));
229 buf.header.dwBufferLength = unsigned(
size);
230 w32_midiOutFlushExclusiveMsg(idx);
232 DWORD midiMsg = 0x000000;
233 for (
unsigned i = 0; i <
size && i < 4; i++) {
234 midiMsg |= data[i] << (8 * i);
236 midiOutShortMsg(hMidiOut, midiMsg);
243static int w32_midiInFindDev(
unsigned *idx,
unsigned *dev,
const char *vfn)
245 for (
auto i :
xrange(vfnt_midiin_num)) {
246 if (!strcmp(vfnt_midiin[i].vfname, vfn)) {
248 *dev = vfnt_midiin[i].devid;
259 unsigned num = midiInGetNumDevs();
262 vfnt_midiin.resize(num + 1);
263 for (
auto i :
xrange(num)) {
265 if (midiInGetDevCapsA(i, &cap,
sizeof(cap)) != MMSYSERR_NOERROR) {
268 vfnt_midiin[i].devid = i;
269 w32_midiDevNameConv(vfnt_midiin[i].devname, cap.szPname);
270 snprintf(vfnt_midiin[i].vfname,
MAXPATHLEN + 1,
"midi-in-%u", i);
276void w32_midiInClean()
282unsigned w32_midiInGetVFNsNum()
284 return vfnt_midiin_num;
287std::string w32_midiInGetVFN(
unsigned nmb)
289 assert(nmb < vfnt_midiin_num);
290 return vfnt_midiin[nmb].vfname;
293std::string w32_midiInGetRDN(
unsigned nmb)
295 assert(nmb < vfnt_midiin_num);
296 return vfnt_midiin[nmb].devname;
299unsigned w32_midiInOpen(
const char *vfn, DWORD thrdid)
302 if (w32_midiInFindDev(&idx, &devid, vfn)) {
305 if (midiInOpen(
reinterpret_cast<HMIDIIN*
>(&vfnt_midiin[idx].handle), devid, thrdid, 0, CALLBACK_THREAD) != MMSYSERR_NOERROR) {
308 memset(&inhdr, 0,
sizeof(inhdr));
309 inhdr.lpData = inlongmes;
310 inhdr.dwBufferLength = OPENMSX_W32_MIDI_SYSMES_MAXLEN;
311 if (midiInPrepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
312 static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr)) != MMSYSERR_NOERROR) {
315 if (midiInAddBuffer(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr)) != MMSYSERR_NOERROR) {
318 if (midiInStart(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle)) != MMSYSERR_NOERROR) {
324int w32_midiInClose(
unsigned idx)
326 midiInStop(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
327 midiInReset(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle));
328 midiInUnprepareHeader(
reinterpret_cast<HMIDIIN
>(vfnt_midiin[idx].handle),
329 static_cast<LPMIDIHDR
>(&inhdr),
sizeof(inhdr));
330 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)