diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9864b62..3bd8712 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,13 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
- VERSION 1.4.79
+ VERSION 1.4.83
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
EXECUTE_PROCESS( COMMAND dpkg --print-architecture COMMAND tr -d '\n' OUTPUT_VARIABLE DEBIAN_ARCHITECTURE )
-set (DISPLAY_VERSION "PiPedal v1.4.79-Beta")
+set (DISPLAY_VERSION "PiPedal v1.4.83-Experimental")
set (PACKAGE_ARCHITECTURE ${DEBIAN_ARCHITECTURE})
set (CMAKE_INSTALL_PREFIX "/usr/")
diff --git a/PiPedalCommon/src/AlsaSequencer.cpp b/PiPedalCommon/src/AlsaSequencer.cpp
index 7506e02..4e21ee4 100644
--- a/PiPedalCommon/src/AlsaSequencer.cpp
+++ b/PiPedalCommon/src/AlsaSequencer.cpp
@@ -259,6 +259,8 @@ namespace pipedal
// Open sequencer in input mode
int rc;
+ Lv2Log::debug("Opening ALSA Sequencer");
+
rc = snd_seq_open(&seqHandle, "default", SND_SEQ_OPEN_DUPLEX, 0);
if (rc < 0)
{
diff --git a/PiPedalCommon/src/include/restrict.hpp b/PiPedalCommon/src/include/restrict.hpp
new file mode 100644
index 0000000..3cf0756
--- /dev/null
+++ b/PiPedalCommon/src/include/restrict.hpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 Robin E. R. Davies
+ * All rights reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#pragma once
+
+
+// define restrict keyword for C++ compilers (which don't yet support it)
+#ifndef restrict
+#if defined(__GNUC__) || defined(__clang__)
+#define restrict __restrict__
+#elif defined(_MSC_VER)
+#define restrict __restrict
+#endif
+#endif
\ No newline at end of file
diff --git a/README.md b/README.md
index 4645e27..a332ae7 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,11 @@
-Download: v1.4.79
+Download: v1.4.83
Website: [https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
Documentation: [https://rerdavies.github.io/pipedal/Documentation.html](https://rerdavies.github.io/pipedal/Documentation.html).
-#### NEW version 1.4.79 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details. New Phaser and Graphic Equalizer plugins.
+#### NEW version 1.4.83 Release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details. New Phaser and Graphic Equalizer plugins.
diff --git a/docs/Installing.md b/docs/Installing.md
index f8935b8..6a66c15 100644
--- a/docs/Installing.md
+++ b/docs/Installing.md
@@ -13,18 +13,18 @@ page_icon: img/Install4.jpg
Download the most recent Debian (.deb) package for your platform:
-- [Raspberry Pi OS bookworm (aarch64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
-- [Ubuntu 24.x (aarch64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
-- [Ubuntu 24.x (amd64) v1.4.79](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_amd64.deb)
+- [Raspberry Pi OS bookworm (aarch64) v1.4.83](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_arm64.deb)
+- [Ubuntu 24.x (aarch64) v1.4.83](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_arm64.deb)
+- [Ubuntu 24.x (amd64) v1.4.83](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_amd64.deb)
-Version 1.4.79 has been tested on Raspberry Pi OS bookworm, Ubuntu 24.04 (amd64), and Ubuntu 24.10 (aarch64). Download the appropriate package for your platform, and install using the following procedure:
+Version 1.4.83 has been tested on Raspberry Pi OS bookworm, Ubuntu 24.04 (amd64), and Ubuntu 24.10 (aarch64). Download the appropriate package for your platform, and install using the following procedure:
```
sudo apt update
sudo apt upgrade
cd ~/Downloads
- sudo apt-get install ./pipedal_1.4.79_arm64.deb
+ sudo apt-get install ./pipedal_1.4.83_arm64.deb
```
You MUST use `apt-get`. `apt` will not install downloaded packages; and `dpkg -i` will not install dependencies.
diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index 3d45137..791e5b0 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -1,4 +1,9 @@
# Release Notes
+## Pipedal 1.4.79 Experimental
+Bug fixes:
+- Thread-per-plugin-instance for LV2_WORKER threads (see issue #339)
+- Fixes for selection issues when modifying pedalboard structure.
+
## Pipedal 1.4.79 Beta
The Big Feature:
diff --git a/docs/download.md b/docs/download.md
index 8e8b412..7cd8397 100644
--- a/docs/download.md
+++ b/docs/download.md
@@ -4,9 +4,9 @@
Download the most recent Debian (.deb) package for your platform:
-- [Raspberry Pi OS bookworm (aarch64) v1.4.79 Beta](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
-- [Ubuntu 24.x (aarch64) v1.4.79 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_arm64.deb)
-- [Ubuntu 24.x (amd64) v1.4.79 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.79/pipedal_1.4.79_amd64.deb)
+- [Raspberry Pi OS bookworm (aarch64) v1.4.83 Beta](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_arm64.deb)
+- [Ubuntu 24.x (aarch64) v1.4.83 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_arm64.deb)
+- [Ubuntu 24.x (amd64) v1.4.83 Alpha](https://github.com/rerdavies/pipedal/releases/download/v1.4.83/pipedal_1.4.83_amd64.deb)
Install the package by running
@@ -14,7 +14,7 @@ Install the package by running
```
sudo apt update
cd ~/Downloads
- sudo apt-get install ./pipedal_1.4.79_arm64.deb
+ sudo apt-get install ./pipedal_1.4.83_arm64.deb
```
You MUST use `apt-get` to install the package. `apt install` will NOT install the package correctly. The message about missing permissions given by `apt-get` is
expected, and can be safely ignored.
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp
index 195cec6..1f833be 100644
--- a/src/AlsaDriver.cpp
+++ b/src/AlsaDriver.cpp
@@ -245,6 +245,8 @@ namespace pipedal
class AlsaDriverImpl : public AudioDriver
{
private:
+ std::recursive_mutex restartMutex;
+
pipedal::CpuUse cpuUse;
#ifdef ALSADRIVER_CONFIG_DBG
@@ -378,16 +380,21 @@ namespace pipedal
}
private:
- void AlsaCleanup()
+ void AlsaCloseAudio()
{
+ std::lock_guard lock{restartMutex};
if (captureHandle)
{
+ Lv2Log::debug("ALSA capture handle closed.");
+ snd_pcm_drain(captureHandle);
snd_pcm_close(captureHandle);
captureHandle = nullptr;
}
if (playbackHandle)
{
+ Lv2Log::debug("ALSA playback handle closed.");
+ snd_pcm_drain(playbackHandle);
snd_pcm_close(playbackHandle);
playbackHandle = nullptr;
}
@@ -411,7 +418,11 @@ namespace pipedal
snd_pcm_sw_params_free(playbackSwParams);
playbackSwParams = nullptr;
}
- this->alsaSequencer = nullptr;
+
+ }
+ void AlsaCleanup()
+ {
+ AlsaCloseAudio();
}
std::string discover_alsa_using_apps()
@@ -1085,6 +1096,34 @@ namespace pipedal
}
}
+ void RestartAlsa()
+ {
+ std::lock_guard lock{restartMutex};
+ Lv2Log::info("Restarting ALSA devices.");
+
+ try {
+ AlsaCloseAudio();
+ } catch (const std::exception &e) {
+ Lv2Log::error(SS("Error cleaning up ALSA: " << e.what()));
+ throw std::runtime_error("Unable to restart the audio stream.");
+ }
+ try {
+ OpenAudio(this->jackServerSettings, this->channelSelection);
+ validate_capture_handle();
+ FillOutputBuffer();
+ audioRunning = true;
+ } catch (const std::exception &e) {
+ Lv2Log::error(SS("Error opening ALSA: " << e.what()));
+ throw std::runtime_error("Unable to restart the audio stream.");
+ }
+ int err;
+ if ((err = snd_pcm_start(captureHandle)) < 0)
+ {
+ throw PiPedalStateException("Unable to restart ALSA capture.");
+ }
+
+ }
+
void PrepareCaptureFunctions(snd_pcm_format_t captureFormat)
{
this->captureFormat = captureFormat;
@@ -1221,6 +1260,8 @@ namespace pipedal
void OpenAudio(const JackServerSettings &jackServerSettings, const JackChannelSelection &channelSelection)
{
+ std::lock_guard lock{ restartMutex };
+
int err;
alsa_device_name = jackServerSettings.GetAlsaInputDevice();
@@ -1389,18 +1430,25 @@ namespace pipedal
void recover_from_output_underrun(snd_pcm_t *capture_handle, snd_pcm_t *playback_handle, int err)
{
validate_capture_handle();
- if (err == -EPIPE)
- {
- err = snd_pcm_prepare(playback_handle);
- if (err < 0)
+ try {
+
+ if (err == -EPIPE)
{
- throw PiPedalStateException(SS("Can't recover from ALSA output underrun. (" << snd_strerror(err) << ")"));
+ err = snd_pcm_prepare(playback_handle);
+ if (err < 0)
+ {
+ throw PiPedalStateException(SS("Can't recover from ALSA output underrun. (" << snd_strerror(err) << ")"));
+ }
+ FillOutputBuffer();
}
- FillOutputBuffer();
- }
- else
- {
- throw PiPedalStateException(SS("Can't recover from ALSA output error. (" << snd_strerror(err) << ")"));
+ else
+ {
+ throw PiPedalStateException(SS("Can't recover from ALSA output error. (" << snd_strerror(err) << ")"));
+ }
+ } catch (const std::exception &e) {
+ Lv2Log::info(SS("Soft audio restart failed. " << e.what()));
+ RestartAlsa();
+ audioRunning = true;
}
validate_capture_handle();
}
@@ -1408,72 +1456,79 @@ namespace pipedal
{
validate_capture_handle();
- if (err == -EPIPE)
- {
+ try {
+ if (err == -EPIPE)
+ {
- // Unlink the streams before recovery
- snd_pcm_unlink(capture_handle);
+ // Unlink the streams before recovery
+ snd_pcm_unlink(capture_handle);
- err = snd_pcm_drop(capture_handle);
- if (err < 0)
- {
- throw PiPedalStateException(SS("Can't recover from ALSA underrun. (" << snd_strerror(err) << ")"));
- }
- err = snd_pcm_drop(playback_handle);
- if (err < 0)
- {
- throw PiPedalStateException(SS("Can't recover from ALSA underrun. (" << snd_strerror(err) << ")"));
- }
-
- // Prepare both streams
- if ((err = snd_pcm_prepare(playback_handle)) < 0)
- {
- throw std::runtime_error(SS("Cannot prepare playback stream: " << snd_strerror(err)));
- }
- if ((err = snd_pcm_prepare(capture_handle)) < 0)
- {
- throw std::runtime_error(SS("Cannot prepare capture stream: " << snd_strerror(err)));
- }
-
- // Fill the playback buffer with silence
- FillOutputBuffer();
-
- // Resynchronize the streams
- if ((err = snd_pcm_link(capture_handle, playback_handle)) < 0)
- {
- throw std::runtime_error(SS("Cannot relink streams: " << snd_strerror(err)));
- }
-
- // Start the streams
- if ((err = snd_pcm_start(capture_handle)) < 0)
- {
- throw std::runtime_error(SS("Cannot restart capture stream: " << snd_strerror(err)));
- }
- validate_capture_handle();
- }
- else if (err == ESTRPIPE)
- {
- audioRunning = false;
- validate_capture_handle();
-
- while ((err = snd_pcm_resume(capture_handle)) == -EAGAIN)
- {
- sleep(1);
- }
- if (err < 0)
- {
- err = snd_pcm_prepare(capture_handle);
+ err = snd_pcm_drop(capture_handle);
if (err < 0)
{
- throw PiPedalStateException(SS("Can't recover from ALSA suspend. (" << snd_strerror(err) << ")"));
+ throw PiPedalStateException(SS("Can't recover from ALSA underrun. (" << snd_strerror(err) << ")"));
}
+ err = snd_pcm_drop(playback_handle);
+ if (err < 0)
+ {
+ throw PiPedalStateException(SS("Can't recover from ALSA underrun. (" << snd_strerror(err) << ")"));
+ }
+
+ // Prepare both streams
+ if ((err = snd_pcm_prepare(playback_handle)) < 0)
+ {
+ throw std::runtime_error(SS("Cannot prepare playback stream: " << snd_strerror(err)));
+ }
+ if ((err = snd_pcm_prepare(capture_handle)) < 0)
+ {
+ throw std::runtime_error(SS("Cannot prepare capture stream: " << snd_strerror(err)));
+ }
+
+ // Fill the playback buffer with silence
+ FillOutputBuffer();
+
+ // Resynchronize the streams
+ if ((err = snd_pcm_link(capture_handle, playback_handle)) < 0)
+ {
+ throw std::runtime_error(SS("Cannot relink streams: " << snd_strerror(err)));
+ }
+
+ // Start the streams
+ if ((err = snd_pcm_start(capture_handle)) < 0)
+ {
+ throw std::runtime_error(SS("Cannot restart capture stream: " << snd_strerror(err)));
+ }
+ validate_capture_handle();
}
+ else if (err == ESTRPIPE)
+ {
+ audioRunning = false;
+ validate_capture_handle();
+
+ while ((err = snd_pcm_resume(capture_handle)) == -EAGAIN)
+ {
+ sleep(1);
+ }
+ if (err < 0)
+ {
+ err = snd_pcm_prepare(capture_handle);
+ if (err < 0)
+ {
+ throw PiPedalStateException(SS("Can't recover from ALSA suspend. (" << snd_strerror(err) << ")"));
+ }
+ }
+ audioRunning = true;
+ validate_capture_handle();
+ }
+ else
+ {
+ throw PiPedalStateException(SS("Can't recover from ALSA input error. (" << snd_strerror(err) << ")"));
+ }
+ } catch (const std::exception &e) {
+ Lv2Log::info(SS("Soft audio restart failed. " << e.what()));
+ RestartAlsa();
audioRunning = true;
- validate_capture_handle();
- }
- else
- {
- throw std::runtime_error(SS("Can't restart audio: " << snd_strerror(err)));
+
}
}
@@ -1526,6 +1581,11 @@ namespace pipedal
AlsaMidiMessage message;
midiEventCount = 0;
+ auto alsaSequener = this->alsaSequencer; // take an addref
+ if (!alsaSequener)
+ {
+ return;
+ }
while (alsaSequencer->ReadMessage(message, 0))
{
size_t messageSize = message.size;
@@ -1675,11 +1735,11 @@ namespace pipedal
Lv2Log::error(e.what());
Lv2Log::error("ALSA audio thread terminated abnormally.");
}
- this->driverHost->OnAlsaDriverStopped();
// if we terminated abnormally, pump messages until we have been terminated.
if (!terminateAudio())
{
+ this->driverHost->OnAlsaDriverStopped();
// zero out input buffers.
for (size_t i = 0; i < this->captureBuffers.size(); ++i)
{
@@ -1848,6 +1908,8 @@ namespace pipedal
Deactivate();
AlsaCleanup();
DeleteBuffers();
+ this->alsaSequencer = nullptr;
+
std::atomic_thread_fence(std::memory_order::release);
}
@@ -1940,7 +2002,7 @@ namespace pipedal
try
{
int err;
- for (int retry = 0; retry < 2; ++retry)
+ for (int retry = 0; retry < 4; ++retry)
{
err = snd_pcm_open(&playbackHandle, alsaDeviceName.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) // field report of a device that is present, but won't immediately open.
@@ -2202,6 +2264,7 @@ namespace pipedal
#endif
}
+
void FreeAlsaGlobals()
{
snd_config_update_free_global(); // to get a clean Valgrind report.
diff --git a/src/AudioHost.cpp b/src/AudioHost.cpp
index 3cdb7cc..79afb3c 100644
--- a/src/AudioHost.cpp
+++ b/src/AudioHost.cpp
@@ -34,6 +34,7 @@
#include "PluginHost.hpp"
#include "PatchPropertyWriter.hpp"
#include "CpuTemperatureMonitor.hpp"
+#include "restrict.hpp"
using namespace pipedal;
@@ -618,7 +619,7 @@ private:
{
for (size_t i = 0; i < audioDriver->OutputBufferCount(); ++i)
{
- float *out = (float *)audioDriver->GetOutputBuffer(i);
+ float * out = (float *)audioDriver->GetOutputBuffer(i);
if (out)
{
ZeroBuffer(out, nframes);
@@ -1141,7 +1142,7 @@ private:
{
try
{
- float *in, *out;
+ float * restrict in , * restrict out;
Lv2Pedalboard *pedalboard = nullptr;
pedalboard = this->realtimeActivePedalboard;
@@ -1724,6 +1725,7 @@ public:
{
Close();
active = false;
+ isOpen = false;
throw;
}
}
diff --git a/src/AvahiService.cpp b/src/AvahiService.cpp
index a3feb36..c88487d 100644
--- a/src/AvahiService.cpp
+++ b/src/AvahiService.cpp
@@ -40,6 +40,40 @@
using namespace pipedal;
+int avahiPollLockCount = 0;
+static std::mutex avahiLockMutex;
+class AvahiPollLock {
+public:
+ AvahiPollLock() = delete;
+ AvahiPollLock(AvahiThreadedPoll*threadedPoll)
+ : threadedPoll(threadedPoll) {
+ std::lock_guard lock(avahiLockMutex);
+ if (!threadedPoll) {
+ throw std::runtime_error("AvahiPollLock: threadedPoll is null.");
+ }
+ if (++avahiPollLockCount > 1) {
+ throw std::runtime_error("AvahiPollLock: nested locks are not allowed.");
+ }
+ avahi_threaded_poll_lock(threadedPoll);
+ }
+ void release() {
+ std::lock_guard lock(avahiLockMutex);
+ if (threadedPoll)
+ {
+ if (avahiPollLockCount <= 0) {
+ throw std::runtime_error("AvahiPollLock: release called without a lock.");
+ }
+ --avahiPollLockCount;
+ avahi_threaded_poll_unlock(threadedPoll);
+ threadedPoll = nullptr;
+ }
+ }
+ ~AvahiPollLock() {
+ release();
+ }
+private:
+ AvahiThreadedPoll *threadedPoll;
+};
void AvahiService::Announce(
int portNumber,
const std::string &name,
@@ -75,7 +109,7 @@ void AvahiService::Announce(
else
{
// already started, so we have to use poll_lock instead.
- avahi_threaded_poll_lock(threadedPoll);
+ AvahiPollLock lock(threadedPoll);
// all state that we have to protect with the lock now that the avahi serv3ce is running.
this->portNumber = portNumber;
@@ -104,7 +138,7 @@ void AvahiService::Announce(
Lv2Log::error("Failed to update mDNS service because of a synch problem.");
}
}
- avahi_threaded_poll_unlock(threadedPoll);
+ lock.release();
if (wait)
{
Wait();
@@ -118,30 +152,31 @@ void AvahiService::Unannounce(bool wait)
return;
if (this->threadedPoll)
{
- avahi_threaded_poll_lock(threadedPoll);
- if (started)
{
- if (this->createPending)
+ AvahiPollLock lock(threadedPoll);
+ if (started)
{
- // if service is starting up, and we haven't yet made our first announcement,
- // just signal that we don't want to announc.
- this->makeAnnouncement = false;
- }
- else
- {
- this->makeAnnouncement = false;
- // we have previously made a successful announcement. Retract it.
- if (group)
+ if (this->createPending)
{
- int rc = avahi_entry_group_reset(group);
- if (rc < 0)
+ // if service is starting up, and we haven't yet made our first announcement,
+ // just signal that we don't want to announc.
+ this->makeAnnouncement = false;
+ }
+ else
+ {
+ this->makeAnnouncement = false;
+ // we have previously made a successful announcement. Retract it.
+ if (group)
{
- Lv2Log::error("Avahi: failed to un-announce.");
+ int rc = avahi_entry_group_reset(group);
+ if (rc < 0)
+ {
+ Lv2Log::error("Avahi: failed to un-announce.");
+ }
}
}
}
}
- avahi_threaded_poll_unlock(threadedPoll);
if (wait)
{
WaitForUnannounce();
@@ -411,6 +446,7 @@ void AvahiService::Start()
if (!client)
{
+ AvahiPollLock lock(threadedPoll);
/* Allocate a new client */
client = avahi_client_new(avahi_threaded_poll_get(threadedPoll), AvahiClientFlags::AVAHI_CLIENT_NO_FAIL, client_callback, (void *)this, &error);
/* Check wether creating the client object succeeded */
@@ -442,20 +478,22 @@ void AvahiService::Stop()
if (threadedPoll)
{
- avahi_threaded_poll_lock(threadedPoll);
- if (group)
{
- avahi_entry_group_free(group);
- group = nullptr;
+ AvahiPollLock lock(threadedPoll);
+ if (group)
+ {
+ avahi_entry_group_free(group);
+ group = nullptr;
+ }
}
- avahi_threaded_poll_unlock(threadedPoll);
- avahi_threaded_poll_lock(threadedPoll);
- if (client)
{
- avahi_client_free(client);
- client = nullptr;
+ AvahiPollLock lock(threadedPoll);
+ if (client)
+ {
+ avahi_client_free(client);
+ client = nullptr;
+ }
}
- avahi_threaded_poll_unlock(threadedPoll);
avahi_threaded_poll_stop(threadedPoll);
avahi_threaded_poll_free(threadedPoll);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 95faca4..ec8462f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -59,8 +59,8 @@ find_package(sdbus-c++ REQUIRED)
-find_package(ICU REQUIRED COMPONENTS uc i18n )
-message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}")
+find_package(ICU REQUIRED COMPONENTS uc i18n)
+message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}")
if(DEFINED ENV{GITHUB_ACTIONS})
@@ -72,19 +72,19 @@ endif()
#################################################################
# ENABLE/DISABLE VST3 Support.
# Disabled, pending approval of Steinberg VST3 License.
-# Do not enable unless you have non-GPL3 access to the Steinberg
+# Do not enable unless you have non-GPL3 access to the Steinberg
# SDK.
#
-# Plus, there don't seem to be any VST3 plugins for linux, as it
-# turns out. :-/ Status: not completely implemented due to lack
+# Plus, there don't seem to be any VST3 plugins for linux, as it
+# turns out. :-/ Status: not completely implemented due to lack
# of test targets. Deprecated, and non-functional.
#################################################################
set (ENABLE_VST3 0)
-if (ENABLE_VST3)
- set (VST3PATH "../../vst3sdk")
+if (ENABLE_VST3)
+ set (VST3PATH "../../vst3sdk")
message(STATUS " VST3 Support Enabled")
set (VST3_INCLUDES "${VST3PATH}")
set (VST3_LIBRARIES vst3_lib dl)
@@ -129,11 +129,11 @@ pkg_check_modules(ZIP "lilv-0")
set (LV2DEV_INCLUDE_DIRS ) # use lvt headers fro /usr/include
-# Use submodules/websocketpp heders taken from websocketpp/develop branch, because debian-provided
+# Use submodules/websocketpp heders taken from websocketpp/develop branch, because debian-provided
# version of websocketpp cannot compile under GCC 12.x.
-set (WEBSOCKETPP_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/modules/websocketpp)
-message(STATUS "WEBSOCKETPP_INCLUDE_DIRS ${WEBSOCKETPP_INCLUDE_DIRS}" )
+set (WEBSOCKETPP_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/modules/websocketpp)
+message(STATUS "WEBSOCKETPP_INCLUDE_DIRS ${WEBSOCKETPP_INCLUDE_DIRS}")
# pkg_check_modules(JACK "jack")
# if(!JACK_FOUND)
@@ -151,7 +151,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
if (!ENABLE_VST3)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-psabi -DARCHITECTURE=${CPACK_SYSTEM_NAME}")
else()
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar -Wno-psabi")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar -Wno-psabi")
endif()
EXECUTE_PROCESS( COMMAND dpkg --print-architecture COMMAND tr -d '\n' OUTPUT_VARIABLE DEBIAN_ARCHITECTURE )
@@ -163,22 +163,22 @@ if (CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Debug build")
# Must not -D_GLIBCXX_DEBUG, since it conflict with SQLiteCpp.lol
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -DDEBUG " )
- if (USE_SANITIZE)
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -static-libasan " )
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -DDEBUG " )
+ if (USE_SANITIZE)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -static-libasan " )
endif()
elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "RelWithgDebInfo build")
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O3 -DNDEBUG" )
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O3 -ffast-math -DNDEBUG" )
else()
message(STATUS "Release build")
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG" )
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math -DNDEBUG" )
endif()
if (ENABLE_BACKTRACE)
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
if (${DEBIAN_ARCHITECTURE} MATCHES arm64)
- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funwind-tables")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funwind-tables")
endif()
endif()
@@ -189,11 +189,11 @@ endif()
# message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
# set(CMAKE_ENABLE_EXPORTS 1)
-message (STATUS "Cxx flags: ${CMAKE_CXX_FLAGS}" )
+message (STATUS "Cxx flags: ${CMAKE_CXX_FLAGS}")
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_BIND_GLOBAL_PLACEHOLDERS -DONBOARDING)
-
+
if (VST3PATH)
set (VST3_SOURCES
vst3/Vst3Effect.hpp Vst3Effect.cpp
@@ -233,8 +233,8 @@ set (PIPEDAL_SOURCES
WebServerConfig.cpp WebServerConfig.hpp
Locale.hpp Locale.cpp
ZipFile.cpp ZipFile.hpp
- TemporaryFile.cpp TemporaryFile.hpp
- FilePropertyDirectoryTree.cpp FilePropertyDirectoryTree.hpp
+ TemporaryFile.cpp TemporaryFile.hpp
+ FilePropertyDirectoryTree.cpp FilePropertyDirectoryTree.hpp
FileEntry.cpp FileEntry.hpp
atom_object.hpp atom_object.cpp
lv2ext/pipedal.lv2/ext/fileBrowser.h
@@ -243,7 +243,7 @@ set (PIPEDAL_SOURCES
DbDezipper.hpp DbDezipper.cpp
WebServerLog.hpp
WifiChannelSelectors.cpp WifiChannelSelectors.hpp
-
+
PiPedalUI.hpp
PiPedalUI.cpp
MapPathFeature.hpp
@@ -319,15 +319,15 @@ set (PIPEDAL_SOURCES
configure_file(config.hpp.in config.hpp)
include_directories(
- ${pipedald_SOURCE_DIR}/.
+ ${pipedald_SOURCE_DIR}/.
../build/src
- )
+ )
-set (PIPEDAL_INCLUDES
+set (PIPEDAL_INCLUDES
${LV2DEV_INCLUDE_DIRS}
- ${JACK_INCLUDE_DIRS} ${LILV_0_INCLUDE_DIRS}
+ ${JACK_INCLUDE_DIRS} ${LILV_0_INCLUDE_DIRS}
${VST3_INCLUDES}
- ${WEBSOCKETPP_INCLUDE_DIRS}
+ ${WEBSOCKETPP_INCLUDE_DIRS}
${PipeWire_INCLUDE_DIRS}
.
)
@@ -337,7 +337,7 @@ set(PIPEDAL_LIBS libpipedald zip
PiPedalCommon
pthread atomic stdc++fs asound avahi-common avahi-client systemd
${VST3_LIBRARIES}
- ${LILV_0_LIBRARIES}
+ ${LILV_0_LIBRARIES}
asound
# ${JACK_LIBRARIES} - pending delete for JACK support.
)
@@ -345,16 +345,15 @@ set(PIPEDAL_LIBS libpipedald zip
##########################
-
+
add_library(libpipedald STATIC ${PIPEDAL_SOURCES})
target_compile_definitions(libpipedald PUBLIC "_REENTRANT")
-target_include_directories(libpipedald PUBLIC ${PIPEDAL_INCLUDES}
- )
+target_include_directories(libpipedald PUBLIC ${PIPEDAL_INCLUDES})
-target_link_libraries(libpipedald
- PUBLIC
+target_link_libraries(libpipedald
+ PUBLIC
PiPedalCommon
SQLiteCpp
${PipeWire_LIBRARIES}
@@ -382,26 +381,23 @@ target_link_libraries(pipedal_kconfig
PRIVATE PiPedalCommon
asound
systemd
-)
+)
#################################
-add_executable(pipedald
+add_executable(pipedald
asan_options.cpp # disable leak checking for sanitize=address.
- main.cpp
+ main.cpp
)
target_include_directories(pipedald PRIVATE ${PIPEDAL_INCLUDES})
target_compile_definitions(pipedald PRIVATE "ENABLE_BACKTRACE=${ENABLE_BACKTRACE}")
-target_link_libraries(pipedald PRIVATE PiPedalCommon
-
- ${PIPEDAL_LIBS}
- )
+target_link_libraries(pipedald PRIVATE PiPedalCommon ${PIPEDAL_LIBS})
#################################
-add_executable(hotspotManagerTest
+add_executable(hotspotManagerTest
hotspotManagerTestMain.cpp
HotspotManager.cpp HotspotManager.hpp)
@@ -416,7 +412,7 @@ add_executable(AuxInTest
AuxInTest.cpp
)
-add_executable(pipedaltest
+add_executable(pipedaltest
testMain.cpp
ModGuiTest.cpp
@@ -427,9 +423,9 @@ add_executable(pipedaltest
ModFileTypesTest.cpp
jsonTest.cpp
UpdaterTest.cpp
-
+
utilTest.cpp
-
+
AlsaDriverTest.cpp
AvahiServiceTest.cpp
WifiChannelsTest.cpp
@@ -448,29 +444,23 @@ add_executable(pipedaltest
MemDebug.hpp
)
target_link_libraries(pipedaltest PRIVATE ${PIPEDAL_LIBS} ${ICU_LIBRARIES})
-target_include_directories(pipedaltest PRIVATE ${PIPEDAL_INCLUDES}
-)
+target_include_directories(pipedaltest PRIVATE ${PIPEDAL_INCLUDES})
set_target_properties(pipedaltest PROPERTIES EXCLUDE_FROM_ALL ${PIPEDAL_EXCLUDE_TESTS})
if (NOT GITHUB_ACTIONS) # Google perftools are not available on Github action servers.
-
-
-
add_executable(pipedalProfilePlugin
profilePluginMain.cpp ArmPerformanceCounters.hpp
)
- target_link_libraries(pipedalProfilePlugin PRIVATE profiler ${PIPEDAL_LIBS})
+ target_link_libraries(pipedalProfilePlugin PRIVATE profiler ${PIPEDAL_LIBS})
target_include_directories(pipedalProfilePlugin PRIVATE ${PIPEDAL_INCLUDES}
)
if (${DEBIAN_ARCHITECTURE} MATCHES arm64)
target_compile_definitions(pipedalProfilePlugin PRIVATE "PIPEDAL_AARCH64")
- endif()
-
-
-
+ endif()
endif()
+
add_executable(jsonTest
testMain.cpp
jsonTest.cpp
@@ -484,8 +474,7 @@ add_executable(jsonTest
PromiseTest.cpp
)
target_link_libraries(jsonTest PRIVATE PiPedalCommon)
-target_include_directories(jsonTest PRIVATE ${PIPEDAL_INCLUDES}
- )
+target_include_directories(jsonTest PRIVATE ${PIPEDAL_INCLUDES})
set_target_properties(jsonTest PROPERTIES EXCLUDE_FROM_ALL ${PIPEDAL_EXCLUDE_TESTS})
@@ -498,7 +487,7 @@ add_test(NAME jsonTest COMMAND jsonTest)
-include_directories( ${pipedald_SOURCE_DIR}/. ../build/src)
+include_directories( ${pipedald_SOURCE_DIR}/. ../build/src)
if(${USE_PCH})
target_precompile_headers(pipedaltest PRIVATE pch.h)
@@ -508,25 +497,25 @@ endif()
target_include_directories(pipedaltest PRIVATE ${PIPEDAL_INCLUDES}
)
-target_link_libraries(pipedaltest PRIVATE ${PIPEDAL_LIBS}
+target_link_libraries(pipedaltest PRIVATE ${PIPEDAL_LIBS}
)
#########################################################
# VST3 Source.
#
-# VST3 support is optional, because it poses unfortunate
+# VST3 support is optional, because it poses unfortunate
# licensing problems.
# There's no easy way to get the VST SDK to build without
-# GCC c++11 linkage, which is not compatible with pipedal's
+# GCC c++11 linkage, which is not compatible with pipedal's
# use of C++20 features (strictly a link time breakage).
#
# So pipedal rebuilds the VST3 SDK using pipedal-compatible
# compile flags.
#
-# The current build supports only Linux builds. Refer to the
-# original VST3 SDK build for details on how to build
+# The current build supports only Linux builds. Refer to the
+# original VST3 SDK build for details on how to build
# for other platforms.
#
#########################################################
@@ -566,12 +555,12 @@ if(ENABLE_VST3)
${VST3_BASEPATH}/source/timer.h
${VST3_BASEPATH}/source/updatehandler.cpp
${VST3_BASEPATH}/source/updatehandler.h
-
+
${VST3_BASEPATH}/thread/include/fcondition.h
${VST3_BASEPATH}/thread/include/flock.h
${VST3_BASEPATH}/thread/source/fcondition.cpp
${VST3_BASEPATH}/thread/source/flock.cpp
-
+
# sdk_common files.
@@ -615,7 +604,7 @@ if(ENABLE_VST3)
${VST3_PLUGININTERFACES_BASE_PATH}/ucolorspec.h
${VST3_PLUGININTERFACES_BASE_PATH}/ustring.cpp
${VST3_PLUGININTERFACES_BASE_PATH}/ustring.h
-
+
# sdk files.
# ${VST3_SRCPATH}/main/moduleinit.cpp
@@ -664,7 +653,7 @@ if(ENABLE_VST3)
${VST3_SRCPATH}/vst/hosting/module.cpp
${VST3_SRCPATH}/vst/hosting/module.h
${VST3_SRCPATH}/vst/hosting/parameterchanges.cpp
- ${VST3_SRCPATH}/vst/hosting/parameterchanges.h
+ ${VST3_SRCPATH}/vst/hosting/parameterchanges.h
${VST3_SRCPATH}/vst/hosting/pluginterfacesupport.cpp
${VST3_SRCPATH}/vst/hosting/pluginterfacesupport.h
${VST3_SRCPATH}/vst/hosting/plugprovider.cpp
@@ -693,10 +682,10 @@ if(ENABLE_VST3)
add_library(vst3_lib STATIC ${vst3_sources})
- target_include_directories(vst3_lib PRIVATE ${VST3_INCLUDES}
+ target_include_directories(vst3_lib PRIVATE ${VST3_INCLUDES}
)
-
+
# add_executable(vst3test Vst3test.cpp
# MemDebug.cpp
@@ -705,16 +694,15 @@ if(ENABLE_VST3)
# Vst3SdkRepro.cpp
# ${VST3_FILES}
-
+
# #vst3/Vst3PresetFile.hpp Vst3PresetFile.cpp
# asan_options.cpp
# )
- target_include_directories(vst3test PRIVATE ${PIPEDAL_INCLUDES}
- )
+ target_include_directories(vst3test PRIVATE ${PIPEDAL_INCLUDES})
-
- target_link_libraries(vst3test PRIVATE ${PIPEDAL_LIBS}
+
+ target_link_libraries(vst3test PRIVATE ${PIPEDAL_LIBS}
vst3_lib dl pthread
)
@@ -733,11 +721,11 @@ add_test(NAME DevTest COMMAND pipedaltest "[Dev]")
-add_executable(pipedalconfig
+add_executable(pipedalconfig
PrettyPrinter.hpp
SetWifiConfig.cpp SetWifiConfig.hpp
CommandLineParser.hpp
- PiPedalException.hpp
+ PiPedalException.hpp
ConfigMain.cpp
alsaCheck.cpp
alsaCheck.hpp
@@ -773,13 +761,12 @@ add_executable(pipedal_latency_test
CpuUse.cpp
)
-target_link_libraries(pipedal_latency_test PRIVATE pthread asound PiPedalCommon
- )
-
+target_link_libraries(pipedal_latency_test PRIVATE pthread asound PiPedalCommon)
+
add_executable(pipedal_alsa_info
alsaCheck.cpp alsaCheck.hpp
- alsaCheckMain.cpp
+ alsaCheckMain.cpp
)
target_link_libraries(pipedal_alsa_info PRIVATE asound)
@@ -788,7 +775,7 @@ add_executable(capturepresets
Storage.cpp
Storage.hpp
CommandLineParser.hpp
-)
+)
target_include_directories(capturepresets PRIVATE ${PIPEDAL_INCLUDES})
@@ -797,7 +784,7 @@ target_link_libraries(capturepresets ${PIPEDAL_LIBS})
add_executable(makeRelease
makeReleaseMain.cpp
CommandLineParser.hpp
-)
+)
target_include_directories(makeRelease PRIVATE ${PIPEDAL_INCLUDES})
target_link_libraries(makeRelease ${PIPEDAL_LIBS})
@@ -807,14 +794,14 @@ target_link_libraries(makeRelease ${PIPEDAL_LIBS})
add_executable(pipedal_update
- UpdateMain.cpp
+ UpdateMain.cpp
UpdateResults.cpp UpdateResults.hpp
Lv2SystemdLogger.cpp Lv2SystemdLogger.hpp
TemporaryFile.cpp TemporaryFile.hpp
AdminInstallUpdate.cpp AdminInstallUpdate.hpp
)
-target_link_libraries(pipedal_update PRIVATE stdc++fs systemd PiPedalCommon )
+target_link_libraries(pipedal_update PRIVATE stdc++fs systemd PiPedalCommon )
add_executable(pipedaladmind AdminMain.cpp CommandLineParser.hpp
@@ -824,7 +811,7 @@ add_executable(pipedaladmind AdminMain.cpp CommandLineParser.hpp
JackServerSettings.hpp JackServerSettings.cpp
Lv2SystemdLogger.hpp Lv2SystemdLogger.cpp
- SystemConfigFile.hpp SystemConfigFile.cpp
+ SystemConfigFile.hpp SystemConfigFile.cpp
CpuGovernor.cpp CpuGovernor.hpp
asan_options.cpp
@@ -832,9 +819,9 @@ add_executable(pipedaladmind AdminMain.cpp CommandLineParser.hpp
target_link_libraries(pipedaladmind PRIVATE PiPedalCommon pthread atomic stdc++fs systemd )
add_executable(processcopyrights copyrightMain.cpp
- CommandLineParser.hpp
- PiPedalException.hpp
- asan_options.cpp )
+ CommandLineParser.hpp
+ PiPedalException.hpp
+ asan_options.cpp)
target_link_libraries(processcopyrights PRIVATE PiPedalCommon stdc++fs)
set (REACT_BUILD_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../build/react/build/)
@@ -854,13 +841,13 @@ elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
else()
message(FATAL_ERROR "Boost libary version has changed. Please update me.")
-endif()
+endif()
-add_custom_command(OUTPUT ${REACT_NOTICES_FILE}
+add_custom_command(OUTPUT ${REACT_NOTICES_FILE}
COMMAND "$"
- --output ${REACT_NOTICES_FILE}
- --projectCopyright ${DEBIAN_COPYRIGHT_FILE}
+ --output ${REACT_NOTICES_FILE}
+ --projectCopyright ${DEBIAN_COPYRIGHT_FILE}
liblilv-0-0 ${BOOST_COPYRIGHT_DIR} lv2-dev libsdbus-c++-dev librsvg2-2 libpango-1.0-0 libx11-6 libxrandr2
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${DEBIAN_COPYRIGHT_FILE} "$"
@@ -869,14 +856,14 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
add_custom_target (
CopyrightBuild ALL
- DEPENDS ${REACT_NOTICES_FILE}
+ DEPENDS ${REACT_NOTICES_FILE}
)
install (TARGETS pipedalconfig pipedal_kconfig pipedal_latency_test DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
EXPORT pipedalTargets)
- install (TARGETS pipedald pipedaladmind pipedal_update DESTINATION ${CMAKE_INSTALL_PREFIX}/sbin
+install (TARGETS pipedald pipedaladmind pipedal_update DESTINATION ${CMAKE_INSTALL_PREFIX}/sbin
EXPORT pipedalSbinTargets)
diff --git a/src/Lv2Effect.cpp b/src/Lv2Effect.cpp
index e7dd6cc..c964222 100644
--- a/src/Lv2Effect.cpp
+++ b/src/Lv2Effect.cpp
@@ -18,6 +18,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pch.h"
+#include "restrict.hpp"
#include "Lv2Effect.hpp"
#include "PiPedalException.hpp"
#include
@@ -514,15 +515,15 @@ int Lv2Effect::GetControlIndex(const std::string &key) const
Lv2Effect::~Lv2Effect()
{
- if (activated)
- {
- Deactivate();
- }
if (worker)
{
worker->Close();
worker = nullptr; // delete the worker first!
}
+ if (activated)
+ {
+ Deactivate();
+ }
if (pInstance)
{
lilv_instance_free(pInstance);
@@ -635,7 +636,7 @@ void Lv2Effect::Deactivate()
lilv_instance_deactivate(pInstance);
}
-static inline void CopyBuffer(float *input, float *output, uint32_t frames)
+static inline void CopyBuffer(float *restrict input, float *restrict output, uint32_t frames)
{
for (uint32_t i = 0; i < frames; ++i)
{
@@ -673,7 +674,7 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
{
for (size_t i = 0; i < this->outputMixBuffers.size(); ++i)
{
- float *__restrict input;
+ float *restrict input;
if (i >= this->inputAudioBuffers.size())
{
if (this->inputAudioBuffers.size() == 0)
@@ -686,8 +687,8 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
{
input = this->inputAudioBuffers[i];
}
- float *__restrict pluginOutput = this->outputMixBuffers[i].data();
- float *__restrict finalOutput = this->outputAudioBuffers[i];
+ float *restrict pluginOutput = this->outputMixBuffers[i].data();
+ float *restrict finalOutput = this->outputAudioBuffers[i];
for (uint32_t i = 0; i < samples; ++i)
{
@@ -698,11 +699,11 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
else if (this->outputAudioPortIndices.size() == 1 && this->outputAudioBuffers.size() == 2)
{
// 1 plugin output into 2 outputs.
- float *__restrict pluginOutput = this->outputMixBuffers[0].data();
+ float *restrict pluginOutput = this->outputMixBuffers[0].data();
for (size_t i = 0; i < this->outputMixBuffers.size(); ++i)
{
- float *__restrict input = this->inputAudioBuffers[i];
- float *__restrict finalOutput = this->outputAudioBuffers[i];
+ float *restrict input = this->inputAudioBuffers[i];
+ float *restrict finalOutput = this->outputAudioBuffers[i];
for (uint32_t i = 0; i < samples; ++i)
{
@@ -750,8 +751,8 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
if (this->outputAudioBuffers.size() == 1)
{
- float *input = this->inputAudioBuffers[0];
- float *output = this->outputAudioBuffers[0];
+ float * restrict input = this->inputAudioBuffers[0];
+ float * restrict output = this->outputAudioBuffers[0];
for (uint32_t i = 0; i < samples; ++i)
{
output[i] = currentBypass * output[i] + (1 - currentBypass) * input[i];
@@ -766,8 +767,8 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
}
else
{
- float *inputL;
- float *inputR;
+ float * restrict inputL;
+ float * restrict inputR;
if (this->inputAudioBuffers.size() == 1)
{
inputL = inputR = inputAudioBuffers[0];
@@ -777,8 +778,8 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
inputL = inputAudioBuffers[0];
inputR = inputAudioBuffers[1];
}
- float *outputL = outputAudioBuffers[0];
- float *outputR = outputAudioBuffers[1];
+ float * restrict outputL = outputAudioBuffers[0];
+ float * restrict outputR = outputAudioBuffers[1];
for (uint32_t i = 0; i < samples; ++i)
{
outputL[i] = currentBypass * outputL[i] + (1 - currentBypass) * inputL[i];
diff --git a/src/Lv2Pedalboard.cpp b/src/Lv2Pedalboard.cpp
index df6d0bd..4721f95 100644
--- a/src/Lv2Pedalboard.cpp
+++ b/src/Lv2Pedalboard.cpp
@@ -28,6 +28,7 @@
#include "Lv2EventBufferWriter.hpp"
#include "Lv2Log.hpp"
#include "CrashGuard.hpp"
+#include "restrict.hpp"
using namespace pipedal;
@@ -417,7 +418,7 @@ void Lv2Pedalboard::Deactivate()
}
}
-static void Copy(float *input, float *output, uint32_t samples)
+static void Copy(float *restrict input, float *restrict output, uint32_t samples)
{
for (uint32_t i = 0; i < samples; ++i)
{
@@ -434,6 +435,7 @@ bool Lv2Pedalboard::Run(float **inputBuffers, float **outputBuffers, uint32_t sa
return false;
}
}
+
for (size_t i = 0; i < samples; ++i)
{
float volume = this->inputVolume.Tick();
diff --git a/src/SchedulerPriority.cpp b/src/SchedulerPriority.cpp
index 0eb5194..8effce9 100644
--- a/src/SchedulerPriority.cpp
+++ b/src/SchedulerPriority.cpp
@@ -104,7 +104,7 @@ static void SetPriority(int realtimePriority, const char *priorityName)
int result = sched_setscheduler(0, SCHED_RR, ¶m);
if (result == 0)
{
- Lv2Log::debug("Service thread priority successfully boosted.");
+ Lv2Log::debug(SS("Service thread priority successfully boosted. (" << priorityName << ")"));
return;
}
else
diff --git a/src/Worker.cpp b/src/Worker.cpp
index 7fcca63..a1baea1 100644
--- a/src/Worker.cpp
+++ b/src/Worker.cpp
@@ -143,6 +143,7 @@ bool Worker::EmitResponses()
void Worker::WaitForAllResponses()
{
+ // do what we can to clear the response queue in order to avoid memory/object leaks
using Clock = std::chrono::steady_clock;
auto startTime = Clock::now();
while (true)
@@ -157,11 +158,14 @@ void Worker::WaitForAllResponses()
break;
}
}
- std::chrono::seconds waitDuration = std::chrono::duration_cast(Clock::now()-startTime);
- if (waitDuration.count() > 5) {
- throw std::logic_error("Timed out waiting for a Worker task to complete.");
+ // pump the plugin with a zero-length buffer.
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ std::chrono::milliseconds waitDuration = std::chrono::duration_cast(Clock::now()-startTime);
+ if (waitDuration.count() > 1500) {
+ Lv2Log::error("Timed out waiting for a Worker task to complete.");
+ // better to leak than to terminate the application.
}
- std::this_thread::sleep_for(std::chrono::milliseconds(15));
}
}
@@ -260,21 +264,16 @@ bool HostWorkerThread::StartThread()
void HostWorkerThread::Close()
{
- bool sendClose = false;
{
std::lock_guard lock{submitMutex};
if (pThread) {
if (!closed)
{
closed = true;
- sendClose = true;
+ ScheduleWorkNoLock(nullptr, 0, nullptr);
}
}
}
- if (sendClose)
- {
- ScheduleWork(nullptr, 0, nullptr);
- }
}
HostWorkerThread::~HostWorkerThread()
{
@@ -302,6 +301,11 @@ LV2_Worker_Status HostWorkerThread::ScheduleWork(Worker *worker, size_t size, co
{
exiting = true;
}
+ return ScheduleWorkNoLock(worker, size, data);
+
+}
+LV2_Worker_Status HostWorkerThread::ScheduleWorkNoLock(Worker *worker, size_t size, const void *data)
+{
if (requestRingBuffer.writeSpace() < sizeof(worker) + sizeof(size) + size)
{
diff --git a/src/Worker.hpp b/src/Worker.hpp
index 9cf38aa..154ec3d 100644
--- a/src/Worker.hpp
+++ b/src/Worker.hpp
@@ -57,6 +57,7 @@ namespace pipedal {
bool Closed() const { return closed || pThread == nullptr; }
LV2_Worker_Status ScheduleWork(Worker*worker, size_t size, const void*data);
private:
+ LV2_Worker_Status ScheduleWorkNoLock(Worker*worker, size_t size, const void*data);
std::atomic closed = false;
std::unique_ptr pThread;
void ThreadProc() noexcept;
diff --git a/vite/src/pipedal/PiPedalModel.tsx b/vite/src/pipedal/PiPedalModel.tsx
index 45a0d13..c62ddf6 100644
--- a/vite/src/pipedal/PiPedalModel.tsx
+++ b/vite/src/pipedal/PiPedalModel.tsx
@@ -1844,6 +1844,7 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.deleteItem(fromInstanceId);
newPedalboard.addBefore(fromItem, toInstanceId);
+ newPedalboard.selectedPlugin = fromItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
@@ -1863,7 +1864,7 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.deleteItem(fromInstanceId);
newPedalboard.addAfter(fromItem, toInstanceId);
-
+ newPedalboard.selectedPlugin = fromItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
}
@@ -1885,6 +1886,7 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.addToStart(fromItem);
+ newPedalboard.selectedPlugin = fromItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
}
@@ -1904,6 +1906,7 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.addToEnd(fromItem);
+ newPedalboard.selectedPlugin = fromItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
@@ -1931,7 +1934,7 @@ export class PiPedalModel //implements PiPedalModel
let emptyItem = newPedalboard.createEmptyItem();
newPedalboard.replaceItem(fromInstanceId, emptyItem);
newPedalboard.replaceItem(toInstanceId, fromItem);
-
+ newPedalboard.selectedPlugin = fromItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
@@ -1955,6 +1958,7 @@ export class PiPedalModel //implements PiPedalModel
}
let newItem = newPedalboard.createEmptyItem();
newPedalboard.addItem(newItem, instanceId, append);
+ newPedalboard.selectedPlugin = newItem.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
return newItem.instanceId;
@@ -1980,6 +1984,8 @@ export class PiPedalModel //implements PiPedalModel
}
let newItem = newPedalboard.createEmptySplit();
newPedalboard.addItem(newItem, instanceId, append);
+ newPedalboard.selectedPlugin = newItem.instanceId;
+
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
return newItem.instanceId;
@@ -1998,6 +2004,7 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.setItemEmpty(item);
+ newPedalboard.selectedPlugin = item.instanceId;
this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard();
return item.instanceId;