Browse Source

Introduce ways for standalones to request audio input and midi

Signed-off-by: falkTX <falktx@falktx.com>
pull/321/head
falkTX 3 years ago
parent
commit
e2e2b5507f
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
5 changed files with 212 additions and 14 deletions
  1. +1
    -1
      dgl/src/pugl-upstream
  2. +71
    -0
      distrho/DistrhoStandaloneUtils.hpp
  3. +70
    -1
      distrho/src/jackbridge/JackBridge.cpp
  4. +23
    -0
      distrho/src/jackbridge/NativeBridge.hpp
  5. +47
    -12
      distrho/src/jackbridge/WebBridge.hpp

+ 1
- 1
dgl/src/pugl-upstream

@@ -1 +1 @@
Subproject commit 9552878aa764e577cd9cb0ad9933ce18e5ca9882
Subproject commit e90fdaa11e0763fa31b6e0aedb32edb1ed2807cc

+ 71
- 0
distrho/DistrhoStandaloneUtils.hpp View File

@@ -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

+ 70
- 1
distrho/src/jackbridge/JackBridge.cpp View File

@@ -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

// -----------------------------------------------------------------------------

+ 23
- 0
distrho/src/jackbridge/NativeBridge.hpp View File

@@ -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


+ 47
- 12
distrho/src/jackbridge/WebBridge.hpp View File

@@ -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


Loading…
Cancel
Save