| @@ -116,9 +116,7 @@ public: | |||||
| } | } | ||||
| #endif | #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 DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
| if (fPlugin.getProgramCount() > 0) | if (fPlugin.getProgramCount() > 0) | ||||
| @@ -128,11 +126,18 @@ public: | |||||
| fUI.programLoaded(0); | fUI.programLoaded(0); | ||||
| # endif | # endif | ||||
| } | } | ||||
| # if DISTRHO_PLUGIN_HAS_UI | |||||
| fProgramChanged = -1; | |||||
| # endif | |||||
| #endif | #endif | ||||
| if (const uint32_t count = fPlugin.getParameterCount()) | if (const uint32_t count = fPlugin.getParameterCount()) | ||||
| { | { | ||||
| fLastOutputValues = new float[count]; | 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) | for (uint32_t i=0; i < count; ++i) | ||||
| { | { | ||||
| @@ -143,15 +148,16 @@ public: | |||||
| else | else | ||||
| { | { | ||||
| fLastOutputValues[i] = 0.0f; | fLastOutputValues[i] = 0.0f; | ||||
| # if DISTRHO_PLUGIN_HAS_UI | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | fUI.parameterChanged(i, fPlugin.getParameterValue(i)); | ||||
| # endif | |||||
| #endif | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| fLastOutputValues = nullptr; | fLastOutputValues = nullptr; | ||||
| fParametersChanged = nullptr; | |||||
| } | } | ||||
| jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); | ||||
| @@ -192,10 +198,8 @@ public: | |||||
| if (fClient == nullptr) | if (fClient == nullptr) | ||||
| return; | 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 | #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | ||||
| for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | ||||
| @@ -225,20 +229,31 @@ protected: | |||||
| if (gCloseSignalReceived) | if (gCloseSignalReceived) | ||||
| return fUI.quit(); | 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) | 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(); | fUI.exec_idle(); | ||||
| @@ -310,14 +325,14 @@ protected: | |||||
| fPlugin.setTimePosition(fTimePosition); | fPlugin.setTimePosition(fTimePosition); | ||||
| #endif | #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 (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) | ||||
| { | { | ||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| uint32_t midiEventCount = 0; | uint32_t midiEventCount = 0; | ||||
| MidiEvent midiEvents[eventCount]; | MidiEvent midiEvents[eventCount]; | ||||
| #endif | |||||
| jack_midi_event_t jevent; | jack_midi_event_t jevent; | ||||
| for (uint32_t i=0; i < eventCount; ++i) | for (uint32_t i=0; i < eventCount; ++i) | ||||
| @@ -325,6 +340,45 @@ protected: | |||||
| if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | if (jack_midi_event_get(&jevent, midiBuf, i) != 0) | ||||
| break; | 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& midiEvent(midiEvents[midiEventCount++]); | ||||
| midiEvent.frame = jevent.time; | midiEvent.frame = jevent.time; | ||||
| @@ -334,10 +388,14 @@ protected: | |||||
| midiEvent.dataExt = jevent.buffer; | midiEvent.dataExt = jevent.buffer; | ||||
| else | else | ||||
| std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); | ||||
| #endif | |||||
| } | } | ||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); | ||||
| #endif | |||||
| } | } | ||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| else | else | ||||
| { | { | ||||
| fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); | ||||
| @@ -393,9 +451,7 @@ private: | |||||
| #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | ||||
| jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | ||||
| #endif | #endif | ||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| jack_port_t* fPortMidiIn; | |||||
| #endif | |||||
| jack_port_t* fPortEventsIn; | |||||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | #if DISTRHO_PLUGIN_WANT_TIMEPOS | ||||
| TimePosition fTimePosition; | TimePosition fTimePosition; | ||||
| #endif | #endif | ||||
| @@ -403,6 +459,14 @@ private: | |||||
| // Temporary data | // Temporary data | ||||
| float* fLastOutputValues; | 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 | // Callbacks | ||||