Signed-off-by: falkTX <falktx@falktx.com>pull/321/head
| @@ -1 +1 @@ | |||
| Subproject commit 9552878aa764e577cd9cb0ad9933ce18e5ca9882 | |||
| Subproject commit e90fdaa11e0763fa31b6e0aedb32edb1ed2807cc | |||
| @@ -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 | |||
| @@ -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 | |||
| // ----------------------------------------------------------------------------- | |||
| @@ -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 | |||
| @@ -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 | |||