Entropy Piano Tuner  1.1.3 (documentation not yet complete)
An open-source experimental software for piano tuning by entropy minimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
RtMidiimplementation.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2015 Haye Hinrichsen, Christoph Wick
3  *
4  * This file is part of Entropy Piano Tuner.
5  *
6  * Entropy Piano Tuner is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * Entropy Piano Tuner is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * Entropy Piano Tuner. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 //=============================================================================
21 // MIDI implementaion for various platforms
22 //=============================================================================
23 
24 #include "RtMidiimplementation.h"
25 
26 #if CONFIG_ENABLE_RTMIDI
27 
28 #include <sstream>
29 #include <thread>
30 
31 #include "../../system/log.h"
32 
33 //-----------------------------------------------------------------------------
34 // Constructor without functionality
35 //-----------------------------------------------------------------------------
36 
38  MidiAdapter(),
39  mRtMidi(nullptr),
40  mCurrentPort(0)
41 {}
42 
43 
44 //-----------------------------------------------------------------------------
45 // Initialize the RtMidi-Implementation
46 //-----------------------------------------------------------------------------
47 
52 
54 {
55  try { mRtMidi.reset(new RtMidiIn()); } // try to create the instance
56  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
57 }
58 
59 
60 //-----------------------------------------------------------------------------
61 // Exit from RtMidi-Implementation
62 //-----------------------------------------------------------------------------
63 
67 
69 {
70  mRtMidi.reset();
71 }
72 
73 
74 //-----------------------------------------------------------------------------
75 // Return the number of available Midi ports
76 //-----------------------------------------------------------------------------
77 
81 
83 {
84  if (not mRtMidi)
85  {
86  LogW("Midi has not been initialized");
87  return 0;
88  }
89 
90  int cnt = 0;
91  try { cnt = mRtMidi->getPortCount(); }
92  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
93  return cnt;
94 }
95 
96 
97 
98 //-----------------------------------------------------------------------------
99 // Get the MIDI device name for a given port
100 //-----------------------------------------------------------------------------
101 
106 
108 {
109  std::stringstream ss;
110  try
111  {
112  if (i<0 or i>=static_cast<int>(mRtMidi->getPortCount()))
113  ss << "Midi input port #" << i << " not available.";
114  else ss << i << mRtMidi->getPortName(i);
115  }
116  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
117  return ss.str();
118 }
119 
120 
121 //-----------------------------------------------------------------------------
122 // Return a list of all available Midi devices
123 //-----------------------------------------------------------------------------
124 
128 
130 {
131  if (not mRtMidi)
132  {
133  LogW("Midi has not been initialized");
134  return std::string();
135  }
136 
137  std::stringstream ss;
138  try
139  {
140  if (mRtMidi->getPortCount()==0) return "No Midi input ports available.";
141  for (int i=0; i<static_cast<int>(mRtMidi->getPortCount()); i++)
142  ss << "Midi input port #" << i << ": " << mRtMidi->getPortName(i) << '\n';
143  }
144  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
145  return ss.str();
146 }
147 
148 
149 //-----------------------------------------------------------------------------
150 // Open port number i
151 //-----------------------------------------------------------------------------
152 
159 
160 bool RtMidiImplementation::OpenPort (int i, std::string AppName)
161 {
162  try
163  {
164  if (i<0 or i>=static_cast<int>(mRtMidi->getPortCount()))
165  {
166  LogW ("Invalid port number");
167  return false;
168  }
169  else
170  {
171  mRtMidi->openPort (i,AppName);
172  ClearQueue ();
173  mRtMidi->setCallback (&StaticCallback,this);
174  mCurrentPort = i;
175  }
176  }
177  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
178  return true;
179 }
180 
181 
182 //-----------------------------------------------------------------------------
183 // Open the port with the highest number
184 //-----------------------------------------------------------------------------
185 
195 
196 bool RtMidiImplementation::OpenPort (std::string AppName)
197 {
198  int n = GetNumberOfPorts();
199  if (n>0) return OpenPort(n-1,AppName);
200  else return false;
201 }
202 
203 
204 //-----------------------------------------------------------------------------
205 // Clear the MIDI input queue
206 //-----------------------------------------------------------------------------
207 
218 
220 {
221  try
222  {
223  std::vector<unsigned char> message;
224  bool clearing;
225  int timeout=1000;
226  do
227  {
228  clearing=false;
229  for (int i=0; i<256; ++i)
230  {
231  std::this_thread::sleep_for(
232  std::chrono::microseconds(2));
233  mRtMidi->getMessage(&message);
234  if (message.size()>0) clearing=true;
235  }
236  }
237  while (clearing and --timeout>0);
238  }
239  catch (const RtMidiError &error) LogE("%s", error.getMessage().c_str());
240 }
241 
242 
243 //-----------------------------------------------------------------------------
244 // STATIC CALLBACK FUNCTION
245 //-----------------------------------------------------------------------------
246 
261 
263  std::vector< unsigned char > *message,
264  void* obj)
265 {
267 
268  if (message->size()==3)
269  {
270  int byte0 = (*message)[0];
271  Data data;
272  data.event = MIDI_UNDEFINED;
273  data.byte1 = (*message)[1];
274  data.byte2 = (*message)[2];
275  data.event = byteToEvent(byte0);
276  if (data.event == MIDI_KEY_PRESS && data.byte2 == 0)
277  {
278  data.event = MIDI_KEY_RELEASE;
279  }
280 
281  data.deltatime = deltatime;
282  myself->send(data);
283  }
284 }
285 
286 #endif // CONFIG_ENABLE_RTMIDI
double deltatime
Time elapsed since the last MIDI event.
Definition: midiadapter.h:93
RtMidiImplementation()
Constructor without functionality.
int mCurrentPort
The current port that is used or -1 of none.
void init() overridefinal
Initialize RtMidi implementation.
std::unique_ptr< RtMidiIn > mRtMidi
Instance of the third-party MIDI interface.
MidiEvent event
Midi event, encoded by the enumeration MidiEvent.
Definition: midiadapter.h:90
std::string GetPortName(int i) overridefinal
Get the name of device number i (starting with zero)
#define LogW(...)
Definition: log.h:56
Midi event when a key is pressed.
Definition: midiadapter.h:71
void send(Data &data)
Send new MIDI data to the messaging system.
Definition: midiadapter.cpp:84
Interface for reading an externally connected MIDI keyboard.
std::string GetPortNames() overridefinal
Get a list of all available input devices.
static void StaticCallback(double deltatime, std::vector< unsigned char > *message, void *)
Static callback function (private)
int byte1
Data byte, usually representing the MIDI key index.
Definition: midiadapter.h:91
#define LogE(...)
Definition: log.h:62
void exit() overridefinal
Shut down RtMidi implementation.
Midi event when a key is released.
Definition: midiadapter.h:72
static MidiEvent byteToEvent(int byte)
Convert MIDI code to MidiEvent.
Definition: midiadapter.cpp:63
int GetNumberOfPorts() overridefinal
Get the number of available MIDI input ports.
Adapter class for reading an externally connected MIDI keyboard.
Definition: midiadapter.h:43
bool OpenPort(int i, std::string AppName="") overridefinal
Open MIDI input device number i.
int byte2
Data byte, usually representing the keystroke intensity.
Definition: midiadapter.h:92
Midi event undefined.
Definition: midiadapter.h:70
void ClearQueue()
Clear the MIDI input queue.
Structure of the data associated with a MIDI event.
Definition: midiadapter.h:88