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.

230 lines
5.7KB

  1. #include <app/MidiWidget.hpp>
  2. #include <ui/MenuSeparator.hpp>
  3. #include <helpers.hpp>
  4. namespace rack {
  5. namespace app {
  6. struct MidiDriverValueItem : ui::MenuItem {
  7. midi::Port* port;
  8. int driverId;
  9. void onAction(const event::Action& e) override {
  10. port->setDriverId(driverId);
  11. }
  12. };
  13. static void appendMidiDriverMenu(ui::Menu* menu, midi::Port* port) {
  14. if (!port)
  15. return;
  16. for (int driverId : midi::getDriverIds()) {
  17. MidiDriverValueItem* item = new MidiDriverValueItem;
  18. item->port = port;
  19. item->driverId = driverId;
  20. item->text = midi::getDriver(driverId)->getName();
  21. item->rightText = CHECKMARK(item->driverId == port->getDriverId());
  22. menu->addChild(item);
  23. }
  24. }
  25. struct MidiDriverChoice : LedDisplayChoice {
  26. midi::Port* port;
  27. void onAction(const event::Action& e) override {
  28. ui::Menu* menu = createMenu();
  29. menu->addChild(createMenuLabel("MIDI driver"));
  30. appendMidiDriverMenu(menu, port);
  31. }
  32. void step() override {
  33. text = (port && port->driver) ? port->getDriver()->getName() : "";
  34. if (text.empty()) {
  35. text = "(No driver)";
  36. color.a = 0.5f;
  37. }
  38. else {
  39. color.a = 1.f;
  40. }
  41. }
  42. };
  43. struct MidiDriverItem : ui::MenuItem {
  44. midi::Port* port;
  45. ui::Menu* createChildMenu() override {
  46. ui::Menu* menu = new ui::Menu;
  47. appendMidiDriverMenu(menu, port);
  48. return menu;
  49. }
  50. };
  51. struct MidiDeviceValueItem : ui::MenuItem {
  52. midi::Port* port;
  53. int deviceId;
  54. void onAction(const event::Action& e) override {
  55. port->setDeviceId(deviceId);
  56. }
  57. };
  58. static void appendMidiDeviceMenu(ui::Menu* menu, midi::Port* port) {
  59. if (!port)
  60. return;
  61. {
  62. MidiDeviceValueItem* item = new MidiDeviceValueItem;
  63. item->port = port;
  64. item->deviceId = -1;
  65. item->text = "(No device)";
  66. item->rightText = CHECKMARK(item->deviceId == port->getDeviceId());
  67. menu->addChild(item);
  68. }
  69. for (int deviceId : port->getDeviceIds()) {
  70. MidiDeviceValueItem* item = new MidiDeviceValueItem;
  71. item->port = port;
  72. item->deviceId = deviceId;
  73. item->text = port->getDeviceName(deviceId);
  74. item->rightText = CHECKMARK(item->deviceId == port->getDeviceId());
  75. menu->addChild(item);
  76. }
  77. }
  78. struct MidiDeviceChoice : LedDisplayChoice {
  79. midi::Port* port;
  80. void onAction(const event::Action& e) override {
  81. ui::Menu* menu = createMenu();
  82. menu->addChild(createMenuLabel("MIDI device"));
  83. appendMidiDeviceMenu(menu, port);
  84. }
  85. void step() override {
  86. text = (port && port->device) ? port->getDevice()->getName() : "";
  87. if (text.empty()) {
  88. text = "(No device)";
  89. color.a = 0.5f;
  90. }
  91. else {
  92. color.a = 1.f;
  93. }
  94. }
  95. };
  96. struct MidiDeviceItem : ui::MenuItem {
  97. midi::Port* port;
  98. ui::Menu* createChildMenu() override {
  99. ui::Menu* menu = new ui::Menu;
  100. appendMidiDeviceMenu(menu, port);
  101. return menu;
  102. }
  103. };
  104. struct MidiChannelValueItem : ui::MenuItem {
  105. midi::Port* port;
  106. int channel;
  107. void onAction(const event::Action& e) override {
  108. port->setChannel(channel);
  109. }
  110. };
  111. static void appendMidiChannelMenu(ui::Menu* menu, midi::Port* port) {
  112. if (!port)
  113. return;
  114. for (int channel : port->getChannels()) {
  115. MidiChannelValueItem* item = new MidiChannelValueItem;
  116. item->port = port;
  117. item->channel = channel;
  118. item->text = port->getChannelName(channel);
  119. item->rightText = CHECKMARK(item->channel == port->getChannel());
  120. menu->addChild(item);
  121. }
  122. }
  123. struct MidiChannelChoice : LedDisplayChoice {
  124. midi::Port* port;
  125. void onAction(const event::Action& e) override {
  126. ui::Menu* menu = createMenu();
  127. menu->addChild(createMenuLabel("MIDI channel"));
  128. appendMidiChannelMenu(menu, port);
  129. }
  130. void step() override {
  131. text = port ? port->getChannelName(port->getChannel()) : "Channel 1";
  132. }
  133. };
  134. struct MidiChannelItem : ui::MenuItem {
  135. midi::Port* port;
  136. ui::Menu* createChildMenu() override {
  137. ui::Menu* menu = new ui::Menu;
  138. appendMidiChannelMenu(menu, port);
  139. return menu;
  140. }
  141. };
  142. void MidiWidget::setMidiPort(midi::Port* port) {
  143. clearChildren();
  144. math::Vec pos;
  145. MidiDriverChoice* driverChoice = createWidget<MidiDriverChoice>(pos);
  146. driverChoice->box.size.x = box.size.x;
  147. driverChoice->port = port;
  148. addChild(driverChoice);
  149. pos = driverChoice->box.getBottomLeft();
  150. this->driverChoice = driverChoice;
  151. this->driverSeparator = createWidget<LedDisplaySeparator>(pos);
  152. this->driverSeparator->box.size.x = box.size.x;
  153. addChild(this->driverSeparator);
  154. MidiDeviceChoice* deviceChoice = createWidget<MidiDeviceChoice>(pos);
  155. deviceChoice->box.size.x = box.size.x;
  156. deviceChoice->port = port;
  157. addChild(deviceChoice);
  158. pos = deviceChoice->box.getBottomLeft();
  159. this->deviceChoice = deviceChoice;
  160. this->deviceSeparator = createWidget<LedDisplaySeparator>(pos);
  161. this->deviceSeparator->box.size.x = box.size.x;
  162. addChild(this->deviceSeparator);
  163. MidiChannelChoice* channelChoice = createWidget<MidiChannelChoice>(pos);
  164. channelChoice->box.size.x = box.size.x;
  165. channelChoice->port = port;
  166. addChild(channelChoice);
  167. this->channelChoice = channelChoice;
  168. }
  169. void appendMidiMenu(ui::Menu* menu, midi::Port* port) {
  170. menu->addChild(createMenuLabel("MIDI driver"));
  171. appendMidiDriverMenu(menu, port);
  172. menu->addChild(new ui::MenuSeparator);
  173. menu->addChild(createMenuLabel("MIDI device"));
  174. appendMidiDeviceMenu(menu, port);
  175. menu->addChild(new ui::MenuSeparator);
  176. // menu->addChild(createMenuLabel("MIDI channel"));
  177. // appendMidiChannelMenu(menu, port);
  178. // Uncomment this to use sub-menus instead of one big menu.
  179. // MidiDriverItem* driverItem = createMenuItem<MidiDriverItem>("MIDI driver", RIGHT_ARROW);
  180. // driverItem->port = port;
  181. // menu->addChild(driverItem);
  182. // MidiDeviceItem* deviceItem = createMenuItem<MidiDeviceItem>("MIDI device", RIGHT_ARROW);
  183. // deviceItem->port = port;
  184. // menu->addChild(deviceItem);
  185. MidiChannelItem* channelItem = createMenuItem<MidiChannelItem>("MIDI channel", RIGHT_ARROW);
  186. channelItem->port = port;
  187. menu->addChild(channelItem);
  188. }
  189. } // namespace app
  190. } // namespace rack