forked from VCVRack/Rack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrtmidi.cpp
118 lines (96 loc) · 2.96 KB
/
rtmidi.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "rtmidi.hpp"
#include <map>
namespace rack {
static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) {
if (!message) return;
if (!userData) return;
RtMidiInputDevice *midiInputDevice = (RtMidiInputDevice*) userData;
if (!midiInputDevice) return;
MidiMessage msg;
if (message->size() >= 1)
msg.cmd = (*message)[0];
if (message->size() >= 2)
msg.data1 = (*message)[1];
if (message->size() >= 3)
msg.data2 = (*message)[2];
midiInputDevice->onMessage(msg);
}
RtMidiInputDevice::RtMidiInputDevice(int driverId, int deviceId) {
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId, "VCV Rack");
assert(rtMidiIn);
rtMidiIn->ignoreTypes(false, false, false);
rtMidiIn->setCallback(midiInputCallback, this);
rtMidiIn->openPort(deviceId, "VCV Rack input");
}
RtMidiInputDevice::~RtMidiInputDevice() {
rtMidiIn->closePort();
delete rtMidiIn;
}
RtMidiDriver::RtMidiDriver(int driverId) {
this->driverId = driverId;
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId);
assert(rtMidiIn);
rtMidiOut = new RtMidiOut((RtMidi::Api) driverId);
assert(rtMidiOut);
}
RtMidiDriver::~RtMidiDriver() {
delete rtMidiIn;
delete rtMidiOut;
}
std::string RtMidiDriver::getName() {
switch (driverId) {
case RtMidi::UNSPECIFIED: return "Unspecified";
case RtMidi::MACOSX_CORE: return "Core MIDI";
case RtMidi::LINUX_ALSA: return "ALSA";
case RtMidi::UNIX_JACK: return "JACK";
case RtMidi::WINDOWS_MM: return "Windows MIDI";
case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
default: return "";
}
}
std::vector<int> RtMidiDriver::getInputDeviceIds() {
// TODO The IDs unfortunately jump around in RtMidi. Is there a way to keep them constant when a MIDI device is added/removed?
int count = rtMidiIn->getPortCount();
std::vector<int> deviceIds;
for (int i = 0; i < count; i++)
deviceIds.push_back(i);
return deviceIds;
}
std::string RtMidiDriver::getInputDeviceName(int deviceId) {
if (deviceId >= 0) {
return rtMidiIn->getPortName(deviceId);
}
return "";
}
MidiInputDevice *RtMidiDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (!(0 <= deviceId && deviceId < (int) rtMidiIn->getPortCount()))
return NULL;
RtMidiInputDevice *device = devices[deviceId];
if (!device) {
devices[deviceId] = device = new RtMidiInputDevice(driverId, deviceId);
}
device->subscribe(midiInput);
return device;
}
void RtMidiDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
auto it = devices.find(deviceId);
if (it == devices.end())
return;
RtMidiInputDevice *device = it->second;
device->unsubscribe(midiInput);
// Destroy device if nothing is subscribed anymore
if (device->subscribed.empty()) {
devices.erase(it);
delete device;
}
}
void rtmidiInit() {
std::vector<RtMidi::Api> rtApis;
RtMidi::getCompiledApi(rtApis);
for (RtMidi::Api api : rtApis) {
int driverId = (int) api;
MidiDriver *driver = new RtMidiDriver(driverId);
midiDriverAdd(driverId, driver);
}
}
} // namespace rack