11/*
22 * RtAudio Bridge for DPF
3- * Copyright (C) 2021-2025 Filipe Coelho <falktx@falktx.com>
3+ * Copyright (C) 2021-2026 Filipe Coelho <falktx@falktx.com>
44 *
55 * Permission to use, copy, modify, and/or distribute this software for any purpose with
66 * or without fee is hereby granted, provided that the above copyright notice and this
1919
2020#include " NativeBridge.hpp"
2121
22- #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) == 0
23- # error RtAudio without audio does not make sense
24- #endif
25-
2622#if defined(DISTRHO_OS_MAC)
2723# define __MACOSX_CORE__
2824# define RTAUDIO_API_TYPE MACOSX_CORE
5147# include " ../../extra/ScopedPointer.hpp"
5248# include " ../../extra/String.hpp"
5349# include " ../../extra/ScopedDenormalDisable.hpp"
50+ # include " ../../extra/Thread.hpp"
5451
5552using DISTRHO_NAMESPACE ::ScopedDenormalDisable;
5653using DISTRHO_NAMESPACE ::ScopedPointer;
5754using DISTRHO_NAMESPACE ::String;
5855
59- struct RtAudioBridge : NativeBridge {
60- // pointer to RtAudio instance
56+ struct RtAudioBridge : NativeBridge
57+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) == 0
58+ , private DISTRHO_NAMESPACE ::Thread
59+ #endif
60+ {
61+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
6162 ScopedPointer<RtAudio> handle;
62- bool captureEnabled = false ;
63+ # endif
6364 #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT
6465 std::vector<RtMidiIn> midiIns;
6566 #endif
6667 #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
6768 std::vector<RtMidiOut> midiOuts;
6869 #endif
70+ bool audioCaptureEnabled = false ;
6971
7072 // caching
7173 String name;
@@ -86,11 +88,19 @@ struct RtAudioBridge : NativeBridge {
8688 bool open (const char * const clientName) override
8789 {
8890 name = clientName;
91+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
8992 return _open (false );
93+ #else
94+ bufferSize = 512 ;
95+ sampleRate = 48000 ;
96+ allocBuffers (false , true );
97+ return true ;
98+ #endif
9099 }
91100
92101 bool close () override
93102 {
103+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
94104 DISTRHO_SAFE_ASSERT_RETURN (handle != nullptr , false );
95105
96106 if (handle->isStreamRunning ())
@@ -99,40 +109,49 @@ struct RtAudioBridge : NativeBridge {
99109 handle->abortStream ();
100110 } DISTRHO_SAFE_EXCEPTION (" handle->abortStream()" );
101111 }
112+ #endif
102113
103- #if DISTRHO_PLUGIN_NUM_INPUTS > 0
104114 freeBuffers ();
105- #endif
115+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
106116 handle = nullptr ;
117+ #endif
107118 return true ;
108119 }
109120
110121 bool activate () override
111122 {
123+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
112124 DISTRHO_SAFE_ASSERT_RETURN (handle != nullptr , false );
113125
114126 try {
115127 handle->startStream ();
116128 } DISTRHO_SAFE_EXCEPTION_RETURN (" handle->startStream()" , false );
129+ #else
130+ startThread ();
131+ #endif
117132
118133 return true ;
119134 }
120135
121136 bool deactivate () override
122137 {
138+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
123139 DISTRHO_SAFE_ASSERT_RETURN (handle != nullptr , false );
124140
125141 try {
126142 handle->stopStream ();
127143 } DISTRHO_SAFE_EXCEPTION_RETURN (" handle->stopStream()" , false );
144+ #else
145+ stopThread (-1 );
146+ #endif
128147
129148 return true ;
130149 }
131150
132151 bool isAudioInputEnabled () const override
133152 {
134153 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
135- return captureEnabled ;
154+ return audioCaptureEnabled ;
136155 #else
137156 return false ;
138157 #endif
@@ -149,7 +168,7 @@ struct RtAudioBridge : NativeBridge {
149168 const bool ok = _open (true );
150169
151170 if (ok)
152- captureEnabled = true ;
171+ audioCaptureEnabled = true ;
153172 else
154173 _open (false );
155174
@@ -252,6 +271,7 @@ struct RtAudioBridge : NativeBridge {
252271 return true ;
253272 }
254273
274+ #if (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) != 0
255275 bool supportsBufferSizeChanges () const override
256276 {
257277 return true ;
@@ -266,13 +286,13 @@ struct RtAudioBridge : NativeBridge {
266286 // try to open with new buffer size
267287 nextBufferSize = newBufferSize;
268288
269- const bool ok = _open (captureEnabled );
289+ const bool ok = _open (audioCaptureEnabled );
270290
271291 if (!ok)
272292 {
273293 // revert to old buffer size if new one failed
274294 nextBufferSize = bufferSize;
275- _open (captureEnabled );
295+ _open (audioCaptureEnabled );
276296 }
277297
278298 if (bufferSizeCallback != nullptr )
@@ -416,6 +436,43 @@ struct RtAudioBridge : NativeBridge {
416436
417437 return 0 ;
418438 }
439+ #else
440+ void run () override
441+ {
442+ if (jackProcessCallback == nullptr )
443+ return ;
444+
445+ const ScopedDenormalDisable sdd;
446+
447+ while (! shouldThreadExit ())
448+ {
449+ DISTRHO_NAMESPACE::d_msleep (10 );
450+ jackProcessCallback (512 , jackProcessArg);
451+
452+ #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
453+ if (midiOutBuffer.isDataAvailableForReading ())
454+ {
455+ static_assert (kMaxMIDIInputMessageSize + 1u == 4 , " change code if bumping this value" );
456+ uint8_t data[4 ] = {};
457+
458+ while (midiOutBuffer.isDataAvailableForReading () &&
459+ midiOutBuffer.readCustomData (data, ARRAY_SIZE (data)))
460+ {
461+ // offset not used in RtMidiOut
462+ midiOutBuffer.readUInt ();
463+
464+ for (std::vector<RtMidiOut>::iterator it = midiOuts.begin (), end = midiOuts.end (); it != end; ++it)
465+ {
466+ static_cast <RtMidiOut&>(*it).sendMessage (data + 1 , data[0 ]);
467+ }
468+ }
469+
470+ midiOutBuffer.flush ();
471+ }
472+ #endif
473+ }
474+ }
475+ #endif
419476
420477 #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT
421478 static void RtMidiCallback (double /* timestamp*/ , std::vector<uchar>* const message, void * const userData)
0 commit comments