b262ba5391d90bf70af285a0e314afe3d96a0e2a
[ardour.git] / libs / backends / wavesaudio / portmidi / src / pm_common / portmidi.c
1 #ifdef _MSC_VER
2  #pragma warning(disable: 4244) // stop warnings about downsize typecasts
3  #pragma warning(disable: 4018) // stop warnings about signed/unsigned
4 #endif
5
6 #include "stdlib.h"
7 #include "string.h"
8 #include "portmidi.h"
9 #include "porttime.h"
10 #include "pmutil.h"
11 #include "pminternal.h"
12 #include <assert.h>
13
14 #define MIDI_CLOCK      0xf8
15 #define MIDI_ACTIVE     0xfe
16 #define MIDI_STATUS_MASK 0x80
17 #define MIDI_SYSEX      0xf0
18 #define MIDI_EOX        0xf7
19 #define MIDI_START      0xFA
20 #define MIDI_STOP       0xFC
21 #define MIDI_CONTINUE   0xFB
22 #define MIDI_F9         0xF9
23 #define MIDI_FD         0xFD
24 #define MIDI_RESET      0xFF
25 #define MIDI_NOTE_ON    0x90
26 #define MIDI_NOTE_OFF   0x80
27 #define MIDI_CHANNEL_AT 0xD0
28 #define MIDI_POLY_AT    0xA0
29 #define MIDI_PROGRAM    0xC0
30 #define MIDI_CONTROL    0xB0
31 #define MIDI_PITCHBEND  0xE0
32 #define MIDI_MTC        0xF1
33 #define MIDI_SONGPOS    0xF2
34 #define MIDI_SONGSEL    0xF3
35 #define MIDI_TUNE       0xF6
36
37 #define is_empty(midi) ((midi)->tail == (midi)->head)
38
39 /* this is not static so that pm_init can set it directly if
40  *   (see pmmac.c:pm_init())
41  */
42 int pm_initialized = FALSE;
43
44 int pm_hosterror;
45 char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];
46
47 #ifdef PM_CHECK_ERRORS
48
49 #include <stdio.h>
50
51 #define STRING_MAX 80
52
53 static void prompt_and_exit(void)
54 {
55     char line[STRING_MAX];
56     printf("type ENTER...");
57     fgets(line, STRING_MAX, stdin);
58     /* this will clean up open ports: */
59     exit(-1);
60 }
61
62
63 static PmError pm_errmsg(PmError err)
64 {
65     if (err == pmHostError) {
66         /* it seems pointless to allocate memory and copy the string,
67          * so I will do the work of Pm_GetHostErrorText directly
68          */
69         printf("PortMidi found host error...\n  %s\n", pm_hosterror_text);
70         pm_hosterror = FALSE;
71         pm_hosterror_text[0] = 0; /* clear the message */
72         prompt_and_exit();
73     } else if (err < 0) {
74         printf("PortMidi call failed...\n  %s\n", Pm_GetErrorText(err));
75         prompt_and_exit();
76     }
77     return err;
78 }
79 #else
80 #define pm_errmsg(err) err
81 #endif
82
83 /*
84 ====================================================================
85 system implementation of portmidi interface
86 ====================================================================
87 */
88
89 int pm_descriptor_max = 0;
90 int pm_descriptor_index = 0;
91 descriptor_type descriptors = NULL;
92
93 /* pm_add_device -- describe interface/device pair to library 
94  *
95  * This is called at intialization time, once for each 
96  * interface (e.g. DirectSound) and device (e.g. SoundBlaster 1)
97  * The strings are retained but NOT COPIED, so do not destroy them!
98  *
99  * returns pmInvalidDeviceId if device memory is exceeded
100  * otherwise returns pmNoError
101  */
102 PmError pm_add_device(char *interf, char *name, int input, 
103                       void *descriptor, pm_fns_type dictionary) {
104     if (pm_descriptor_index >= pm_descriptor_max) {
105         // expand descriptors
106         descriptor_type new_descriptors = (descriptor_type) 
107             pm_alloc(sizeof(descriptor_node) * (pm_descriptor_max + 32));
108         if (!new_descriptors) return pmInsufficientMemory;
109         if (descriptors) {
110             memcpy(new_descriptors, descriptors, 
111                    sizeof(descriptor_node) * pm_descriptor_max);
112             free(descriptors);
113         }
114         pm_descriptor_max += 32;
115         descriptors = new_descriptors;
116     }
117     descriptors[pm_descriptor_index].pub.interf = interf;
118     descriptors[pm_descriptor_index].pub.name = name;
119     descriptors[pm_descriptor_index].pub.input = input;
120     descriptors[pm_descriptor_index].pub.output = !input;
121
122     /* default state: nothing to close (for automatic device closing) */
123     descriptors[pm_descriptor_index].pub.opened = FALSE;
124
125     /* ID number passed to win32 multimedia API open */
126     descriptors[pm_descriptor_index].descriptor = descriptor;
127     
128     /* points to PmInternal, allows automatic device closing */
129     descriptors[pm_descriptor_index].internalDescriptor = NULL;
130
131     descriptors[pm_descriptor_index].dictionary = dictionary;
132     
133     pm_descriptor_index++;
134     
135     return pmNoError;
136 }
137
138
139 /* utility to look up device, given a pattern, 
140    note: pattern is modified
141  */
142 int pm_find_default_device(char *pattern, int is_input)
143 {
144     int id = pmNoDevice;
145     int i;
146     /* first parse pattern into name, interf parts */
147     char *interf_pref = ""; /* initially assume it is not there */
148     char *name_pref = strstr(pattern, ", ");
149
150     if (name_pref) { /* found separator, adjust the pointer */
151         interf_pref = pattern;
152         name_pref[0] = 0;
153         name_pref += 2;
154     } else {
155         name_pref = pattern; /* whole string is the name pattern */
156     }
157     for (i = 0; i < pm_descriptor_index; i++) {
158         const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
159         if (info->input == is_input &&
160             strstr(info->name, name_pref) &&
161             strstr(info->interf, interf_pref)) {
162             id = i;
163             break;
164         }
165     }    
166     return id;
167 }
168
169
170 /*
171 ====================================================================
172 portmidi implementation
173 ====================================================================
174 */
175
176 PMEXPORT int Pm_CountDevices( void ) {
177     Pm_Initialize();
178     /* no error checking -- Pm_Initialize() does not fail */
179     return pm_descriptor_index;
180 }
181
182
183 PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id ) {
184     Pm_Initialize(); /* no error check needed */
185     if (id >= 0 && id < pm_descriptor_index) {
186         return &descriptors[id].pub;
187     }
188     return NULL;
189 }
190
191 /* pm_success_fn -- "noop" function pointer */
192 PmError pm_success_fn(PmInternal *midi) {
193     return pmNoError;
194 }
195
196 /* none_write -- returns an error if called */
197 PmError none_write_short(PmInternal *midi, PmEvent *buffer) {
198     return pmBadPtr;
199 }
200
201 /* pm_fail_timestamp_fn -- placeholder for begin_sysex and flush */
202 PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp) {
203     return pmBadPtr;
204 }
205
206 PmError none_write_byte(PmInternal *midi, unsigned char byte, 
207                         PmTimestamp timestamp) {
208     return pmBadPtr;
209 }
210
211 /* pm_fail_fn -- generic function, returns error if called */
212 PmError pm_fail_fn(PmInternal *midi) {
213     return pmBadPtr;
214 }
215
216 static PmError none_open(PmInternal *midi, void *driverInfo) {
217     return pmBadPtr;
218 }
219 static void none_get_host_error(PmInternal * midi, char * msg, unsigned int len) {
220     *msg = 0; // empty string
221 }
222 static unsigned int none_has_host_error(PmInternal * midi) {
223     return FALSE;
224 }
225 PmTimestamp none_synchronize(PmInternal *midi) {
226     return 0;
227 }
228
229 #define none_abort pm_fail_fn
230 #define none_close pm_fail_fn
231
232 pm_fns_node pm_none_dictionary = {
233     none_write_short,
234     none_sysex,
235     none_sysex,
236     none_write_byte,
237     none_write_short,
238     none_write_flush,
239     none_synchronize,
240     none_open,
241     none_abort, 
242     none_close,
243     none_poll,
244     none_has_host_error,
245     none_get_host_error 
246 };
247
248
249 PMEXPORT const char *Pm_GetErrorText( PmError errnum ) {
250     const char *msg;
251
252     switch(errnum)
253     {
254     case pmNoError:                  
255         msg = ""; 
256         break;
257     case pmHostError:                
258         msg = "PortMidi: `Host error'"; 
259         break;
260     case pmInvalidDeviceId:          
261         msg = "PortMidi: `Invalid device ID'"; 
262         break;
263     case pmInsufficientMemory:       
264         msg = "PortMidi: `Insufficient memory'"; 
265         break;
266     case pmBufferTooSmall:           
267         msg = "PortMidi: `Buffer too small'"; 
268         break;
269     case pmBadPtr:                   
270         msg = "PortMidi: `Bad pointer'"; 
271         break;
272     case pmInternalError:            
273         msg = "PortMidi: `Internal PortMidi Error'"; 
274         break;
275     case pmBufferOverflow:
276         msg = "PortMidi: `Buffer overflow'";
277         break;
278     case pmBadData:
279         msg = "PortMidi: `Invalid MIDI message Data'";
280         break;
281     case pmBufferMaxSize:
282         msg = "PortMidi: `Buffer cannot be made larger'";
283         break;
284     default:                         
285         msg = "PortMidi: `Illegal error number'"; 
286         break;
287     }
288     return msg;
289 }
290
291
292 /* This can be called whenever you get a pmHostError return value.
293  * The error will always be in the global pm_hosterror_text.
294  */
295 PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) {
296     assert(msg);
297     assert(len > 0);
298     if (pm_hosterror) {
299         strncpy(msg, (char *) pm_hosterror_text, len);
300         pm_hosterror = FALSE;
301         pm_hosterror_text[0] = 0; /* clear the message; not necessary, but it
302                                      might help with debugging */
303         msg[len - 1] = 0; /* make sure string is terminated */
304     } else {
305         msg[0] = 0; /* no string to return */
306     }
307 }
308
309
310 PMEXPORT int Pm_HasHostError(PortMidiStream * stream) {
311     if (pm_hosterror) return TRUE;
312     if (stream) {
313         PmInternal * midi = (PmInternal *) stream;
314         pm_hosterror = (*midi->dictionary->has_host_error)(midi);
315         if (pm_hosterror) {
316             midi->dictionary->host_error(midi, pm_hosterror_text, 
317                                          PM_HOST_ERROR_MSG_LEN);
318             /* now error message is global */
319             return TRUE;
320         }
321     }
322     return FALSE;
323 }
324
325
326 PMEXPORT PmError Pm_Initialize( void ) {
327     if (!pm_initialized) {
328         pm_hosterror = FALSE;
329         pm_hosterror_text[0] = 0; /* the null string */
330         pm_init();
331         pm_initialized = TRUE;
332     }
333     return pmNoError;
334 }
335
336
337 PMEXPORT PmError Pm_Terminate( void ) {
338     if (pm_initialized) {
339         pm_term();
340         // if there are no devices, descriptors might still be NULL
341         if (descriptors != NULL) {
342             free(descriptors);
343             descriptors = NULL;
344         }
345         pm_descriptor_index = 0;
346         pm_descriptor_max = 0;
347         pm_initialized = FALSE;
348     }
349     return pmNoError;
350 }
351
352
353 /* Pm_Read -- read up to length messages from source into buffer */
354 /*
355  * returns number of messages actually read, or error code
356  */
357 PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) {
358     PmInternal *midi = (PmInternal *) stream;
359     int n = 0;
360     PmError err = pmNoError;
361     pm_hosterror = FALSE;
362     /* arg checking */
363     if(midi == NULL)
364         err = pmBadPtr;
365     else if(!descriptors[midi->device_id].pub.opened)
366         err = pmBadPtr;
367     else if(!descriptors[midi->device_id].pub.input)
368         err = pmBadPtr;    
369     /* First poll for data in the buffer...
370      * This either simply checks for data, or attempts first to fill the buffer
371      * with data from the MIDI hardware; this depends on the implementation.
372      * We could call Pm_Poll here, but that would redo a lot of redundant
373      * parameter checking, so I copied some code from Pm_Poll to here: */
374     else err = (*(midi->dictionary->poll))(midi);
375
376     if (err != pmNoError) {
377         if (err == pmHostError) {
378             midi->dictionary->host_error(midi, pm_hosterror_text, 
379                                          PM_HOST_ERROR_MSG_LEN);
380           pm_hosterror = TRUE;
381         }
382         return pm_errmsg(err);
383     }
384
385     while (n < length) {
386         PmError err = Pm_Dequeue(midi->queue, buffer++);
387         if (err == pmBufferOverflow) {
388             /* ignore the data we have retreived so far */
389             return pm_errmsg(pmBufferOverflow);
390         } else if (err == 0) { /* empty queue */
391             break;
392         }
393         n++;
394     }
395     return n;
396 }
397
398 PMEXPORT PmError Pm_Poll( PortMidiStream *stream )
399 {
400     PmInternal *midi = (PmInternal *) stream;
401     PmError err;
402
403     pm_hosterror = FALSE;
404     /* arg checking */
405     if(midi == NULL)
406         err = pmBadPtr;
407     else if (!descriptors[midi->device_id].pub.opened)
408         err = pmBadPtr;
409     else if (!descriptors[midi->device_id].pub.input)
410         err = pmBadPtr;
411     else
412         err = (*(midi->dictionary->poll))(midi);
413
414     if (err != pmNoError) {
415         if (err == pmHostError) {
416             midi->dictionary->host_error(midi, pm_hosterror_text, 
417                                          PM_HOST_ERROR_MSG_LEN);
418            pm_hosterror = TRUE;
419         }
420         return pm_errmsg(err);
421     }
422
423     return (PmError) !Pm_QueueEmpty(midi->queue);
424 }
425
426
427 /* this is called from Pm_Write and Pm_WriteSysEx to issue a
428  * call to the system-dependent end_sysex function and handle 
429  * the error return
430  */
431 static PmError pm_end_sysex(PmInternal *midi)
432 {
433     PmError err = (*midi->dictionary->end_sysex)(midi, 0);
434     midi->sysex_in_progress = FALSE;
435     if (err == pmHostError) {
436         midi->dictionary->host_error(midi, pm_hosterror_text, 
437                                      PM_HOST_ERROR_MSG_LEN);
438         pm_hosterror = TRUE;
439     }
440     return err;
441 }
442
443
444 /* to facilitate correct error-handling, Pm_Write, Pm_WriteShort, and
445    Pm_WriteSysEx all operate a state machine that "outputs" calls to
446    write_short, begin_sysex, write_byte, end_sysex, and write_realtime */
447
448 PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t length)
449 {
450     PmInternal *midi = (PmInternal *) stream;
451     PmError err = pmNoError;
452     int i;
453     int bits;
454     
455     pm_hosterror = FALSE;
456     /* arg checking */
457     if(midi == NULL)
458         err = pmBadPtr;
459     else if(!descriptors[midi->device_id].pub.opened)
460         err = pmBadPtr;
461     else if(!descriptors[midi->device_id].pub.output)
462         err = pmBadPtr;
463     else
464         err = pmNoError;
465     
466     if (err != pmNoError) goto pm_write_error;
467     
468     if (midi->latency == 0) {
469         midi->now = 0;
470     } else {
471         midi->now = (*(midi->time_proc))(midi->time_info);
472         if (midi->first_message || midi->sync_time + 100 /*ms*/ < midi->now) {
473             /* time to resync */
474             midi->now = (*midi->dictionary->synchronize)(midi);
475             midi->first_message = FALSE;
476         }
477     }
478     /* error recovery: when a sysex is detected, we call
479      *   dictionary->begin_sysex() followed by calls to
480      *   dictionary->write_byte() and dictionary->write_realtime()
481      *   until an end-of-sysex is detected, when we call
482      *   dictionary->end_sysex(). After an error occurs, 
483      *   Pm_Write() continues to call functions. For example,
484      *   it will continue to call write_byte() even after
485      *   an error sending a sysex message, and end_sysex() will be
486      *   called when an EOX or non-real-time status is found.
487      * When errors are detected, Pm_Write() returns immediately, 
488      *   so it is possible that this will drop data and leave
489      *   sysex messages in a partially transmitted state.
490      */
491     for (i = 0; i < length; i++) {
492         uint32_t msg = buffer[i].message;
493         bits = 0;
494         /* is this a sysex message? */
495         if (Pm_MessageStatus(msg) == MIDI_SYSEX) {
496             if (midi->sysex_in_progress) {
497                 /* error: previous sysex was not terminated by EOX */
498                 midi->sysex_in_progress = FALSE;
499                 err = pmBadData;
500                 goto pm_write_error;
501             }
502             midi->sysex_in_progress = TRUE;
503             if ((err = (*midi->dictionary->begin_sysex)(midi, 
504                                buffer[i].timestamp)) != pmNoError)
505                 goto pm_write_error;
506             if ((err = (*midi->dictionary->write_byte)(midi, MIDI_SYSEX,
507                                buffer[i].timestamp)) != pmNoError) 
508                 goto pm_write_error;
509             bits = 8;
510             /* fall through to continue sysex processing */
511         } else if ((msg & MIDI_STATUS_MASK) && 
512                    (Pm_MessageStatus(msg) != MIDI_EOX)) {
513             /* a non-sysex message */
514             if (midi->sysex_in_progress) {
515                 /* this should be a realtime message */
516                 if (is_real_time(msg)) {
517                     if ((err = (*midi->dictionary->write_realtime)(midi, 
518                                        &(buffer[i]))) != pmNoError)
519                         goto pm_write_error;
520                 } else {
521                     midi->sysex_in_progress = FALSE;
522                     err = pmBadData;
523                     /* ignore any error from this, because we already have one */
524                     /* pass 0 as timestamp -- it's ignored */
525                     (*midi->dictionary->end_sysex)(midi, 0);
526                     goto pm_write_error;
527                 }
528             } else { /* regular short midi message */
529                 if ((err = (*midi->dictionary->write_short)(midi, 
530                                    &(buffer[i]))) != pmNoError)
531                     goto pm_write_error;
532                 continue;
533             }
534         }
535         if (midi->sysex_in_progress) { /* send sysex bytes until EOX */
536             /* see if we can accelerate data transfer */
537             if (bits == 0 && midi->fill_base && /* 4 bytes to copy */
538                 (*midi->fill_offset_ptr) + 4 <= midi->fill_length &&
539                 (msg & 0x80808080) == 0) { /* all data */
540                     /* copy 4 bytes from msg to fill_base + fill_offset */
541                     unsigned char *ptr = midi->fill_base + 
542                                          *(midi->fill_offset_ptr);
543                     ptr[0] = msg; ptr[1] = msg >> 8; 
544                     ptr[2] = msg >> 16; ptr[3] = msg >> 24;
545                     (*midi->fill_offset_ptr) += 4;
546                      continue;
547             }
548             /* no acceleration, so do byte-by-byte copying */
549             while (bits < 32) {
550                 unsigned char midi_byte = (unsigned char) (msg >> bits);
551                 if ((err = (*midi->dictionary->write_byte)(midi, midi_byte, 
552                                    buffer[i].timestamp)) != pmNoError)
553                     goto pm_write_error;
554                 if (midi_byte == MIDI_EOX) {
555                     err = pm_end_sysex(midi);
556                     if (err != pmNoError) goto error_exit;
557                     break; /* from while loop */
558                 }
559                 bits += 8;
560             }
561         } else {
562             /* not in sysex mode, but message did not start with status */
563             err = pmBadData;
564             goto pm_write_error;
565         }
566     }
567     /* after all messages are processed, send the data */
568     if (!midi->sysex_in_progress)
569         err = (*midi->dictionary->write_flush)(midi, 0);
570 pm_write_error:
571     if (err == pmHostError) {
572         midi->dictionary->host_error(midi, pm_hosterror_text, 
573                                      PM_HOST_ERROR_MSG_LEN);
574         pm_hosterror = TRUE;
575     }
576 error_exit:
577     return pm_errmsg(err);
578 }
579
580
581 PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, PmMessage msg)
582 {
583     PmEvent event;
584     
585     event.timestamp = when;
586     event.message = msg;
587     return Pm_Write(stream, &event, 1);
588 }
589
590
591 PMEXPORT PmError Pm_WriteSysEx(PortMidiStream *stream, PmTimestamp when, 
592                       unsigned char *msg)
593 {
594     /* allocate buffer space for PM_DEFAULT_SYSEX_BUFFER_SIZE bytes */
595     /* each PmEvent holds sizeof(PmMessage) bytes of sysex data */
596     #define BUFLEN ((int) (PM_DEFAULT_SYSEX_BUFFER_SIZE / sizeof(PmMessage)))
597     PmEvent buffer[BUFLEN];
598     int buffer_size = 1; /* first time, send 1. After that, it's BUFLEN */
599     PmInternal *midi = (PmInternal *) stream;
600     /* the next byte in the buffer is represented by an index, bufx, and
601        a shift in bits */
602     int shift = 0;
603     int bufx = 0;
604     buffer[0].message = 0;
605     buffer[0].timestamp = when;
606
607     while (1) {
608         /* insert next byte into buffer */
609         buffer[bufx].message |= ((*msg) << shift);
610         shift += 8;
611         if (*msg++ == MIDI_EOX) break;
612         if (shift == 32) {
613             shift = 0;
614             bufx++;
615             if (bufx == buffer_size) {
616                 PmError err = Pm_Write(stream, buffer, buffer_size);
617                 /* note: Pm_Write has already called errmsg() */
618                 if (err) return err;
619                 /* prepare to fill another buffer */
620                 bufx = 0;
621                 buffer_size = BUFLEN;
622                 /* optimization: maybe we can just copy bytes */
623                 if (midi->fill_base) {
624                     PmError err;
625                     while (*(midi->fill_offset_ptr) < midi->fill_length) {
626                         midi->fill_base[(*midi->fill_offset_ptr)++] = *msg;
627                         if (*msg++ == MIDI_EOX) {
628                             err = pm_end_sysex(midi);
629                             if (err != pmNoError) return pm_errmsg(err);
630                             goto end_of_sysex;
631                         }
632                     }
633                     /* I thought that I could do a pm_Write here and
634                      * change this if to a loop, avoiding calls in Pm_Write
635                      * to the slower write_byte, but since 
636                      * sysex_in_progress is true, this will not flush
637                      * the buffer, and we'll infinite loop: */
638                     /* err = Pm_Write(stream, buffer, 0);
639                        if (err) return err; */
640                     /* instead, the way this works is that Pm_Write calls
641                      * write_byte on 4 bytes. The first, since the buffer
642                      * is full, will flush the buffer and allocate a new
643                      * one. This primes the buffer so
644                      * that we can return to the loop above and fill it
645                      * efficiently without a lot of function calls.
646                      */
647                     buffer_size = 1; /* get another message started */
648                 }
649             }
650             buffer[bufx].message = 0;
651             buffer[bufx].timestamp = when;
652         } 
653         /* keep inserting bytes until you find MIDI_EOX */
654     }
655 end_of_sysex:
656     /* we're finished sending full buffers, but there may
657      * be a partial one left.
658      */
659     if (shift != 0) bufx++; /* add partial message to buffer len */
660     if (bufx) { /* bufx is number of PmEvents to send from buffer */
661         PmError err = Pm_Write(stream, buffer, bufx);
662         if (err) return err;
663     }
664     return pmNoError;
665 }
666
667
668
669 PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream,
670                      PmDeviceID inputDevice,
671                      void *inputDriverInfo,
672                      int32_t bufferSize,
673                      PmTimeProcPtr time_proc,
674                      void *time_info)
675 {
676     PmInternal *midi;
677     PmError err = pmNoError;
678     pm_hosterror = FALSE;
679     *stream = NULL;
680     
681     /* arg checking */
682     if (inputDevice < 0 || inputDevice >= pm_descriptor_index) 
683         err = pmInvalidDeviceId;
684     else if (!descriptors[inputDevice].pub.input) 
685         err =  pmInvalidDeviceId;
686     else if(descriptors[inputDevice].pub.opened)
687         err =  pmInvalidDeviceId;
688     
689     if (err != pmNoError) 
690         goto error_return;
691
692     /* create portMidi internal data */
693     midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); 
694     *stream = midi;
695     if (!midi) {
696         err = pmInsufficientMemory;
697         goto error_return;
698     }
699     midi->device_id = inputDevice;
700     midi->write_flag = FALSE;
701     midi->time_proc = time_proc;
702     midi->time_info = time_info;
703     /* windows adds timestamps in the driver and these are more accurate than
704        using a time_proc, so do not automatically provide a time proc. Non-win
705        implementations may want to provide a default time_proc in their
706        system-specific midi_out_open() method.
707      */
708     if (bufferSize <= 0) bufferSize = 256; /* default buffer size */
709     midi->queue = Pm_QueueCreate(bufferSize, (int32_t) sizeof(PmEvent));
710     if (!midi->queue) {
711         /* free portMidi data */
712         *stream = NULL;
713         pm_free(midi); 
714         err = pmInsufficientMemory;
715         goto error_return;
716     }
717     midi->buffer_len = bufferSize; /* portMidi input storage */
718     midi->latency = 0; /* not used */
719     midi->sysex_in_progress = FALSE;
720     midi->sysex_message = 0; 
721     midi->sysex_message_count = 0; 
722     midi->filters = PM_FILT_ACTIVE;
723     midi->channel_mask = 0xFFFF;
724     midi->sync_time = 0;
725     midi->first_message = TRUE;
726     midi->dictionary = descriptors[inputDevice].dictionary;
727     midi->fill_base = NULL;
728     midi->fill_offset_ptr = NULL;
729     midi->fill_length = 0;
730     descriptors[inputDevice].internalDescriptor = midi;
731     /* open system dependent input device */
732     err = (*midi->dictionary->open)(midi, inputDriverInfo);
733     if (err) {
734         *stream = NULL;
735         descriptors[inputDevice].internalDescriptor = NULL;
736         /* free portMidi data */
737         Pm_QueueDestroy(midi->queue);
738         pm_free(midi);
739     } else {
740         /* portMidi input open successful */
741         descriptors[inputDevice].pub.opened = TRUE;
742     }
743 error_return:
744     /* note: if there is a pmHostError, it is the responsibility
745      * of the system-dependent code (*midi->dictionary->open)()
746      * to set pm_hosterror and pm_hosterror_text
747      */
748     return pm_errmsg(err);
749 }
750
751
752 PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream,
753                       PmDeviceID outputDevice,
754                       void *outputDriverInfo,
755                       int32_t bufferSize,
756                       PmTimeProcPtr time_proc,
757                       void *time_info,
758                       int32_t latency ) 
759 {
760     PmInternal *midi;
761     PmError err = pmNoError;
762     pm_hosterror = FALSE;
763     *stream =  NULL;
764     
765     /* arg checking */
766     if (outputDevice < 0 || outputDevice >= pm_descriptor_index)
767         err = pmInvalidDeviceId;
768     else if (!descriptors[outputDevice].pub.output) 
769         err = pmInvalidDeviceId;
770     else if (descriptors[outputDevice].pub.opened)
771         err = pmInvalidDeviceId;
772     if (err != pmNoError) 
773         goto error_return;
774
775     /* create portMidi internal data */
776     midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); 
777     *stream = midi;                 
778     if (!midi) {
779         err = pmInsufficientMemory;
780         goto error_return;
781     }
782     midi->device_id = outputDevice;
783     midi->write_flag = TRUE;
784     midi->time_proc = time_proc;
785     /* if latency > 0, we need a time reference. If none is provided,
786        use PortTime library */
787     if (time_proc == NULL && latency != 0) {
788         if (!Pt_Started()) 
789             Pt_Start(1, 0, 0);
790         /* time_get does not take a parameter, so coerce */
791         midi->time_proc = (PmTimeProcPtr) Pt_Time;
792     }
793     midi->time_info = time_info;
794     midi->buffer_len = bufferSize;
795     midi->queue = NULL; /* unused by output */
796     /* if latency zero, output immediate (timestamps ignored) */
797     /* if latency < 0, use 0 but don't return an error */
798     if (latency < 0) latency = 0;
799     midi->latency = latency;
800     midi->sysex_in_progress = FALSE;
801     midi->sysex_message = 0; /* unused by output */
802     midi->sysex_message_count = 0; /* unused by output */
803     midi->filters = 0; /* not used for output */
804     midi->channel_mask = 0xFFFF;
805     midi->sync_time = 0;
806     midi->first_message = TRUE;
807     midi->dictionary = descriptors[outputDevice].dictionary;
808     midi->fill_base = NULL;
809     midi->fill_offset_ptr = NULL;
810     midi->fill_length = 0;
811     descriptors[outputDevice].internalDescriptor = midi;
812     /* open system dependent output device */
813     err = (*midi->dictionary->open)(midi, outputDriverInfo);
814     if (err) {
815         *stream = NULL;
816         descriptors[outputDevice].internalDescriptor = NULL;
817         /* free portMidi data */
818         pm_free(midi); 
819     } else {
820         /* portMidi input open successful */
821         descriptors[outputDevice].pub.opened = TRUE;
822     }
823 error_return:
824     /* note: system-dependent code must set pm_hosterror and
825      * pm_hosterror_text if a pmHostError occurs
826      */
827     return pm_errmsg(err);
828 }
829
830
831 PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask)
832 {
833     PmInternal *midi = (PmInternal *) stream;
834     PmError err = pmNoError;
835
836     if (midi == NULL)
837         err = pmBadPtr;
838     else
839         midi->channel_mask = mask;
840
841     return pm_errmsg(err);
842 }
843
844
845 PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) {
846     PmInternal *midi = (PmInternal *) stream;
847     PmError err = pmNoError;
848
849     /* arg checking */
850     if (midi == NULL)
851         err = pmBadPtr;
852     else if (!descriptors[midi->device_id].pub.opened)
853         err = pmBadPtr;
854     else
855         midi->filters = filters;
856     return pm_errmsg(err);
857 }
858
859
860 PMEXPORT PmError Pm_Close( PortMidiStream *stream ) {
861     PmInternal *midi = (PmInternal *) stream;
862     PmError err = pmNoError;
863
864     pm_hosterror = FALSE;
865     /* arg checking */
866     if (midi == NULL) /* midi must point to something */
867         err = pmBadPtr;
868     /* if it is an open device, the device_id will be valid */
869     else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_index)
870         err = pmBadPtr;
871     /* and the device should be in the opened state */
872     else if (!descriptors[midi->device_id].pub.opened)
873         err = pmBadPtr;
874     
875     if (err != pmNoError) 
876         goto error_return;
877
878     /* close the device */
879     err = (*midi->dictionary->close)(midi);
880     /* even if an error occurred, continue with cleanup */
881     descriptors[midi->device_id].internalDescriptor = NULL;
882     descriptors[midi->device_id].pub.opened = FALSE;
883     if (midi->queue) Pm_QueueDestroy(midi->queue);
884     pm_free(midi); 
885 error_return:
886     /* system dependent code must set pm_hosterror and
887      * pm_hosterror_text if a pmHostError occurs.
888      */
889     return pm_errmsg(err);
890 }
891
892 PmError Pm_Synchronize( PortMidiStream* stream ) {
893     PmInternal *midi = (PmInternal *) stream;
894     PmError err = pmNoError;
895     if (midi == NULL)
896         err = pmBadPtr;
897     else if (!descriptors[midi->device_id].pub.output)
898         err = pmBadPtr;
899     else if (!descriptors[midi->device_id].pub.opened)
900         err = pmBadPtr;
901     else
902         midi->first_message = TRUE;
903     return err;
904 }
905
906 PMEXPORT PmError Pm_Abort( PortMidiStream* stream ) {
907     PmInternal *midi = (PmInternal *) stream;
908     PmError err;
909     /* arg checking */
910     if (midi == NULL)
911         err = pmBadPtr;
912     else if (!descriptors[midi->device_id].pub.output)
913         err = pmBadPtr;
914     else if (!descriptors[midi->device_id].pub.opened)
915         err = pmBadPtr;
916     else
917         err = (*midi->dictionary->abort)(midi);
918
919     if (err == pmHostError) {
920         midi->dictionary->host_error(midi, pm_hosterror_text, 
921                                      PM_HOST_ERROR_MSG_LEN);
922         pm_hosterror = TRUE;
923     }
924     return pm_errmsg(err);
925 }
926
927
928
929 /* pm_channel_filtered returns non-zero if the channel mask is blocking the current channel */
930 #define pm_channel_filtered(status, mask) \
931     ((((status) & 0xF0) != 0xF0) && (!(Pm_Channel((status) & 0x0F) & (mask))))
932
933
934 /* The following two functions will checks to see if a MIDI message matches
935    the filtering criteria.  Since the sysex routines only want to filter realtime messages,
936    we need to have separate routines.
937  */
938
939
940 /* pm_realtime_filtered returns non-zero if the filter will kill the current message.
941    Note that only realtime messages are checked here.
942  */
943 #define pm_realtime_filtered(status, filters) \
944     ((((status) & 0xF0) == 0xF0) && ((1 << ((status) & 0xF)) & (filters)))
945
946 /*
947     return ((status == MIDI_ACTIVE) && (filters & PM_FILT_ACTIVE))
948             ||  ((status == MIDI_CLOCK) && (filters & PM_FILT_CLOCK))
949             ||  ((status == MIDI_START) && (filters & PM_FILT_PLAY))
950             ||  ((status == MIDI_STOP) && (filters & PM_FILT_PLAY))
951             ||  ((status == MIDI_CONTINUE) && (filters & PM_FILT_PLAY))
952             ||  ((status == MIDI_F9) && (filters & PM_FILT_F9))
953             ||  ((status == MIDI_FD) && (filters & PM_FILT_FD))
954             ||  ((status == MIDI_RESET) && (filters & PM_FILT_RESET))
955             ||  ((status == MIDI_MTC) && (filters & PM_FILT_MTC))
956             ||  ((status == MIDI_SONGPOS) && (filters & PM_FILT_SONG_POSITION))
957             ||  ((status == MIDI_SONGSEL) && (filters & PM_FILT_SONG_SELECT))
958             ||  ((status == MIDI_TUNE) && (filters & PM_FILT_TUNE));
959 }*/
960
961
962 /* pm_status_filtered returns non-zero if a filter will kill the current message, based on status.
963    Note that sysex and real time are not checked.  It is up to the subsystem (winmm, core midi, alsa)
964    to filter sysex, as it is handled more easily and efficiently at that level.
965    Realtime message are filtered in pm_realtime_filtered.
966  */
967 #define pm_status_filtered(status, filters) ((1 << (16 + ((status) >> 4))) & (filters))
968
969
970 /*
971     return  ((status == MIDI_NOTE_ON) && (filters & PM_FILT_NOTE))
972             ||  ((status == MIDI_NOTE_OFF) && (filters & PM_FILT_NOTE))
973             ||  ((status == MIDI_CHANNEL_AT) && (filters & PM_FILT_CHANNEL_AFTERTOUCH))
974             ||  ((status == MIDI_POLY_AT) && (filters & PM_FILT_POLY_AFTERTOUCH))
975             ||  ((status == MIDI_PROGRAM) && (filters & PM_FILT_PROGRAM))
976             ||  ((status == MIDI_CONTROL) && (filters & PM_FILT_CONTROL))
977             ||  ((status == MIDI_PITCHBEND) && (filters & PM_FILT_PITCHBEND));
978
979 }
980 */
981
982 static void pm_flush_sysex(PmInternal *midi, PmTimestamp timestamp)
983 {
984     PmEvent event;
985     
986     /* there may be nothing in the buffer */
987     if (midi->sysex_message_count == 0) return; /* nothing to flush */
988     
989     event.message = midi->sysex_message;
990     event.timestamp = timestamp;
991     /* copied from pm_read_short, avoids filtering */
992     if (Pm_Enqueue(midi->queue, &event) == pmBufferOverflow) {
993         midi->sysex_in_progress = FALSE;
994     }
995     midi->sysex_message_count = 0;
996     midi->sysex_message = 0;
997 }
998
999
1000 /* pm_read_short and pm_read_bytes
1001    are the interface between system-dependent MIDI input handlers
1002    and the system-independent PortMIDI code.
1003    The input handler MUST obey these rules:
1004    1) all short input messages must be sent to pm_read_short, which
1005       enqueues them to a FIFO for the application.
1006    2) each buffer of sysex bytes should be reported by calling pm_read_bytes
1007       (which sets midi->sysex_in_progress). After the eox byte, 
1008       pm_read_bytes will clear sysex_in_progress
1009  */
1010
1011 /* pm_read_short is the place where all input messages arrive from 
1012    system-dependent code such as pmwinmm.c. Here, the messages
1013    are entered into the PortMidi input buffer. 
1014  */
1015 void pm_read_short(PmInternal *midi, PmEvent *event)
1016
1017     int status;
1018     /* arg checking */
1019     assert(midi != NULL);
1020     /* midi filtering is applied here */
1021     status = Pm_MessageStatus(event->message);
1022     if (!pm_status_filtered(status, midi->filters)
1023         && (!is_real_time(status) || 
1024             !pm_realtime_filtered(status, midi->filters))
1025         && !pm_channel_filtered(status, midi->channel_mask)) {
1026         /* if sysex is in progress and we get a status byte, it had
1027            better be a realtime message or the starting SYSEX byte;
1028            otherwise, we exit the sysex_in_progress state
1029          */
1030         if (midi->sysex_in_progress && (status & MIDI_STATUS_MASK)) {
1031             /* two choices: real-time or not. If it's real-time, then
1032              * this should be delivered as a sysex byte because it is
1033              * embedded in a sysex message
1034              */
1035             if (is_real_time(status)) {
1036                 midi->sysex_message |= 
1037                         (status << (8 * midi->sysex_message_count++));
1038                 if (midi->sysex_message_count == 4) {
1039                     pm_flush_sysex(midi, event->timestamp);
1040                 }
1041             } else { /* otherwise, it's not real-time. This interrupts
1042                       * a sysex message in progress */
1043                 midi->sysex_in_progress = FALSE;
1044             }
1045         } else if (Pm_Enqueue(midi->queue, event) == pmBufferOverflow) {
1046             midi->sysex_in_progress = FALSE;
1047         }
1048     }
1049 }
1050
1051 /* pm_read_bytes -- read one (partial) sysex msg from MIDI data */
1052 /*
1053  * returns how many bytes processed
1054  */
1055 unsigned int pm_read_bytes(PmInternal *midi, const unsigned char *data, 
1056                     int len, PmTimestamp timestamp)
1057 {
1058     int i = 0; /* index into data, must not be unsigned (!) */
1059     PmEvent event;
1060     event.timestamp = timestamp;
1061     assert(midi);
1062     /* note that since buffers may not have multiples of 4 bytes,
1063      * pm_read_bytes may be called in the middle of an outgoing
1064      * 4-byte PortMidi message. sysex_in_progress indicates that
1065      * a sysex has been sent but no eox.
1066      */
1067     if (len == 0) return 0; /* sanity check */
1068     if (!midi->sysex_in_progress) {
1069         while (i < len) { /* process all data */
1070             unsigned char byte = data[i++];
1071             if (byte == MIDI_SYSEX &&
1072                 !pm_realtime_filtered(byte, midi->filters)) {
1073                 midi->sysex_in_progress = TRUE;
1074                 i--; /* back up so code below will get SYSEX byte */
1075                 break; /* continue looping below to process msg */
1076             } else if (byte == MIDI_EOX) {
1077                 midi->sysex_in_progress = FALSE;
1078                 return i; /* done with one message */
1079             } else if (byte & MIDI_STATUS_MASK) {
1080                 /* We're getting MIDI but no sysex in progress.
1081                  * Either the SYSEX status byte was dropped or
1082                  * the message was filtered. Drop the data, but
1083                  * send any embedded realtime bytes.
1084                  */
1085                 /* assume that this is a real-time message:
1086                  * it is an error to pass non-real-time messages
1087                  * to pm_read_bytes
1088                  */
1089                 event.message = byte;
1090                 pm_read_short(midi, &event);
1091             }
1092         } /* all bytes in the buffer are processed */
1093     }
1094     /* Now, i<len implies sysex_in_progress. If sysex_in_progress
1095      * becomes false in the loop, there must have been an overflow
1096      * and we can just drop all remaining bytes 
1097      */
1098     while (i < len && midi->sysex_in_progress) {
1099         if (midi->sysex_message_count == 0 && i <= len - 4 &&
1100             ((event.message = (((PmMessage) data[i]) | 
1101                              (((PmMessage) data[i+1]) << 8) |
1102                              (((PmMessage) data[i+2]) << 16) |
1103                              (((PmMessage) data[i+3]) << 24))) &
1104              0x80808080) == 0) { /* all data, no status */ 
1105             if (Pm_Enqueue(midi->queue, &event) == pmBufferOverflow) {
1106                 midi->sysex_in_progress = FALSE;
1107             }
1108             i += 4;
1109         } else {
1110             while (i < len) {
1111                 /* send one byte at a time */
1112                 unsigned char byte = data[i++];
1113                 if (is_real_time(byte) && 
1114                     pm_realtime_filtered(byte, midi->filters)) {
1115                     continue; /* real-time data is filtered, so omit */
1116                 }
1117                 midi->sysex_message |= 
1118                     (byte << (8 * midi->sysex_message_count++));
1119                 if (byte == MIDI_EOX) {
1120                     midi->sysex_in_progress = FALSE;
1121                     pm_flush_sysex(midi, event.timestamp);
1122                     return i;
1123                 } else if (midi->sysex_message_count == 4) {
1124                     pm_flush_sysex(midi, event.timestamp);
1125                     /* after handling at least one non-data byte
1126                      * and reaching a 4-byte message boundary,
1127                      * resume trying to send 4 at a time in outer loop
1128                      */
1129                     break;
1130                 }
1131             }
1132         }
1133     }
1134     return i;
1135 }
1136
1137