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.

121 lines
2.6KB

  1. #include <midiloopback.hpp>
  2. #include <context.hpp>
  3. #include <string.hpp>
  4. namespace rack {
  5. namespace midiloopback {
  6. static const int DRIVER_ID = -12;
  7. static const size_t NUM_DEVICES = 16;
  8. struct Device : midi::InputDevice, midi::OutputDevice {
  9. int id = -1;
  10. std::string getName() override {
  11. return string::f("Loopback %d", id + 1);
  12. }
  13. void sendMessage(const midi::Message& message) override {
  14. onMessage(message);
  15. }
  16. };
  17. struct Driver : midi::Driver {
  18. std::string getName() override {
  19. return "Loopback";
  20. }
  21. // Input methods
  22. std::vector<int> getInputDeviceIds() override {
  23. std::vector<int> deviceIds;
  24. for (size_t i = 0; i < NUM_DEVICES; i++) {
  25. deviceIds.push_back(i);
  26. }
  27. return deviceIds;
  28. }
  29. int getDefaultInputDeviceId() override {
  30. return 0;
  31. }
  32. std::string getInputDeviceName(int deviceId) override {
  33. return getDevice(deviceId)->getName();
  34. }
  35. midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override {
  36. midi::InputDevice* inputDevice = getDevice(deviceId);
  37. if (!inputDevice)
  38. return NULL;
  39. inputDevice->subscribe(input);
  40. return inputDevice;
  41. }
  42. void unsubscribeInput(int deviceId, midi::Input* input) override {
  43. midi::InputDevice* inputDevice = getDevice(deviceId);
  44. if (!inputDevice)
  45. return;
  46. inputDevice->unsubscribe(input);
  47. }
  48. // Output methods
  49. std::vector<int> getOutputDeviceIds() override {
  50. // Output IDs match input IDs
  51. return getInputDeviceIds();
  52. }
  53. int getDefaultOutputDeviceId() override {
  54. return getDefaultInputDeviceId();
  55. }
  56. std::string getOutputDeviceName(int deviceId) override {
  57. return getInputDeviceName(deviceId);
  58. }
  59. midi::OutputDevice* subscribeOutput(int deviceId, midi::Output* output) override {
  60. midi::OutputDevice* outputDevice = getDevice(deviceId);
  61. if (!outputDevice)
  62. return NULL;
  63. outputDevice->subscribe(output);
  64. return outputDevice;
  65. }
  66. void unsubscribeOutput(int deviceId, midi::Output* output) override {
  67. midi::OutputDevice* outputDevice = getDevice(deviceId);
  68. if (!outputDevice)
  69. return;
  70. outputDevice->unsubscribe(output);
  71. }
  72. // Custom methods
  73. Device* getDevice(int deviceId) {
  74. if (!APP->midiLoopbackContext)
  75. return NULL;
  76. if (!(0 <= deviceId && (size_t) deviceId < NUM_DEVICES))
  77. return NULL;
  78. Context* context = APP->midiLoopbackContext;
  79. return context->devices[deviceId];
  80. }
  81. };
  82. Context::Context() {
  83. for (size_t i = 0; i < NUM_DEVICES; i++) {
  84. Device* device = new Device;
  85. device->id = i;
  86. devices.push_back(device);
  87. }
  88. }
  89. Context::~Context() {
  90. for (Device* device : devices) {
  91. delete device;
  92. }
  93. devices.clear();
  94. }
  95. void init() {
  96. Driver* driver = new Driver;
  97. midi::addDriver(DRIVER_ID, driver);
  98. }
  99. } // namespace midiloopback
  100. } // namespace rack