annotate data/midi/MIDIInput.cpp @ 588:d04b8674b710

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