X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Fcoreaudio%2Fcoremidi_io.cc;h=0cef589b89fe758ab86c43b0821dc1a22ccc3fd1;hb=087b5dc43b545262689f32b9065ac24a0cc2b33d;hp=87f88a3a029a05938550e31c322a1ae32c11dc4b;hpb=c3430e58843c54646c411650830e29786f99a82b;p=ardour.git diff --git a/libs/backends/coreaudio/coremidi_io.cc b/libs/backends/coreaudio/coremidi_io.cc index 87f88a3a02..0cef589b89 100644 --- a/libs/backends/coreaudio/coremidi_io.cc +++ b/libs/backends/coreaudio/coremidi_io.cc @@ -17,9 +17,13 @@ */ #include -#include "coremidi_io.h" #include +#include "coremidi_io.h" +#include "coreaudio_backend.h" + +using namespace ARDOUR; + static void notifyProc (const MIDINotification *message, void *refCon) { CoreMidiIo *self = static_cast(refCon); self->notify_proc(message); @@ -33,21 +37,24 @@ static void midiInputCallback(const MIDIPacketList *list, void *procRef, void *s } RingBuffer * rb = static_cast *> (srcRef); if (!rb) return; - for (UInt32 i = 0; i < list->numPackets; i++) { - const MIDIPacket *packet = &list->packet[i]; - if (rb->write_space() < sizeof(MIDIPacket)) { + MIDIPacket const *p = &list->packet[0]; + for (UInt32 i = 0; i < list->numPackets; ++i) { + uint32_t len = ((p->length + 3)&~3) + sizeof(MIDITimeStamp) + sizeof(UInt16); + if (rb->write_space() < sizeof(uint32_t) + len) { fprintf(stderr, "CoreMIDI: dropped MIDI event\n"); continue; } - rb->write((uint8_t*)packet, sizeof(MIDIPacket)); + rb->write ((uint8_t*)&len, sizeof(uint32_t)); + rb->write ((uint8_t*)p, len); + p = MIDIPacketNext (p); } } -static std::string getDisplayName(MIDIObjectRef object) +static std::string getPropertyString (MIDIObjectRef object, CFStringRef key) { - CFStringRef name = nil; + CFStringRef name = NULL; std::string rv = ""; - if (noErr == MIDIObjectGetStringProperty(object, kMIDIPropertyDisplayName, &name)) { + if (noErr == MIDIObjectGetStringProperty(object, key, &name)) { const CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8); char *tmp = (char*) malloc(size); if (CFStringGetCString(name, tmp, size, kCFStringEncodingUTF8)) { @@ -59,6 +66,10 @@ static std::string getDisplayName(MIDIObjectRef object) return rv; } +static std::string getDisplayName (MIDIObjectRef object) { + return getPropertyString(object, kMIDIPropertyDisplayName); +} + CoreMidiIo::CoreMidiIo() : _midi_client (0) , _input_endpoints (0) @@ -169,10 +180,16 @@ CoreMidiIo::recv_event (uint32_t port, double cycle_time_us, uint64_t &time, uin } assert(port < _n_midi_in); - while (_rb[port]->read_space() >= sizeof(MIDIPacket)) { + const size_t minsize = 1 + sizeof(uint32_t) + sizeof(MIDITimeStamp) + sizeof(UInt16); + + while (_rb[port]->read_space() > minsize) { MIDIPacket packet; - size_t rv = _rb[port]->read((uint8_t*)&packet, sizeof(MIDIPacket)); - assert(rv == sizeof(MIDIPacket)); + size_t rv; + uint32_t s = 0; + rv = _rb[port]->read((uint8_t*)&s, sizeof(uint32_t)); + assert(rv == sizeof(uint32_t)); + rv = _rb[port]->read((uint8_t*)&packet, s); + assert(rv == s); _input_queue[port].push_back(boost::shared_ptr(new _CoreMIDIPacket (&packet))); } @@ -183,10 +200,16 @@ CoreMidiIo::recv_event (uint32_t port, double cycle_time_us, uint64_t &time, uin if ((*it)->timeStamp < end) { if ((*it)->timeStamp < start) { uint64_t dt = AudioConvertHostTimeToNanos(start - (*it)->timeStamp); - //printf("Stale Midi Event dt:%.2fms\n", dt * 1e-6); - if (dt > 1e-4) { // 100ms, maybe too large + if (dt > 1e7) { // 10ms, +#ifndef NDEBUG + printf("Dropped Stale Midi Event. dt:%.2fms\n", dt * 1e-6); +#endif it = _input_queue[port].erase(it); continue; + } else { +#if 0 + printf("Stale Midi Event. dt:%.2fms\n", dt * 1e-6); +#endif } time = 0; } else { @@ -205,6 +228,40 @@ CoreMidiIo::recv_event (uint32_t port, double cycle_time_us, uint64_t &time, uin return 0; } +int +CoreMidiIo::send_events (uint32_t port, double timescale, const void *b) +{ + if (!_active || _time_at_cycle_start == 0) { + return 0; + } + + assert(port < _n_midi_out); + const UInt64 ts = AudioConvertHostTimeToNanos(_time_at_cycle_start); + + const CoreMidiBuffer *src = static_cast(b); + + int32_t bytes[8192]; // int for alignment + MIDIPacketList *mpl = (MIDIPacketList*)bytes; + MIDIPacket *cur = MIDIPacketListInit(mpl); + + for (CoreMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) { + assert((*mit)->size() < 256); + cur = MIDIPacketListAdd(mpl, sizeof(bytes), cur, + AudioConvertNanosToHostTime(ts + (*mit)->timestamp() / timescale), + (*mit)->size(), (*mit)->data()); + if (!cur) { +#ifndef DEBUG + printf("CoreMidi: Packet list overflow, dropped events\n"); +#endif + break; + } + } + if (mpl->numPackets > 0) { + MIDISend(_output_ports[port], _output_endpoints[port], mpl); + } + return 0; +} + int CoreMidiIo::send_event (uint32_t port, double reltime_us, const uint8_t *d, const size_t s) { @@ -231,28 +288,44 @@ CoreMidiIo::send_event (uint32_t port, double reltime_us, const uint8_t *d, cons return 0; } + std::string -CoreMidiIo::port_name (uint32_t port, bool input) +CoreMidiIo::port_id (uint32_t port, bool input) { std::stringstream ss; - std::string pn; - // XXX including the number will not yield persistent port-names - // when disconnecting devices in the middle. if (input) { - ss << "system:midi_capture_" << port; + ss << "system:midi_capture_"; + SInt32 id; + if (noErr == MIDIObjectGetIntegerProperty(_input_endpoints[port], kMIDIPropertyUniqueID, &id)) { + ss << (unsigned int)id; + } else { + ss << port; + } + } else { + ss << "system:midi_playback_"; + SInt32 id; + if (noErr == MIDIObjectGetIntegerProperty(_output_endpoints[port], kMIDIPropertyUniqueID, &id)) { + ss << (unsigned int)id; + } else { + ss << port; + } + } + return ss.str(); +} + +std::string +CoreMidiIo::port_name (uint32_t port, bool input) +{ + if (input) { if (port < _n_midi_in) { - pn = getDisplayName(_input_endpoints[port]); + return getDisplayName(_input_endpoints[port]); } } else { - ss << "system:midi_playback_" << port; if (port < _n_midi_out) { - pn = getDisplayName(_output_endpoints[port]); + return getDisplayName(_output_endpoints[port]); } } - if (!pn.empty()) { - ss << " - " << pn; - } - return ss.str(); + return ""; } void @@ -324,7 +397,7 @@ CoreMidiIo::discover() fprintf(stderr, "Cannot create Midi Output\n"); continue; } - _rb[_n_midi_in] = new RingBuffer(1024 * sizeof(MIDIPacket)); + _rb[_n_midi_in] = new RingBuffer(32768); _input_queue[_n_midi_in] = CoreMIDIQueue(); MIDIPortConnectSource(_input_ports[_n_midi_in], src, (void*) _rb[_n_midi_in]); CFRelease(port_name);