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.

249 lines
5.2KB

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