*/
#include <sstream>
-#include "coremidi_io.h"
#include <CoreAudio/HostTime.h>
+#include "coremidi_io.h"
+#include "coreaudio_backend.h"
+
+using namespace ARDOUR;
+
+#ifndef NDEBUG
+static int _debug_mode = 0;
+#endif
+
static void notifyProc (const MIDINotification *message, void *refCon) {
CoreMidiIo *self = static_cast<CoreMidiIo*>(refCon);
self->notify_proc(message);
}
+#ifndef NDEBUG
+static void print_packet (const MIDIPacket *p) {
+ fprintf (stderr, "CoreMIDI: Packet %d bytes [ ", p->length);
+ for (int bb = 0; bb < p->length; ++bb) {
+ fprintf (stderr, "%02x ", ((uint8_t*)p->data)[bb]);
+ }
+ fprintf (stderr, "]\n");
+}
+
+static void dump_packet_list (const UInt32 numPackets, MIDIPacket const *p) {
+ for (UInt32 i = 0; i < numPackets; ++i) {
+ print_packet (p);
+ p = MIDIPacketNext (p);
+ }
+}
+#endif
+
static void midiInputCallback(const MIDIPacketList *list, void *procRef, void *srcRef) {
CoreMidiIo *self = static_cast<CoreMidiIo*> (procRef);
if (!self || !self->enabled()) {
// skip while freewheeling
+#ifndef NDEBUG
+ if (_debug_mode & 2) {
+ fprintf (stderr, "Ignored Midi Packet while freewheeling:\n");
+ dump_packet_list (list->numPackets, &list->packet[0]);
+ }
+#endif
return;
}
RingBuffer<uint8_t> * rb = static_cast<RingBuffer < uint8_t > *> (srcRef);
- if (!rb) return;
- for (UInt32 i = 0; i < list->numPackets; i++) {
- const MIDIPacket *packet = &list->packet[i];
- if (rb->write_space() < sizeof(MIDIPacket)) {
- fprintf(stderr, "CoreMIDI: dropped MIDI event\n");
- continue;
+ if (!rb) {
+#ifndef NDEBUG
+ if (_debug_mode & 4) {
+ fprintf (stderr, "Ignored Midi Packet - no ringbuffer:\n");
+ dump_packet_list (list->numPackets, &list->packet[0]);
}
- rb->write((uint8_t*)packet, sizeof(MIDIPacket));
+#endif
+ return;
+ }
+ 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);
+#ifndef NDEBUG
+ if (_debug_mode & 1) {
+ print_packet (p);
+ }
+#endif
+ if (rb->write_space() > sizeof(uint32_t) + len) {
+ rb->write ((uint8_t*)&len, sizeof(uint32_t));
+ rb->write ((uint8_t*)p, len);
+ }
+#ifndef NDEBUG
+ else {
+ fprintf (stderr, "CoreMIDI: dropped MIDI event\n");
+ }
+#endif
+ p = MIDIPacketNext (p);
}
}
static std::string getPropertyString (MIDIObjectRef object, CFStringRef key)
{
- CFStringRef name = nil;
+ CFStringRef name = NULL;
std::string rv = "";
if (noErr == MIDIObjectGetStringProperty(object, key, &name)) {
const CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8);
, _changed_arg (0)
{
pthread_mutex_init (&_discovery_lock, 0);
+
+#ifndef NDEBUG
+ const char *p = getenv ("COREMIDIDEBUG");
+ if (p && *p) _debug_mode = atoi (p);
+#endif
}
CoreMidiIo::~CoreMidiIo()
}
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<CoreMIDIPacket>(new _CoreMIDIPacket (&packet)));
}
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 {
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<CoreMidiBuffer const *>(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)
{
ss << "system:midi_capture_";
SInt32 id;
if (noErr == MIDIObjectGetIntegerProperty(_input_endpoints[port], kMIDIPropertyUniqueID, &id)) {
- ss << (int)id;
+ ss << (unsigned int)id;
} else {
ss << port;
}
ss << "system:midi_playback_";
SInt32 id;
if (noErr == MIDIObjectGetIntegerProperty(_output_endpoints[port], kMIDIPropertyUniqueID, &id)) {
- ss << (int)id;
+ ss << (unsigned int)id;
} else {
ss << port;
}
fprintf(stderr, "Cannot create Midi Output\n");
continue;
}
- _rb[_n_midi_in] = new RingBuffer<uint8_t>(1024 * sizeof(MIDIPacket));
+ _rb[_n_midi_in] = new RingBuffer<uint8_t>(32768);
_input_queue[_n_midi_in] = CoreMIDIQueue();
MIDIPortConnectSource(_input_ports[_n_midi_in], src, (void*) _rb[_n_midi_in]);
CFRelease(port_name);