diff options
author | R. Belmont <rb6502@users.noreply.github.com> | 2013-01-13 03:48:10 +0000 |
---|---|---|
committer | R. Belmont <rb6502@users.noreply.github.com> | 2013-01-13 03:48:10 +0000 |
commit | f6c44c6e9bbf1720d481707cbee73aadbae21572 (patch) | |
tree | 93d48913f4afee3080c2aca425119f0840b74276 /src/osd/portmedia | |
parent | fa807d8a30cd94a3f4f283db378f47312271d61f (diff) |
MIDI core updates: [R. Belmont]
- Add MIDI in and out ports as image device types
- Add OSD calls to check for and read MIDI input
- Add MIDI in image device which reads input and converts it to a serial bitstream
nw section:
Note that the MIDI In device uses the new image device override to prevent the core from attempting to fopen() the "file" name and instead it handles open/close itself in call_load/call_unload. This allows greater flexibilty than the hack used for sockets/ptys/named pipes where the OSD file layer has to know about them.
Diffstat (limited to 'src/osd/portmedia')
-rw-r--r-- | src/osd/portmedia/pmmidi.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/osd/portmedia/pmmidi.c b/src/osd/portmedia/pmmidi.c index 40c2b3d4fd7..9669d761ba4 100644 --- a/src/osd/portmedia/pmmidi.c +++ b/src/osd/portmedia/pmmidi.c @@ -10,6 +10,15 @@ #include "portmidi/portmidi.h" #include "osdcore.h" +struct osd_midi_device +{ + #ifndef DISABLE_MIDI + PortMidiStream *pmStream; + PmEvent rx_evBuf[20]; // up to 20 events + #endif + UINT8 xmit_in[3]; // Pm_Messages mean we can at most have 3 residue bytes +}; + void osd_list_midi_devices(void) { #ifndef DISABLE_MIDI @@ -52,16 +61,177 @@ void osd_list_midi_devices(void) osd_midi_device *osd_open_midi_input(const char *devname) { + #ifndef DISABLE_MIDI + int num_devs = Pm_CountDevices(); + int found_dev = -1; + const PmDeviceInfo *pmInfo; + PortMidiStream *stm; + osd_midi_device *ret; + + for (int i = 0; i < num_devs; i++) + { + pmInfo = Pm_GetDeviceInfo(i); + + if (pmInfo->input) + { + if (!strcmp(devname, pmInfo->name)) + { + found_dev = i; + break; + } + } + } + + if (found_dev >= 0) + { + if (Pm_OpenInput(&stm, found_dev, NULL, 20, NULL, NULL) == pmNoError) + { + ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device)); + memset(ret, 0, sizeof(osd_midi_device)); + ret->pmStream = stm; + return ret; + } + else + { + printf("Couldn't open PM device\n"); + return NULL; + } + } + else + { + return NULL; + } + #else return NULL; + #endif } osd_midi_device *osd_open_midi_output(const char *devname) { + #ifndef DISABLE_MIDI + int num_devs = Pm_CountDevices(); + int found_dev = -1; + const PmDeviceInfo *pmInfo; + PortMidiStream *stm; + osd_midi_device *ret; + + for (int i = 0; i < num_devs; i++) + { + pmInfo = Pm_GetDeviceInfo(i); + + if (pmInfo->output) + { + if (!strcmp(devname, pmInfo->name)) + { + found_dev = i; + break; + } + } + } + + if (found_dev >= 0) + { + if (Pm_OpenOutput(&stm, found_dev, NULL, 20, NULL, NULL, 0) == pmNoError) + { + ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device)); + memset(ret, 0, sizeof(osd_midi_device)); + ret->pmStream = stm; + return ret; + } + else + { + printf("Couldn't open PM device\n"); + return NULL; + } + } + else + { + return NULL; + } + #endif return NULL; } void osd_close_midi_channel(osd_midi_device *dev) { + #ifndef DISABLE_MIDI + Pm_Close(dev->pmStream); + osd_free(dev); + #endif +} + +bool osd_poll_midi_channel(osd_midi_device *dev) +{ + #ifndef DISABLE_MIDI + PmError chk = Pm_Poll(dev->pmStream); + + return (chk == pmGotData) ? true : false; + #else + return false; + #endif +} + +int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut) +{ + #ifndef DISABLE_MIDI + int msgsRead = Pm_Read(dev->pmStream, dev->rx_evBuf, 20); + int bytesOut = 0; + + if (msgsRead <= 0) + { + return 0; + } + + for (int msg = 0; msg < msgsRead; msg++) + { + UINT8 status = Pm_MessageStatus(dev->rx_evBuf[msg].message); + switch ((status>>4) & 0xf) + { + case 0xc: // 2-byte messages + case 0xd: + *pOut++ = status; + *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message); + bytesOut += 2; + break; + + case 0xf: // system common + switch (status & 0xf) + { + case 0: // System Exclusive + printf("No SEx please!\n"); + break; + + case 7: // End of System Exclusive + *pOut++ = status; + bytesOut += 1; + break; + + case 2: // song pos + case 3: // song select + *pOut++ = status; + *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message); + *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message); + bytesOut += 3; + break; + + default: // all other defined Fx messages are 1 byte + break; + } + break; + + default: + *pOut++ = status; + *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message); + *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message); + bytesOut += 3; + break; + } + } + + return bytesOut; + #else + return 0; + #endif } void osd_init_midi(void) |