portmidi.c (39208B)
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 !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