| @@ -37,10 +37,10 @@ struct OpenItem : MenuItem { | |||||
| struct FileChoice : ChoiceButton { | struct FileChoice : ChoiceButton { | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
| { | { | ||||
| MenuItem *newItem = new NewItem(); | MenuItem *newItem = new NewItem(); | ||||
| newItem->text = "New"; | newItem->text = "New"; | ||||
| @@ -58,8 +58,6 @@ struct FileChoice : ChoiceButton { | |||||
| saveAsItem->text = "Save As"; | saveAsItem->text = "Save As"; | ||||
| menu->pushChild(saveAsItem); | menu->pushChild(saveAsItem); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -73,8 +71,7 @@ struct SampleRateItem : MenuItem { | |||||
| struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
| @@ -86,9 +83,6 @@ struct SampleRateChoice : ChoiceButton { | |||||
| item->sampleRate = sampleRates[i]; | item->sampleRate = sampleRates[i]; | ||||
| menu->pushChild(item); | menu->pushChild(item); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | } | ||||
| void step() { | void step() { | ||||
| text = stringf("%.0f Hz", gSampleRate); | text = stringf("%.0f Hz", gSampleRate); | ||||
| @@ -116,7 +110,6 @@ Toolbar::Toolbar() { | |||||
| SampleRateChoice *srChoice = new SampleRateChoice(); | SampleRateChoice *srChoice = new SampleRateChoice(); | ||||
| srChoice->box.pos = Vec(xPos, margin); | srChoice->box.pos = Vec(xPos, margin); | ||||
| srChoice->box.size.x = 100; | srChoice->box.size.x = 100; | ||||
| srChoice->text = ""; | |||||
| addChild(srChoice); | addChild(srChoice); | ||||
| xPos += srChoice->box.size.x; | xPos += srChoice->box.size.x; | ||||
| } | } | ||||
| @@ -300,9 +300,9 @@ struct AudioItem : MenuItem { | |||||
| struct AudioChoice : ChoiceButton { | struct AudioChoice : ChoiceButton { | ||||
| AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | |||||
| int deviceCount = audioInterface->getDeviceCount(); | int deviceCount = audioInterface->getDeviceCount(); | ||||
| { | { | ||||
| @@ -319,8 +319,6 @@ struct AudioChoice : ChoiceButton { | |||||
| audioItem->text = audioInterface->getDeviceName(deviceId); | audioItem->text = audioInterface->getDeviceName(deviceId); | ||||
| menu->pushChild(audioItem); | menu->pushChild(audioItem); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | } | ||||
| void step() { | void step() { | ||||
| std::string name = audioInterface->getDeviceName(audioInterface->deviceId); | std::string name = audioInterface->getDeviceName(audioInterface->deviceId); | ||||
| @@ -340,9 +338,9 @@ struct SampleRateItem : MenuItem { | |||||
| struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
| AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | |||||
| const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; | const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; | ||||
| int sampleRatesLen = sizeof(sampleRates) / sizeof(sampleRates[0]); | int sampleRatesLen = sizeof(sampleRates) / sizeof(sampleRates[0]); | ||||
| @@ -353,9 +351,6 @@ struct SampleRateChoice : ChoiceButton { | |||||
| item->text = stringf("%.0f Hz", sampleRates[i]); | item->text = stringf("%.0f Hz", sampleRates[i]); | ||||
| menu->pushChild(item); | menu->pushChild(item); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | } | ||||
| void step() { | void step() { | ||||
| this->text = stringf("%.0f Hz", audioInterface->sampleRate); | this->text = stringf("%.0f Hz", audioInterface->sampleRate); | ||||
| @@ -374,9 +369,9 @@ struct BlockSizeItem : MenuItem { | |||||
| struct BlockSizeChoice : ChoiceButton { | struct BlockSizeChoice : ChoiceButton { | ||||
| AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | |||||
| const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096}; | const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096}; | ||||
| int blockSizesLen = sizeof(blockSizes) / sizeof(blockSizes[0]); | int blockSizesLen = sizeof(blockSizes) / sizeof(blockSizes[0]); | ||||
| @@ -387,9 +382,6 @@ struct BlockSizeChoice : ChoiceButton { | |||||
| item->text = stringf("%d", blockSizes[i]); | item->text = stringf("%d", blockSizes[i]); | ||||
| menu->pushChild(item); | menu->pushChild(item); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | } | ||||
| void step() { | void step() { | ||||
| this->text = stringf("%d", audioInterface->blockSize); | this->text = stringf("%d", audioInterface->blockSize); | ||||
| @@ -423,7 +415,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||||
| AudioChoice *choice = new AudioChoice(); | AudioChoice *choice = new AudioChoice(); | ||||
| choice->audioInterface = dynamic_cast<AudioInterface*>(module); | choice->audioInterface = dynamic_cast<AudioInterface*>(module); | ||||
| choice->box.pos = Vec(margin, yPos); | choice->box.pos = Vec(margin, yPos); | ||||
| choice->box.size.x = box.size.x - 10; | |||||
| choice->box.size.x = box.size.x - 2*margin; | |||||
| addChild(choice); | addChild(choice); | ||||
| yPos += choice->box.size.y + margin; | yPos += choice->box.size.y + margin; | ||||
| } | } | ||||
| @@ -438,7 +430,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||||
| SampleRateChoice *choice = new SampleRateChoice(); | SampleRateChoice *choice = new SampleRateChoice(); | ||||
| choice->audioInterface = dynamic_cast<AudioInterface*>(module); | choice->audioInterface = dynamic_cast<AudioInterface*>(module); | ||||
| choice->box.pos = Vec(margin, yPos); | choice->box.pos = Vec(margin, yPos); | ||||
| choice->box.size.x = box.size.x - 10; | |||||
| choice->box.size.x = box.size.x - 2*margin; | |||||
| addChild(choice); | addChild(choice); | ||||
| yPos += choice->box.size.y + margin; | yPos += choice->box.size.y + margin; | ||||
| } | } | ||||
| @@ -453,7 +445,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||||
| BlockSizeChoice *choice = new BlockSizeChoice(); | BlockSizeChoice *choice = new BlockSizeChoice(); | ||||
| choice->audioInterface = dynamic_cast<AudioInterface*>(module); | choice->audioInterface = dynamic_cast<AudioInterface*>(module); | ||||
| choice->box.pos = Vec(margin, yPos); | choice->box.pos = Vec(margin, yPos); | ||||
| choice->box.size.x = box.size.x - 10; | |||||
| choice->box.size.x = box.size.x - 2*margin; | |||||
| addChild(choice); | addChild(choice); | ||||
| yPos += choice->box.size.y + margin; | yPos += choice->box.size.y + margin; | ||||
| } | } | ||||
| @@ -30,15 +30,23 @@ struct MidiInterface : Module { | |||||
| NUM_INPUTS | NUM_INPUTS | ||||
| }; | }; | ||||
| enum OutputIds { | enum OutputIds { | ||||
| GATE_OUTPUT, | |||||
| PITCH_OUTPUT, | PITCH_OUTPUT, | ||||
| GATE_OUTPUT, | |||||
| MOD_OUTPUT, | |||||
| PITCHWHEEL_OUTPUT, | |||||
| NUM_OUTPUTS | NUM_OUTPUTS | ||||
| }; | }; | ||||
| int portId = -1; | |||||
| PortMidiStream *stream = NULL; | PortMidiStream *stream = NULL; | ||||
| std::list<int> notes; | std::list<int> notes; | ||||
| /** Filter MIDI channel | |||||
| -1 means all MIDI channels | |||||
| */ | |||||
| int channel = -1; | |||||
| bool pedal = false; | bool pedal = false; | ||||
| int note = 60; // C4, most modules should use 261.626 Hz | int note = 60; // C4, most modules should use 261.626 Hz | ||||
| int mod = 0; | |||||
| int pitchWheel = 64; | int pitchWheel = 64; | ||||
| bool retrigger = false; | bool retrigger = false; | ||||
| bool retriggered = false; | bool retriggered = false; | ||||
| @@ -62,6 +70,8 @@ MidiInterface::MidiInterface() { | |||||
| inputs.resize(NUM_INPUTS); | inputs.resize(NUM_INPUTS); | ||||
| outputs.resize(NUM_OUTPUTS); | outputs.resize(NUM_OUTPUTS); | ||||
| midiInit(); | midiInit(); | ||||
| printf("<<<%d>>>\n", getPortCount()); | |||||
| } | } | ||||
| MidiInterface::~MidiInterface() { | MidiInterface::~MidiInterface() { | ||||
| @@ -77,6 +87,9 @@ void MidiInterface::step() { | |||||
| } | } | ||||
| } | } | ||||
| if (outputs[PITCH_OUTPUT]) { | |||||
| *outputs[PITCH_OUTPUT] = ((note - 64)) / 12.0; | |||||
| } | |||||
| if (outputs[GATE_OUTPUT]) { | if (outputs[GATE_OUTPUT]) { | ||||
| bool gate = pedal || !notes.empty(); | bool gate = pedal || !notes.empty(); | ||||
| if (retrigger && retriggered) { | if (retrigger && retriggered) { | ||||
| @@ -85,8 +98,11 @@ void MidiInterface::step() { | |||||
| } | } | ||||
| *outputs[GATE_OUTPUT] = gate ? 5.0 : 0.0; | *outputs[GATE_OUTPUT] = gate ? 5.0 : 0.0; | ||||
| } | } | ||||
| if (outputs[PITCH_OUTPUT]) { | |||||
| *outputs[PITCH_OUTPUT] = ((note - 64) + 2.0*(pitchWheel - 64) / 64.0) / 12.0; | |||||
| if (outputs[MOD_OUTPUT]) { | |||||
| *outputs[MOD_OUTPUT] = mod; | |||||
| } | |||||
| if (outputs[PITCHWHEEL_OUTPUT]) { | |||||
| *outputs[PITCHWHEEL_OUTPUT] = (pitchWheel - 64) / 64.0 / 12.0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -121,6 +137,7 @@ void MidiInterface::openPort(int portId) { | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| this->portId = portId; | |||||
| } | } | ||||
| void MidiInterface::pressNote(int note) { | void MidiInterface::pressNote(int note) { | ||||
| @@ -202,9 +219,9 @@ struct MidiItem : MenuItem { | |||||
| struct MidiChoice : ChoiceButton { | struct MidiChoice : ChoiceButton { | ||||
| MidiInterface *midiInterface; | MidiInterface *midiInterface; | ||||
| void onAction() { | void onAction() { | ||||
| MenuOverlay *overlay = new MenuOverlay(); | |||||
| Menu *menu = new Menu(); | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
| menu->box.size.x = box.size.x; | |||||
| int portCount = midiInterface->getPortCount(); | int portCount = midiInterface->getPortCount(); | ||||
| { | { | ||||
| @@ -221,8 +238,45 @@ struct MidiChoice : ChoiceButton { | |||||
| midiItem->text = midiInterface->getPortName(portId); | midiItem->text = midiInterface->getPortName(portId); | ||||
| menu->pushChild(midiItem); | menu->pushChild(midiItem); | ||||
| } | } | ||||
| overlay->addChild(menu); | |||||
| gScene->setOverlay(overlay); | |||||
| } | |||||
| void step() { | |||||
| std::string name = midiInterface->getPortName(midiInterface->portId); | |||||
| text = name.empty() ? "(no device)" : ellipsize(name, 14); | |||||
| } | |||||
| }; | |||||
| struct ChannelItem : MenuItem { | |||||
| MidiInterface *midiInterface; | |||||
| int channel; | |||||
| void onAction() { | |||||
| midiInterface->channel = channel; | |||||
| } | |||||
| }; | |||||
| struct ChannelChoice : ChoiceButton { | |||||
| MidiInterface *midiInterface; | |||||
| void onAction() { | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | |||||
| menu->box.size.x = box.size.x; | |||||
| { | |||||
| ChannelItem *channelItem = new ChannelItem(); | |||||
| channelItem->midiInterface = midiInterface; | |||||
| channelItem->channel = -1; | |||||
| channelItem->text = "All"; | |||||
| menu->pushChild(channelItem); | |||||
| } | |||||
| for (int channel = 0; channel < 16; channel++) { | |||||
| ChannelItem *channelItem = new ChannelItem(); | |||||
| channelItem->midiInterface = midiInterface; | |||||
| channelItem->channel = channel; | |||||
| channelItem->text = stringf("%d", channel + 1); | |||||
| menu->pushChild(channelItem); | |||||
| } | |||||
| } | |||||
| void step() { | |||||
| text = (midiInterface->channel >= 0) ? stringf("%d", midiInterface->channel + 1) : "All"; | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -239,42 +293,52 @@ MidiInterfaceWidget::MidiInterfaceWidget() { | |||||
| } | } | ||||
| float margin = 5; | float margin = 5; | ||||
| float labelHeight = 15; | |||||
| float yPos = margin; | float yPos = margin; | ||||
| { | { | ||||
| Label *label = new Label(); | Label *label = new Label(); | ||||
| label->box.pos = Vec(margin, yPos); | label->box.pos = Vec(margin, yPos); | ||||
| label->text = "MIDI Interface"; | |||||
| label->text = "MIDI device"; | |||||
| addChild(label); | addChild(label); | ||||
| yPos += label->box.size.y + margin; | |||||
| } | |||||
| yPos += labelHeight + margin; | |||||
| { | |||||
| MidiChoice *midiChoice = new MidiChoice(); | MidiChoice *midiChoice = new MidiChoice(); | ||||
| midiChoice->midiInterface = dynamic_cast<MidiInterface*>(module); | midiChoice->midiInterface = dynamic_cast<MidiInterface*>(module); | ||||
| midiChoice->text = "MIDI device"; | |||||
| midiChoice->box.pos = Vec(margin, yPos); | midiChoice->box.pos = Vec(margin, yPos); | ||||
| midiChoice->box.size.x = box.size.x - 10; | midiChoice->box.size.x = box.size.x - 10; | ||||
| addChild(midiChoice); | addChild(midiChoice); | ||||
| yPos += midiChoice->box.size.y + margin; | yPos += midiChoice->box.size.y + margin; | ||||
| } | } | ||||
| { | |||||
| Label *label = new Label(); | |||||
| label->box.pos = Vec(margin, yPos); | |||||
| label->text = "MIDI channel"; | |||||
| addChild(label); | |||||
| yPos += labelHeight + margin; | |||||
| ChannelChoice *channelChoice = new ChannelChoice(); | |||||
| channelChoice->midiInterface = dynamic_cast<MidiInterface*>(module); | |||||
| channelChoice->box.pos = Vec(margin, yPos); | |||||
| channelChoice->box.size.x = box.size.x - 10; | |||||
| addChild(channelChoice); | |||||
| yPos += channelChoice->box.size.y + margin; | |||||
| } | |||||
| yPos += 5; | yPos += 5; | ||||
| addOutput(createOutput<PJ3410Port>(Vec(20, yPos), module, MidiInterface::PITCH_OUTPUT)); | addOutput(createOutput<PJ3410Port>(Vec(20, yPos), module, MidiInterface::PITCH_OUTPUT)); | ||||
| addOutput(createOutput<PJ3410Port>(Vec(70, yPos), module, MidiInterface::GATE_OUTPUT)); | |||||
| yPos += 25 + margin; | |||||
| yPos += 37 + margin; | |||||
| { | |||||
| Label *pitchLabel = new Label(); | |||||
| pitchLabel->box.pos = Vec(25-12, yPos); | |||||
| pitchLabel->text = "Pitch"; | |||||
| addChild(pitchLabel); | |||||
| yPos += 5; | |||||
| addOutput(createOutput<PJ3410Port>(Vec(20, yPos), module, MidiInterface::GATE_OUTPUT)); | |||||
| yPos += 37 + margin; | |||||
| Label *gateLabel = new Label(); | |||||
| gateLabel->box.pos = Vec(75-12, yPos); | |||||
| gateLabel->text = "Gate"; | |||||
| addChild(gateLabel); | |||||
| yPos += 5; | |||||
| addOutput(createOutput<PJ3410Port>(Vec(20, yPos), module, MidiInterface::MOD_OUTPUT)); | |||||
| yPos += 37 + margin; | |||||
| yPos += pitchLabel->box.size.y + margin; | |||||
| } | |||||
| yPos += 5; | |||||
| addOutput(createOutput<PJ3410Port>(Vec(20, yPos), module, MidiInterface::PITCHWHEEL_OUTPUT)); | |||||
| yPos += 37 + margin; | |||||
| } | } | ||||