svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006-2009 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "MIDIInput.h" 00017 00018 #include "rtmidi/RtMidi.h" 00019 00020 #include <unistd.h> 00021 00022 MIDIInput::MIDIInput(QString name, FrameTimer *timer) : 00023 m_rtmidi(), 00024 m_frameTimer(timer), 00025 m_buffer(1023) 00026 { 00027 try { 00028 m_rtmidi = new RtMidiIn(name.toStdString()); 00029 m_rtmidi->setCallback(staticCallback, this); 00030 m_rtmidi->openPort(0, tr("Input").toStdString()); 00031 } catch (RtError e) { 00032 e.printMessage(); 00033 delete m_rtmidi; 00034 m_rtmidi = 0; 00035 } 00036 } 00037 00038 MIDIInput::~MIDIInput() 00039 { 00040 delete m_rtmidi; 00041 } 00042 00043 void 00044 MIDIInput::staticCallback(double timestamp, std::vector<unsigned char> *message, 00045 void *userData) 00046 { 00047 ((MIDIInput *)userData)->callback(timestamp, message); 00048 } 00049 00050 void 00051 MIDIInput::callback(double timestamp, std::vector<unsigned char> *message) 00052 { 00053 SVDEBUG << "MIDIInput::callback(" << timestamp << ")" << endl; 00054 // In my experience so far, the timings passed to this function 00055 // are not reliable enough to use. We request instead an audio 00056 // frame time from whatever FrameTimer we have been given, and use 00057 // that as the event time. 00058 if (!message || message->empty()) return; 00059 unsigned long t = m_frameTimer->getFrame(); 00060 MIDIByte code = (*message)[0]; 00061 MIDIEvent ev(t, 00062 code, 00063 message->size() > 1 ? (*message)[1] : 0, 00064 message->size() > 2 ? (*message)[2] : 0); 00065 postEvent(ev); 00066 } 00067 00068 MIDIEvent 00069 MIDIInput::readEvent() 00070 { 00071 MIDIEvent *event = m_buffer.readOne(); 00072 MIDIEvent revent = *event; 00073 delete event; 00074 return revent; 00075 } 00076 00077 void 00078 MIDIInput::postEvent(MIDIEvent e) 00079 { 00080 int count = 0, max = 5; 00081 while (m_buffer.getWriteSpace() == 0) { 00082 if (count == max) { 00083 cerr << "ERROR: MIDIInput::postEvent: MIDI event queue is full and not clearing -- abandoning incoming event" << endl; 00084 return; 00085 } 00086 cerr << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << " is full!" << endl; 00087 SVDEBUG << "Waiting for something to be processed" << endl; 00088 #ifdef _WIN32 00089 Sleep(1); 00090 #else 00091 sleep(1); 00092 #endif 00093 count++; 00094 } 00095 00096 MIDIEvent *me = new MIDIEvent(e); 00097 m_buffer.write(&me, 1); 00098 emit eventsAvailable(); 00099 } 00100