NiCMidi 1.1.0
A MIDI library derived from J.D.Koftinoff jdksmidi
driver.h
Go to the documentation of this file.
1/*
2 * NiCMidi - A C++ Class Library for MIDI
3 *
4 * Copyright (C) 2004 J.D. Koftinoff Software, Ltd.
5 * www.jdkoftinoff.com jeffk@jdkoftinoff.com
6 * Copyright (C) 2021, 2022 Nicola Cassetta
7 * https://github.com/ncassetta/NiCMidi
8 *
9 * This file is part of NiCMidi.
10 *
11 * NiCMidi is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as
13 * published by the Free Software Foundation, either version 3 of
14 * the License, or (at your option) any later version.
15 *
16 * NiCMidi is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with NiCMidi. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25
29
30
31#ifndef _NICMIDI_DRIVER_H
32#define _NICMIDI_DRIVER_H
33
34#include "msg.h"
35#include "processor.h"
36#include "timer.h"
37
38
39#include "../rtmidi-4.0.0/RtMidi.h"
40
41#include <vector>
42#include <string>
43#include <mutex>
44//#include <atomic>
45
46
47// TODO: implements RtMidi functions (error callback, selection of input, etc.)
48
49
52
58#define DRIVER_USES_MIDIMATRIX 0
59#if DRIVER_USES_MIDIMATRIX
60 #include "matrix.h"
61#endif // DRIVER_USES_MIDIMATRIX
63
64
65
71 MIDIRawMessage() : timestamp(0), port(0) {}
73 MIDIRawMessage(const MIDIMessage& m, tMsecs t, int p) :
74 msg(m), timestamp(t), port(p) {}
77 int port;
78};
79
80
81// EXCLUDED FROM DOCUMENTATION BECAUSE UNDOCUMENTED
82// This is a queue of MIDIRawMessage
83class MIDIRawMessageQueue {
84 public:
85 // The constructor creates a queue of the given size. When the queue is full, older messages
86 // are pulled from the queue.
87
88 MIDIRawMessageQueue(unsigned int size) :
89 next_in(0), next_out(0), buffer(size) {}
90 // The destructor deletes all the MIDIRawMessage objects actually contained in the queue.
91 virtual ~MIDIRawMessageQueue() {}
92 // Empties the queue and turns into a NoOp all the messages contained.
93 void Reset();
94 // Quickly empties the queue acting only on in and out indexes.
95 void Flush() { next_out = next_in; }
96 // Adds the given MIDIRawMessage as the last element in the queue. If the queue was full
97 // the first message is pulled out.
98 void PutMessage(const MIDIRawMessage& msg);
99 // Gets the first MIDIRawMessage in the queue, pulling it out. It returns a reference
100 // to a static copy, which is valid until the next call to the function.
101 MIDIRawMessage& GetMessage();
102 // Gets the n-th MIDIRawMessage in the queue, without pulling it out. It returns a
103 // direct reference to the message (and it's so faster than GetMessage(), which copies it)
104 // which is valid until an operation on the queue is done. If the queue has an actual
105 // size lesser than _n_, returns a NoOp message.
106 MIDIRawMessage& ReadMessage(unsigned int n);
107 // Returns *true* is the queue is empty.
108 bool IsEmpty() const { return next_in == next_out; }
109 // Returns *true* if the queue has reached its max size (you can however add other messages,
110 // deleting the older ones.
111 bool IsFull() const { return ((next_in + 1) % buffer.size()) == next_out; }
112 // Returns the actual length of the queue.
113 unsigned int GetLength() const { return (next_in - next_out) % buffer.size(); }
114
115 protected:
116 unsigned int next_in;
117 unsigned int next_out;
118 std::vector<MIDIRawMessage> buffer;
119};
120
121
131 public:
140 virtual ~MIDIOutDriver();
141
146 virtual void Reset();
147
149 int GetPortId() const { return port_id; }
151 std::string GetPortName() { return port->getPortName(port_id); }
153 bool IsPortOpen() const { return port->isPortOpen(); }
155 MIDIProcessor* GetOutProcessor() { return processor; }
157 const MIDIProcessor* GetOutProcessor() const { return processor; }
158
162 virtual void SetOutProcessor(MIDIProcessor* proc)
163 { processor = proc; }
164
168 virtual void OpenPort();
172 virtual void ClosePort();
178 virtual void AllNotesOff(int chan = -1);
182 // TODO: actually it writes to cerr, Should we raise an exception?
183 virtual void OutputMessage(const MIDITimedMessage& msg);
184
185 protected:
187 static const int DRIVER_MAX_RETRIES = 100;
189 static const int DRIVER_WAIT_AFTER_SYSEX = 20;
191 virtual void HardwareMsgOut(const MIDIMessage &msg);
192
194 MIDIProcessor* processor; // The out processor
195 RtMidiOut* port; // The hardware port
196 const int port_id; // The id of the port
197 int num_open; // Counts the number of OpenPort() calls
198 std::recursive_mutex out_mutex; // Used internally for thread safe operating
199
200#if DRIVER_USES_MIDIMATRIX
201 MIDIMatrix out_matrix; // To keep track of notes on going to MIDI out
202#endif // DRIVER_USES_MIDIMATRIX
204
205 private:
206 // this vector is used by HardwareMsgOut to feed the port
207 std::vector<unsigned char> msg_bytes;
208};
209
210
211
212
225 public:
234 MIDIInDriver(int id, unsigned int queue_size = DEFAULT_QUEUE_SIZE);
236 virtual ~MIDIInDriver();
242 virtual void Reset();
243
245 int GetPortId() const { return port_id; }
247 std::string GetPortName() { return port->getPortName(port_id); }
249 bool IsPortOpen() const { return port->isPortOpen(); }
251 bool CanGet() const { return in_queue.GetLength() > 0; }
253 unsigned int GetQueueSize() const { return in_queue.GetLength(); }
255 MIDIProcessor* GetProcessor() { return processor; }
257 const MIDIProcessor* GetProcessor() const { return processor; }
258
266 virtual void SetProcessor(MIDIProcessor* proc);
267
271 virtual void OpenPort();
275 virtual void ClosePort();
279 void LockQueue() { in_mutex.lock(); }
281 void UnlockQueue() { in_mutex.unlock(); }
288 virtual bool InputMessage(MIDIRawMessage& msg);
295 virtual bool ReadMessage(MIDIRawMessage& msg, unsigned int n);
296
297protected:
298
302 static void HardwareMsgIn(double time,
303 std::vector<unsigned char>* msg_bytes,
304 void* p);
305
307 // This is the default queue size.
308 static const unsigned int DEFAULT_QUEUE_SIZE = 256;
309
310 MIDIProcessor* processor; // The in processor
311 RtMidiIn* port; // The hardware port
312 const int port_id; // The id of the port
313 int num_open; // Counts the number of OpenPort() calls
314
315 MIDIRawMessageQueue in_queue; // The incoming message queue (see MIDIRawMessage)
316 std::recursive_mutex in_mutex; // Locks/unlocks the queue
318};
319
320
321#endif // _JDKMIDI_DRIVER_H
Receives MIDI messages from an hardware MIDI in port.
Definition: driver.h:224
unsigned int GetQueueSize() const
Returns the queue size.
Definition: driver.h:253
void LockQueue()
Locks the queue so it cannot be written by other threads (such as the RtMidi callback).
Definition: driver.h:279
void FlushQueue()
Empties the queue in a thread-safe way.
MIDIInDriver(int id, unsigned int queue_size=DEFAULT_QUEUE_SIZE)
Creates a MIDIInDriver object which can receive MIDI messages from the given hardware in port.
const MIDIProcessor * GetProcessor() const
Returns a pointer to the in processor.
Definition: driver.h:257
virtual ~MIDIInDriver()
The destructor closes the hardware port and deletes the object.
virtual bool ReadMessage(MIDIRawMessage &msg, unsigned int n)
Gets the n-th message in the queue without deleting it (so the message remains available for other pu...
bool CanGet() const
Returns true if the queue is non-empty.
Definition: driver.h:251
virtual void ClosePort()
Closes the hardware out port.
int GetPortId() const
Returns the id number of the hardware in port.
Definition: driver.h:245
virtual void SetProcessor(MIDIProcessor *proc)
Sets the in processor, which can manipulate all incoming messages (see MIDIProcessor).
static void HardwareMsgIn(double time, std::vector< unsigned char > *msg_bytes, void *p)
This is the callback function executed by RtMidi when a message arrives to the hardware port.
virtual void Reset()
Resets the driver to default conditions:
MIDIProcessor * GetProcessor()
Returns a pointer to the in processor.
Definition: driver.h:255
std::string GetPortName()
Returns the name of the hardware in port.
Definition: driver.h:247
void UnlockQueue()
Unlocks the queue (see LockQueue()).
Definition: driver.h:281
virtual bool InputMessage(MIDIRawMessage &msg)
Gets the next message in the queue, copying it into msg (the message is deleted from the queue).
bool IsPortOpen() const
Returns true is the hardware port is open.
Definition: driver.h:249
virtual void OpenPort()
Opens the hardware in port.
This MIDIProcessor subclass implements a matrix which keeps track of notes on and hold pedal for ever...
Definition: matrix.h:43
Stores data representing a MIDI event message.
Definition: msg.h:49
Sends MIDI messages to an hardware MIDI out port.
Definition: driver.h:130
virtual void OpenPort()
Opens the hardware out port.
const MIDIProcessor * GetOutProcessor() const
Returns a pointer to the out processor.
Definition: driver.h:157
virtual void Reset()
Resets the driver to default conditions:
virtual void SetOutProcessor(MIDIProcessor *proc)
Sets the out processor, which can manipulate all outgoing messages (see MIDIProcessor).
Definition: driver.h:162
static const int DRIVER_WAIT_AFTER_SYSEX
The number of milliseconds the driver waits after sending a MIDI system exclusive message.
Definition: driver.h:189
MIDIProcessor * GetOutProcessor()
Returns a pointer to the out processor.
Definition: driver.h:155
static const int DRIVER_MAX_RETRIES
The maximum number of retries the method OutputMessage() will try before hanging (and skipping a mess...
Definition: driver.h:187
virtual void HardwareMsgOut(const MIDIMessage &msg)
Sends the message to the hardware MIDI port using the RtMidi library functions.
virtual void OutputMessage(const MIDITimedMessage &msg)
Makes a copy of the message, processes it with the out processor and then sends it to the hardware po...
virtual void AllNotesOff(int chan=-1)
Turns off all the sounding notes on the port (or on the given MIDI channel).
virtual void ClosePort()
Closes the hardware out port.
virtual ~MIDIOutDriver()
The destructor closes the hardware port and deletes the object.
std::string GetPortName()
Returns the name of the hardware out port.
Definition: driver.h:151
MIDIOutDriver(int id)
Creates a MIDIOutDriver object which can send MIDI messages to the given hardware out port.
int GetPortId() const
Returns the id number of the hardware out port.
Definition: driver.h:149
bool IsPortOpen() const
Returns true is the hardware port is open.
Definition: driver.h:153
A pure virtual class implementing an object that can manipulate a MIDI message, inspecting or changin...
Definition: processor.h:47
The MIDITimedMessage class inherits from the MIDIMessage and represents a message associated with a s...
Definition: msg.h:382
unsigned long long tMsecs
The type of a variable which can hold the elapsed time in milliseconds.
Definition: timer.h:44
Contains the definition of the class MIDIMatrix.
Contains the definition of the classes MIDIMessage and MIDITimedMessage.
Contains the definition of the pure virtual MIDIProcessor class and its specializations MIDIMultiProc...
Used by the MIDIInDriver to keep track of incoming messages.
Definition: driver.h:70
MIDIMessage msg
The MIDI Message received from the port.
Definition: driver.h:75
tMsecs timestamp
The absolute time in msecs.
Definition: driver.h:76
int port
The id of the MIDI in port which received the message.
Definition: driver.h:77
MIDIRawMessage(const MIDIMessage &m, tMsecs t, int p)
The constructor.
Definition: driver.h:73
Contains the definition of the MIDITimer class and some other typedef related to MIDI timing.