|
|
@@ -117,213 +117,10 @@ struct Message { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
//////////////////// |
|
|
|
// Driver |
|
|
|
//////////////////// |
|
|
|
|
|
|
|
struct InputDevice; |
|
|
|
struct Input; |
|
|
|
struct OutputDevice; |
|
|
|
struct Output; |
|
|
|
|
|
|
|
/** Wraps a MIDI driver API containing any number of MIDI devices. |
|
|
|
*/ |
|
|
|
struct Driver { |
|
|
|
virtual ~Driver() {} |
|
|
|
/** Returns the name of the driver. E.g. "ALSA". */ |
|
|
|
virtual std::string getName() { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
/** Returns a list of all input device IDs that can be subscribed to. */ |
|
|
|
virtual std::vector<int> getInputDeviceIds() { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
/** Returns the default device to use when the driver is selected, or -1 for none. */ |
|
|
|
virtual int getDefaultInputDeviceId() { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
/** Returns the name of an input device without obtaining it. */ |
|
|
|
virtual std::string getInputDeviceName(int deviceId) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
/** Adds the given port as a reference holder of a device and returns the it. |
|
|
|
Creates the Device if no ports are subscribed before calling. |
|
|
|
*/ |
|
|
|
virtual InputDevice* subscribeInput(int deviceId, Input* input) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
/** Removes the give port as a reference holder of a device. |
|
|
|
Deletes the Device if no ports are subscribed after calling. |
|
|
|
*/ |
|
|
|
virtual void unsubscribeInput(int deviceId, Input* input) {} |
|
|
|
|
|
|
|
// The following behave identically as the above methods except for outputs. |
|
|
|
|
|
|
|
virtual std::vector<int> getOutputDeviceIds() { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
virtual int getDefaultOutputDeviceId() { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
virtual std::string getOutputDeviceName(int deviceId) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
virtual OutputDevice* subscribeOutput(int deviceId, Output* output) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
virtual void unsubscribeOutput(int deviceId, Output* output) {} |
|
|
|
}; |
|
|
|
|
|
|
|
//////////////////// |
|
|
|
// Device |
|
|
|
//////////////////// |
|
|
|
|
|
|
|
/** A single MIDI device of a driver API. |
|
|
|
|
|
|
|
Modules and the UI should not interact with this API directly. Use Port instead. |
|
|
|
|
|
|
|
Methods throw `rack::Exception` if the driver API has an exception. |
|
|
|
*/ |
|
|
|
struct Device { |
|
|
|
virtual ~Device() {} |
|
|
|
virtual std::string getName() { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct InputDevice : Device { |
|
|
|
std::set<Input*> subscribed; |
|
|
|
/** Not public. Use Driver::subscribeInput(). */ |
|
|
|
void subscribe(Input* input); |
|
|
|
/** Not public. Use Driver::unsubscribeInput(). */ |
|
|
|
void unsubscribe(Input* input); |
|
|
|
/** Called when a MIDI message is received from the device. */ |
|
|
|
void onMessage(const Message& message); |
|
|
|
}; |
|
|
|
|
|
|
|
struct OutputDevice : Device { |
|
|
|
std::set<Output*> subscribed; |
|
|
|
/** Not public. Use Driver::subscribeOutput(). */ |
|
|
|
void subscribe(Output* output); |
|
|
|
/** Not public. Use Driver::unsubscribeOutput(). */ |
|
|
|
void unsubscribe(Output* output); |
|
|
|
/** Sends a MIDI message to the device. */ |
|
|
|
virtual void sendMessage(const Message& message) {} |
|
|
|
}; |
|
|
|
|
|
|
|
//////////////////// |
|
|
|
// Port |
|
|
|
//////////////////// |
|
|
|
|
|
|
|
/** A handle to a Device, typically owned by modules to have shared access to a single Device. |
|
|
|
|
|
|
|
All Port methods safely wrap Drivers methods. |
|
|
|
That is, if the active Device throws a `rack::Exception`, it is caught and logged inside all Port methods, so they do not throw exceptions. |
|
|
|
|
|
|
|
Use Input or Output subclasses in your module, not Port directly. |
|
|
|
*/ |
|
|
|
struct Port { |
|
|
|
/** For MIDI output, the channel to automatically set outbound messages. |
|
|
|
If -1, the channel is not overwritten and must be set by MIDI generator. |
|
|
|
|
|
|
|
For MIDI input, messages will be filtered by the channel. |
|
|
|
If -1, all MIDI channels pass through. |
|
|
|
*/ |
|
|
|
int channel = -1; |
|
|
|
|
|
|
|
// private |
|
|
|
int driverId = -1; |
|
|
|
int deviceId = -1; |
|
|
|
/** Not owned */ |
|
|
|
Driver* driver = NULL; |
|
|
|
Device* device = NULL; |
|
|
|
Context* context; |
|
|
|
|
|
|
|
Port(); |
|
|
|
virtual ~Port(); |
|
|
|
|
|
|
|
Driver* getDriver(); |
|
|
|
int getDriverId(); |
|
|
|
void setDriverId(int driverId); |
|
|
|
|
|
|
|
Device* getDevice(); |
|
|
|
virtual std::vector<int> getDeviceIds() = 0; |
|
|
|
virtual int getDefaultDeviceId() = 0; |
|
|
|
int getDeviceId(); |
|
|
|
virtual void setDeviceId(int deviceId) = 0; |
|
|
|
virtual std::string getDeviceName(int deviceId) = 0; |
|
|
|
|
|
|
|
virtual std::vector<int> getChannels() = 0; |
|
|
|
int getChannel(); |
|
|
|
void setChannel(int channel); |
|
|
|
std::string getChannelName(int channel); |
|
|
|
|
|
|
|
json_t* toJson(); |
|
|
|
void fromJson(json_t* rootJ); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct Input : Port { |
|
|
|
/** Not owned */ |
|
|
|
InputDevice* inputDevice = NULL; |
|
|
|
|
|
|
|
Input(); |
|
|
|
~Input(); |
|
|
|
void reset(); |
|
|
|
|
|
|
|
std::vector<int> getDeviceIds() override; |
|
|
|
int getDefaultDeviceId() override; |
|
|
|
void setDeviceId(int deviceId) override; |
|
|
|
std::string getDeviceName(int deviceId) override; |
|
|
|
|
|
|
|
std::vector<int> getChannels() override; |
|
|
|
|
|
|
|
virtual void onMessage(const Message& message) {} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** An Input port that stores incoming MIDI messages and releases them when ready according to their frame timestamp. |
|
|
|
*/ |
|
|
|
struct InputQueue : Input { |
|
|
|
struct Internal; |
|
|
|
Internal* internal; |
|
|
|
|
|
|
|
InputQueue(); |
|
|
|
~InputQueue(); |
|
|
|
void onMessage(const Message& message) override; |
|
|
|
/** Pops and returns the next message (by setting `messageOut`) if its frame timestamp is `maxFrame` or earlier. |
|
|
|
Returns whether a message was returned. |
|
|
|
*/ |
|
|
|
bool tryPop(Message* messageOut, int64_t maxFrame); |
|
|
|
size_t size(); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct Output : Port { |
|
|
|
/** Not owned */ |
|
|
|
OutputDevice* outputDevice = NULL; |
|
|
|
|
|
|
|
Output(); |
|
|
|
~Output(); |
|
|
|
void reset(); |
|
|
|
|
|
|
|
std::vector<int> getDeviceIds() override; |
|
|
|
int getDefaultDeviceId() override; |
|
|
|
void setDeviceId(int deviceId) override; |
|
|
|
std::string getDeviceName(int deviceId) override; |
|
|
|
|
|
|
|
std::vector<int> getChannels() override; |
|
|
|
|
|
|
|
void sendMessage(const Message& message); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
PRIVATE void init(); |
|
|
|
PRIVATE void destroy(); |
|
|
|
/** Registers a new MIDI driver. Takes pointer ownership. */ |
|
|
|
void addDriver(int driverId, Driver* driver); |
|
|
|
std::vector<int> getDriverIds(); |
|
|
|
Driver* getDriver(int driverId); |
|
|
|
/* NOTE all the other MIDI stuff (drivers, ports etc) is purposefully missing here, unwanted in Cardinal |
|
|
|
*/ |
|
|
|
struct Port; |
|
|
|
|
|
|
|
|
|
|
|
} // namespace midi |
|
|
|