diff --git a/resources/ui/carla_settings_driver.ui b/resources/ui/carla_settings_driver.ui
index 784d9c111..37b5d410c 100644
--- a/resources/ui/carla_settings_driver.ui
+++ b/resources/ui/carla_settings_driver.ui
@@ -37,7 +37,7 @@
- 1
+ 40
1
@@ -61,6 +61,9 @@
Qt::Horizontal
+
+ QSizePolicy::Fixed
+
40
@@ -94,10 +97,13 @@
Qt::Horizontal
+
+ QSizePolicy::Fixed
+
40
- 20
+ 1
diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp
index 143bf8ad6..6b7064859 100644
--- a/source/backend/CarlaEngine.hpp
+++ b/source/backend/CarlaEngine.hpp
@@ -837,8 +837,16 @@ public:
*/
virtual void clearXruns() const noexcept;
+ /*!
+ * Dynamically change buffer size and/or sample rate while engine is running.
+ * @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE
+ * @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE
+ */
+ virtual bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate);
+
/*!
* Show the custom control panel for the current engine device.
+ * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL
*/
virtual bool showDeviceControlPanel() const noexcept;
diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h
index fd6cb52c3..85430e9df 100644
--- a/source/backend/CarlaHost.h
+++ b/source/backend/CarlaHost.h
@@ -427,8 +427,16 @@ CARLA_EXPORT const CarlaRuntimeEngineInfo* carla_get_runtime_engine_info();
*/
CARLA_EXPORT const CarlaRuntimeEngineDriverDeviceInfo* carla_get_runtime_engine_driver_device_info();
+/*!
+ * Dynamically change buffer size and/or sample rate while engine is running.
+ * @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE
+ * @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE
+ */
+CARLA_EXPORT bool carla_set_engine_buffer_size_and_sample_rate(uint bufferSize, double sampleRate);
+
/*!
* Show the custom control panel for the current engine device.
+ * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL
*/
CARLA_EXPORT bool carla_show_engine_device_control_panel();
diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp
index 4ee276e5b..a2ea3d409 100644
--- a/source/backend/CarlaStandalone.cpp
+++ b/source/backend/CarlaStandalone.cpp
@@ -541,6 +541,14 @@ const CarlaRuntimeEngineDriverDeviceInfo* carla_get_runtime_engine_driver_device
return &retInfo;
}
+bool carla_set_engine_buffer_size_and_sample_rate(uint bufferSize, double sampleRate)
+{
+ CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, false);
+ carla_debug("carla_set_engine_buffer_size_and_sample_rate(%u, %f)", bufferSize, sampleRate);
+
+ return gStandalone.engine->setBufferSizeAndSampleRate(bufferSize, sampleRate);
+}
+
bool carla_show_engine_device_control_panel()
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, false);
diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp
index 79efa21f0..7c05310e0 100644
--- a/source/backend/engine/CarlaEngine.cpp
+++ b/source/backend/engine/CarlaEngine.cpp
@@ -410,6 +410,11 @@ bool CarlaEngine::showDeviceControlPanel() const noexcept
return false;
}
+bool CarlaEngine::setBufferSizeAndSampleRate(const uint, const double)
+{
+ return false;
+}
+
// -----------------------------------------------------------------------
// Plugin management
diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp
index f63decb02..a3fb81c37 100644
--- a/source/backend/engine/CarlaEngineJack.cpp
+++ b/source/backend/engine/CarlaEngineJack.cpp
@@ -1191,6 +1191,16 @@ public:
}
#endif
+ bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate) override
+ {
+ CARLA_SAFE_ASSERT_RETURN(carla_isEqual(pData->sampleRate, sampleRate), false);
+ CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false);
+
+ try {
+ return jackbridge_set_buffer_size(fClient, bufferSize);
+ } CARLA_SAFE_EXCEPTION_RETURN("setBufferSizeAndSampleRate", false);
+ }
+
EngineTimeInfo getTimeInfo() const noexcept override
{
if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK)
diff --git a/source/backend/engine/CarlaEngineJuce.cpp b/source/backend/engine/CarlaEngineJuce.cpp
index 5299afcb2..17c35ec21 100644
--- a/source/backend/engine/CarlaEngineJuce.cpp
+++ b/source/backend/engine/CarlaEngineJuce.cpp
@@ -352,6 +352,69 @@ public:
pData->xruns = xruns > 0 ? static_cast(xruns) : 0;
}
+ bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate) override
+ {
+ CARLA_SAFE_ASSERT_RETURN(fDevice != nullptr, false);
+
+ juce::StringArray inputNames(fDevice->getInputChannelNames());
+ juce::StringArray outputNames(fDevice->getOutputChannelNames());
+
+ if (inputNames.size() < 0 || outputNames.size() <= 0)
+ {
+ setLastError("Selected device does not have any outputs");
+ return false;
+ }
+
+ juce::BigInteger inputChannels;
+ inputChannels.setRange(0, inputNames.size(), true);
+
+ juce::BigInteger outputChannels;
+ outputChannels.setRange(0, outputNames.size(), true);
+
+ // stop stream first
+ if (fDevice->isPlaying())
+ fDevice->stop();
+ if (fDevice->isOpen())
+ fDevice->close();
+
+ juce::String error = fDevice->open(inputChannels, outputChannels, sampleRate, static_cast(bufferSize));
+
+ if (error.isNotEmpty())
+ {
+ setLastError(error.toUTF8());
+
+ // try to roll back
+ error = fDevice->open(inputChannels, outputChannels, pData->sampleRate, static_cast(pData->bufferSize));
+
+ // if we failed, we are screwed...
+ if (error.isNotEmpty())
+ {
+ fDevice = nullptr;
+ close();
+ }
+
+ return false;
+ }
+
+ const uint32_t newBufferSize = static_cast(fDevice->getCurrentBufferSizeSamples());
+ const double newSampleRate = fDevice->getCurrentSampleRate();
+
+ if (carla_isNotEqual(pData->sampleRate, newSampleRate))
+ {
+ pData->sampleRate = newSampleRate;
+ sampleRateChanged(newSampleRate);
+ }
+
+ if (pData->bufferSize != newBufferSize)
+ {
+ pData->bufferSize = newBufferSize;
+ bufferSizeChanged(newBufferSize);
+ }
+
+ fDevice->start(this);
+ return true;
+ }
+
bool showDeviceControlPanel() const noexcept override
{
try {
diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp
index 6bd1c766d..f84c8047a 100644
--- a/source/backend/engine/CarlaEngineNative.cpp
+++ b/source/backend/engine/CarlaEngineNative.cpp
@@ -2738,6 +2738,7 @@ uint CarlaEngine::getJuceApiCount() { return 0;
const char* CarlaEngine::getJuceApiName(const uint) { return nullptr; }
const char* const* CarlaEngine::getJuceApiDeviceNames(const uint) { return nullptr; }
const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint, const char* const) { return nullptr; }
+bool CarlaEngine::showJuceDeviceControlPanel(const uint, const char* const) { return false; }
# else
CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
uint CarlaEngine::getRtAudioApiCount() { return 0; }
diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py
index 8ff16d45b..cb1ac2eb4 100644
--- a/source/frontend/carla_backend.py
+++ b/source/frontend/carla_backend.py
@@ -1508,7 +1508,14 @@ class CarlaHostMeta(object):
def get_runtime_engine_driver_device_info(self):
raise NotImplementedError
+ # Dynamically change buffer size and/or sample rate while engine is running.
+ # @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE
+ # @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE
+ def set_engine_buffer_size_and_sample_rate(self, bufferSize, sampleRate):
+ raise NotImplementedError
+
# Show the custom control panel for the current engine device.
+ # @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL
def show_engine_device_control_panel(self):
raise NotImplementedError
@@ -2168,6 +2175,9 @@ class CarlaHostNull(CarlaHostMeta):
def get_runtime_engine_driver_device_info(self):
return PyCarlaRuntimeEngineDriverDeviceInfo
+ def set_engine_buffer_size_and_sample_rate(self, bufferSize, sampleRate):
+ return False
+
def show_engine_device_control_panel(self):
return False
@@ -2477,6 +2487,9 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib.carla_get_runtime_engine_driver_device_info.argtypes = None
self.lib.carla_get_runtime_engine_driver_device_info.restype = POINTER(CarlaRuntimeEngineDriverDeviceInfo)
+ self.lib.carla_set_engine_buffer_size_and_sample_rate.argtypes = [c_uint, c_double]
+ self.lib.carla_set_engine_buffer_size_and_sample_rate.restype = c_bool
+
self.lib.carla_show_engine_device_control_panel.argtypes = None
self.lib.carla_show_engine_device_control_panel.restype = c_bool
@@ -2776,6 +2789,9 @@ class CarlaHostDLL(CarlaHostMeta):
def get_runtime_engine_driver_device_info(self):
return structToDict(self.lib.carla_get_runtime_engine_driver_device_info().contents)
+ def set_engine_buffer_size_and_sample_rate(self, bufferSize, sampleRate):
+ return bool(self.lib.carla_set_engine_buffer_size_and_sample_rate(bufferSize, sampleRate))
+
def show_engine_device_control_panel(self):
return bool(self.lib.carla_show_engine_device_control_panel())
@@ -3166,6 +3182,9 @@ class CarlaHostPlugin(CarlaHostMeta):
def get_runtime_engine_driver_device_info(self):
return PyCarlaRuntimeEngineDriverDeviceInfo
+ def set_engine_buffer_size_and_sample_rate(self, bufferSize, sampleRate):
+ return False
+
def show_engine_device_control_panel(self):
return False
diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py
index ccf1df6d5..236b2d456 100644
--- a/source/frontend/carla_host.py
+++ b/source/frontend/carla_host.py
@@ -877,6 +877,9 @@ class HostWindow(QMainWindow):
QMessageBox.warning(self, self.tr("Warning"), self.tr("Engine was stopped while configuring settings, all changes have been ignored"))
return
+ bufferSize, sampleRate = dialog.getValues()
+ self.host.set_engine_buffer_size_and_sample_rate(bufferSize, sampleRate)
+
@pyqtSlot()
def slot_engineStopTryAgain(self):
if self.host.is_engine_running() and not self.host.set_engine_about_to_close():
diff --git a/source/frontend/carla_settings.py b/source/frontend/carla_settings.py
index f48c4831c..af8738186 100755
--- a/source/frontend/carla_settings.py
+++ b/source/frontend/carla_settings.py
@@ -281,9 +281,9 @@ class RuntimeDriverSettingsW(QDialog):
bufferSize = self.ui.cb_buffersize.currentText()
sampleRate = self.ui.cb_samplerate.currentText()
- if bufferSize == self.AUTOMATIC_OPTION:
+ if bufferSize == DriverSettingsW.AUTOMATIC_OPTION:
bufferSize = "0"
- if sampleRate == self.AUTOMATIC_OPTION:
+ if sampleRate == DriverSettingsW.AUTOMATIC_OPTION:
sampleRate = "0"
return (int(bufferSize), int(sampleRate))