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.

250 lines
5.2KB

  1. #include <rack.hpp>
  2. namespace rack {
  3. namespace core {
  4. extern Model* modelAudio2;
  5. extern Model* modelAudio8;
  6. extern Model* modelAudio16;
  7. extern Model* modelMIDI_CV;
  8. extern Model* modelMIDICC_CV;
  9. extern Model* modelMIDI_Gate;
  10. extern Model* modelMIDIMap;
  11. extern Model* modelCV_MIDI;
  12. extern Model* modelCV_MIDICC;
  13. extern Model* modelGate_MIDI;
  14. extern Model* modelBlank;
  15. extern Model* modelNotes;
  16. template <class TChoice>
  17. struct Grid16MidiDisplay : MidiDisplay {
  18. LedDisplaySeparator* hSeparators[4];
  19. LedDisplaySeparator* vSeparators[4];
  20. TChoice* choices[4][4];
  21. template <class TModule>
  22. void setModule(TModule* module) {
  23. Vec pos = channelChoice->box.getBottomLeft();
  24. // Add vSeparators
  25. for (int x = 1; x < 4; x++) {
  26. vSeparators[x] = createWidget<LedDisplaySeparator>(pos);
  27. vSeparators[x]->box.pos.x = box.size.x / 4 * x;
  28. addChild(vSeparators[x]);
  29. }
  30. // Add hSeparators and choice widgets
  31. for (int y = 0; y < 4; y++) {
  32. hSeparators[y] = createWidget<LedDisplaySeparator>(pos);
  33. hSeparators[y]->box.size.x = box.size.x;
  34. addChild(hSeparators[y]);
  35. for (int x = 0; x < 4; x++) {
  36. choices[x][y] = new TChoice;
  37. choices[x][y]->box.pos = pos;
  38. choices[x][y]->setId(4 * y + x);
  39. choices[x][y]->box.size.x = box.size.x / 4;
  40. choices[x][y]->box.pos.x = box.size.x / 4 * x;
  41. choices[x][y]->setModule(module);
  42. addChild(choices[x][y]);
  43. }
  44. pos = choices[0][y]->box.getBottomLeft();
  45. }
  46. for (int x = 1; x < 4; x++) {
  47. vSeparators[x]->box.size.y = pos.y - vSeparators[x]->box.pos.y;
  48. }
  49. }
  50. };
  51. template <class TModule>
  52. struct CcChoice : LedDisplayChoice {
  53. TModule* module;
  54. int id;
  55. int focusCc;
  56. CcChoice() {
  57. box.size.y = mm2px(6.666);
  58. textOffset.y -= 4;
  59. }
  60. void setModule(TModule* module) {
  61. this->module = module;
  62. }
  63. void setId(int id) {
  64. this->id = id;
  65. }
  66. void step() override {
  67. int cc;
  68. if (!module) {
  69. cc = id;
  70. }
  71. else if (module->learningId == id) {
  72. cc = focusCc;
  73. color.a = 0.5;
  74. }
  75. else {
  76. cc = module->learnedCcs[id];
  77. color.a = 1.0;
  78. // Cancel focus if no longer learning
  79. if (APP->event->getSelectedWidget() == this)
  80. APP->event->setSelectedWidget(NULL);
  81. }
  82. // Set text
  83. if (cc < 0)
  84. text = "--";
  85. else
  86. text = string::f("%d", cc);
  87. }
  88. void onSelect(const SelectEvent& e) override {
  89. if (!module)
  90. return;
  91. module->learningId = id;
  92. focusCc = -1;
  93. e.consume(this);
  94. }
  95. void onDeselect(const DeselectEvent& e) override {
  96. if (!module)
  97. return;
  98. if (module->learningId == id) {
  99. if (0 <= focusCc && focusCc < 128) {
  100. module->learnedCcs[id] = focusCc;
  101. }
  102. module->learningId = -1;
  103. }
  104. }
  105. void onSelectText(const SelectTextEvent& e) override {
  106. int c = e.codepoint;
  107. if ('0' <= c && c <= '9') {
  108. if (focusCc < 0)
  109. focusCc = 0;
  110. focusCc = focusCc * 10 + (c - '0');
  111. }
  112. if (focusCc >= 128)
  113. focusCc = -1;
  114. e.consume(this);
  115. }
  116. void onSelectKey(const SelectKeyEvent& e) override {
  117. if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0) {
  118. DeselectEvent eDeselect;
  119. onDeselect(eDeselect);
  120. APP->event->selectedWidget = NULL;
  121. e.consume(this);
  122. }
  123. }
  124. };
  125. template <class TModule>
  126. struct NoteChoice : LedDisplayChoice {
  127. TModule* module;
  128. int id;
  129. int focusNote;
  130. NoteChoice() {
  131. box.size.y = mm2px(6.666);
  132. textOffset.y -= 4;
  133. textOffset.x -= 4;
  134. }
  135. void setId(int id) {
  136. this->id = id;
  137. }
  138. void setModule(TModule* module) {
  139. this->module = module;
  140. }
  141. void step() override {
  142. int note;
  143. if (!module) {
  144. note = id + 36;
  145. }
  146. else if (module->learningId == id) {
  147. note = focusNote;
  148. color.a = 0.5;
  149. }
  150. else {
  151. note = module->learnedNotes[id];
  152. color.a = 1.0;
  153. // Cancel focus if no longer learning
  154. if (APP->event->getSelectedWidget() == this)
  155. APP->event->setSelectedWidget(NULL);
  156. }
  157. // Set text
  158. if (note < 0) {
  159. text = "--";
  160. }
  161. else {
  162. static const char* noteNames[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
  163. int oct = note / 12 - 1;
  164. int semi = note % 12;
  165. text = string::f("%s%d", noteNames[semi], oct);
  166. }
  167. }
  168. void onSelect(const SelectEvent& e) override {
  169. if (!module)
  170. return;
  171. module->learningId = id;
  172. focusNote = -1;
  173. e.consume(this);
  174. }
  175. void onDeselect(const DeselectEvent& e) override {
  176. if (!module)
  177. return;
  178. if (module->learningId == id) {
  179. if (0 <= focusNote && focusNote < 128) {
  180. module->learnedNotes[id] = focusNote;
  181. }
  182. module->learningId = -1;
  183. }
  184. }
  185. void onSelectText(const SelectTextEvent& e) override {
  186. int c = e.codepoint;
  187. if ('a' <= c && c <= 'g') {
  188. static const int majorNotes[7] = {9, 11, 0, 2, 4, 5, 7};
  189. focusNote = majorNotes[c - 'a'];
  190. }
  191. else if (c == '#') {
  192. if (focusNote >= 0) {
  193. focusNote += 1;
  194. }
  195. }
  196. else if ('0' <= c && c <= '9') {
  197. if (focusNote >= 0) {
  198. focusNote = focusNote % 12;
  199. focusNote += 12 * (c - '0' + 1);
  200. }
  201. }
  202. if (focusNote >= 128)
  203. focusNote = -1;
  204. e.consume(this);
  205. }
  206. void onSelectKey(const SelectKeyEvent& e) override {
  207. if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0) {
  208. DeselectEvent eDeselect;
  209. onDeselect(eDeselect);
  210. APP->event->selectedWidget = NULL;
  211. e.consume(this);
  212. }
  213. }
  214. };
  215. } // namespace core
  216. } // namespace rack