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.

233 lines
3.8KB

  1. #include <unordered_map>
  2. #include "rack.hpp"
  3. #include "rtmidi/RtMidi.h"
  4. using namespace rack;
  5. struct IgnoreFlags {
  6. bool midiSysex = true;
  7. bool midiTime = true;
  8. bool midiSense = true;
  9. };
  10. struct MidiMessage {
  11. std::vector<unsigned char> bytes;
  12. double timeStamp;
  13. MidiMessage() : bytes(0), timeStamp(0.0) {};
  14. };
  15. /**
  16. * This class allows to use one instance of rtMidiIn with
  17. * multiple modules. A MidiIn port will be opened only once while multiple
  18. * instances can use it simultaniously, each receiving all its incoming messages.
  19. */
  20. struct MidiInWrapper : RtMidiIn {
  21. std::unordered_map<int, std::list<MidiMessage>> idMessagesMap;
  22. std::unordered_map<int, IgnoreFlags> ignoresMap;
  23. int uid_c = 0;
  24. MidiInWrapper() : RtMidiIn() {
  25. idMessagesMap = {};
  26. };
  27. int add() {
  28. int id = ++uid_c;
  29. idMessagesMap[id] = {};
  30. ignoresMap[id] = IgnoreFlags();
  31. return id;
  32. }
  33. void erase(int id) {
  34. idMessagesMap.erase(id);
  35. ignoresMap.erase(id);
  36. }
  37. };
  38. /**
  39. * Note: MidiIO is not thread safe which might become
  40. * important in the future
  41. */
  42. struct MidiIO {
  43. private:
  44. static std::unordered_map<std::string, MidiInWrapper *> midiInMap;
  45. /* TODO: add for midi out*/
  46. int id = -1;
  47. std::string deviceName = "";
  48. bool isOut = false;
  49. public:
  50. int channel;
  51. MidiIO(bool isOut = false);
  52. ~MidiIO() {
  53. close();
  54. }
  55. std::vector<std::string> getDevices();
  56. void openDevice(std::string deviceName);
  57. void setIgnores(bool ignoreSysex = true, bool ignoreTime = true, bool ignoreSense = true);
  58. std::string getDeviceName();
  59. void setChannel(int channel);
  60. double getMessage(std::vector<unsigned char> *msg);
  61. json_t *addBaseJson(json_t *rootJ);
  62. void baseFromJson(json_t *rootJ);
  63. bool isPortOpen();
  64. void close();
  65. /* called when midi port is set */
  66. virtual void resetMidi()=0;
  67. /* called if a user switches or sets the device (and after this device is initialised)*/
  68. virtual void onDeviceChange() {};
  69. };
  70. struct TransitionSmoother {
  71. enum TransitionFunction {
  72. SMOOTHSTEP,
  73. EXP,
  74. LIN,
  75. };
  76. enum TransitionMode {
  77. DELTA,
  78. CONST,
  79. };
  80. float start;
  81. float end;
  82. float x;
  83. float delta;
  84. float step;
  85. TransitionFunction t;
  86. void set(float start, float end, int l = 1500, TransitionFunction t = LIN, TransitionMode m = DELTA, bool reset = true) {
  87. this->start = start;
  88. this->end = end;
  89. this->delta = end - start;
  90. this->t = t;
  91. if (reset || x >= 1) {
  92. this->x = 0;
  93. }
  94. switch (m) {
  95. case DELTA:
  96. /* If the change is smaller, the transition phase is longer */
  97. this->step = delta > 0 ? delta/l : -delta/l;
  98. break;
  99. case CONST:
  100. this->step = 1.0/l;
  101. break;
  102. }
  103. }
  104. float next() {
  105. float next = start;
  106. x += step;
  107. if (x >= 1)
  108. return end;
  109. switch (t) {
  110. case SMOOTHSTEP:
  111. next += delta*x*x*(3-2*x);
  112. break;
  113. case EXP:
  114. next += delta*x*x;
  115. break;
  116. case LIN:
  117. next += delta*x;
  118. break;
  119. }
  120. if ((delta > 0 && next > end) || (delta <= 0 && next < end))
  121. return end;
  122. return next;;
  123. }
  124. };
  125. //////////////////////
  126. // MIDI module widgets
  127. //////////////////////
  128. struct MidiItem : MenuItem {
  129. MidiIO *midiModule;
  130. void onAction(EventAction &e);
  131. };
  132. struct MidiChoice : ChoiceButton {
  133. MidiIO *midiModule;
  134. void onAction(EventAction &e);
  135. void step();
  136. };
  137. struct ChannelItem : MenuItem {
  138. MidiIO *midiModule;
  139. int channel;
  140. void onAction(EventAction &e);
  141. };
  142. struct ChannelChoice : ChoiceButton {
  143. MidiIO *midiModule;
  144. void onAction(EventAction &e);
  145. void step();
  146. };
  147. struct MidiToCVWidget : ModuleWidget {
  148. MidiToCVWidget();
  149. void step();
  150. };
  151. struct MIDICCToCVWidget : ModuleWidget {
  152. MIDICCToCVWidget();
  153. void step();
  154. };
  155. struct MIDIClockToCVWidget : ModuleWidget {
  156. MIDIClockToCVWidget();
  157. void step();
  158. };
  159. struct MIDITriggerToCVWidget : ModuleWidget {
  160. MIDITriggerToCVWidget();
  161. void step();
  162. };
  163. struct QuadMidiToCVWidget : ModuleWidget {
  164. QuadMidiToCVWidget();
  165. void step();
  166. };