1
/* pmwinmm.c -- system specific definitions */
3
/* without this define, InitializeCriticalSectionAndSpinCount is undefined */
4
/* this version level means "Windows 2000 and higher" */
5
#define _WIN32_WINNT 0x0500
13
#include "pminternal.h"
18
/* asserts used to verify portMidi code logic is sound; later may want
19
something more graceful */
23
/* this printf stuff really important for debugging client app w/host errors.
24
probably want to do something else besides read/write from/to console
25
for portability, however */
30
#define streql(x, y) (strcmp(x, y) == 0)
32
#define MIDI_SYSEX 0xf0
35
/* callback routines */
36
static void CALLBACK winmm_in_callback(HMIDIIN hMidiIn,
37
WORD wMsg, DWORD dwInstance,
38
DWORD dwParam1, DWORD dwParam2);
39
static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg,
40
DWORD dwInstance, DWORD dwParam1,
42
static void CALLBACK winmm_out_callback(HMIDIOUT hmo, UINT wMsg,
43
DWORD dwInstance, DWORD dwParam1,
46
extern pm_fns_node pm_winmm_in_dictionary;
47
extern pm_fns_node pm_winmm_out_dictionary;
49
static void winmm_out_delete(PmInternal *midi); /* forward reference */
52
A note about buffers: WinMM seems to hold onto buffers longer than
53
one would expect, e.g. when I tried using 2 small buffers to send
54
long sysex messages, at some point WinMM held both buffers. This problem
55
was fixed by making buffers bigger. Therefore, it seems that there should
56
be enough buffer space to hold a whole sysex message.
58
The bufferSize passed into Pm_OpenInput (passed into here as buffer_len)
59
will be used to estimate the largest sysex message (= buffer_len * 4 bytes).
60
Call that the max_sysex_len = buffer_len * 4.
62
For simple midi output (latency == 0), allocate 3 buffers, each with half
63
the size of max_sysex_len, but each at least 256 bytes.
65
For stream output, there will already be enough space in very short
66
buffers, so use them, but make sure there are at least 16.
68
For input, use many small buffers rather than 2 large ones so that when
69
there are short sysex messages arriving frequently (as in control surfaces)
70
there will be more free buffers to fill. Use max_sysex_len / 64 buffers,
71
but at least 16, of size 64 bytes each.
73
The following constants help to represent these design parameters:
75
#define NUM_SIMPLE_SYSEX_BUFFERS 3
76
#define MIN_SIMPLE_SYSEX_LEN 256
78
#define MIN_STREAM_BUFFERS 16
79
#define STREAM_BUFFER_LEN 24
81
#define INPUT_SYSEX_LEN 64
82
#define MIN_INPUT_BUFFERS 16
84
/* if we run out of space for output (assume this is due to a sysex msg,
85
expand by up to NUM_EXPANSION_BUFFERS in increments of EXPANSION_BUFFER_LEN
87
#define NUM_EXPANSION_BUFFERS 128
88
#define EXPANSION_BUFFER_LEN 1024
90
/* A sysex buffer has 3 DWORDS as a header plus the actual message size */
91
#define MIDIHDR_SYSEX_BUFFER_LENGTH(x) ((x) + sizeof(long)*3)
92
/* A MIDIHDR with a sysex message is the buffer length plus the header size */
93
#define MIDIHDR_SYSEX_SIZE(x) (MIDIHDR_SYSEX_BUFFER_LENGTH(x) + sizeof(MIDIHDR))
94
#ifdef USE_SYSEX_BUFFERS
95
/* Size of a MIDIHDR with a buffer contaning multiple MIDIEVENT structures */
96
#define MIDIHDR_SIZE(x) ((x) + sizeof(MIDIHDR))
100
==============================================================================
101
win32 mmedia system specific structure passed to midi callbacks
102
==============================================================================
105
/* global winmm device info */
106
MIDIINCAPS *midi_in_caps = NULL;
107
MIDIINCAPS midi_in_mapper_caps;
108
UINT midi_num_inputs = 0;
109
MIDIOUTCAPS *midi_out_caps = NULL;
110
MIDIOUTCAPS midi_out_mapper_caps;
111
UINT midi_num_outputs = 0;
113
/* per device info */
114
typedef struct midiwinmm_struct {
116
HMIDISTRM stream; /* windows handle for stream */
117
HMIDIOUT out; /* windows handle for out calls */
118
HMIDIIN in; /* windows handle for in calls */
121
/* midi output messages are sent in these buffers, which are allocated
122
* in a round-robin fashion, using next_buffer as an index
124
LPMIDIHDR *buffers; /* pool of buffers for midi in or out data */
125
int max_buffers; /* length of buffers array */
126
int buffers_expanded; /* buffers array expanded for extra msgs? */
127
int num_buffers; /* how many buffers allocated in buffers array */
128
int next_buffer; /* index of next buffer to send */
129
HANDLE buffer_signal; /* used to wait for buffer to become free */
130
#ifdef USE_SYSEX_BUFFERS
131
/* sysex buffers will be allocated only when
132
* a sysex message is sent. The size of the buffer is fixed.
134
LPMIDIHDR sysex_buffers[NUM_SYSEX_BUFFERS]; /* pool of buffers for sysex data */
135
int next_sysex_buffer; /* index of next sysexbuffer to send */
137
unsigned long last_time; /* last output time */
138
int first_message; /* flag: treat first message differently */
139
int sysex_mode; /* middle of sending sysex */
140
unsigned long sysex_word; /* accumulate data when receiving sysex */
141
unsigned int sysex_byte_count; /* count how many received */
142
LPMIDIHDR hdr; /* the message accumulating sysex to send */
143
unsigned long sync_time; /* when did we last determine delta? */
144
long delta; /* difference between stream time and
146
int error; /* host error from doing port midi call */
147
CRITICAL_SECTION lock; /* prevents reentrant callbacks (input only) */
148
} midiwinmm_node, *midiwinmm_type;
152
=============================================================================
153
general MIDI device queries
154
=============================================================================
156
static void pm_winmm_general_inputs()
160
midi_num_inputs = midiInGetNumDevs();
161
midi_in_caps = pm_alloc(sizeof(MIDIINCAPS) * midi_num_inputs);
163
if (midi_in_caps == NULL) {
164
/* if you can't open a particular system-level midi interface
165
* (such as winmm), we just consider that system or API to be
166
* unavailable and move on without reporting an error.
171
for (i = 0; i < midi_num_inputs; i++) {
172
wRtn = midiInGetDevCaps(i, (LPMIDIINCAPS) & midi_in_caps[i],
174
if (wRtn == MMSYSERR_NOERROR) {
175
/* ignore errors here -- if pm_descriptor_max is exceeded, some
176
devices will not be accessible. */
177
pm_add_device("MMSystem", midi_in_caps[i].szPname, TRUE,
178
(void *) i, &pm_winmm_in_dictionary);
184
static void pm_winmm_mapper_input()
187
/* Note: if MIDIMAPPER opened as input (documentation implies you
188
can, but current system fails to retrieve input mapper
189
capabilities) then you still should retrieve some formof
191
wRtn = midiInGetDevCaps((UINT) MIDIMAPPER,
192
(LPMIDIINCAPS) & midi_in_mapper_caps,
194
if (wRtn == MMSYSERR_NOERROR) {
195
pm_add_device("MMSystem", midi_in_mapper_caps.szPname, TRUE,
196
(void *) MIDIMAPPER, &pm_winmm_in_dictionary);
201
static void pm_winmm_general_outputs()
205
midi_num_outputs = midiOutGetNumDevs();
206
midi_out_caps = pm_alloc( sizeof(MIDIOUTCAPS) * midi_num_outputs );
208
if (midi_out_caps == NULL) {
209
/* no error is reported -- see pm_winmm_general_inputs */
213
for (i = 0; i < midi_num_outputs; i++) {
214
wRtn = midiOutGetDevCaps(i, (LPMIDIOUTCAPS) & midi_out_caps[i],
215
sizeof(MIDIOUTCAPS));
216
if (wRtn == MMSYSERR_NOERROR) {
217
pm_add_device("MMSystem", midi_out_caps[i].szPname, FALSE,
218
(void *) i, &pm_winmm_out_dictionary);
224
static void pm_winmm_mapper_output()
227
/* Note: if MIDIMAPPER opened as output (pseudo MIDI device
228
maps device independent messages into device dependant ones,
229
via NT midimapper program) you still should get some setup info */
230
wRtn = midiOutGetDevCaps((UINT) MIDIMAPPER, (LPMIDIOUTCAPS)
231
& midi_out_mapper_caps, sizeof(MIDIOUTCAPS));
232
if (wRtn == MMSYSERR_NOERROR) {
233
pm_add_device("MMSystem", midi_out_mapper_caps.szPname, FALSE,
234
(void *) MIDIMAPPER, &pm_winmm_out_dictionary);
240
=========================================================================================
242
=========================================================================================
244
static unsigned int winmm_has_host_error(PmInternal * midi)
246
midiwinmm_type m = (midiwinmm_type)midi->descriptor;
251
/* str_copy_len -- like strcat, but won't overrun the destination string */
253
* returns length of resulting string
255
static int str_copy_len(char *dst, char *src, int len)
257
strncpy(dst, src, len);
258
/* just in case suffex is greater then len, terminate with zero */
264
static void winmm_get_host_error(PmInternal * midi, char * msg, UINT len)
266
/* precondition: midi != NULL */
267
midiwinmm_node * m = (midiwinmm_node *) midi->descriptor;
268
char *hdr1 = "Host error: ";
269
char *hdr2 = "Host callback error: ";
271
msg[0] = 0; /* initialize result string to empty */
273
if (descriptors[midi->device_id].pub.input) {
274
/* input and output use different winmm API calls */
275
if (m) { /* make sure there is an open device to examine */
276
if (m->error != MMSYSERR_NOERROR) {
277
int n = str_copy_len(msg, hdr1, len);
278
/* read and record host error */
279
int err = midiInGetErrorText(m->error, msg + n, len - n);
280
assert(err == MMSYSERR_NOERROR);
281
m->error = MMSYSERR_NOERROR;
284
} else { /* output port */
286
if (m->error != MMSYSERR_NOERROR) {
287
int n = str_copy_len(msg, hdr1, len);
288
int err = midiOutGetErrorText(m->error, msg + n, len - n);
289
assert(err == MMSYSERR_NOERROR);
290
m->error = MMSYSERR_NOERROR;
298
=============================================================================
300
=============================================================================
302
static MIDIHDR *allocate_buffer(long data_size)
304
LPMIDIHDR hdr = (LPMIDIHDR) pm_alloc(MIDIHDR_SYSEX_SIZE(data_size));
306
if (!hdr) return NULL;
307
evt = (MIDIEVENT *) (hdr + 1); /* place MIDIEVENT after header */
308
hdr->lpData = (LPSTR) evt;
309
hdr->dwBufferLength = MIDIHDR_SYSEX_BUFFER_LENGTH(data_size);
310
hdr->dwBytesRecorded = 0;
312
hdr->dwUser = hdr->dwBufferLength;
316
#ifdef USE_SYSEX_BUFFERS
317
static MIDIHDR *allocate_sysex_buffer(long data_size)
319
/* we're actually allocating more than data_size because the buffer
320
* will include the MIDIEVENT header in addition to the data
322
LPMIDIHDR hdr = (LPMIDIHDR) pm_alloc(MIDIHDR_SYSEX_SIZE(data_size));
324
if (!hdr) return NULL;
325
evt = (MIDIEVENT *) (hdr + 1); /* place MIDIEVENT after header */
326
hdr->lpData = (LPSTR) evt;
333
static PmError allocate_buffers(midiwinmm_type m, long data_size, long count)
336
/* buffers is an array of count pointers to MIDIHDR/MIDIEVENT struct */
337
m->num_buffers = 0; /* in case no memory can be allocated */
338
m->buffers = (LPMIDIHDR *) pm_alloc(sizeof(LPMIDIHDR) * count);
339
if (!m->buffers) return pmInsufficientMemory;
340
m->max_buffers = count;
341
for (i = 0; i < count; i++) {
342
LPMIDIHDR hdr = allocate_buffer(data_size);
343
if (!hdr) { /* free everything allocated so far and return */
344
for (i = i - 1; i >= 0; i--) pm_free(m->buffers[i]);
347
return pmInsufficientMemory;
349
m->buffers[i] = hdr; /* this may be NULL if allocation fails */
351
m->num_buffers = count;
355
#ifdef USE_SYSEX_BUFFERS
356
static PmError allocate_sysex_buffers(midiwinmm_type m, long data_size)
358
PmError rslt = pmNoError;
359
/* sysex_buffers is an array of count pointers to MIDIHDR/MIDIEVENT struct */
361
for (i = 0; i < NUM_SYSEX_BUFFERS; i++) {
362
LPMIDIHDR hdr = allocate_sysex_buffer(data_size);
364
if (!hdr) rslt = pmInsufficientMemory;
365
m->sysex_buffers[i] = hdr; /* this may be NULL if allocation fails */
366
hdr->dwFlags = 0; /* mark as free */
372
#ifdef USE_SYSEX_BUFFERS
373
static LPMIDIHDR get_free_sysex_buffer(PmInternal *midi)
376
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
377
if (!m->sysex_buffers[0]) {
378
if (allocate_sysex_buffers(m, SYSEX_BYTES_PER_BUFFER)) {
382
/* busy wait until we find a free buffer */
385
for (i = 0; i < NUM_SYSEX_BUFFERS; i++) {
386
/* cycle through buffers, modulo NUM_SYSEX_BUFFERS */
387
m->next_sysex_buffer++;
388
if (m->next_sysex_buffer >= NUM_SYSEX_BUFFERS) m->next_sysex_buffer = 0;
389
r = m->sysex_buffers[m->next_sysex_buffer];
390
if ((r->dwFlags & MHDR_PREPARED) == 0) goto found_sysex_buffer;
392
/* after scanning every buffer and not finding anything, block */
393
if (WaitForSingleObject(m->buffer_signal, 1000) == WAIT_TIMEOUT) {
395
printf("PortMidi warning: get_free_sysex_buffer() wait timed out after 1000ms\n");
400
r->dwBytesRecorded = 0;
401
r->dwBufferLength = 0; /* changed to correct value later */
406
static LPMIDIHDR get_free_output_buffer(PmInternal *midi)
409
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
412
for (i = 0; i < m->num_buffers; i++) {
413
/* cycle through buffers, modulo m->num_buffers */
415
if (m->next_buffer >= m->num_buffers) m->next_buffer = 0;
416
r = m->buffers[m->next_buffer];
417
if ((r->dwFlags & MHDR_PREPARED) == 0) goto found_buffer;
419
/* after scanning every buffer and not finding anything, block */
420
if (WaitForSingleObject(m->buffer_signal, 1000) == WAIT_TIMEOUT) {
422
printf("PortMidi warning: get_free_output_buffer() wait timed out after 1000ms\n");
424
/* if we're trying to send a sysex message, maybe the
425
* message is too big and we need more message buffers.
426
* Expand the buffer pool by 128KB using 1024-byte buffers.
428
/* first, expand the buffers array if necessary */
429
if (!m->buffers_expanded) {
430
LPMIDIHDR *new_buffers = (LPMIDIHDR *) pm_alloc(
431
(m->num_buffers + NUM_EXPANSION_BUFFERS) *
433
/* if no memory, we could return a no-memory error, but user
434
* probably will be unprepared to deal with it. Maybe the
435
* MIDI driver is temporarily hung so we should just wait.
436
* I don't know the right answer, but waiting is easier.
438
if (!new_buffers) continue;
439
/* copy buffers to new_buffers and replace buffers */
440
memcpy(new_buffers, m->buffers,
441
m->num_buffers * sizeof(LPMIDIHDR));
443
m->buffers = new_buffers;
444
m->max_buffers = m->num_buffers + NUM_EXPANSION_BUFFERS;
445
m->buffers_expanded = TRUE;
447
/* next, add one buffer and return it */
448
if (m->num_buffers < m->max_buffers) {
449
r = allocate_buffer(EXPANSION_BUFFER_LEN);
450
/* again, if there's no memory, we may not really be
451
* dead -- maybe the system is temporarily hung and
452
* we can just wait longer for a message buffer */
454
m->buffers[m->num_buffers++] = r;
455
goto found_buffer; /* break out of 2 loops */
457
/* else, we've allocated all NUM_EXPANSION_BUFFERS buffers,
458
* and we have no free buffers to send. We'll just keep
459
* polling to see if any buffers show up.
464
r->dwBytesRecorded = 0;
465
/* actual buffer length is saved in dwUser field */
466
r->dwBufferLength = (DWORD) r->dwUser;
470
#ifdef EXPANDING_SYSEX_BUFFERS
471
note: this is not working code, but might be useful if you want
472
to grow sysex buffers.
473
static PmError resize_sysex_buffer(PmInternal *midi, long old_size, long new_size)
477
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
478
/* buffer must be smaller than 64k, but be also a multiple of 4 */
479
if (new_size > 65520) {
480
if (old_size >= 65520)
481
return pmBufferMaxSize;
485
/* allocate a bigger message */
486
big = allocate_sysex_buffer(new_size);
487
/* printf("expand to %d bytes\n", new_size);*/
488
if (!big) return pmInsufficientMemory;
489
m->error = midiOutPrepareHeader(m->handle.out, big, sizeof(MIDIHDR));
494
/* make sure we're not going to overwrite any memory */
495
assert(old_size <= new_size);
496
memcpy(big->lpData, m->hdr->lpData, old_size);
497
/* keep track of how many sysex bytes are in message so far */
498
big->dwBytesRecorded = m->hdr->dwBytesRecorded;
499
big->dwBufferLength = new_size;
500
/* find which buffer this was, and replace it */
501
for (i = 0; i < NUM_SYSEX_BUFFERS; i++) {
502
if (m->sysex_buffers[i] == m->hdr) {
503
m->sysex_buffers[i] = big;
504
m->sysex_buffer_size[i] = new_size;
510
assert(i != NUM_SYSEX_BUFFERS);
517
=========================================================================================
518
begin midi input implementation
519
=========================================================================================
523
static PmError allocate_input_buffer(HMIDIIN h, long buffer_len)
525
LPMIDIHDR hdr = allocate_buffer(buffer_len);
526
if (!hdr) return pmInsufficientMemory;
527
pm_hosterror = midiInPrepareHeader(h, hdr, sizeof(MIDIHDR));
532
pm_hosterror = midiInAddBuffer(h, hdr, sizeof(MIDIHDR));
537
static PmError winmm_in_open(PmInternal *midi, void *driverInfo)
540
int i = midi->device_id;
541
int max_sysex_len = midi->buffer_len * 4;
542
int num_input_buffers = max_sysex_len / INPUT_SYSEX_LEN;
545
dwDevice = (DWORD) descriptors[i].descriptor;
547
/* create system dependent device data */
548
m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */
549
midi->descriptor = m;
550
if (!m) goto no_memory;
552
m->buffers = NULL; /* not used for input */
553
m->num_buffers = 0; /* not used for input */
554
m->max_buffers = FALSE; /* not used for input */
555
m->buffers_expanded = 0; /* not used for input */
556
m->next_buffer = 0; /* not used for input */
557
m->buffer_signal = 0; /* not used for input */
558
#ifdef USE_SYSEX_BUFFERS
559
for (i = 0; i < NUM_SYSEX_BUFFERS; i++)
560
m->sysex_buffers[i] = NULL; /* not used for input */
561
m->next_sysex_buffer = 0; /* not used for input */
564
m->first_message = TRUE; /* not used for input */
565
m->sysex_mode = FALSE;
567
m->sysex_byte_count = 0;
568
m->hdr = NULL; /* not used for input */
571
m->error = MMSYSERR_NOERROR;
572
/* 4000 is based on Windows documentation -- that's the value used in the
573
memory manager. It's small enough that it should not hurt performance even
576
InitializeCriticalSectionAndSpinCount(&m->lock, 4000);
578
pm_hosterror = midiInOpen(&(m->handle.in), /* input device handle */
579
dwDevice, /* device ID */
580
(DWORD) winmm_in_callback, /* callback address */
581
(DWORD) midi, /* callback instance data */
582
CALLBACK_FUNCTION); /* callback is a procedure */
583
if (pm_hosterror) goto free_descriptor;
585
if (num_input_buffers < MIN_INPUT_BUFFERS)
586
num_input_buffers = MIN_INPUT_BUFFERS;
587
for (i = 0; i < num_input_buffers; i++) {
588
if (allocate_input_buffer(m->handle.in, INPUT_SYSEX_LEN)) {
589
/* either pm_hosterror was set, or the proper return code
590
is pmInsufficientMemory */
595
pm_hosterror = midiInStart(m->handle.in);
596
if (pm_hosterror) goto reset_device;
599
/* undo steps leading up to the detected error */
601
/* ignore return code (we already have an error to report) */
602
midiInReset(m->handle.in);
604
midiInClose(m->handle.in); /* ignore return code */
606
midi->descriptor = NULL;
610
int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text,
611
PM_HOST_ERROR_MSG_LEN);
612
assert(err == MMSYSERR_NOERROR);
615
/* if !pm_hosterror, then the error must be pmInsufficientMemory */
616
return pmInsufficientMemory;
617
/* note: if we return an error code, the device will be
618
closed and memory will be freed. It's up to the caller
619
to free the parameter midi */
622
static PmError winmm_in_poll(PmInternal *midi) {
623
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
629
/* winmm_in_close -- close an open midi input device */
631
* assume midi is non-null (checked by caller)
633
static PmError winmm_in_close(PmInternal *midi)
635
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
636
if (!m) return pmBadPtr;
637
/* device to close */
638
if (pm_hosterror = midiInStop(m->handle.in)) {
639
midiInReset(m->handle.in); /* try to reset and close port */
640
midiInClose(m->handle.in);
641
} else if (pm_hosterror = midiInReset(m->handle.in)) {
642
midiInClose(m->handle.in); /* best effort to close midi port */
644
pm_hosterror = midiInClose(m->handle.in);
646
midi->descriptor = NULL;
647
DeleteCriticalSection(&m->lock);
648
pm_free(m); /* delete */
650
int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text,
651
PM_HOST_ERROR_MSG_LEN);
652
assert(err == MMSYSERR_NOERROR);
659
/* Callback function executed via midiInput SW interrupt (via midiInOpen). */
660
static void FAR PASCAL winmm_in_callback(
661
HMIDIIN hMidiIn, /* midiInput device Handle */
662
WORD wMsg, /* midi msg */
663
DWORD dwInstance, /* application data */
664
DWORD dwParam1, /* MIDI data */
665
DWORD dwParam2) /* device timestamp (wrt most recent midiInStart) */
667
static int entry = 0;
668
PmInternal *midi = (PmInternal *) dwInstance;
669
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
671
/* if this callback is reentered with data, we're in trouble. It's hard
672
* to imagine that Microsoft would allow callbacks to be reentrant --
673
* isn't the model that this is like a hardware interrupt? -- but I've
674
* seen reentrant behavior using a debugger, so it happens.
676
EnterCriticalSection(&m->lock);
680
/* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of
682
dwParam2 is time message received by input device driver, specified
683
in [ms] from when midiInStart called.
684
each message is expanded to include the status byte */
686
long new_driver_time = dwParam2;
688
if ((dwParam1 & 0x80) == 0) {
689
/* not a status byte -- ignore it. This happened running the
690
sysex.c test under Win2K with MidiMan USB 1x1 interface,
691
but I can't reproduce it. -RBD
693
/* printf("non-status byte found\n"); */
694
} else { /* data to process */
697
dwParam2 = (*midi->time_proc)(midi->time_info);
698
event.timestamp = dwParam2;
699
event.message = dwParam1;
700
pm_read_short(midi, &event);
705
MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1;
706
unsigned char *data = lpMidiHdr->lpData;
707
unsigned int processed = 0;
708
int remaining = lpMidiHdr->dwBytesRecorded;
709
/* printf("midi_in_callback -- lpMidiHdr %x, %d bytes, %2x...\n",
710
lpMidiHdr, lpMidiHdr->dwBytesRecorded, *data); */
712
dwParam2 = (*midi->time_proc)(midi->time_info);
713
/* can there be more than one message in one buffer? */
714
/* assume yes and iterate through them */
715
while (remaining > 0) {
716
unsigned int amt = pm_read_bytes(midi, data + processed,
717
remaining, dwParam2);
723
long size = sizeof(MIDIHDR) + lpMidiHdr->dwBufferLength;
725
while (i < lpMidiHdr->dwBytesRecorded) {
726
/* optimization: if message_count == 0, we are on an (output)
727
* message boundary so we can transfer data directly to the
731
if (midi->sysex_message_count == 0 &&
733
i <= lpMidiHdr->dwBytesRecorded - 4 &&
734
((event.message = (((long) data[0]) |
735
(((long) data[1]) << 8) | (((long) data[2]) << 16) |
736
(((long) data[3]) << 24))) &
737
0x80808080) == 0) { /* all data, no status */
738
event.timestamp = dwParam2;
739
if (Pm_Enqueue(midi->queue, &event) == pmBufferOverflow) {
744
/* non-optimized: process one byte at a time. This is used to
745
* handle any embedded SYSEX or EOX bytes and to finish */
747
pm_read_byte(midi, *data, dwParam2);
753
/* when a device is closed, the pending MIM_LONGDATA buffers are
754
returned to this callback with dwBytesRecorded == 0. In this
755
case, we do not want to send them back to the interface (if
756
we do, the interface will not close, and Windows OS may hang). */
757
if (lpMidiHdr->dwBytesRecorded > 0) {
758
lpMidiHdr->dwBytesRecorded = 0;
759
lpMidiHdr->dwFlags = 0;
760
/* note: no error checking -- can this actually fail? */
761
assert(midiInPrepareHeader(hMidiIn, lpMidiHdr,
762
sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
763
/* note: I don't think this can fail except possibly for
764
* MMSYSERR_NOMEM, but the pain of reporting this
765
* unlikely but probably catastrophic error does not seem
768
assert(midiInAddBuffer(hMidiIn, lpMidiHdr,
769
sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
780
/* printf("MIM_ERROR\n"); */
783
/* printf("MIM_LONGERROR\n"); */
788
LeaveCriticalSection(&m->lock);
792
=========================================================================================
793
begin midi output implementation
794
=========================================================================================
797
/* begin helper routines used by midiOutStream interface */
799
/* add_to_buffer -- adds timestamped short msg to buffer, returns fullp */
800
static int add_to_buffer(midiwinmm_type m, LPMIDIHDR hdr,
801
unsigned long delta, unsigned long msg)
803
unsigned long *ptr = (unsigned long *)
804
(hdr->lpData + hdr->dwBytesRecorded);
805
*ptr++ = delta; /* dwDeltaTime */
806
*ptr++ = 0; /* dwStream */
807
*ptr++ = msg; /* dwEvent */
808
hdr->dwBytesRecorded += 3 * sizeof(long);
809
/* if the addition of three more words (a message) would extend beyond
810
the buffer length, then return TRUE (full)
812
return hdr->dwBytesRecorded + 3 * sizeof(long) > hdr->dwBufferLength;
816
static PmTimestamp pm_time_get(midiwinmm_type m)
820
mmtime.wType = TIME_TICKS;
822
wRtn = midiStreamPosition(m->handle.stream, &mmtime, sizeof(mmtime));
823
assert(wRtn == MMSYSERR_NOERROR);
824
return mmtime.u.ticks;
828
/* end helper routines used by midiOutStream interface */
831
static PmError winmm_out_open(PmInternal *midi, void *driverInfo)
834
int i = midi->device_id;
836
MIDIPROPTEMPO propdata;
837
MIDIPROPTIMEDIV divdata;
838
int max_sysex_len = midi->buffer_len * 4;
839
int output_buffer_len;
841
dwDevice = (DWORD) descriptors[i].descriptor;
843
/* create system dependent device data */
844
m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */
845
midi->descriptor = m;
846
if (!m) goto no_memory;
847
m->handle.out = NULL;
851
m->buffers_expanded = FALSE;
853
#ifdef USE_SYSEX_BUFFERS
854
m->sysex_buffers[0] = NULL;
855
m->sysex_buffers[1] = NULL;
856
m->next_sysex_buffer = 0;
859
m->first_message = TRUE; /* we treat first message as special case */
860
m->sysex_mode = FALSE;
862
m->sysex_byte_count = 0;
866
m->error = MMSYSERR_NOERROR;
868
/* create a signal */
869
m->buffer_signal = CreateEvent(NULL, FALSE, FALSE, NULL);
871
/* this should only fail when there are very serious problems */
872
assert(m->buffer_signal);
875
if (midi->latency == 0) {
876
/* use simple midi out calls */
877
pm_hosterror = midiOutOpen((LPHMIDIOUT) & m->handle.out, /* device Handle */
878
dwDevice, /* device ID */
879
/* note: same callback fn as for StreamOpen: */
880
(DWORD) winmm_streamout_callback, /* callback fn */
881
(DWORD) midi, /* callback instance data */
882
CALLBACK_FUNCTION); /* callback type */
884
/* use stream-based midi output (schedulable in future) */
885
pm_hosterror = midiStreamOpen(&m->handle.stream, /* device Handle */
886
(LPUINT) & dwDevice, /* device ID pointer */
887
1, /* reserved, must be 1 */
888
(DWORD) winmm_streamout_callback,
889
(DWORD) midi, /* callback instance data */
892
if (pm_hosterror != MMSYSERR_NOERROR) {
893
goto free_descriptor;
896
if (midi->latency == 0) {
897
num_buffers = NUM_SIMPLE_SYSEX_BUFFERS;
898
output_buffer_len = max_sysex_len / num_buffers;
899
if (output_buffer_len < MIN_SIMPLE_SYSEX_LEN)
900
output_buffer_len = MIN_SIMPLE_SYSEX_LEN;
903
num_buffers = max(midi->buffer_len, midi->latency / 2);
904
if (num_buffers < MIN_STREAM_BUFFERS)
905
num_buffers = MIN_STREAM_BUFFERS;
906
output_buffer_len = STREAM_BUFFER_LEN;
908
propdata.cbStruct = sizeof(MIDIPROPTEMPO);
909
propdata.dwTempo = 480000; /* microseconds per quarter */
910
pm_hosterror = midiStreamProperty(m->handle.stream,
912
MIDIPROP_SET | MIDIPROP_TEMPO);
913
if (pm_hosterror) goto close_device;
915
divdata.cbStruct = sizeof(MIDIPROPTEMPO);
916
divdata.dwTimeDiv = 480; /* divisions per quarter */
917
pm_hosterror = midiStreamProperty(m->handle.stream,
919
MIDIPROP_SET | MIDIPROP_TIMEDIV);
920
if (pm_hosterror) goto close_device;
922
/* allocate buffers */
923
if (allocate_buffers(m, output_buffer_len, num_buffers))
926
if (midi->latency != 0) {
927
pm_hosterror = midiStreamRestart(m->handle.stream);
928
if (pm_hosterror != MMSYSERR_NOERROR) goto free_buffers;
933
/* buffers are freed below by winmm_out_delete */
935
midiOutClose(m->handle.out);
937
midi->descriptor = NULL;
938
winmm_out_delete(midi); /* frees buffers and m */
941
int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text,
942
PM_HOST_ERROR_MSG_LEN);
943
assert(err == MMSYSERR_NOERROR);
946
return pmInsufficientMemory;
950
/* winmm_out_delete -- carefully free data associated with midi */
952
static void winmm_out_delete(PmInternal *midi)
955
/* delete system dependent device data */
956
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
958
if (m->buffer_signal) {
959
/* don't report errors -- better not to stop cleanup */
960
CloseHandle(m->buffer_signal);
962
/* if using stream output, free buffers */
963
for (i = 0; i < m->num_buffers; i++) {
964
if (m->buffers[i]) pm_free(m->buffers[i]);
969
#ifdef USE_SYSEX_BUFFERS
970
/* free sysex buffers */
971
for (i = 0; i < NUM_SYSEX_BUFFERS; i++) {
972
if (m->sysex_buffers[i]) pm_free(m->sysex_buffers[i]);
976
midi->descriptor = NULL;
977
pm_free(m); /* delete */
981
/* see comments for winmm_in_close */
982
static PmError winmm_out_close(PmInternal *midi)
984
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
986
/* device to close */
987
if (midi->latency == 0) {
988
pm_hosterror = midiOutClose(m->handle.out);
990
pm_hosterror = midiStreamClose(m->handle.stream);
992
/* regardless of outcome, free memory */
993
winmm_out_delete(midi);
996
int err = midiOutGetErrorText(pm_hosterror,
997
(char *) pm_hosterror_text,
998
PM_HOST_ERROR_MSG_LEN);
999
assert(err == MMSYSERR_NOERROR);
1006
static PmError winmm_out_abort(PmInternal *midi)
1008
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1009
m->error = MMSYSERR_NOERROR;
1011
/* only stop output streams */
1012
if (midi->latency > 0) {
1013
m->error = midiStreamStop(m->handle.stream);
1015
return m->error ? pmHostError : pmNoError;
1019
static PmError winmm_write_flush(PmInternal *midi, PmTimestamp timestamp)
1021
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1024
m->error = midiOutPrepareHeader(m->handle.out, m->hdr,
1027
/* do not send message */
1028
} else if (midi->latency == 0) {
1029
/* As pointed out by Nigel Brown, 20Sep06, dwBytesRecorded
1030
* should be zero. This is set in get_free_sysex_buffer().
1031
* The msg length goes in dwBufferLength in spite of what
1032
* Microsoft documentation says (or doesn't say). */
1033
m->hdr->dwBufferLength = m->hdr->dwBytesRecorded;
1034
m->hdr->dwBytesRecorded = 0;
1035
m->error = midiOutLongMsg(m->handle.out, m->hdr, sizeof(MIDIHDR));
1037
m->error = midiStreamOut(m->handle.stream, m->hdr,
1040
midi->fill_base = NULL;
1043
m->hdr->dwFlags = 0; /* release the buffer */
1053
static PmError winmm_write_sysex_byte(PmInternal *midi, unsigned char byte)
1055
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1056
unsigned char *msg_buffer;
1058
/* at the beginning of sysex, m->hdr is NULL */
1059
if (!m->hdr) { /* allocate a buffer if none allocated yet */
1060
m->hdr = get_free_output_buffer(midi);
1061
if (!m->hdr) return pmInsufficientMemory;
1062
m->sysex_byte_count = 0;
1064
/* figure out where to write byte */
1065
msg_buffer = (unsigned char *) (m->hdr->lpData);
1066
assert(m->hdr->lpData == (char *) (m->hdr + 1));
1068
/* check for overflow */
1069
if (m->sysex_byte_count >= m->hdr->dwBufferLength) {
1070
/* allocate a bigger message -- double it every time */
1071
LPMIDIHDR big = allocate_buffer(m->sysex_byte_count * 2);
1072
/* printf("expand to %d bytes\n", m->sysex_byte_count * 2); */
1073
if (!big) return pmInsufficientMemory;
1074
m->error = midiOutPrepareHeader(m->handle.out, big,
1080
memcpy(big->lpData, msg_buffer, m->sysex_byte_count);
1081
msg_buffer = (unsigned char *) (big->lpData);
1082
if (m->buffers[0] == m->hdr) {
1083
m->buffers[0] = big;
1085
/* printf("freed m->hdr\n"); */
1086
} else if (m->buffers[1] == m->hdr) {
1087
m->buffers[1] = big;
1089
/* printf("freed m->hdr\n"); */
1094
/* append byte to message */
1095
msg_buffer[m->sysex_byte_count++] = byte;
1097
/* see if we have a complete message */
1098
if (byte == MIDI_EOX) {
1099
m->hdr->dwBytesRecorded = m->sysex_byte_count;
1101
{ int i; int len = m->hdr->dwBytesRecorded;
1102
printf("OutLongMsg %d ", len);
1103
for (i = 0; i < len; i++) {
1104
printf("%2x ", msg_buffer[i]);
1108
m->error = midiOutLongMsg(m->handle.out, m->hdr, sizeof(MIDIHDR));
1109
m->hdr = NULL; /* stop using this message buffer */
1110
if (m->error) return pmHostError;
1117
static PmError winmm_write_short(PmInternal *midi, PmEvent *event)
1119
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1120
PmError rslt = pmNoError;
1123
if (midi->latency == 0) { /* use midiOut interface, ignore timestamps */
1124
m->error = midiOutShortMsg(m->handle.out, event->message);
1125
if (m->error) rslt = pmHostError;
1126
} else { /* use midiStream interface -- pass data through buffers */
1127
unsigned long when = event->timestamp;
1128
unsigned long delta;
1130
if (when == 0) when = midi->now;
1131
/* when is in real_time; translate to intended stream time */
1132
when = when + m->delta + midi->latency;
1133
/* make sure we don't go backward in time */
1134
if (when < m->last_time) when = m->last_time;
1135
delta = when - m->last_time;
1136
m->last_time = when;
1137
/* before we insert any data, we must have a buffer */
1138
if (m->hdr == NULL) {
1139
/* stream interface: buffers allocated when stream is opened */
1140
m->hdr = get_free_output_buffer(midi);
1142
full = add_to_buffer(m, m->hdr, delta, event->message);
1143
if (full) rslt = winmm_write_flush(midi, when);
1148
#define winmm_begin_sysex winmm_write_flush
1149
#ifndef winmm_begin_sysex
1150
static PmError winmm_begin_sysex(PmInternal *midi, PmTimestamp timestamp)
1152
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1153
PmError rslt = pmNoError;
1155
if (midi->latency == 0) {
1156
/* do nothing -- it's handled in winmm_write_byte */
1158
/* sysex expects an empty sysex buffer, so send whatever is here */
1159
rslt = winmm_write_flush(midi);
1165
static PmError winmm_end_sysex(PmInternal *midi, PmTimestamp timestamp)
1167
/* could check for callback_error here, but I haven't checked
1168
* what happens if we exit early and don't finish the sysex msg
1171
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1172
PmError rslt = pmNoError;
1173
LPMIDIHDR hdr = m->hdr;
1174
if (!hdr) return rslt; /* something bad happened earlier,
1175
do not report an error because it would have been
1176
reported (at least) once already */
1177
/* a(n old) version of MIDI YOKE requires a zero byte after
1178
* the sysex message, but do not increment dwBytesRecorded: */
1179
hdr->lpData[hdr->dwBytesRecorded] = 0;
1180
if (midi->latency == 0) {
1181
#ifdef DEBUG_PRINT_BEFORE_SENDING_SYSEX
1183
{ int i; int len = m->hdr->dwBufferLength;
1184
printf("OutLongMsg %d ", len);
1185
for (i = 0; i < len; i++) {
1186
printf("%2x ", (unsigned char) (m->hdr->lpData[i]));
1191
/* Using stream interface. There are accumulated bytes in m->hdr
1192
to send using midiStreamOut
1194
/* add bytes recorded to MIDIEVENT length, but don't
1195
count the MIDIEVENT data (3 longs) */
1196
MIDIEVENT *evt = (MIDIEVENT *) (hdr->lpData);
1197
evt->dwEvent += hdr->dwBytesRecorded - 3 * sizeof(long);
1198
/* round up BytesRecorded to multiple of 4 */
1199
hdr->dwBytesRecorded = (hdr->dwBytesRecorded + 3) & ~3;
1201
rslt = winmm_write_flush(midi, timestamp);
1206
static PmError winmm_write_byte(PmInternal *midi, unsigned char byte,
1207
PmTimestamp timestamp)
1209
/* write a sysex byte */
1210
PmError rslt = pmNoError;
1211
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1212
LPMIDIHDR hdr = m->hdr;
1213
unsigned char *msg_buffer;
1216
m->hdr = hdr = get_free_output_buffer(midi);
1218
midi->fill_base = m->hdr->lpData;
1219
midi->fill_offset_ptr = &(hdr->dwBytesRecorded);
1220
/* when buffer fills, Pm_WriteSysEx will revert to calling
1221
* pmwin_write_byte, which expect to have space, so leave
1222
* one byte free for pmwin_write_byte. Leave another byte
1223
* of space for zero after message to make early version of
1224
* MIDI YOKE driver happy -- therefore dwBufferLength - 2 */
1225
midi->fill_length = hdr->dwBufferLength - 2;
1226
if (midi->latency != 0) {
1227
unsigned long when = (unsigned long) timestamp;
1228
unsigned long delta;
1230
if (when == 0) when = midi->now;
1231
/* when is in real_time; translate to intended stream time */
1232
when = when + m->delta + midi->latency;
1233
/* make sure we don't go backward in time */
1234
if (when < m->last_time) when = m->last_time;
1235
delta = when - m->last_time;
1236
m->last_time = when;
1238
ptr = (unsigned long *) hdr->lpData;
1242
hdr->dwBytesRecorded = 3 * sizeof(long);
1243
/* data will be added at an offset of dwBytesRecorded ... */
1246
/* add the data byte */
1247
msg_buffer = (unsigned char *) (hdr->lpData);
1248
msg_buffer[hdr->dwBytesRecorded++] = byte;
1250
/* see if buffer is full, leave one byte extra for pad */
1251
if (hdr->dwBytesRecorded >= hdr->dwBufferLength - 1) {
1252
/* write what we've got and continue */
1253
rslt = winmm_end_sysex(midi, timestamp);
1258
#ifdef EXPANDING_SYSEX_BUFFERS
1259
note: this code is here as an aid in case you want sysex buffers
1260
to expand to hold large messages completely. If so, you
1261
will want to change SYSEX_BYTES_PER_BUFFER above to some
1262
variable that remembers the buffer size. A good place to
1263
put this value would be in the hdr->dwUser field.
1265
rslt = resize_sysex_buffer(midi, m->sysex_byte_count,
1266
m->sysex_byte_count * 2);
1268
if (rslt == pmBufferMaxSize) /* if the buffer can't be resized */
1270
#ifdef EXPANDING_SYSEX_BUFFERS
1271
int bytesRecorded = hdr->dwBytesRecorded; /* this field gets wiped out, so we'll save it */
1272
rslt = resize_sysex_buffer(midi, bytesRecorded, 2 * bytesRecorded);
1273
hdr->dwBytesRecorded = bytesRecorded;
1275
if (rslt == pmBufferMaxSize) /* if buffer can't be resized */
1280
static PmTimestamp winmm_synchronize(PmInternal *midi)
1283
unsigned long pm_stream_time_2;
1284
unsigned long real_time;
1285
unsigned long pm_stream_time;
1287
/* only synchronize if we are using stream interface */
1288
if (midi->latency == 0) return 0;
1290
/* figure out the time */
1291
m = (midiwinmm_type) midi->descriptor;
1292
pm_stream_time_2 = pm_time_get(m);
1295
/* read real_time between two reads of stream time */
1296
pm_stream_time = pm_stream_time_2;
1297
real_time = (*midi->time_proc)(midi->time_info);
1298
pm_stream_time_2 = pm_time_get(m);
1299
/* repeat if more than 1ms elapsed */
1300
} while (pm_stream_time_2 > pm_stream_time + 1);
1301
m->delta = pm_stream_time - real_time;
1302
m->sync_time = real_time;
1306
#ifdef USE_SYSEX_BUFFERS
1307
/* winmm_out_callback -- recycle sysex buffers */
1308
static void CALLBACK winmm_out_callback(HMIDIOUT hmo, UINT wMsg,
1309
DWORD dwInstance, DWORD dwParam1,
1312
PmInternal *midi = (PmInternal *) dwInstance;
1313
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1314
LPMIDIHDR hdr = (LPMIDIHDR) dwParam1;
1315
int err = 0; /* set to 0 so that no buffer match will also be an error */
1317
/* Future optimization: eliminate UnprepareHeader calls -- they aren't
1318
necessary; however, this code uses the prepared-flag to indicate which
1319
buffers are free, so we need to do something to flag empty buffers if
1320
we leave them prepared
1322
printf("out_callback: hdr %x, wMsg %x, MOM_DONE %x\n",
1323
hdr, wMsg, MOM_DONE);
1324
if (wMsg == MOM_DONE)
1325
assert(midiOutUnprepareHeader(m->handle.out, hdr,
1326
sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
1327
/* notify waiting sender that a buffer is available */
1328
err = SetEvent(m->buffer_signal);
1329
assert(err); /* false -> error */
1333
/* winmm_streamout_callback -- unprepare (free) buffer header */
1334
static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg,
1335
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1337
PmInternal *midi = (PmInternal *) dwInstance;
1338
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1339
LPMIDIHDR hdr = (LPMIDIHDR) dwParam1;
1342
/* Even if an error is pending, I think we should unprepare msgs and
1343
signal their arrival
1345
/* printf("streamout_callback: hdr %x, wMsg %x, MOM_DONE %x\n",
1346
hdr, wMsg, MOM_DONE); */
1347
if (wMsg == MOM_DONE) {
1348
assert(midiOutUnprepareHeader(m->handle.out, hdr,
1349
sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
1351
/* signal client in case it is blocked waiting for buffer */
1352
err = SetEvent(m->buffer_signal);
1353
assert(err); /* false -> error */
1358
=========================================================================================
1359
begin exported functions
1360
=========================================================================================
1363
#define winmm_in_abort pm_fail_fn
1364
pm_fns_node pm_winmm_in_dictionary = {
1376
winmm_has_host_error,
1377
winmm_get_host_error
1380
pm_fns_node pm_winmm_out_dictionary = {
1385
winmm_write_short, /* short realtime message */
1392
winmm_has_host_error,
1393
winmm_get_host_error
1397
/* initialize winmm interface. Note that if there is something wrong
1398
with winmm (e.g. it is not supported or installed), it is not an
1399
error. We should simply return without having added any devices to
1400
the table. Hence, no error code is returned. Furthermore, this init
1401
code is called along with every other supported interface, so the
1402
user would have a very hard time figuring out what hardware and API
1403
generated the error. Finally, it would add complexity to pmwin.c to
1404
remember where the error code came from in order to convert to text.
1406
void pm_winmm_init( void )
1408
pm_winmm_mapper_input();
1409
pm_winmm_mapper_output();
1410
pm_winmm_general_inputs();
1411
pm_winmm_general_outputs();
1415
/* no error codes are returned, even if errors are encountered, because
1416
there is probably nothing the user could do (e.g. it would be an error
1419
void pm_winmm_term( void )
1423
char msg[PM_HOST_ERROR_MSG_LEN];
1427
printf("pm_winmm_term called\n");
1429
for (i = 0; i < pm_descriptor_index; i++) {
1430
PmInternal * midi = descriptors[i].internalDescriptor;
1432
midiwinmm_type m = (midiwinmm_type) midi->descriptor;
1433
if (m->handle.out) {
1434
/* close next open device*/
1437
printf("begin closing open devices...\n");
1440
/* report any host errors; this EXTEREMELY useful when
1441
trying to debug client app */
1442
if (winmm_has_host_error(midi)) {
1443
winmm_get_host_error(midi, msg, PM_HOST_ERROR_MSG_LEN);
1444
printf("%s\n", msg);
1447
/* close all open ports */
1448
(*midi->dictionary->close)(midi);
1453
pm_free(midi_in_caps);
1454
midi_in_caps = NULL;
1456
if (midi_out_caps) {
1457
pm_free(midi_out_caps);
1458
midi_out_caps = NULL;
1462
printf("warning: devices were left open. They have been closed.\n");
1464
printf("pm_winmm_term exiting\n");
1466
pm_descriptor_index = 0;