Previous 199869 Revisions Next

r20234 Sunday 13th January, 2013 at 03:48:10 UTC by R. Belmont
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.
[src/emu]diimage.c diimage.h emu.mak
[src/emu/imagedev]midiin.c* midiin.h*
[src/osd]osdcore.h
[src/osd/portmedia]pmmidi.c

trunk/src/osd/osdcore.h
r20233r20234
895895osd_midi_device *osd_open_midi_input(const char *devname);
896896osd_midi_device *osd_open_midi_output(const char *devname);
897897void osd_close_midi_channel(osd_midi_device *dev);
898bool osd_poll_midi_channel(osd_midi_device *dev);
899int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut);
898900
899901/***************************************************************************
900902    UNCATEGORIZED INTERFACES
trunk/src/osd/portmedia/pmmidi.c
r20233r20234
1010#include "portmidi/portmidi.h"
1111#include "osdcore.h"
1212
13struct osd_midi_device
14{
15   #ifndef DISABLE_MIDI
16   PortMidiStream *pmStream;
17   PmEvent rx_evBuf[20];      // up to 20 events
18   #endif
19   UINT8 xmit_in[3]; // Pm_Messages mean we can at most have 3 residue bytes
20};
21
1322void osd_list_midi_devices(void)
1423{
1524   #ifndef DISABLE_MIDI
r20233r20234
5261
5362osd_midi_device *osd_open_midi_input(const char *devname)
5463{
64   #ifndef DISABLE_MIDI
65   int num_devs = Pm_CountDevices();
66   int found_dev = -1;
67   const PmDeviceInfo *pmInfo;
68   PortMidiStream *stm;
69   osd_midi_device *ret;
70
71   for (int i = 0; i < num_devs; i++)
72   {
73      pmInfo = Pm_GetDeviceInfo(i);
74
75      if (pmInfo->input)
76      {
77         if (!strcmp(devname, pmInfo->name))
78         {
79            found_dev = i;
80            break;
81         }
82      }
83   }
84
85   if (found_dev >= 0)
86   {
87      if (Pm_OpenInput(&stm, found_dev, NULL, 20, NULL, NULL) == pmNoError)
88      {
89         ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device));
90         memset(ret, 0, sizeof(osd_midi_device));
91         ret->pmStream = stm;
92         return ret;
93      }
94      else
95      {
96         printf("Couldn't open PM device\n");
97         return NULL;
98      }
99   }
100   else
101   {
102      return NULL;
103   }
104   #else
55105   return NULL;
106   #endif
56107}
57108
58109osd_midi_device *osd_open_midi_output(const char *devname)
59110{
111   #ifndef DISABLE_MIDI
112   int num_devs = Pm_CountDevices();
113   int found_dev = -1;
114   const PmDeviceInfo *pmInfo;
115   PortMidiStream *stm;
116   osd_midi_device *ret;
117
118   for (int i = 0; i < num_devs; i++)
119   {
120      pmInfo = Pm_GetDeviceInfo(i);
121
122      if (pmInfo->output)
123      {
124         if (!strcmp(devname, pmInfo->name))
125         {
126            found_dev = i;
127            break;
128         }
129      }
130   }
131
132   if (found_dev >= 0)
133   {
134      if (Pm_OpenOutput(&stm, found_dev, NULL, 20, NULL, NULL, 0) == pmNoError)
135      {
136         ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device));
137         memset(ret, 0, sizeof(osd_midi_device));
138         ret->pmStream = stm;
139         return ret;
140      }
141      else
142      {
143         printf("Couldn't open PM device\n");
144         return NULL;
145      }
146   }
147   else
148   {
149      return NULL;
150   }
151   #endif
60152   return NULL;
61153}
62154
63155void osd_close_midi_channel(osd_midi_device *dev)
64156{
157   #ifndef DISABLE_MIDI
158   Pm_Close(dev->pmStream);
159   osd_free(dev);
160   #endif
65161}
66162
163bool osd_poll_midi_channel(osd_midi_device *dev)
164{
165   #ifndef DISABLE_MIDI
166   PmError chk = Pm_Poll(dev->pmStream);
167
168   return (chk == pmGotData) ? true : false;
169   #else
170   return false;
171   #endif
172}
173
174int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut)
175{
176   #ifndef DISABLE_MIDI
177   int msgsRead = Pm_Read(dev->pmStream, dev->rx_evBuf, 20);
178   int bytesOut = 0;
179
180   if (msgsRead <= 0)
181   {
182      return 0;
183   }
184
185   for (int msg = 0; msg < msgsRead; msg++)
186   {
187      UINT8 status = Pm_MessageStatus(dev->rx_evBuf[msg].message);
188      switch ((status>>4) & 0xf)
189      {
190         case 0xc:   // 2-byte messages
191         case 0xd:
192            *pOut++ = status;
193            *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
194            bytesOut += 2;
195            break;
196
197         case 0xf:   // system common
198            switch (status & 0xf)
199            {
200               case 0:   // System Exclusive
201                  printf("No SEx please!\n");
202                  break;
203
204               case 7:   // End of System Exclusive
205                  *pOut++ = status;
206                  bytesOut += 1;
207                  break;
208
209               case 2:   // song pos
210               case 3:   // song select
211                  *pOut++ = status;
212                  *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
213                  *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message);
214                  bytesOut += 3;
215                  break;
216
217               default:   // all other defined Fx messages are 1 byte
218                  break;
219            }
220            break;
221
222         default:
223            *pOut++ = status;
224            *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
225            *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message);
226            bytesOut += 3;
227            break;
228      }
229   }
230
231   return bytesOut;
232   #else
233   return 0;
234   #endif
235}
236
67237void osd_init_midi(void)
68238{
69239   #ifndef DISABLE_MIDI
trunk/src/emu/imagedev/midiin.c
r0r20234
1/*********************************************************************
2
3    midiin.c
4
5    MIDI In image device and serial transmitter
6
7*********************************************************************/
8
9#include "emu.h"
10#include "midiin.h"
11
12/***************************************************************************
13    IMPLEMENTATION
14***************************************************************************/
15
16const device_type MIDIIN = &device_creator<midiin_device>;
17
18/*-------------------------------------------------
19    ctor
20-------------------------------------------------*/
21
22midiin_device::midiin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
23   : device_t(mconfig, MIDIIN, "MIDI In image device", tag, owner, clock),
24   device_image_interface(mconfig, *this),
25      device_serial_interface(mconfig, *this)
26{
27}
28
29/*-------------------------------------------------
30    device_start
31-------------------------------------------------*/
32
33void midiin_device::device_start()
34{
35   m_input_func.resolve(m_input_callback, *this);
36   m_timer = timer_alloc(0);
37}
38
39void midiin_device::device_reset()
40{
41   m_tx_busy = false;
42   m_xmit_read = m_xmit_write = 0;
43   m_timer->adjust(attotime::from_hz(1500), 0, attotime::from_hz(1500));
44
45   // we don't Rx, we Tx at 31250 8-N-1
46   set_rcv_rate(0);
47   set_tra_rate(31250);
48   set_data_frame(8, 1, SERIAL_PARITY_NONE);
49}
50
51/*-------------------------------------------------
52    device_config_complete
53-------------------------------------------------*/
54
55void midiin_device::device_config_complete(void)
56{
57   const midiin_config *intf = reinterpret_cast<const midiin_config *>(static_config());
58   if(intf != NULL)
59   {
60      *static_cast<midiin_config *>(this) = *intf;
61   }
62   else
63   {
64      memset(&m_input_callback, 0, sizeof(m_input_callback));
65   }
66   update_names();
67}
68
69/*-------------------------------------------------
70    device_timer
71-------------------------------------------------*/
72
73void midiin_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
74{
75   UINT8 buf[256];
76   int bytesRead;
77
78   if (osd_poll_midi_channel(m_midi))
79   {
80      bytesRead = osd_read_midi_channel(m_midi, buf);
81
82      if (bytesRead > 0)
83      {
84         for (int i = 0; i < bytesRead; i++)
85         {
86            xmit_char(buf[i]);
87         }
88      }
89   }
90}
91
92/*-------------------------------------------------
93    call_load
94-------------------------------------------------*/
95
96bool midiin_device::call_load(void)
97{
98   m_midi = osd_open_midi_input(filename());
99
100   if (m_midi == NULL)
101   {
102      return IMAGE_INIT_FAIL;
103   }
104
105   return IMAGE_INIT_PASS;
106}
107
108/*-------------------------------------------------
109    call_unload
110-------------------------------------------------*/
111
112void midiin_device::call_unload(void)
113{
114   osd_close_midi_channel(m_midi);
115}
116
117void midiin_device::tra_complete()
118{
119   // is there more waiting to send?
120   if (m_xmit_read != m_xmit_write)
121   {
122//      printf("tx1 %02x\n", m_xmitring[m_xmit_read]);
123      transmit_register_setup(m_xmitring[m_xmit_read++]);
124      if (m_xmit_read >= XMIT_RING_SIZE)
125      {
126         m_xmit_read = 0;
127      }
128   }
129   else
130   {
131      m_tx_busy = false;
132   }
133}
134
135void midiin_device::tra_callback()
136{
137   int bit = transmit_register_get_data_bit();
138   m_input_func(bit);
139}
140
141void midiin_device::xmit_char(UINT8 data)
142{
143//  printf("MIDI in: xmit %02x\n", data);
144
145   // if tx is busy it'll pick this up automatically when it completes
146   if (!m_tx_busy)
147   {
148      m_tx_busy = true;
149//      printf("tx0 %02x\n", data);
150      transmit_register_setup(data);
151   }
152   else
153   {
154      // tx is busy, it'll pick this up next time
155      m_xmitring[m_xmit_write++] = data;
156      if (m_xmit_write >= XMIT_RING_SIZE)
157      {
158         m_xmit_write = 0;
159      }
160   }
161}
162
163void midiin_device::input_callback(UINT8 state)
164{
165}
166
trunk/src/emu/imagedev/midiin.h
r0r20234
1/*********************************************************************
2
3    midiin.h
4
5    MIDI In image device
6
7*********************************************************************/
8
9#ifndef __MIDIIN_H__
10#define __MIDIIN_H__
11
12#include "image.h"
13
14/***************************************************************************
15    CONSTANTS
16***************************************************************************/
17
18struct midiin_config
19{
20   /* callback to driver */
21   devcb_write_line        m_input_callback;
22};
23
24#define MCFG_MIDIIN_ADD(_tag, _config) \
25   MCFG_DEVICE_ADD(_tag, MIDIIN, 0) \
26   MCFG_DEVICE_CONFIG(_config)
27
28
29/***************************************************************************
30    TYPE DEFINITIONS
31***************************************************************************/
32
33class midiin_device :    public device_t,
34                  public device_image_interface,
35                  public device_serial_interface,
36                  public midiin_config
37{
38public:
39   // construction/destruction
40   midiin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
41
42   // image-level overrides
43   virtual bool call_load();
44   virtual void call_unload();
45
46   // image device
47   virtual iodevice_t image_type() const { return IO_MIDIIN; }
48   virtual bool is_readable()  const { return 1; }
49   virtual bool is_writeable() const { return 0; }
50   virtual bool is_creatable() const { return 0; }
51   virtual bool must_be_loaded() const { return 1; }
52   virtual bool is_reset_on_load() const { return 0; }
53   virtual const char *file_extensions() const { return "mid"; }
54   virtual bool core_opens_image_file() const { return FALSE; }
55   virtual const option_guide *create_option_guide() const { return NULL; }
56
57protected:
58   // device-level overrides
59   virtual void device_start();
60   virtual void device_reset();
61
62   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
63   virtual void device_config_complete();
64
65   // serial overrides
66   virtual void tra_complete();    // Tx completed sending byte
67   virtual void tra_callback();    // Tx send bit
68   void input_callback(UINT8 state);
69
70private:
71   static const int XMIT_RING_SIZE = 64;
72
73   void xmit_char(UINT8 data);
74
75   osd_midi_device *m_midi;
76   emu_timer *m_timer;
77   devcb_resolved_write_line m_input_func;
78   UINT8 m_xmitring[XMIT_RING_SIZE];
79   int m_xmit_read, m_xmit_write;
80   bool m_tx_busy;
81};
82
83// device type definition
84extern const device_type MIDIIN;
85
86// device iterator
87typedef device_type_iterator<&device_creator<midiin_device>, midiin_device> midiin_device_iterator;
88
89#endif /* __MIDIIN_H__ */
trunk/src/emu/emu.mak
r20233r20234
345345   $(EMUIMAGEDEV)/flopdrv.o    \
346346   $(EMUIMAGEDEV)/floppy.o     \
347347   $(EMUIMAGEDEV)/harddriv.o   \
348   $(EMUIMAGEDEV)/midiin.o     \
348349   $(EMUIMAGEDEV)/printer.o    \
349350   $(EMUIMAGEDEV)/serial.o     \
350351   $(EMUIMAGEDEV)/snapquik.o   \
trunk/src/emu/diimage.c
r20233r20234
6767      { IO_CDROM,     "cdrom",        "cdrm" }, /* 13 */
6868      { IO_MAGTAPE,   "magtape",      "magt" }, /* 14 */
6969      { IO_ROM,       "romimage",     "rom"  }, /* 15 */
70      { IO_MIDIIN,   "midiin",       "min"  }, /* 16 */
71      { IO_MIDIOUT,   "midiout",      "mout" }  /* 17 */
7072   };
7173
7274
trunk/src/emu/diimage.h
r20233r20234
7070   IO_CDROM,       /* 14 - optical CD-ROM disc */
7171   IO_MAGTAPE,     /* 15 - Magentic tape */
7272   IO_ROM,         /* 16 - Individual ROM image - the Amstrad CPC has a few applications that were sold on 16kB ROMs */
73   IO_COUNT        /* 17 - Total Number of IO_devices for searching */
73   IO_MIDIIN,      /* 17 - MIDI In port */
74   IO_MIDIOUT,      /* 18 - MIDI Out port */
75   IO_COUNT        /* 19 - Total Number of IO_devices for searching */
7476};
7577
7678enum image_error_t

Previous 199869 Revisions Next


© 1997-2024 The MAME Team