summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/portmedia
diff options
context:
space:
mode:
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
commitf6c44c6e9bbf1720d481707cbee73aadbae21572 (patch)
tree93d48913f4afee3080c2aca425119f0840b74276 /src/osd/portmedia
parentfa807d8a30cd94a3f4f283db378f47312271d61f (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.c170
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)