Skip to content

Commit

Permalink
- added TransportHandler.setOnBypass() function to handle the DAW b…
Browse files Browse the repository at this point in the history
…ypass state
  • Loading branch information
christoph-hart committed Jan 3, 2024
1 parent bd51d8a commit b49efc9
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 230 deletions.
13 changes: 11 additions & 2 deletions hi_backend/backend/BackendProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,17 @@ void BackendProcessor::refreshExpansionType()
void BackendProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
TRACE_DSP();


if(externalClockSim.bypassed)
{
processBlockBypassed(buffer, midiMessages);
return;
}





#if !HISE_BACKEND_AS_FX
buffer.clear();
#endif
Expand Down Expand Up @@ -351,7 +361,6 @@ void BackendProcessor::processBlockBypassed(AudioSampleBuffer& buffer, MidiBuffe
{
buffer.clear();
midiMessages.clear();
//allNotesOff();
}

void BackendProcessor::handleControllersForMacroKnobs(const MidiBuffer &/*midiMessages*/)
Expand Down
23 changes: 18 additions & 5 deletions hi_core/hi_components/floating_layout/BackendPanelTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,13 +753,15 @@ DAWClockController::DAWClockController(MainController* mc):
SimpleTimer(mc->getGlobalUIUpdater()),
ControlledObject(mc),
clock(&dynamic_cast<BackendProcessor*>(mc)->externalClockSim),
bypass("bypass", nullptr, f),
play("play", nullptr, f),
stop("stop", nullptr, f),
loop("loop", nullptr, f),
grid("grid", nullptr, f),
rewind("rewind", nullptr, f),
metronome("metronome", nullptr, f)
{
addAndMakeVisible(bypass);
addAndMakeVisible(play);
addAndMakeVisible(stop);
addAndMakeVisible(rewind);
Expand All @@ -773,7 +775,8 @@ DAWClockController::DAWClockController(MainController* mc):

addAndMakeVisible(grid);
addAndMakeVisible(length);


bypass.setToggleModeWithColourChange(true);
play.setToggleModeWithColourChange(true);
stop.setToggleModeWithColourChange(true);
loop.setToggleModeWithColourChange(true);
Expand All @@ -796,7 +799,12 @@ DAWClockController::DAWClockController(MainController* mc):
length.setRange(1, 128.0, 1.0);

length.setValue(dynamic_cast<Ruler*>(ruler.get())->numBars, dontSendNotification);


bypass.onClick = [this]()
{
clock->bypassed = !clock->bypassed;
};

play.onClick = [this]()
{
clock->isPlaying = true;
Expand Down Expand Up @@ -837,7 +845,8 @@ DAWClockController::DAWClockController(MainController* mc):
position.setEditable(false);
position.setFont(GLOBAL_BOLD_FONT().withHeight(17.0f));
position.setColour(Label::ColourIds::textColourId, Colours::white.withAlpha(0.5f));


bypass.setTooltip("Simulate the bypass state of the plugin");
play.setTooltip("Start the external DAW playback simulator [Space]");
stop.setTooltip("Stop the external DAW playback simulator [Space]");
loop.setTooltip("Toggle the loop playback");
Expand Down Expand Up @@ -913,7 +922,9 @@ void DAWClockController::timerCallback()
posString << String(bars+1) << " | " << String(quarters+1) << " | " << String(ticks);

position.setText(posString, dontSendNotification);



bypass.setToggleStateAndUpdateIcon(!clock->bypassed);
play.setToggleStateAndUpdateIcon(clock->isPlaying);
stop.setToggleStateAndUpdateIcon(!clock->isPlaying);
loop.setToggleStateAndUpdateIcon(clock->isLooping);
Expand All @@ -934,7 +945,8 @@ void DAWClockController::resized()
top.removeFromLeft(TopHeight);

b.removeFromTop(5);


bypass.setBounds(top.removeFromLeft(TopHeight).reduced(Margin));
play.setBounds(top.removeFromLeft(TopHeight).reduced(Margin));
stop.setBounds(top.removeFromLeft(TopHeight).reduced(Margin));
rewind.setBounds(top.removeFromLeft(TopHeight).reduced(Margin));
Expand Down Expand Up @@ -1137,6 +1149,7 @@ Path DAWClockController::Icons::createPath(const String& url) const
LOAD_PATH_IF_URL("loopEnd", ClockIcons::loopEnd);
LOAD_PATH_IF_URL("rewind", ClockIcons::rewind);
LOAD_PATH_IF_URL("metronome", ClockIcons::metronome);
LOAD_EPATH_IF_URL("bypass", HiBinaryData::ProcessorEditorHeaderIcons::bypassShape);

return p;
}
Expand Down
4 changes: 3 additions & 1 deletion hi_core/hi_components/floating_layout/BackendPanelTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class ExternalClockSimulator: public juce::AudioPlayHead

void prepareToPlay(double newSampleRate);

bool bypassed = false;

bool isLooping = false;
bool isPlaying = false;
bool metronomeEnabled = false;
Expand Down Expand Up @@ -185,7 +187,7 @@ struct DAWClockController: public Component,
WeakReference<ExternalClockSimulator> clock;
Icons f;

HiseShapeButton play, stop, loop, grid, rewind, metronome;
HiseShapeButton bypass, play, stop, loop, grid, rewind, metronome;

Slider bpm, nom, denom, length;

Expand Down
51 changes: 50 additions & 1 deletion hi_core/hi_core/MainController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,53 @@ namespace hise { using namespace juce;
bool MainController::unitTestMode = false;
#endif

MainController::MainController() :
void MainController::PluginBypassHandler::timerCallback()
{
if(listeners.hasListeners())
{
auto thisTime = Time::getApproximateMillisecondCounter();

auto numSamples = (double)getMainController()->getOriginalBufferSize();
auto sampleRate = (double)getMainController()->getOriginalSamplerate();

if(sampleRate != 0.0)
{
auto blockLengthSeconds = numSamples / sampleRate;

// If there is no watchdog call for 10 buffers worth of time we assume that it's bypassed...
auto deltaForBypassDetection = roundToInt(1000.0 * 10.0 * blockLengthSeconds);

auto deltaSinceLastCall = (thisTime - lastProcessBlockTime);
auto noCallsLately = deltaSinceLastCall > deltaForBypassDetection;

if(reactivateOnNextCall)
{
lastBypassFlag = false;
reactivateOnNextCall = false;
listeners.sendMessage(sendNotificationSync, false);
}
else if(noCallsLately != lastBypassFlag)
{
lastBypassFlag = noCallsLately;
listeners.sendMessage(sendNotificationSync, lastBypassFlag);
}
}
}
}

void MainController::PluginBypassHandler::bumpWatchDog()
{
if(listeners.hasListeners())
{
if(lastBypassFlag)
reactivateOnNextCall = true;

lastBypassFlag = false;
lastProcessBlockTime = Time::getApproximateMillisecondCounter();
}
}

MainController::MainController() :

sampleManager(new SampleManager(this)),
javascriptThreadPool(new JavascriptThreadPool(this)),
Expand Down Expand Up @@ -81,6 +127,7 @@ MainController::MainController() :
processorChangeHandler(this),
killStateHandler(this),
debugLogger(this),
bypassHandler(this),
globalAsyncModuleHandler(this),
//presetLoadRampFlag(OldUserPresetHandler::Active),
controlUndoManager(new UndoManager()),
Expand Down Expand Up @@ -849,6 +896,8 @@ void MainController::connectToRuntimeTargets(scriptnode::OpaqueNode& on, bool sh

void MainController::processBlockCommon(AudioSampleBuffer &buffer, MidiBuffer &midiMessages)
{
getPluginBypassHandler().bumpWatchDog();

PerfettoHelpers::setCurrentThreadName("Audio Thread");

if (getKillStateHandler().getStateLoadFlag())
Expand Down
24 changes: 24 additions & 0 deletions hi_core/hi_core/MainController.h
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,25 @@ class MainController: public GlobalScriptCompileBroadcaster,
UnorderedStack<void*, 32> audioThreads;
};

struct PluginBypassHandler: public PooledUIUpdater::SimpleTimer,
public ControlledObject
{
PluginBypassHandler(MainController* mc):
ControlledObject(mc),
SimpleTimer(mc->getGlobalUIUpdater())
{};

void timerCallback() override;

void bumpWatchDog();

uint32 lastProcessBlockTime = 0;
bool lastBypassFlag = false;
bool currentBypassState = false;
bool reactivateOnNextCall = false;
LambdaBroadcaster<bool> listeners;
};

MainController();

virtual ~MainController();
Expand All @@ -1446,6 +1465,9 @@ class MainController: public GlobalScriptCompileBroadcaster,
AutoSaver &getAutoSaver() noexcept { return autoSaver; }
const AutoSaver &getAutoSaver() const noexcept { return autoSaver; }

PluginBypassHandler& getPluginBypassHandler() noexcept { return bypassHandler; }
const PluginBypassHandler& getPluginBypassHandler() const noexcept { return bypassHandler; }

DelayedRenderer& getDelayedRenderer() noexcept { return delayedRenderer; };
const DelayedRenderer& getDelayedRenderer() const noexcept { return delayedRenderer; };

Expand Down Expand Up @@ -2076,6 +2098,8 @@ class MainController: public GlobalScriptCompileBroadcaster,
dispatch::library::ProcessorHandler processorHandler;
dispatch::library::CustomAutomationSourceManager customAutomationSourceManager;

PluginBypassHandler bypassHandler;

AudioSampleBuffer previewBuffer;
double previewBufferIndex = -1.0;
double previewBufferDelta = 1.0;
Expand Down
15 changes: 15 additions & 0 deletions hi_scripting/scripting/api/ScriptingApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7806,6 +7806,7 @@ struct ScriptingApi::TransportHandler::Wrapper
API_VOID_METHOD_WRAPPER_2(TransportHandler, setOnGridChange);
API_VOID_METHOD_WRAPPER_2(TransportHandler, setOnSignatureChange);
API_VOID_METHOD_WRAPPER_2(TransportHandler, setOnTransportChange);
API_VOID_METHOD_WRAPPER_1(TransportHandler, setOnBypass);
API_VOID_METHOD_WRAPPER_1(TransportHandler, setSyncMode);
API_VOID_METHOD_WRAPPER_2(TransportHandler, setEnableGrid);
API_VOID_METHOD_WRAPPER_1(TransportHandler, startInternalClock);
Expand All @@ -7832,6 +7833,7 @@ ScriptingApi::TransportHandler::TransportHandler(ProcessorWithScriptingContent*
ADD_TYPED_API_METHOD_2(setOnGridChange, VarTypeChecker::Number, VarTypeChecker::Function);
ADD_TYPED_API_METHOD_2(setOnSignatureChange, VarTypeChecker::Number, VarTypeChecker::Function);
ADD_TYPED_API_METHOD_2(setOnTransportChange, VarTypeChecker::Number, VarTypeChecker::Function);
ADD_TYPED_API_METHOD_1(setOnBypass, VarTypeChecker::Function);
ADD_API_METHOD_1(setSyncMode);
ADD_API_METHOD_1(startInternalClock);
ADD_API_METHOD_1(stopInternalClock);
Expand All @@ -7843,6 +7845,7 @@ ScriptingApi::TransportHandler::TransportHandler(ProcessorWithScriptingContent*

ScriptingApi::TransportHandler::~TransportHandler()
{
getMainController()->getPluginBypassHandler().listeners.removeListener(*this);
getMainController()->removeTempoListener(this);
getMainController()->removeMusicalUpdateListener(this);
}
Expand Down Expand Up @@ -8020,6 +8023,13 @@ void ScriptingApi::TransportHandler::setOnGridChange(var sync, var f)
}
}

void ScriptingApi::TransportHandler::setOnBypass(var f)
{
bypassCallback = new Callback(this, "onGridChange", f, false, 1);

getMainController()->getPluginBypassHandler().listeners.addListener(*this, TransportHandler::onBypassUpdate, true);
}

void ScriptingApi::TransportHandler::setEnableGrid(bool shouldBeEnabled, int tempoFactor)
{
if (isPositiveAndBelow(tempoFactor, (int)TempoSyncer::numTempos))
Expand Down Expand Up @@ -8058,4 +8068,9 @@ void ScriptingApi::TransportHandler::setLinkBpmToSyncMode(bool shouldPrefer)
getMainController()->getMasterClock().setLinkBpmToSyncMode(shouldPrefer);
}

void ScriptingApi::TransportHandler::onBypassUpdate(TransportHandler& handler, bool state)
{
if(handler.bypassCallback != nullptr)
handler.bypassCallback->call(state, {}, {}, true);
}
} // namespace hise
7 changes: 7 additions & 0 deletions hi_scripting/scripting/api/ScriptingApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1474,6 +1474,9 @@ class ScriptingApi
/** Registers a callback to changes in the grid. */
void setOnGridChange(var sync, var f);

/** Registers a callback that will be executed asynchronously when the plugin's bypass state changes. */
void setOnBypass(var f);

/** Enables a high precision grid timer. */
void setEnableGrid(bool shouldBeEnabled, int tempoFactor);

Expand All @@ -1497,6 +1500,8 @@ class ScriptingApi

private:

static void onBypassUpdate(TransportHandler& handler, bool state);

void clearIf(ScopedPointer<Callback>& cb, const var& f)
{
if (cb != nullptr && cb->matches(f))
Expand All @@ -1521,6 +1526,8 @@ class ScriptingApi
ScopedPointer<Callback> beatCallback;
ScopedPointer<Callback> gridCallback;

ScopedPointer<Callback> bypassCallback;

ScopedPointer<Callback> tempoChangeCallbackAsync;
ScopedPointer<Callback> transportChangeCallbackAsync;
ScopedPointer<Callback> timeSignatureCallbackAsync;
Expand Down
Loading

0 comments on commit b49efc9

Please sign in to comment.