mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
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.
This commit is contained in:
parent
fa807d8a30
commit
f6c44c6e9b
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1041,6 +1041,8 @@ src/emu/imagedev/floppy.c svneol=native#text/plain
|
||||
src/emu/imagedev/floppy.h svneol=native#text/plain
|
||||
src/emu/imagedev/harddriv.c svneol=native#text/plain
|
||||
src/emu/imagedev/harddriv.h svneol=native#text/plain
|
||||
src/emu/imagedev/midiin.c svneol=native#text/plain
|
||||
src/emu/imagedev/midiin.h svneol=native#text/plain
|
||||
src/emu/imagedev/printer.c svneol=native#text/plain
|
||||
src/emu/imagedev/printer.h svneol=native#text/plain
|
||||
src/emu/imagedev/serial.c svneol=native#text/plain
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
166
src/emu/imagedev/midiin.c
Normal file
166
src/emu/imagedev/midiin.c
Normal file
@ -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)
|
||||
{
|
||||
}
|
||||
|
89
src/emu/imagedev/midiin.h
Normal file
89
src/emu/imagedev/midiin.h
Normal file
@ -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__ */
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user