1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Sonic Visualiser
An audio file viewer and annotation editor.
Centre for Digital Music, Queen Mary, University of London.
This file copyright 2006-2009 Chris Cannam and QMUL.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See the file
COPYING included with this distribution for more information.
*/
#include "MIDIInput.h"
#include "rtmidi/RtMidi.h"
#include <unistd.h>
MIDIInput::MIDIInput(QString name, FrameTimer *timer) :
m_rtmidi(),
m_frameTimer(timer),
m_buffer(1023)
{
try {
m_rtmidi = new RtMidiIn(name.toStdString());
m_rtmidi->setCallback(staticCallback, this);
m_rtmidi->openPort(0, tr("Input").toStdString());
} catch (RtError e) {
e.printMessage();
delete m_rtmidi;
m_rtmidi = 0;
}
}
MIDIInput::~MIDIInput()
{
delete m_rtmidi;
}
void
MIDIInput::staticCallback(double timestamp, std::vector<unsigned char> *message,
void *userData)
{
((MIDIInput *)userData)->callback(timestamp, message);
}
void
MIDIInput::callback(double timestamp, std::vector<unsigned char> *message)
{
SVDEBUG << "MIDIInput::callback(" << timestamp << ")" << endl;
// In my experience so far, the timings passed to this function
// are not reliable enough to use. We request instead an audio
// frame time from whatever FrameTimer we have been given, and use
// that as the event time.
if (!message || message->empty()) return;
unsigned long t = m_frameTimer->getFrame();
MIDIByte code = (*message)[0];
MIDIEvent ev(t,
code,
message->size() > 1 ? (*message)[1] : 0,
message->size() > 2 ? (*message)[2] : 0);
postEvent(ev);
}
MIDIEvent
MIDIInput::readEvent()
{
MIDIEvent *event = m_buffer.readOne();
MIDIEvent revent = *event;
delete event;
return revent;
}
void
MIDIInput::postEvent(MIDIEvent e)
{
int count = 0, max = 5;
while (m_buffer.getWriteSpace() == 0) {
if (count == max) {
cerr << "ERROR: MIDIInput::postEvent: MIDI event queue is full and not clearing -- abandoning incoming event" << endl;
return;
}
cerr << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << " is full!" << endl;
SVDEBUG << "Waiting for something to be processed" << endl;
#ifdef _WIN32
Sleep(1);
#else
sleep(1);
#endif
count++;
}
MIDIEvent *me = new MIDIEvent(e);
m_buffer.write(&me, 1);
emit eventsAvailable();
}
|