From b5b1f2cfec9a0a892d416fd085dcad2dcb9ed7db Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 19 Nov 2016 13:10:57 +0000 Subject: Use MIDI program and CC messages under JACK mode --- distrho/src/DistrhoPluginJack.cpp | 112 ++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/distrho/src/DistrhoPluginJack.cpp b/distrho/src/DistrhoPluginJack.cpp index 8b0b0eba..b5b95488 100644 --- a/distrho/src/DistrhoPluginJack.cpp +++ b/distrho/src/DistrhoPluginJack.cpp @@ -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(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 -- cgit v1.2.3