| 1528 | } |
| 1529 | |
| 1530 | void MidiOutCore :: sendMessage( const unsigned char *message, size_t size ) |
| 1531 | { |
| 1532 | // We use the MIDISendSysex() function to asynchronously send sysex |
| 1533 | // messages. Otherwise, we use a single CoreMidi MIDIPacket. |
| 1534 | unsigned int nBytes = static_cast<unsigned int> (size); |
| 1535 | if ( nBytes == 0 ) { |
| 1536 | errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; |
| 1537 | error( RtMidiError::WARNING, errorString_ ); |
| 1538 | return; |
| 1539 | } |
| 1540 | |
| 1541 | if ( message[0] != 0xF0 && nBytes > 3 ) { |
| 1542 | errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; |
| 1543 | error( RtMidiError::WARNING, errorString_ ); |
| 1544 | return; |
| 1545 | } |
| 1546 | |
| 1547 | MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); |
| 1548 | CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); |
| 1549 | OSStatus result; |
| 1550 | |
| 1551 | ByteCount bufsize = nBytes > 65535 ? 65535 : nBytes; |
| 1552 | Byte buffer[bufsize+16]; // pad for other struct members |
| 1553 | ByteCount listSize = sizeof( buffer ); |
| 1554 | MIDIPacketList *packetList = (MIDIPacketList*)buffer; |
| 1555 | |
| 1556 | ByteCount remainingBytes = nBytes; |
| 1557 | while ( remainingBytes ) { |
| 1558 | MIDIPacket *packet = MIDIPacketListInit( packetList ); |
| 1559 | // A MIDIPacketList can only contain a maximum of 64K of data, so if our message is longer, |
| 1560 | // break it up into chunks of 64K or less and send out as a MIDIPacketList with only one |
| 1561 | // MIDIPacket. Here, we reuse the memory allocated above on the stack for all. |
| 1562 | ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; |
| 1563 | const Byte* dataStartPtr = (const Byte *) &message[nBytes - remainingBytes]; |
| 1564 | packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr ); |
| 1565 | remainingBytes -= bytesForPacket; |
| 1566 | |
| 1567 | if ( !packet ) { |
| 1568 | errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; |
| 1569 | error( RtMidiError::DRIVER_ERROR, errorString_ ); |
| 1570 | return; |
| 1571 | } |
| 1572 | |
| 1573 | // Send to any destinations that may have connected to us. |
| 1574 | if ( data->endpoint ) { |
| 1575 | result = MIDIReceived( data->endpoint, packetList ); |
| 1576 | if ( result != noErr ) { |
| 1577 | errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; |
| 1578 | error( RtMidiError::WARNING, errorString_ ); |
| 1579 | } |
| 1580 | } |
| 1581 | |
| 1582 | // And send to an explicit destination port if we're connected. |
| 1583 | if ( connected_ ) { |
| 1584 | result = MIDISend( data->port, data->destinationId, packetList ); |
| 1585 | if ( result != noErr ) { |
| 1586 | errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; |
| 1587 | error( RtMidiError::WARNING, errorString_ ); |