2 #pragma warning(disable: 4244) // stop warnings about downsize typecasts
3 #pragma warning(disable: 4018) // stop warnings about signed/unsigned
11 #include "pminternal.h"
14 #define MIDI_CLOCK 0xf8
15 #define MIDI_ACTIVE 0xfe
16 #define MIDI_STATUS_MASK 0x80
17 #define MIDI_SYSEX 0xf0
19 #define MIDI_START 0xFA
20 #define MIDI_STOP 0xFC
21 #define MIDI_CONTINUE 0xFB
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
33 #define MIDI_SONGPOS 0xF2
34 #define MIDI_SONGSEL 0xF3
35 #define MIDI_TUNE 0xF6
37 #define is_empty(midi) ((midi)->tail == (midi)->head)
39 /* this is not static so that pm_init can set it directly if
40 * (see pmmac.c:pm_init())
42 int pm_initialized = FALSE;
45 char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];
47 #ifdef PM_CHECK_ERRORS
53 static void prompt_and_exit(void)
55 char line[STRING_MAX];
56 printf("type ENTER...");
57 fgets(line, STRING_MAX, stdin);
58 /* this will clean up open ports: */
63 static PmError pm_errmsg(PmError err)
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
69 printf("PortMidi found host error...\n %s\n", pm_hosterror_text);
71 pm_hosterror_text[0] = 0; /* clear the message */
74 printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err));
80 #define pm_errmsg(err) err
84 ====================================================================
85 system implementation of portmidi interface
86 ====================================================================
89 int pm_descriptor_max = 0;
90 int pm_descriptor_index = 0;
91 descriptor_type descriptors = NULL;
93 /* pm_add_device -- describe interface/device pair to library
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!
99 * returns pmInvalidDeviceId if device memory is exceeded
100 * otherwise returns pmNoError
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;
110 memcpy(new_descriptors, descriptors,
111 sizeof(descriptor_node) * pm_descriptor_max);
114 pm_descriptor_max += 32;
115 descriptors = new_descriptors;
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;
122 /* default state: nothing to close (for automatic device closing) */
123 descriptors[pm_descriptor_index].pub.opened = FALSE;
125 /* ID number passed to win32 multimedia API open */
126 descriptors[pm_descriptor_index].descriptor = descriptor;
128 /* points to PmInternal, allows automatic device closing */
129 descriptors[pm_descriptor_index].internalDescriptor = NULL;
131 descriptors[pm_descriptor_index].dictionary = dictionary;
133 pm_descriptor_index++;
139 /* utility to look up device, given a pattern,
140 note: pattern is modified
142 int pm_find_default_device(char *pattern, int is_input)
146 /* first parse pattern into name, interf parts */
147 char *interf_pref = ""; /* initially assume it is not there */
148 char *name_pref = strstr(pattern, ", ");
150 if (name_pref) { /* found separator, adjust the pointer */
151 interf_pref = pattern;
155 name_pref = pattern; /* whole string is the name pattern */
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)) {
171 ====================================================================
172 portmidi implementation
173 ====================================================================
176 PMEXPORT int Pm_CountDevices( void ) {
178 /* no error checking -- Pm_Initialize() does not fail */
179 return pm_descriptor_index;
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;
191 /* pm_success_fn -- "noop" function pointer */
192 PmError pm_success_fn(PmInternal *midi) {
196 /* none_write -- returns an error if called */
197 PmError none_write_short(PmInternal *midi, PmEvent *buffer) {
201 /* pm_fail_timestamp_fn -- placeholder for begin_sysex and flush */
202 PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp) {
206 PmError none_write_byte(PmInternal *midi, unsigned char byte,
207 PmTimestamp timestamp) {
211 /* pm_fail_fn -- generic function, returns error if called */
212 PmError pm_fail_fn(PmInternal *midi) {
216 static PmError none_open(PmInternal *midi, void *driverInfo) {
219 static void none_get_host_error(PmInternal * midi, char * msg, unsigned int len) {
220 *msg = 0; // empty string
222 static unsigned int none_has_host_error(PmInternal * midi) {
225 PmTimestamp none_synchronize(PmInternal *midi) {
229 #define none_abort pm_fail_fn
230 #define none_close pm_fail_fn
232 pm_fns_node pm_none_dictionary = {
249 PMEXPORT const char *Pm_GetErrorText( PmError errnum ) {
258 msg = "PortMidi: `Host error'";
260 case pmInvalidDeviceId:
261 msg = "PortMidi: `Invalid device ID'";
263 case pmInsufficientMemory:
264 msg = "PortMidi: `Insufficient memory'";
266 case pmBufferTooSmall:
267 msg = "PortMidi: `Buffer too small'";
270 msg = "PortMidi: `Bad pointer'";
272 case pmInternalError:
273 msg = "PortMidi: `Internal PortMidi Error'";
275 case pmBufferOverflow:
276 msg = "PortMidi: `Buffer overflow'";
279 msg = "PortMidi: `Invalid MIDI message Data'";
281 case pmBufferMaxSize:
282 msg = "PortMidi: `Buffer cannot be made larger'";
285 msg = "PortMidi: `Illegal error number'";
292 /* This can be called whenever you get a pmHostError return value.
293 * The error will always be in the global pm_hosterror_text.
295 PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) {
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 */
305 msg[0] = 0; /* no string to return */
310 PMEXPORT int Pm_HasHostError(PortMidiStream * stream) {
311 if (pm_hosterror) return TRUE;
313 PmInternal * midi = (PmInternal *) stream;
314 pm_hosterror = (*midi->dictionary->has_host_error)(midi);
316 midi->dictionary->host_error(midi, pm_hosterror_text,
317 PM_HOST_ERROR_MSG_LEN);
318 /* now error message is global */
326 PMEXPORT PmError Pm_Initialize( void ) {
327 if (!pm_initialized) {
328 pm_hosterror = FALSE;
329 pm_hosterror_text[0] = 0; /* the null string */
331 pm_initialized = TRUE;
337 PMEXPORT PmError Pm_Terminate( void ) {
338 if (pm_initialized) {
340 // if there are no devices, descriptors might still be NULL
341 if (descriptors != NULL) {
345 pm_descriptor_index = 0;
346 pm_descriptor_max = 0;
347 pm_initialized = FALSE;
353 /* Pm_Read -- read up to length messages from source into buffer */
355 * returns number of messages actually read, or error code
357 PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) {
358 PmInternal *midi = (PmInternal *) stream;
360 PmError err = pmNoError;
361 pm_hosterror = FALSE;
365 else if(!descriptors[midi->device_id].pub.opened)
367 else if(!descriptors[midi->device_id].pub.input)
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);
376 if (err != pmNoError) {
377 if (err == pmHostError) {
378 midi->dictionary->host_error(midi, pm_hosterror_text,
379 PM_HOST_ERROR_MSG_LEN);
382 return pm_errmsg(err);
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 */
398 PMEXPORT PmError Pm_Poll( PortMidiStream *stream )
400 PmInternal *midi = (PmInternal *) stream;
403 pm_hosterror = FALSE;
407 else if (!descriptors[midi->device_id].pub.opened)
409 else if (!descriptors[midi->device_id].pub.input)
412 err = (*(midi->dictionary->poll))(midi);
414 if (err != pmNoError) {
415 if (err == pmHostError) {
416 midi->dictionary->host_error(midi, pm_hosterror_text,
417 PM_HOST_ERROR_MSG_LEN);
420 return pm_errmsg(err);
423 return (PmError) !Pm_QueueEmpty(midi->queue);
427 /* this is called from Pm_Write and Pm_WriteSysEx to issue a
428 * call to the system-dependent end_sysex function and handle
431 static PmError pm_end_sysex(PmInternal *midi)
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);
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 */
448 PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t length)
450 PmInternal *midi = (PmInternal *) stream;
451 PmError err = pmNoError;
455 pm_hosterror = FALSE;
459 else if(!descriptors[midi->device_id].pub.opened)
461 else if(!descriptors[midi->device_id].pub.output)
466 if (err != pmNoError) goto pm_write_error;
468 if (midi->latency == 0) {
471 midi->now = (*(midi->time_proc))(midi->time_info);
472 if (midi->first_message || midi->sync_time + 100 /*ms*/ < midi->now) {
474 midi->now = (*midi->dictionary->synchronize)(midi);
475 midi->first_message = FALSE;
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.
491 for (i = 0; i < length; i++) {
492 uint32_t msg = buffer[i].message;
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;
502 midi->sysex_in_progress = TRUE;
503 if ((err = (*midi->dictionary->begin_sysex)(midi,
504 buffer[i].timestamp)) != pmNoError)
506 if ((err = (*midi->dictionary->write_byte)(midi, MIDI_SYSEX,
507 buffer[i].timestamp)) != pmNoError)
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)
521 midi->sysex_in_progress = FALSE;
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);
528 } else { /* regular short midi message */
529 if ((err = (*midi->dictionary->write_short)(midi,
530 &(buffer[i]))) != pmNoError)
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;
548 /* no acceleration, so do byte-by-byte copying */
550 unsigned char midi_byte = (unsigned char) (msg >> bits);
551 if ((err = (*midi->dictionary->write_byte)(midi, midi_byte,
552 buffer[i].timestamp)) != pmNoError)
554 if (midi_byte == MIDI_EOX) {
555 err = pm_end_sysex(midi);
556 if (err != pmNoError) goto error_exit;
557 break; /* from while loop */
562 /* not in sysex mode, but message did not start with status */
567 /* after all messages are processed, send the data */
568 if (!midi->sysex_in_progress)
569 err = (*midi->dictionary->write_flush)(midi, 0);
571 if (err == pmHostError) {
572 midi->dictionary->host_error(midi, pm_hosterror_text,
573 PM_HOST_ERROR_MSG_LEN);
577 return pm_errmsg(err);
581 PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, PmMessage msg)
585 event.timestamp = when;
587 return Pm_Write(stream, &event, 1);
591 PMEXPORT PmError Pm_WriteSysEx(PortMidiStream *stream, PmTimestamp when,
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
604 buffer[0].message = 0;
605 buffer[0].timestamp = when;
608 /* insert next byte into buffer */
609 buffer[bufx].message |= ((*msg) << shift);
611 if (*msg++ == MIDI_EOX) break;
615 if (bufx == buffer_size) {
616 PmError err = Pm_Write(stream, buffer, buffer_size);
617 /* note: Pm_Write has already called errmsg() */
619 /* prepare to fill another buffer */
621 buffer_size = BUFLEN;
622 /* optimization: maybe we can just copy bytes */
623 if (midi->fill_base) {
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);
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.
647 buffer_size = 1; /* get another message started */
650 buffer[bufx].message = 0;
651 buffer[bufx].timestamp = when;
653 /* keep inserting bytes until you find MIDI_EOX */
656 /* we're finished sending full buffers, but there may
657 * be a partial one left.
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);
669 PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream,
670 PmDeviceID inputDevice,
671 void *inputDriverInfo,
673 PmTimeProcPtr time_proc,
677 PmError err = pmNoError;
678 pm_hosterror = FALSE;
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;
689 if (err != pmNoError)
692 /* create portMidi internal data */
693 midi = (PmInternal *) pm_alloc(sizeof(PmInternal));
696 err = pmInsufficientMemory;
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.
708 if (bufferSize <= 0) bufferSize = 256; /* default buffer size */
709 midi->queue = Pm_QueueCreate(bufferSize, (int32_t) sizeof(PmEvent));
711 /* free portMidi data */
714 err = pmInsufficientMemory;
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;
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);
735 descriptors[inputDevice].internalDescriptor = NULL;
736 /* free portMidi data */
737 Pm_QueueDestroy(midi->queue);
740 /* portMidi input open successful */
741 descriptors[inputDevice].pub.opened = TRUE;
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
748 return pm_errmsg(err);
752 PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream,
753 PmDeviceID outputDevice,
754 void *outputDriverInfo,
756 PmTimeProcPtr time_proc,
761 PmError err = pmNoError;
762 pm_hosterror = FALSE;
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)
775 /* create portMidi internal data */
776 midi = (PmInternal *) pm_alloc(sizeof(PmInternal));
779 err = pmInsufficientMemory;
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) {
790 /* time_get does not take a parameter, so coerce */
791 midi->time_proc = (PmTimeProcPtr) Pt_Time;
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;
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);
816 descriptors[outputDevice].internalDescriptor = NULL;
817 /* free portMidi data */
820 /* portMidi input open successful */
821 descriptors[outputDevice].pub.opened = TRUE;
824 /* note: system-dependent code must set pm_hosterror and
825 * pm_hosterror_text if a pmHostError occurs
827 return pm_errmsg(err);
831 PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask)
833 PmInternal *midi = (PmInternal *) stream;
834 PmError err = pmNoError;
839 midi->channel_mask = mask;
841 return pm_errmsg(err);
845 PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) {
846 PmInternal *midi = (PmInternal *) stream;
847 PmError err = pmNoError;
852 else if (!descriptors[midi->device_id].pub.opened)
855 midi->filters = filters;
856 return pm_errmsg(err);
860 PMEXPORT PmError Pm_Close( PortMidiStream *stream ) {
861 PmInternal *midi = (PmInternal *) stream;
862 PmError err = pmNoError;
864 pm_hosterror = FALSE;
866 if (midi == NULL) /* midi must point to something */
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)
871 /* and the device should be in the opened state */
872 else if (!descriptors[midi->device_id].pub.opened)
875 if (err != pmNoError)
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);
886 /* system dependent code must set pm_hosterror and
887 * pm_hosterror_text if a pmHostError occurs.
889 return pm_errmsg(err);
892 PmError Pm_Synchronize( PortMidiStream* stream ) {
893 PmInternal *midi = (PmInternal *) stream;
894 PmError err = pmNoError;
897 else if (!descriptors[midi->device_id].pub.output)
899 else if (!descriptors[midi->device_id].pub.opened)
902 midi->first_message = TRUE;
906 PMEXPORT PmError Pm_Abort( PortMidiStream* stream ) {
907 PmInternal *midi = (PmInternal *) stream;
912 else if (!descriptors[midi->device_id].pub.output)
914 else if (!descriptors[midi->device_id].pub.opened)
917 err = (*midi->dictionary->abort)(midi);
919 if (err == pmHostError) {
920 midi->dictionary->host_error(midi, pm_hosterror_text,
921 PM_HOST_ERROR_MSG_LEN);
924 return pm_errmsg(err);
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))))
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.
940 /* pm_realtime_filtered returns non-zero if the filter will kill the current message.
941 Note that only realtime messages are checked here.
943 #define pm_realtime_filtered(status, filters) \
944 ((((status) & 0xF0) == 0xF0) && ((1 << ((status) & 0xF)) & (filters)))
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));
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.
967 #define pm_status_filtered(status, filters) ((1 << (16 + ((status) >> 4))) & (filters))
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));
982 static void pm_flush_sysex(PmInternal *midi, PmTimestamp timestamp)
986 /* there may be nothing in the buffer */
987 if (midi->sysex_message_count == 0) return; /* nothing to flush */
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;
995 midi->sysex_message_count = 0;
996 midi->sysex_message = 0;
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
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.
1015 void pm_read_short(PmInternal *midi, PmEvent *event)
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
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
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);
1041 } else { /* otherwise, it's not real-time. This interrupts
1042 * a sysex message in progress */
1043 midi->sysex_in_progress = FALSE;
1045 } else if (Pm_Enqueue(midi->queue, event) == pmBufferOverflow) {
1046 midi->sysex_in_progress = FALSE;
1051 /* pm_read_bytes -- read one (partial) sysex msg from MIDI data */
1053 * returns how many bytes processed
1055 unsigned int pm_read_bytes(PmInternal *midi, const unsigned char *data,
1056 int len, PmTimestamp timestamp)
1058 int i = 0; /* index into data, must not be unsigned (!) */
1060 event.timestamp = timestamp;
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.
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.
1085 /* assume that this is a real-time message:
1086 * it is an error to pass non-real-time messages
1089 event.message = byte;
1090 pm_read_short(midi, &event);
1092 } /* all bytes in the buffer are processed */
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
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;
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 */
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);
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