annotate data/midi/MIDIInput.cpp @ 985:f073d924a7c3

Fix #1058 clicking row in Layer Edit dialog when colour 3d plot layer active jumps to wrong frame (was using sample rate where resolution intended)
author Chris Cannam
date Tue, 16 Sep 2014 10:29:19 +0100
parents e802e550a1f2
children 6b847a59d908
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@608 20 #include <unistd.h>
Chris@608 21
Chris@567 22 MIDIInput::MIDIInput(QString name, FrameTimer *timer) :
Chris@562 23 m_rtmidi(),
Chris@567 24 m_frameTimer(timer),
Chris@562 25 m_buffer(1023)
Chris@562 26 {
Chris@562 27 try {
Chris@562 28 m_rtmidi = new RtMidiIn(name.toStdString());
Chris@562 29 m_rtmidi->setCallback(staticCallback, this);
Chris@565 30 m_rtmidi->openPort(0, tr("Input").toStdString());
Chris@562 31 } catch (RtError e) {
Chris@562 32 e.printMessage();
Chris@562 33 delete m_rtmidi;
Chris@562 34 m_rtmidi = 0;
Chris@562 35 }
Chris@562 36 }
Chris@562 37
Chris@562 38 MIDIInput::~MIDIInput()
Chris@562 39 {
Chris@562 40 delete m_rtmidi;
Chris@562 41 }
Chris@562 42
Chris@562 43 void
Chris@562 44 MIDIInput::staticCallback(double timestamp, std::vector<unsigned char> *message,
Chris@562 45 void *userData)
Chris@562 46 {
Chris@562 47 ((MIDIInput *)userData)->callback(timestamp, message);
Chris@562 48 }
Chris@562 49
Chris@562 50 void
Chris@562 51 MIDIInput::callback(double timestamp, std::vector<unsigned char> *message)
Chris@562 52 {
Chris@690 53 SVDEBUG << "MIDIInput::callback(" << timestamp << ")" << endl;
Chris@567 54 // In my experience so far, the timings passed to this function
Chris@567 55 // are not reliable enough to use. We request instead an audio
Chris@567 56 // frame time from whatever FrameTimer we have been given, and use
Chris@567 57 // that as the event time.
Chris@566 58 if (!message || message->empty()) return;
Chris@567 59 unsigned long t = m_frameTimer->getFrame();
Chris@569 60 MIDIByte code = (*message)[0];
Chris@567 61 MIDIEvent ev(t,
Chris@569 62 code,
Chris@566 63 message->size() > 1 ? (*message)[1] : 0,
Chris@566 64 message->size() > 2 ? (*message)[2] : 0);
Chris@566 65 postEvent(ev);
Chris@562 66 }
Chris@562 67
Chris@562 68 MIDIEvent
Chris@562 69 MIDIInput::readEvent()
Chris@562 70 {
Chris@562 71 MIDIEvent *event = m_buffer.readOne();
Chris@562 72 MIDIEvent revent = *event;
Chris@562 73 delete event;
Chris@562 74 return revent;
Chris@562 75 }
Chris@562 76
Chris@562 77 void
Chris@562 78 MIDIInput::postEvent(MIDIEvent e)
Chris@562 79 {
Chris@562 80 int count = 0, max = 5;
Chris@562 81 while (m_buffer.getWriteSpace() == 0) {
Chris@562 82 if (count == max) {
Chris@843 83 cerr << "ERROR: MIDIInput::postEvent: MIDI event queue is full and not clearing -- abandoning incoming event" << endl;
Chris@562 84 return;
Chris@562 85 }
Chris@843 86 cerr << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << " is full!" << endl;
Chris@690 87 SVDEBUG << "Waiting for something to be processed" << endl;
Chris@562 88 #ifdef _WIN32
Chris@562 89 Sleep(1);
Chris@562 90 #else
Chris@562 91 sleep(1);
Chris@562 92 #endif
Chris@562 93 count++;
Chris@562 94 }
Chris@562 95
Chris@562 96 MIDIEvent *me = new MIDIEvent(e);
Chris@562 97 m_buffer.write(&me, 1);
Chris@562 98 emit eventsAvailable();
Chris@562 99 }
Chris@562 100