Previous 199869 Revisions Next

r34297 Friday 9th January, 2015 at 23:09:06 UTC by Couriersud
Fix windows compile and add missing files. (nw)
[src/osd/modules/midi]none.c* portmidi.c*
[src/osd/windows]winmain.c

trunk/src/osd/modules/midi/none.c
r0r242809
1/***************************************************************************
2
3    none.c
4
5    Empty shim for systems not supporting midi / portmidi
6
7*******************************************************************c********/
8
9#include "osdcore.h"
10
11struct osd_midi_device
12{
13    int dummy;
14};
15
16bool osd_midi_init()
17{
18    return true;
19}
20
21void osd_midi_exit()
22{
23}
24
25void osd_list_midi_devices(void)
26{
27    osd_printf_warning("\nMIDI is not supported in this build\n");
28}
29
30osd_midi_device *osd_open_midi_input(const char *devname)
31{
32    return NULL;
33}
34
35osd_midi_device *osd_open_midi_output(const char *devname)
36{
37    return NULL;
38}
39
40void osd_close_midi_channel(osd_midi_device *dev)
41{
42}
43
44bool osd_poll_midi_channel(osd_midi_device *dev)
45{
46    return false;
47}
48
49int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut)
50{
51    return 0;
52}
53
54void osd_write_midi_channel(osd_midi_device *dev, UINT8 data)
55{
56}
trunk/src/osd/modules/midi/portmidi.c
r0r242809
1/***************************************************************************
2
3    portmap.c
4
5    Midi implementation based on portmidi library
6
7*******************************************************************c********/
8
9#include "portmidi/portmidi.h"
10#include "osdcore.h"
11
12static const int RX_EVENT_BUF_SIZE = 512;
13
14#define MIDI_SYSEX  0xf0
15#define MIDI_EOX    0xf7
16
17struct osd_midi_device
18{
19    PortMidiStream *pmStream;
20    PmEvent rx_evBuf[RX_EVENT_BUF_SIZE];
21    UINT8 xmit_in[4]; // Pm_Messages mean we can at most have 3 residue bytes
22    int xmit_cnt;
23    UINT8 last_status;
24    bool rx_sysex;
25};
26
27bool osd_midi_init()
28{
29    Pm_Initialize();
30    return true;
31}
32
33void osd_midi_exit()
34{
35    Pm_Terminate();
36}
37
38void osd_list_midi_devices(void)
39{
40    int num_devs = Pm_CountDevices();
41    const PmDeviceInfo *pmInfo;
42
43    printf("\n");
44
45    if (num_devs == 0)
46    {
47        printf("No MIDI ports were found\n");
48        return;
49    }
50
51    printf("MIDI input ports:\n");
52    for (int i = 0; i < num_devs; i++)
53    {
54        pmInfo = Pm_GetDeviceInfo(i);
55
56        if (pmInfo->input)
57        {
58            printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultInputDeviceID()) ? "(default)" : "");
59        }
60    }
61
62    printf("\nMIDI output ports:\n");
63    for (int i = 0; i < num_devs; i++)
64    {
65        pmInfo = Pm_GetDeviceInfo(i);
66
67        if (pmInfo->output)
68        {
69            printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultOutputDeviceID()) ? "(default)" : "");
70        }
71    }
72}
73
74osd_midi_device *osd_open_midi_input(const char *devname)
75{
76    int num_devs = Pm_CountDevices();
77    int found_dev = -1;
78    const PmDeviceInfo *pmInfo;
79    PortMidiStream *stm;
80    osd_midi_device *ret;
81
82    if (!strcmp("default", devname))
83    {
84        found_dev = Pm_GetDefaultInputDeviceID();
85    }
86    else
87    {
88        for (int i = 0; i < num_devs; i++)
89        {
90            pmInfo = Pm_GetDeviceInfo(i);
91
92            if (pmInfo->input)
93            {
94                if (!strcmp(devname, pmInfo->name))
95                {
96                    found_dev = i;
97                    break;
98                }
99            }
100        }
101    }
102
103    if (found_dev >= 0)
104    {
105        if (Pm_OpenInput(&stm, found_dev, NULL, RX_EVENT_BUF_SIZE, NULL, NULL) == pmNoError)
106        {
107            ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device));
108            memset(ret, 0, sizeof(osd_midi_device));
109            ret->pmStream = stm;
110            return ret;
111        }
112        else
113        {
114            printf("Couldn't open PM device\n");
115            return NULL;
116        }
117    }
118    else
119    {
120        return NULL;
121    }
122}
123
124osd_midi_device *osd_open_midi_output(const char *devname)
125{
126    int num_devs = Pm_CountDevices();
127    int found_dev = -1;
128    const PmDeviceInfo *pmInfo;
129    PortMidiStream *stm;
130    osd_midi_device *ret;
131
132    if (!strcmp("default", devname))
133    {
134        found_dev = Pm_GetDefaultOutputDeviceID();
135    }
136    else
137    {
138        for (int i = 0; i < num_devs; i++)
139        {
140            pmInfo = Pm_GetDeviceInfo(i);
141
142            if (pmInfo->output)
143            {
144                if (!strcmp(devname, pmInfo->name))
145                {
146                    found_dev = i;
147                    break;
148                }
149            }
150        }
151    }
152
153    if (found_dev >= 0)
154    {
155        if (Pm_OpenOutput(&stm, found_dev, NULL, 100, NULL, NULL, 0) == pmNoError)
156        {
157            ret = (osd_midi_device *)osd_malloc(sizeof(osd_midi_device));
158            memset(ret, 0, sizeof(osd_midi_device));
159            ret->pmStream = stm;
160            return ret;
161        }
162        else
163        {
164            printf("Couldn't open PM device\n");
165            return NULL;
166        }
167    }
168    else
169    {
170        return NULL;
171    }
172    return NULL;
173}
174
175void osd_close_midi_channel(osd_midi_device *dev)
176{
177    Pm_Close(dev->pmStream);
178    osd_free(dev);
179}
180
181bool osd_poll_midi_channel(osd_midi_device *dev)
182{
183    PmError chk = Pm_Poll(dev->pmStream);
184
185    return (chk == pmGotData) ? true : false;
186}
187
188int osd_read_midi_channel(osd_midi_device *dev, UINT8 *pOut)
189{
190    int msgsRead = Pm_Read(dev->pmStream, dev->rx_evBuf, RX_EVENT_BUF_SIZE);
191    int bytesOut = 0;
192
193    if (msgsRead <= 0)
194    {
195        return 0;
196    }
197
198    for (int msg = 0; msg < msgsRead; msg++)
199    {
200        UINT8 status = Pm_MessageStatus(dev->rx_evBuf[msg].message);
201
202        if (dev->rx_sysex)
203        {
204            if (status & 0x80)  // sys real-time imposing on us?
205            {
206                if ((status == 0xf2) || (status == 0xf3))
207                {
208                    *pOut++ = status;
209                    *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
210                    *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message);
211                    bytesOut += 3;
212                }
213                else
214                {
215                    *pOut++ = status;
216                    bytesOut++;
217                    if (status == MIDI_EOX)
218                    {
219                        dev->rx_sysex = false;
220                    }
221                }
222            }
223            else    // shift out the sysex bytes
224            {
225                for (int i = 0; i < 4; i++)
226                {
227                    UINT8 byte = dev->rx_evBuf[msg].message & 0xff;
228                    *pOut++ = byte;
229                    bytesOut++;
230                    if (byte == MIDI_EOX)
231                    {
232                        dev->rx_sysex = false;
233                        break;
234                    }
235                    dev->rx_evBuf[msg].message >>= 8;
236                }
237            }
238        }
239        else
240        {
241            switch ((status>>4) & 0xf)
242            {
243                case 0xc:   // 2-byte messages
244                case 0xd:
245                    *pOut++ = status;
246                    *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
247                    bytesOut += 2;
248                    break;
249
250                case 0xf:   // system common
251                    switch (status & 0xf)
252                    {
253                        case 0: // System Exclusive
254                        {
255                            *pOut++ = status;   // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe
256                            *pOut++ = (dev->rx_evBuf[msg].message>>8) & 0xff;
257                            *pOut++ = (dev->rx_evBuf[msg].message>>16) & 0xff;
258                            UINT8 last = *pOut++ = (dev->rx_evBuf[msg].message>>24) & 0xff;
259                            bytesOut += 4;
260                            dev->rx_sysex = (last != MIDI_EOX);
261                            break;
262                        }
263
264                        case 7: // End of System Exclusive
265                            *pOut++ = status;
266                            bytesOut += 1;
267                            dev->rx_sysex = false;
268                            break;
269
270                        case 2: // song pos
271                        case 3: // song select
272                            *pOut++ = status;
273                            *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
274                            *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message);
275                            bytesOut += 3;
276                            break;
277
278                        default:    // all other defined Fx messages are 1 byte
279                            break;
280                    }
281                    break;
282
283                default:
284                    *pOut++ = status;
285                    *pOut++ = Pm_MessageData1(dev->rx_evBuf[msg].message);
286                    *pOut++ = Pm_MessageData2(dev->rx_evBuf[msg].message);
287                    bytesOut += 3;
288                    break;
289            }
290        }
291    }
292
293    return bytesOut;
294}
295
296void osd_write_midi_channel(osd_midi_device *dev, UINT8 data)
297{
298    int bytes_needed = 0;
299    PmEvent ev;
300    ev.timestamp = 0;   // use the current time
301
302//  printf("write: %02x (%d)\n", data, dev->xmit_cnt);
303
304    // reject data bytes when no valid status exists
305    if ((dev->last_status == 0) && !(data & 0x80))
306    {
307        dev->xmit_cnt = 0;
308        return;
309    }
310
311    if (dev->xmit_cnt >= 4)
312    {
313        printf("MIDI out: packet assembly overflow, contact MAMEdev!\n");
314        return;
315    }
316
317    // handle sysex
318    if (dev->last_status == MIDI_SYSEX)
319    {
320//      printf("sysex: %02x (%d)\n", data, dev->xmit_cnt);
321
322        // if we get a status that isn't sysex, assume it's system common
323        if ((data & 0x80) && (data != MIDI_EOX))
324        {
325//          printf("common during sysex!\n");
326            ev.message = Pm_Message(data, 0, 0);
327            Pm_Write(dev->pmStream, &ev, 1);
328            return;
329        }
330
331        dev->xmit_in[dev->xmit_cnt++] = data;
332
333        // if EOX or 4 bytes filled, transmit 4 bytes
334        if ((dev->xmit_cnt == 4) || (data == MIDI_EOX))
335        {
336            ev.message = dev->xmit_in[0] | (dev->xmit_in[1]<<8) | (dev->xmit_in[2]<<16) | (dev->xmit_in[3]<<24);
337            Pm_Write(dev->pmStream, &ev, 1);
338            dev->xmit_in[0] = dev->xmit_in[1] = dev->xmit_in[2] = dev->xmit_in[3] = 0;
339            dev->xmit_cnt = 0;
340
341//          printf("SysEx packet: %08x\n", ev.message);
342
343            // if this is EOX, kill the running status
344            if (data == MIDI_EOX)
345            {
346                dev->last_status = 0;
347            }
348        }
349
350        return;
351    }
352
353    // handle running status.  don't allow system real-time messages to be considered as running status.
354    if ((dev->xmit_cnt == 0) && (data & 0x80) && (data < 0xf8))
355    {
356        dev->last_status = data;
357    }
358
359    if ((dev->xmit_cnt == 0) && !(data & 0x80))
360    {
361        dev->xmit_in[dev->xmit_cnt++] = dev->last_status;
362        dev->xmit_in[dev->xmit_cnt++] = data;
363//      printf("\trunning status: [%d] = %02x, [%d] = %02x, last_status = %02x\n", dev->xmit_cnt-2, dev->last_status, dev->xmit_cnt-1, data, dev->last_status);
364    }
365    else
366    {
367        dev->xmit_in[dev->xmit_cnt++] = data;
368//      printf("\tNRS: [%d] = %02x\n", dev->xmit_cnt-1, data);
369    }
370
371    if ((dev->xmit_cnt == 1) && (dev->xmit_in[0] == MIDI_SYSEX))
372    {
373//      printf("Start SysEx!\n");
374        dev->last_status = MIDI_SYSEX;
375        return;
376    }
377
378    // are we there yet?
379//  printf("status check: %02x\n", dev->xmit_in[0]);
380    switch ((dev->xmit_in[0]>>4) & 0xf)
381    {
382        case 0xc:   // 2-byte messages
383        case 0xd:
384            bytes_needed = 2;
385            break;
386
387        case 0xf:   // system common
388            switch (dev->xmit_in[0] & 0xf)
389            {
390                case 0: // System Exclusive is handled above
391                    break;
392
393                case 7: // End of System Exclusive
394                    bytes_needed = 1;
395                    break;
396
397                case 2: // song pos
398                case 3: // song select
399                    bytes_needed = 3;
400                    break;
401
402                default:    // all other defined Fx messages are 1 byte
403                    bytes_needed = 1;
404                    break;
405            }
406            break;
407
408        default:
409            bytes_needed = 3;
410            break;
411    }
412
413    if (dev->xmit_cnt == bytes_needed)
414    {
415        ev.message = Pm_Message(dev->xmit_in[0], dev->xmit_in[1], dev->xmit_in[2]);
416        Pm_Write(dev->pmStream, &ev, 1);
417        dev->xmit_cnt = 0;
418    }
419
420}
trunk/src/osd/windows/winmain.c
r242808r242809
18241824      Sleep(1);
18251825   }
18261826}
1827
1828//-------------------------------------------------
1829// FIXME: Doesn't belong here but there's no better
1830//        place currently.
1831//-------------------------------------------------
1832
1833bool osd_interface::midi_init()
1834{
1835    // this should be done on the OS_level
1836    return osd_midi_init();
1837}
1838
1839//-------------------------------------------------
1840//  list_midi_devices - list available midi devices
1841//-------------------------------------------------
1842
1843void osd_interface::list_midi_devices(void)
1844{
1845    osd_list_midi_devices();
1846}
1847
1848void osd_interface::midi_exit()
1849{
1850    osd_midi_exit();
1851}


Previous 199869 Revisions Next


© 1997-2024 The MAME Team