| @@ -19,24 +19,30 @@ struct Merge : Module { | |||||
| }; | }; | ||||
| dsp::Counter lightCounter; | dsp::Counter lightCounter; | ||||
| int channels; | |||||
| Merge() { | Merge() { | ||||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
| lightCounter.setPeriod(512); | lightCounter.setPeriod(512); | ||||
| onReset(); | |||||
| } | |||||
| void onReset() override { | |||||
| channels = -1; | |||||
| } | } | ||||
| void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
| int lastChannel = -1; | int lastChannel = -1; | ||||
| for (int c = 0; c < 16; c++) { | for (int c = 0; c < 16; c++) { | ||||
| float v = 0.f; | |||||
| if (inputs[MONO_INPUTS + c].isConnected()) { | if (inputs[MONO_INPUTS + c].isConnected()) { | ||||
| lastChannel = c; | lastChannel = c; | ||||
| float v = inputs[MONO_INPUTS + c].getVoltage(); | |||||
| outputs[POLY_OUTPUT].setVoltage(v, c); | |||||
| v = inputs[MONO_INPUTS + c].getVoltage(); | |||||
| } | } | ||||
| outputs[POLY_OUTPUT].setVoltage(v, c); | |||||
| } | } | ||||
| // This also sets higher channels to 0V if the number of channels shrinks. | |||||
| outputs[POLY_OUTPUT].setChannels(lastChannel + 1); | |||||
| outputs[POLY_OUTPUT].setChannels((channels >= 0) ? channels : (lastChannel + 1)); | |||||
| // Set channel lights infrequently | // Set channel lights infrequently | ||||
| if (lightCounter.process()) { | if (lightCounter.process()) { | ||||
| @@ -46,6 +52,47 @@ struct Merge : Module { | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| json_t *dataToJson() override { | |||||
| json_t *rootJ = json_object(); | |||||
| json_object_set_new(rootJ, "channels", json_integer(channels)); | |||||
| return rootJ; | |||||
| } | |||||
| void dataFromJson(json_t *rootJ) override { | |||||
| json_t *channelsJ = json_object_get(rootJ, "channels"); | |||||
| if (channelsJ) | |||||
| channels = json_integer_value(channelsJ); | |||||
| } | |||||
| }; | |||||
| struct MergeChannelItem : MenuItem { | |||||
| Merge *module; | |||||
| int channels; | |||||
| void onAction(const event::Action &e) override { | |||||
| module->channels = channels; | |||||
| } | |||||
| }; | |||||
| struct MergeChannelsItem : MenuItem { | |||||
| Merge *module; | |||||
| Menu *createChildMenu() override { | |||||
| Menu *menu = new Menu; | |||||
| for (int channels = -1; channels <= 16; channels++) { | |||||
| MergeChannelItem *item = new MergeChannelItem; | |||||
| if (channels < 0) | |||||
| item->text = "Automatic"; | |||||
| else | |||||
| item->text = string::f("%d", channels); | |||||
| item->rightText = CHECKMARK(module->channels == channels); | |||||
| item->module = module; | |||||
| item->channels = channels; | |||||
| menu->addChild(item); | |||||
| } | |||||
| return menu; | |||||
| } | |||||
| }; | }; | ||||
| @@ -95,6 +142,18 @@ struct MergeWidget : ModuleWidget { | |||||
| addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 14)); | addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(19.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 14)); | ||||
| addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 15)); | addChild(createLightCentered<TinyLight<BlueLight>>(mm2px(Vec(21.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 15)); | ||||
| } | } | ||||
| void appendContextMenu(Menu *menu) override { | |||||
| Merge *module = dynamic_cast<Merge*>(this->module); | |||||
| menu->addChild(new MenuEntry); | |||||
| MergeChannelsItem *channelsItem = new MergeChannelsItem; | |||||
| channelsItem->text = "Channels"; | |||||
| channelsItem->rightText = RIGHT_ARROW; | |||||
| channelsItem->module = module; | |||||
| menu->addChild(channelsItem); | |||||
| } | |||||
| }; | }; | ||||