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.

161 lines
6.5KB

  1. #include "plugin.hpp"
  2. struct Merge : Module {
  3. enum ParamIds {
  4. NUM_PARAMS
  5. };
  6. enum InputIds {
  7. ENUMS(MONO_INPUTS, 16),
  8. NUM_INPUTS
  9. };
  10. enum OutputIds {
  11. POLY_OUTPUT,
  12. NUM_OUTPUTS
  13. };
  14. enum LightIds {
  15. ENUMS(CHANNEL_LIGHTS, 16),
  16. NUM_LIGHTS
  17. };
  18. dsp::ClockDivider lightDivider;
  19. int channels;
  20. Merge() {
  21. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  22. lightDivider.setDivision(512);
  23. onReset();
  24. }
  25. void onReset() override {
  26. channels = -1;
  27. }
  28. void process(const ProcessArgs &args) override {
  29. int lastChannel = -1;
  30. for (int c = 0; c < 16; c++) {
  31. float v = 0.f;
  32. if (inputs[MONO_INPUTS + c].isConnected()) {
  33. lastChannel = c;
  34. v = inputs[MONO_INPUTS + c].getVoltage();
  35. }
  36. outputs[POLY_OUTPUT].setVoltage(v, c);
  37. }
  38. outputs[POLY_OUTPUT].setChannels((channels >= 0) ? channels : (lastChannel + 1));
  39. // Set channel lights infrequently
  40. if (lightDivider.process()) {
  41. for (int c = 0; c < 16; c++) {
  42. bool active = (c < outputs[POLY_OUTPUT].getChannels());
  43. lights[CHANNEL_LIGHTS + c].setBrightness(active);
  44. }
  45. }
  46. }
  47. json_t *dataToJson() override {
  48. json_t *rootJ = json_object();
  49. json_object_set_new(rootJ, "channels", json_integer(channels));
  50. return rootJ;
  51. }
  52. void dataFromJson(json_t *rootJ) override {
  53. json_t *channelsJ = json_object_get(rootJ, "channels");
  54. if (channelsJ)
  55. channels = json_integer_value(channelsJ);
  56. }
  57. };
  58. struct MergeChannelItem : MenuItem {
  59. Merge *module;
  60. int channels;
  61. void onAction(const ActionEvent &e) override {
  62. module->channels = channels;
  63. }
  64. };
  65. struct MergeChannelsItem : MenuItem {
  66. Merge *module;
  67. Menu *createChildMenu() override {
  68. Menu *menu = new Menu;
  69. for (int channels = -1; channels <= 16; channels++) {
  70. MergeChannelItem *item = new MergeChannelItem;
  71. if (channels < 0)
  72. item->text = "Automatic";
  73. else
  74. item->text = string::f("%d", channels);
  75. item->rightText = CHECKMARK(module->channels == channels);
  76. item->module = module;
  77. item->channels = channels;
  78. menu->addChild(item);
  79. }
  80. return menu;
  81. }
  82. };
  83. struct MergeWidget : ModuleWidget {
  84. MergeWidget(Merge *module) {
  85. setModule(module);
  86. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Merge.svg")));
  87. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  88. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  89. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  90. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  91. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.771, 37.02)), module, Merge::MONO_INPUTS + 0));
  92. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.771, 48.02)), module, Merge::MONO_INPUTS + 1));
  93. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.77, 59.02)), module, Merge::MONO_INPUTS + 2));
  94. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.77, 70.02)), module, Merge::MONO_INPUTS + 3));
  95. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.77, 81.02)), module, Merge::MONO_INPUTS + 4));
  96. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.77, 92.02)), module, Merge::MONO_INPUTS + 5));
  97. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.771, 103.02)), module, Merge::MONO_INPUTS + 6));
  98. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.771, 114.02)), module, Merge::MONO_INPUTS + 7));
  99. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.275, 37.02)), module, Merge::MONO_INPUTS + 8));
  100. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.275, 48.02)), module, Merge::MONO_INPUTS + 9));
  101. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.274, 59.02)), module, Merge::MONO_INPUTS + 10));
  102. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.274, 70.02)), module, Merge::MONO_INPUTS + 11));
  103. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.274, 81.02)), module, Merge::MONO_INPUTS + 12));
  104. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.274, 92.02)), module, Merge::MONO_INPUTS + 13));
  105. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.275, 103.02)), module, Merge::MONO_INPUTS + 14));
  106. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.275, 114.02)), module, Merge::MONO_INPUTS + 15));
  107. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(6.77, 21.347)), module, Merge::POLY_OUTPUT));
  108. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(15.276, 17.775)), module, Merge::CHANNEL_LIGHTS + 0));
  109. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(17.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 1));
  110. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 2));
  111. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 3));
  112. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(15.276, 19.775)), module, Merge::CHANNEL_LIGHTS + 4));
  113. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(17.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 5));
  114. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 6));
  115. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 7));
  116. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(15.276, 21.775)), module, Merge::CHANNEL_LIGHTS + 8));
  117. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(17.275, 21.775)), module, Merge::CHANNEL_LIGHTS + 9));
  118. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 21.775)), module, Merge::CHANNEL_LIGHTS + 10));
  119. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.276, 21.775)), module, Merge::CHANNEL_LIGHTS + 11));
  120. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(15.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 12));
  121. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(17.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 13));
  122. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 14));
  123. addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 15));
  124. }
  125. void appendContextMenu(Menu *menu) override {
  126. Merge *module = dynamic_cast<Merge*>(this->module);
  127. menu->addChild(new MenuEntry);
  128. MergeChannelsItem *channelsItem = new MergeChannelsItem;
  129. channelsItem->text = "Channels";
  130. channelsItem->rightText = RIGHT_ARROW;
  131. channelsItem->module = module;
  132. menu->addChild(channelsItem);
  133. }
  134. };
  135. Model *modelMerge = createModel<Merge, MergeWidget>("Merge");