| @@ -116,9 +116,7 @@ public: | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| fPortMidiIn = jack_port_register(fClient, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| #endif | |||
| fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| if (fPlugin.getProgramCount() > 0) | |||
| @@ -128,11 +126,18 @@ public: | |||
| fUI.programLoaded(0); | |||
| # endif | |||
| } | |||
| # if DISTRHO_PLUGIN_HAS_UI | |||
| fProgramChanged = -1; | |||
| # endif | |||
| #endif | |||
| if (const uint32_t count = fPlugin.getParameterCount()) | |||
| { | |||
| fLastOutputValues = new float[count]; | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| fParametersChanged = new bool[count]; | |||
| std::memset(fParametersChanged, 0, sizeof(bool)*count); | |||
| #endif | |||
| for (uint32_t i=0; i < count; ++i) | |||
| { | |||
| @@ -143,15 +148,16 @@ public: | |||
| else | |||
| { | |||
| fLastOutputValues[i] = 0.0f; | |||
| # if DISTRHO_PLUGIN_HAS_UI | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | |||
| # endif | |||
| #endif | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| fLastOutputValues = nullptr; | |||
| fParametersChanged = nullptr; | |||
| } | |||
| jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | |||
| @@ -192,10 +198,8 @@ public: | |||
| if (fClient == nullptr) | |||
| return; | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| jack_port_unregister(fClient, fPortMidiIn); | |||
| fPortMidiIn = nullptr; | |||
| #endif | |||
| jack_port_unregister(fClient, fPortEventsIn); | |||
| fPortEventsIn = nullptr; | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
| for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||
| @@ -225,20 +229,31 @@ protected: | |||
| if (gCloseSignalReceived) | |||
| return fUI.quit(); | |||
| float value; | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| if (fProgramChanged >= 0) | |||
| { | |||
| fUI.programLoaded(fProgramChanged); | |||
| fProgramChanged = -1; | |||
| } | |||
| # endif | |||
| for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |||
| { | |||
| if (! fPlugin.isParameterOutput(i)) | |||
| continue; | |||
| value = fPlugin.getParameterValue(i); | |||
| if (fPlugin.isParameterOutput(i)) | |||
| { | |||
| const float value = fPlugin.getParameterValue(i); | |||
| if (fLastOutputValues[i] == value) | |||
| continue; | |||
| if (d_isEqual(fLastOutputValues[i], value)) | |||
| continue; | |||
| fLastOutputValues[i] = value; | |||
| fUI.parameterChanged(i, value); | |||
| fLastOutputValues[i] = value; | |||
| fUI.parameterChanged(i, value); | |||
| } | |||
| else if (fParametersChanged[i]) | |||
| { | |||
| fParametersChanged[i] = false; | |||
| fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | |||
| } | |||
| } | |||
| fUI.exec_idle(); | |||
| @@ -310,14 +325,14 @@ protected: | |||
| fPlugin.setTimePosition(fTimePosition); | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| void* const midiBuf = jack_port_get_buffer(fPortMidiIn, nframes); | |||
| void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes); | |||
| if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) | |||
| { | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| uint32_t midiEventCount = 0; | |||
| MidiEvent midiEvents[eventCount]; | |||
| #endif | |||
| jack_midi_event_t jevent; | |||
| for (uint32_t i=0; i < eventCount; ++i) | |||
| @@ -325,6 +340,45 @@ protected: | |||
| if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | |||
| break; | |||
| // Check if message is control change on channel 1 | |||
| if (jevent.buffer[0] == 0xB0 && jevent.size == 3) | |||
| { | |||
| const uint8_t control = jevent.buffer[1]; | |||
| const uint8_t value = jevent.buffer[2]; | |||
| /* NOTE: This is not optimal, we're iterating all parameters on every CC message. | |||
| Since the JACK standalone is more of a test tool, this will do for now. */ | |||
| for (uint32_t j=0, paramCount=fPlugin.getParameterCount(); j < paramCount; ++j) | |||
| { | |||
| if (fPlugin.isParameterOutput(j)) | |||
| continue; | |||
| if (fPlugin.getParameterMidiCC(j) != control) | |||
| continue; | |||
| const float scaled = static_cast<float>(value)/127.0f; | |||
| const float fvalue = fPlugin.getParameterRanges(j).getUnnormalizedValue(scaled); | |||
| fPlugin.setParameterValue(j, fvalue); | |||
| fParametersChanged[j] = true; | |||
| break; | |||
| } | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| // Check if message is program change on channel 1 | |||
| else if (jevent.buffer[0] == 0xC0 && jevent.size == 2) | |||
| { | |||
| const uint8_t program = jevent.buffer[1]; | |||
| if (program < fPlugin.getProgramCount()) | |||
| { | |||
| fPlugin.loadProgram(program); | |||
| # if DISTRHO_PLUGIN_HAS_UI | |||
| fProgramChanged = program; | |||
| # endif | |||
| } | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| MidiEvent& midiEvent(midiEvents[midiEventCount++]); | |||
| midiEvent.frame = jevent.time; | |||
| @@ -334,10 +388,14 @@ protected: | |||
| midiEvent.dataExt = jevent.buffer; | |||
| else | |||
| std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | |||
| #endif | |||
| } | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | |||
| #endif | |||
| } | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| else | |||
| { | |||
| fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | |||
| @@ -393,9 +451,7 @@ private: | |||
| #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
| jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| jack_port_t* fPortMidiIn; | |||
| #endif | |||
| jack_port_t* fPortEventsIn; | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| TimePosition fTimePosition; | |||
| #endif | |||
| @@ -403,6 +459,14 @@ private: | |||
| // Temporary data | |||
| float* fLastOutputValues; | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| // Store DSP changes to send to UI | |||
| bool* fParametersChanged; | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| int fProgramChanged; | |||
| # endif | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Callbacks | |||