DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit e2e2b5507f683a6b62adbd984b62cdde0ed05c3d
parent 7403ec875198b47894cedb5d8545588907c86280
Author: falkTX <falktx@falktx.com>
Date:   Mon, 11 Jul 2022 14:16:02 +0100

Introduce ways for standalones to request audio input and midi

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Adistrho/DistrhoStandaloneUtils.hpp | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdistrho/src/jackbridge/JackBridge.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mdistrho/src/jackbridge/NativeBridge.hpp | 23+++++++++++++++++++++++
Mdistrho/src/jackbridge/WebBridge.hpp | 59+++++++++++++++++++++++++++++++++++++++++++++++------------
4 files changed, 211 insertions(+), 13 deletions(-)

diff --git a/distrho/DistrhoStandaloneUtils.hpp b/distrho/DistrhoStandaloneUtils.hpp @@ -0,0 +1,71 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_STANDALONE_UTILS_HPP_INCLUDED +#define DISTRHO_STANDALONE_UTILS_HPP_INCLUDED + +#include "src/DistrhoDefines.h" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Standalone plugin related utilities */ + +/** + @defgroup PluginRelatedUtilities Plugin related utilities + + @{ + */ + +/** + Check if the current standalone supports audio input. +*/ +bool supportsAudioInput(); + +/** + Check if the current standalone supports MIDI. +*/ +bool supportsMIDI(); + +/** + Check if the current standalone has audio input enabled. +*/ +bool isAudioInputEnabled(); + +/** + Check if the current standalone has MIDI enabled. +*/ +bool isMIDIEnabled(); + +/** + Request permissions to use audio input. + Only valid to call if audio input is supported but not currently enabled. +*/ +bool requestAudioInput(); + +/** + Request permissions to use MIDI. + Only valid to call if MIDI is supported but not currently enabled. +*/ +bool requestMIDI(); + +/** @} */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_STANDALONE_UTILS_HPP_INCLUDED diff --git a/distrho/src/jackbridge/JackBridge.cpp b/distrho/src/jackbridge/JackBridge.cpp @@ -15,6 +15,7 @@ */ #include "JackBridge.hpp" +#include "../../DistrhoStandaloneUtils.hpp" #if ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY)) @@ -42,7 +43,7 @@ # include "WebBridge.hpp" #endif -#if defined(HAVE_RTAUDIO) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 +#if defined(HAVE_RTAUDIO) && defined(DISTRHO_PROPER_CPP11_SUPPORT) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 # include "RtAudioBridge.hpp" # ifdef RTAUDIO_API_TYPE # include "rtaudio/RtAudio.cpp" @@ -2242,3 +2243,71 @@ bool jackbridge_set_property_change_callback(jack_client_t* client, JackProperty } // ----------------------------------------------------------------------------- + +START_NAMESPACE_DISTRHO + +bool supportsAudioInput() +{ +#if defined(JACKBRIDGE_DUMMY) + return false; +#elif !defined(JACKBRIDGE_DIRECT) + if (usingNativeBridge) + return nativeBridge->supportsAudioInput(); +#endif + return true; +} + +bool supportsMIDI() +{ +#if defined(JACKBRIDGE_DUMMY) + return false; +#elif !defined(JACKBRIDGE_DIRECT) + if (usingNativeBridge) + return nativeBridge->supportsMIDI(); +#endif + return true; +} + +bool isAudioInputEnabled() +{ +#if defined(JACKBRIDGE_DUMMY) + return false; +#elif !defined(JACKBRIDGE_DIRECT) + if (usingNativeBridge) + return nativeBridge->isAudioInputEnabled(); +#endif + return true; +} + +bool isMIDIEnabled() +{ +#if defined(JACKBRIDGE_DUMMY) + return false; +#elif !defined(JACKBRIDGE_DIRECT) + if (usingNativeBridge) + return nativeBridge->isMIDIEnabled(); +#endif + return true; +} + +bool requestAudioInput() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->requestAudioInput(); +#endif + return false; +} + +bool requestMIDI() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->requestMIDI(); +#endif + return false; +} + +END_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------------- diff --git a/distrho/src/jackbridge/NativeBridge.hpp b/distrho/src/jackbridge/NativeBridge.hpp @@ -67,6 +67,29 @@ struct NativeBridge { virtual bool activate() = 0; virtual bool deactivate() = 0; + virtual bool supportsAudioInput() const + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return true; + #else + return false; + #endif + } + + virtual bool isAudioInputEnabled() const + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return true; + #else + return false; + #endif + } + + virtual bool supportsMIDI() const { return false; } + virtual bool isMIDIEnabled() const { return false; } + virtual bool requestAudioInput() { return false; } + virtual bool requestMIDI() { return false; } + uint32_t getEventCount() { #if DISTRHO_PLUGIN_WANT_MIDI_INPUT diff --git a/distrho/src/jackbridge/WebBridge.hpp b/distrho/src/jackbridge/WebBridge.hpp @@ -131,7 +131,7 @@ struct WebBridge : NativeBridge { // main processor WAB.processor = WAB.audioContext['createScriptProcessor'](bufferSize, numInputs, numOutputs); WAB.processor['onaudioprocess'] = function (e) { - var timestamp = performance.now(); + // var timestamp = performance.now(); for (var i = 0; i < numInputs; ++i) { var buffer = e['inputBuffer']['getChannelData'](i); for (var j = 0; j < bufferSize; ++j) { @@ -139,7 +139,7 @@ struct WebBridge : NativeBridge { HEAPF32[$3 + (((bufferSize * i) + j) << 2) >> 2] = buffer[j]; } } - dynCall('vif', $4, [$5, timestamp]); + dynCall('vi', $4, [$5]); for (var i = 0; i < numOutputs; ++i) { var buffer = e['outputBuffer']['getChannelData'](i); var offset = bufferSize * (numInputs + i); @@ -161,9 +161,6 @@ struct WebBridge : NativeBridge { }); }, DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS, bufferSize, audioBufferStorage, WebAudioCallback, this); -// enableInput(); - enableMIDI(); - return true; } @@ -185,7 +182,25 @@ struct WebBridge : NativeBridge { return true; } - bool enableInput() + bool supportsAudioInput() const override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return captureAvailable; + #else + return false; + #endif + } + + bool isAudioInputEnabled() const override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return EM_ASM_INT({ return Module['WebAudioBridge'].captureStreamNode ? 1 : 0 }) != 0; + #else + return false; + #endif + } + + bool requestAudioInput() override { DISTRHO_SAFE_ASSERT_RETURN(DISTRHO_PLUGIN_NUM_INPUTS > 0, false); @@ -224,7 +239,25 @@ struct WebBridge : NativeBridge { return true; } - bool enableMIDI() + bool supportsMIDI() const override + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + return midiAvailable; + #else + return false; + #endif + } + + bool isMIDIEnabled() const override + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + return EM_ASM_INT({ return Module['WebAudioBridge'].midi ? 1 : 0 }) != 0; + #else + return false; + #endif + } + + bool requestMIDI() override { #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT if (midiAvailable) @@ -287,10 +320,10 @@ struct WebBridge : NativeBridge { } } - static void WebAudioCallback(void* const userData, const double timestamp) + static void WebAudioCallback(void* const userData /* , const double timestamp */) { WebBridge* const self = static_cast<WebBridge*>(userData); - self->timestamp = timestamp; + // self->timestamp = timestamp; const uint numFrames = self->bufferSize; @@ -299,11 +332,12 @@ struct WebBridge : NativeBridge { self->jackProcessCallback(numFrames, self->jackProcessArg); #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT - if (self->midiAvailable) + if (self->midiAvailable && self->midiOutBuffer.isDataAvailableForReading()) { static_assert(kMaxMIDIInputMessageSize + 1u == 4, "change code if bumping this value"); uint32_t offset = 0; uint8_t bytes[4] = {}; + double timestamp = EM_ASM_DOUBLE({ return performance.now(); }); while (self->midiOutBuffer.isDataAvailableForReading() && self->midiOutBuffer.readCustomData(bytes, ARRAY_SIZE(bytes))) @@ -313,7 +347,7 @@ struct WebBridge : NativeBridge { EM_ASM({ var WAB = Module['WebAudioBridge']; if (WAB.midi) { - var timestamp = performance.now() + $0; + var timestamp = $5 + $0; var size = $1; WAB.midi.outputs.forEach(function(port) { if (port.state !== 'disconnected') { @@ -323,8 +357,9 @@ struct WebBridge : NativeBridge { } }); } - }, offset, bytes[0], bytes[1], bytes[2], bytes[3]); + }, offset, bytes[0], bytes[1], bytes[2], bytes[3], timestamp); } + self->midiOutBuffer.clearData(); } #endif