You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

midi.hpp 6.2KB

6 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #pragma once
  2. #include <vector>
  3. #include <queue>
  4. #include <set>
  5. #include <jansson.h>
  6. #include <common.hpp>
  7. #include <context.hpp>
  8. namespace rack {
  9. /** MIDI driver
  10. */
  11. namespace midi {
  12. struct Message {
  13. /** Initialized to 3 empty bytes. */
  14. std::vector<uint8_t> bytes;
  15. /** The Engine frame timestamp of the Message.
  16. For output messages, the frame when the message was generated.
  17. For input messages, the frame when it is intended to be processed.
  18. -1 for undefined, to be sent or processed immediately.
  19. */
  20. int64_t frame = -1;
  21. Message() : bytes(3) {}
  22. int getSize() const {
  23. return bytes.size();
  24. }
  25. void setSize(int size) {
  26. bytes.resize(size);
  27. }
  28. uint8_t getChannel() const {
  29. if (bytes.size() < 1)
  30. return 0;
  31. return bytes[0] & 0xf;
  32. }
  33. void setChannel(uint8_t channel) {
  34. if (bytes.size() < 1)
  35. return;
  36. bytes[0] = (bytes[0] & 0xf0) | (channel & 0xf);
  37. }
  38. uint8_t getStatus() const {
  39. if (bytes.size() < 1)
  40. return 0;
  41. return bytes[0] >> 4;
  42. }
  43. void setStatus(uint8_t status) {
  44. if (bytes.size() < 1)
  45. return;
  46. bytes[0] = (bytes[0] & 0xf) | (status << 4);
  47. }
  48. uint8_t getNote() const {
  49. if (bytes.size() < 2)
  50. return 0;
  51. return bytes[1];
  52. }
  53. void setNote(uint8_t note) {
  54. if (bytes.size() < 2)
  55. return;
  56. bytes[1] = note & 0x7f;
  57. }
  58. uint8_t getValue() const {
  59. if (bytes.size() < 3)
  60. return 0;
  61. return bytes[2];
  62. }
  63. void setValue(uint8_t value) {
  64. if (bytes.size() < 3)
  65. return;
  66. bytes[2] = value & 0x7f;
  67. }
  68. std::string toString() const;
  69. };
  70. ////////////////////
  71. // Driver
  72. ////////////////////
  73. struct InputDevice;
  74. struct Input;
  75. struct OutputDevice;
  76. struct Output;
  77. /** Wraps a MIDI driver API containing any number of MIDI devices.
  78. */
  79. struct Driver {
  80. virtual ~Driver() {}
  81. /** Returns the name of the driver. E.g. "ALSA". */
  82. virtual std::string getName() {
  83. return "";
  84. }
  85. /** Returns a list of all input device IDs that can be subscribed to. */
  86. virtual std::vector<int> getInputDeviceIds() {
  87. return {};
  88. }
  89. /** Returns the name of an input device without obtaining it. */
  90. virtual std::string getInputDeviceName(int deviceId) {
  91. return "";
  92. }
  93. /** Adds the given port as a reference holder of a device and returns the it.
  94. Creates the Device if no ports are subscribed before calling.
  95. */
  96. virtual InputDevice* subscribeInput(int deviceId, Input* input) {
  97. return NULL;
  98. }
  99. /** Removes the give port as a reference holder of a device.
  100. Deletes the Device if no ports are subscribed after calling.
  101. */
  102. virtual void unsubscribeInput(int deviceId, Input* input) {}
  103. // The following behave identically as the above methods except for outputs.
  104. virtual std::vector<int> getOutputDeviceIds() {
  105. return {};
  106. }
  107. virtual std::string getOutputDeviceName(int deviceId) {
  108. return "";
  109. }
  110. virtual OutputDevice* subscribeOutput(int deviceId, Output* output) {
  111. return NULL;
  112. }
  113. virtual void unsubscribeOutput(int deviceId, Output* output) {}
  114. };
  115. ////////////////////
  116. // Device
  117. ////////////////////
  118. /** A single MIDI device of a driver API.
  119. Modules and the UI should not interact with this API directly. Use Port instead.
  120. Methods throw `rack::Exception` if the driver API has an exception.
  121. */
  122. struct Device {
  123. virtual ~Device() {}
  124. virtual std::string getName() {
  125. return "";
  126. }
  127. };
  128. struct InputDevice : Device {
  129. std::set<Input*> subscribed;
  130. /** Not public. Use Driver::subscribeInput(). */
  131. void subscribe(Input* input);
  132. /** Not public. Use Driver::unsubscribeInput(). */
  133. void unsubscribe(Input* input);
  134. /** Called when a MIDI message is received from the device. */
  135. void onMessage(const Message& message);
  136. };
  137. struct OutputDevice : Device {
  138. std::set<Output*> subscribed;
  139. /** Not public. Use Driver::subscribeOutput(). */
  140. void subscribe(Output* output);
  141. /** Not public. Use Driver::unsubscribeOutput(). */
  142. void unsubscribe(Output* output);
  143. /** Sends a MIDI message to the device. */
  144. virtual void sendMessage(const Message& message) {}
  145. };
  146. ////////////////////
  147. // Port
  148. ////////////////////
  149. /** A handle to a Device, typically owned by modules to have shared access to a single Device.
  150. All Port methods safely wrap Drivers methods.
  151. 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.
  152. Use Input or Output subclasses in your module, not Port directly.
  153. */
  154. struct Port {
  155. /** For MIDI output, the channel to automatically set outbound messages.
  156. If -1, the channel is not overwritten and must be set by MIDI generator.
  157. For MIDI input, messages will be filtered by the channel.
  158. If -1, all MIDI channels pass through.
  159. */
  160. int channel = -1;
  161. // private
  162. int driverId = -1;
  163. int deviceId = -1;
  164. /** Not owned */
  165. Driver* driver = NULL;
  166. Device* device = NULL;
  167. Context* context;
  168. Port();
  169. virtual ~Port();
  170. Driver* getDriver();
  171. int getDriverId();
  172. void setDriverId(int driverId);
  173. Device* getDevice();
  174. virtual std::vector<int> getDeviceIds() = 0;
  175. int getDeviceId();
  176. virtual void setDeviceId(int deviceId) = 0;
  177. virtual std::string getDeviceName(int deviceId) = 0;
  178. virtual std::vector<int> getChannels() = 0;
  179. int getChannel();
  180. void setChannel(int channel);
  181. std::string getChannelName(int channel);
  182. json_t* toJson();
  183. void fromJson(json_t* rootJ);
  184. };
  185. struct Input : Port {
  186. /** Not owned */
  187. InputDevice* inputDevice = NULL;
  188. Input();
  189. ~Input();
  190. void reset();
  191. std::vector<int> getDeviceIds() override;
  192. void setDeviceId(int deviceId) override;
  193. std::string getDeviceName(int deviceId) override;
  194. std::vector<int> getChannels() override;
  195. virtual void onMessage(const Message& message) {}
  196. };
  197. struct InputQueue : Input {
  198. int queueMaxSize = 8192;
  199. std::queue<Message> queue;
  200. void onMessage(const Message& message) override;
  201. };
  202. struct Output : Port {
  203. /** Not owned */
  204. OutputDevice* outputDevice = NULL;
  205. Output();
  206. ~Output();
  207. void reset();
  208. std::vector<int> getDeviceIds() override;
  209. void setDeviceId(int deviceId) override;
  210. std::string getDeviceName(int deviceId) override;
  211. std::vector<int> getChannels() override;
  212. void sendMessage(const Message& message);
  213. };
  214. void init();
  215. void destroy();
  216. /** Registers a new MIDI driver. Takes pointer ownership. */
  217. void addDriver(int driverId, Driver* driver);
  218. std::vector<int> getDriverIds();
  219. Driver* getDriver(int driverId);
  220. } // namespace midi
  221. } // namespace rack