summaryrefslogtreecommitdiffstatshomepage
path: root/src
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
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')
-rw-r--r--src/emu/diimage.c2
-rw-r--r--src/emu/diimage.h4
-rw-r--r--src/emu/emu.mak1
-rw-r--r--src/emu/imagedev/midiin.c166
-rw-r--r--src/emu/imagedev/midiin.h89
-rw-r--r--src/osd/osdcore.h2
-rw-r--r--src/osd/portmedia/pmmidi.c170
7 files changed, 433 insertions, 1 deletions
diff --git a/src/emu/diimage.c b/src/emu/diimage.c
index a8c921d6e4a..64022a68313 100644
--- a/src/emu/diimage.c
+++ b/src/emu/diimage.c
@@ -67,6 +67,8 @@ const image_device_type_info device_image_interface::m_device_info_array[] =
{ IO_CDROM, "cdrom", "cdrm" }, /* 13 */
{ IO_MAGTAPE, "magtape", "magt" }, /* 14 */
{ IO_ROM, "romimage", "rom" }, /* 15 */
+ { IO_MIDIIN, "midiin", "min" }, /* 16 */
+ { IO_MIDIOUT, "midiout", "mout" } /* 17 */
};
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
index 8b17f4f6587..7781be91dcd 100644
--- a/src/emu/diimage.h
+++ b/src/emu/diimage.h
@@ -70,7 +70,9 @@ enum iodevice_t
IO_CDROM, /* 14 - optical CD-ROM disc */
IO_MAGTAPE, /* 15 - Magentic tape */
IO_ROM, /* 16 - Individual ROM image - the Amstrad CPC has a few applications that were sold on 16kB ROMs */
- IO_COUNT /* 17 - Total Number of IO_devices for searching */
+ IO_MIDIIN, /* 17 - MIDI In port */
+ IO_MIDIOUT, /* 18 - MIDI Out port */
+ IO_COUNT /* 19 - Total Number of IO_devices for searching */
};
enum image_error_t
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index 408bd3d8ea5..52459e696fd 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -345,6 +345,7 @@ EMUIMAGEDEVOBJS = \
$(EMUIMAGEDEV)/flopdrv.o \
$(EMUIMAGEDEV)/floppy.o \
$(EMUIMAGEDEV)/harddriv.o \
+ $(EMUIMAGEDEV)/midiin.o \
$(EMUIMAGEDEV)/printer.o \
$(EMUIMAGEDEV)/serial.o \
$(EMUIMAGEDEV)/snapquik.o \
diff --git a/src/emu/imagedev/midiin.c b/src/emu/imagedev/midiin.c
new file mode 100644
index 00000000000..1ec7ba774fa
--- /dev/null
+++ b/src/emu/imagedev/midiin.c
@@ -0,0 +1,166 @@
+/*********************************************************************
+
+ midiin.c
+
+ MIDI In image device and serial transmitter
+
+*********************************************************************/
+
+#include "emu.h"
+#include "midiin.h"
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+const device_type MIDIIN = &device_creator<midiin_device>;
+
+/*-------------------------------------------------
+ ctor
+-------------------------------------------------*/
+
+midiin_device::midiin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MIDIIN, "MIDI In image device", tag, owner, clock),
+ device_image_interface(mconfig, *this),
+ device_serial_interface(mconfig, *this)
+{
+}
+
+/*-------------------------------------------------
+ device_start
+-------------------------------------------------*/
+
+void midiin_device::device_start()
+{
+ m_input_func.resolve(m_input_callback, *this);
+ m_timer = timer_alloc(0);
+}
+
+void midiin_device::device_reset()
+{
+ m_tx_busy = false;
+ m_xmit_read = m_xmit_write = 0;
+ m_timer->adjust(attotime::from_hz(1500), 0, attotime::from_hz(1500));
+
+ // we don't Rx, we Tx at 31250 8-N-1
+ set_rcv_rate(0);
+ set_tra_rate(31250);
+ set_data_frame(8, 1, SERIAL_PARITY_NONE);
+}
+
+/*-------------------------------------------------
+ device_config_complete
+-------------------------------------------------*/
+
+void midiin_device::device_config_complete(void)
+{
+ const midiin_config *intf = reinterpret_cast<const midiin_config *>(static_config());
+ if(intf != NULL)
+ {
+ *static_cast<midiin_config *>(this) = *intf;
+ }
+ else
+ {
+ memset(&m_input_callback, 0, sizeof(m_input_callback));
+ }
+ update_names();
+}
+
+/*-------------------------------------------------
+ device_timer
+-------------------------------------------------*/
+
+void midiin_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ UINT8 buf[256];
+ int bytesRead;
+
+ if (osd_poll_midi_channel(m_midi))
+ {
+ bytesRead = osd_read_midi_channel(m_midi, buf);
+
+ if (bytesRead > 0)
+ {
+ for (int i = 0; i < bytesRead; i++)
+ {
+ xmit_char(buf[i]);
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------
+ call_load
+-------------------------------------------------*/
+
+bool midiin_device::call_load(void)
+{
+ m_midi = osd_open_midi_input(filename());
+
+ if (m_midi == NULL)
+ {
+ return IMAGE_INIT_FAIL;
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+/*-------------------------------------------------
+ call_unload
+-------------------------------------------------*/
+
+void midiin_device::call_unload(void)
+{
+ osd_close_midi_channel(m_midi);
+}
+
+void midiin_device::tra_complete()
+{
+ // is there more waiting to send?
+ if (m_xmit_read != m_xmit_write)
+ {
+// printf("tx1 %02x\n", m_xmitring[m_xmit_read]);
+ transmit_register_setup(m_xmitring[m_xmit_read++]);
+ if (m_xmit_read >= XMIT_RING_SIZE)
+ {
+ m_xmit_read = 0;
+ }
+ }
+ else
+ {
+ m_tx_busy = false;
+ }
+}
+
+void midiin_device::tra_callback()
+{
+ int bit = transmit_register_get_data_bit();
+ m_input_func(bit);
+}
+
+void midiin_device::xmit_char(UINT8 data)
+{
+// printf("MIDI in: xmit %02x\n", data);
+
+ // if tx is busy it'll pick this up automatically when it completes
+ if (!m_tx_busy)
+ {
+ m_tx_busy = true;
+// printf("tx0 %02x\n", data);
+ transmit_register_setup(data);
+ }
+ else
+ {
+ // tx is busy, it'll pick this up next time
+ m_xmitring[m_xmit_write++] = data;
+ if (m_xmit_write >= XMIT_RING_SIZE)
+ {
+ m_xmit_write = 0;
+ }
+ }
+}
+
+void midiin_device::input_callback(UINT8 state)
+{
+}
+
diff --git a/src/emu/imagedev/midiin.h b/src/emu/imagedev/midiin.h
new file mode 100644
index 00000000000..ac6bbc49a54
--- /dev/null
+++ b/src/emu/imagedev/midiin.h
@@ -0,0 +1,89 @@
+/*********************************************************************
+
+ midiin.h
+
+ MIDI In image device
+
+*********************************************************************/
+
+#ifndef __MIDIIN_H__
+#define __MIDIIN_H__
+
+#include "image.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+struct midiin_config
+{
+ /* callback to driver */
+ devcb_write_line m_input_callback;
+};
+
+#define MCFG_MIDIIN_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, MIDIIN, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+class midiin_device : public device_t,
+ public device_image_interface,
+ public device_serial_interface,
+ public midiin_config
+{
+public:
+ // construction/destruction
+ midiin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+
+ // image device
+ virtual iodevice_t image_type() const { return IO_MIDIIN; }
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 1; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *file_extensions() const { return "mid"; }
+ virtual bool core_opens_image_file() const { return FALSE; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+ virtual void device_config_complete();
+
+ // serial overrides
+ virtual void tra_complete(); // Tx completed sending byte
+ virtual void tra_callback(); // Tx send bit
+ void input_callback(UINT8 state);
+
+private:
+ static const int XMIT_RING_SIZE = 64;
+
+ void xmit_char(UINT8 data);
+
+ osd_midi_device *m_midi;
+ emu_timer *m_timer;
+ devcb_resolved_write_line m_input_func;
+ UINT8 m_xmitring[XMIT_RING_SIZE];
+ int m_xmit_read, m_xmit_write;
+ bool m_tx_busy;
+};
+
+// device type definition
+extern const device_type MIDIIN;
+
+// device iterator
+typedef device_type_iterator<&device_creator<midiin_device>, midiin_device> midiin_device_iterator;
+
+#endif /* __MIDIIN_H__ */
diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h
index c2f8ffb2e6c..bc078888669 100644
--- a/src/osd/osdcore.h
+++ b/src/osd/osdcore.h
@@ -895,6 +895,8 @@ void osd_list_midi_devices(void);
osd_midi_device *osd_open_midi_input(const char *devname);
osd_midi_device *osd_open_midi_output(const char *devname);
void osd_close_midi_channel(osd_midi_device *dev);
+bool osd_poll_midi_channel(osd_midi_device *dev);
+int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut);
/***************************************************************************
UNCATEGORIZED INTERFACES
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)