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