Merge branch 'splitio_base' of https://github.com/rerdavies/pipedal into dev_splitio_merge

This commit is contained in:
Robin E. R. Davies
2025-09-08 08:55:44 -04:00
24 changed files with 664 additions and 207 deletions
+10 -4
View File
@@ -683,6 +683,7 @@ namespace pipedal
if (this->captureHandle)
{
this->alsa_device_name = this->jackServerSettings.GetAlsaInputDevice();
AlsaConfigureStream(
this->alsa_device_name,
"capture",
@@ -695,6 +696,7 @@ namespace pipedal
}
if (this->playbackHandle)
{
this->alsa_device_name = this->jackServerSettings.GetAlsaOutputDevice();
AlsaConfigureStream(
this->alsa_device_name,
"playback",
@@ -1326,7 +1328,9 @@ namespace pipedal
int err;
alsa_device_name = jackServerSettings.GetAlsaInputDevice();
std::string inputName = jackServerSettings.GetAlsaInputDevice();
std::string outputName = jackServerSettings.GetAlsaOutputDevice();
this->numberOfBuffers = jackServerSettings.GetNumberOfBuffers();
this->bufferSize = jackServerSettings.GetBufferSize();
@@ -1335,7 +1339,8 @@ namespace pipedal
try
{
err = snd_pcm_open(&playbackHandle, alsa_device_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
this->alsa_device_name = outputName;
err = snd_pcm_open(&playbackHandle, outputName.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0)
{
switch (errno)
@@ -1369,8 +1374,9 @@ namespace pipedal
{
snd_pcm_nonblock(playbackHandle, 0);
}
err = snd_pcm_open(&captureHandle, alsa_device_name.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
this->alsa_device_name = inputName;
err = snd_pcm_open(&captureHandle, inputName.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
if (err < 0)
{
+1 -1
View File
@@ -64,7 +64,7 @@ public:
AlsaFormatEncodeDecodeTest(this);
JackServerSettings serverSettings("hw:M2",48000,32,3);
JackServerSettings serverSettings("hw:M2","hw:M2",48000,32,3);
JackConfiguration jackConfiguration;
if (useJack)
+11 -6
View File
@@ -140,14 +140,19 @@ namespace pipedal
overheadTime = readTime;
}
SampleT totalTime = writeTime+ readTime + processingTime;
SampleT maxTime = waitTime+processingTime;
SampleT totalTime = writeTime + readTime + processingTime;
SampleT maxTime = waitTime + processingTime;
float result = 100.0f*(processingTime)/(maxTime);
float overhead = 100.0F*(overheadTime*2)/totalTime;
float result = 0.0f;
float overhead = 0.0f;
if (maxTime != 0 && totalTime != 0)
{
std::lock_guard lock { sync};
result = 100.0f * (processingTime) / (maxTime);
overhead = 100.0f * (overheadTime * 2) / totalTime;
}
{
std::lock_guard lock{sync};
currentCpuUse = result;
currentOverhead = overhead;
}
+2
View File
@@ -517,6 +517,8 @@ namespace pipedal
result.sampleRates_.push_back(48000);
result.minBufferSize_ = 16;
result.maxBufferSize_ = 1024;
result.supportsCapture_ = true;
result.supportsPlayback_ = true;
return result;
}
+10 -2
View File
@@ -148,7 +148,13 @@ void JackServerSettings::ReadJackDaemonConfiguration()
this->bufferSize_ = GetJackArg(argv, "-p", "--period");
this->numberOfBuffers_ = (uint32_t)GetJackArg(argv, "-n", "--nperiods");
this->sampleRate_ = (uint32_t)GetJackArg(argv, "-r", "--rate");
this->alsaDevice_ = GetJackStringArg(argv,"-d", "--device");
// read new dual device flags, fallback on old -d/--device
std::string capDev = GetJackStringArg(argv, "-C", "--capture");
std::string playDev = GetJackStringArg(argv, "-P", "--playback");
std::string dev = "";
try { dev = GetJackStringArg(argv, "-d", "--device"); } catch(...) {}
this->alsaInputDevice_ = capDev.empty() ? dev : capDev;
this->alsaOutputDevice_ = playDev.empty() ? dev : playDev;
this->valid_ = true;
}
catch (std::exception &)
@@ -246,7 +252,9 @@ JSON_MAP_REFERENCE(JackServerSettings, valid)
JSON_MAP_REFERENCE(JackServerSettings, isOnboarding)
JSON_MAP_REFERENCE(JackServerSettings, rebootRequired)
JSON_MAP_REFERENCE(JackServerSettings, isJackAudio)
JSON_MAP_REFERENCE(JackServerSettings, alsaDevice)
JSON_MAP_REFERENCE(JackServerSettings, alsaDevice) // legacy field
JSON_MAP_REFERENCE(JackServerSettings, alsaInputDevice)
JSON_MAP_REFERENCE(JackServerSettings, alsaOutputDevice)
JSON_MAP_REFERENCE(JackServerSettings, sampleRate)
JSON_MAP_REFERENCE(JackServerSettings, bufferSize)
JSON_MAP_REFERENCE(JackServerSettings, numberOfBuffers)
+22 -15
View File
@@ -31,7 +31,9 @@ namespace pipedal
bool isOnboarding_ = true;
bool isJackAudio_ = JACK_HOST ? true : false;
bool rebootRequired_ = false;
std::string alsaDevice_;
std::string alsaInputDevice_;
std::string alsaOutputDevice_;
std::string alsaDevice_; // legacy
uint64_t sampleRate_ = 0;
uint32_t bufferSize_ = 64;
uint32_t numberOfBuffers_ = 3;
@@ -39,10 +41,14 @@ namespace pipedal
public:
JackServerSettings();
JackServerSettings(
const std::string alsaInputDevice,
uint64_t sampleRate, uint32_t bufferSize, uint32_t numberOfBuffers)
const std::string &alsaInputDevice,
const std::string &alsaOutputDevice,
uint64_t sampleRate,
uint32_t bufferSize,
uint32_t numberOfBuffers)
: valid_(true),
alsaDevice_(alsaInputDevice),
alsaInputDevice_(alsaInputDevice),
alsaOutputDevice_(alsaOutputDevice),
sampleRate_(sampleRate),
bufferSize_(bufferSize),
numberOfBuffers_(numberOfBuffers),
@@ -51,9 +57,13 @@ namespace pipedal
}
uint64_t GetSampleRate() const { return sampleRate_; }
uint32_t GetBufferSize() const { return bufferSize_; }
uint32_t GetNumberOfBuffers() const { return numberOfBuffers_; }
const std::string &GetAlsaInputDevice() const { return alsaDevice_; }
const std::string &GetAlsaInputDevice() const { return alsaInputDevice_; }
const std::string &GetAlsaOutputDevice() const { return alsaOutputDevice_; }
const std::string &GetLegacyAlsaDevice() const { return alsaDevice_; } //legacy
void SetLegacyAlsaDevice(const std::string &d) { alsaDevice_ = d; }
void UseDummyAudioDevice() {
this->valid_ = true;
if (sampleRate_ == 0) sampleRate_ = 48000;
@@ -69,14 +79,6 @@ namespace pipedal
bool IsValid() const { return valid_; }
// JackServerSettings(uint64_t sampleRate, uint32_t bufferSize, uint32_t numberOfBuffers)
// {
// this->valid_ = true;
// this->rebootRequired_ = true;
// this->sampleRate_ = sampleRate;
// this->bufferSize_ = bufferSize;
// this->numberOfBuffers_ = numberOfBuffers;
// }
void WriteDaemonConfig(); // requires root perms.
void SetRebootRequired(bool value)
{
@@ -87,9 +89,14 @@ namespace pipedal
isOnboarding_ = value;
}
bool Equals(const JackServerSettings &other)
bool Equals(const JackServerSettings &other) const
{
return this->alsaDevice_ == other.alsaDevice_ && this->sampleRate_ == other.sampleRate_ && this->bufferSize_ == other.bufferSize_ && this->numberOfBuffers_ == other.numberOfBuffers_;
return this->alsaInputDevice_ == other.alsaInputDevice_ &&
this->alsaOutputDevice_ == other.alsaOutputDevice_ &&
this->alsaDevice_ == other.alsaDevice_ &&
this->sampleRate_ == other.sampleRate_ &&
this->bufferSize_ == other.bufferSize_ &&
this->numberOfBuffers_ == other.numberOfBuffers_;
}
DECLARE_JSON_MAP(JackServerSettings);
+25 -16
View File
@@ -57,9 +57,9 @@ void PrintHelp()
pp << "Copyright (c) 2022 Robin Davies\n";
pp << "\n";
pp << Indent(0) << "Syntax\n\n";
pp << Indent(2) << "pipedal_latency_test [<options>] <device-name>\n\n";
pp << "where <device-name> is the name of an ALSA device. Typically this should be the name of a hardware "
"device (a device name starting with 'hw:').\n\n";
pp << Indent(2) << "pipedal_latency_test [<options>] <input-device> [<output-device>]\n\n";
pp << "where <input-device> is the name of an ALSA capture device and <output-device> is the name of a playback device. "
"If <output-device> is omitted, the input device will be used for both capture and playback. Typically the device names start with 'hw:'.\n\n";
pp << Indent(0) << "Options\n\n";
pp << Indent(15);
@@ -95,7 +95,8 @@ void PrintHelp()
pp << Indent(0) << "Examples\n\n";
pp << Indent(2) << "pipedal_latency_test --list\n\n";
pp << Indent(2) << "pipedal_latency_test hw:M2\n\n";
pp << Indent(2) << "pipedal_latency_test hw:M2 hw:M2\n";
pp << Indent(2) << "pipedal_latency_test hw:M2 hw:Device2\n\n";
}
void ListDevices()
@@ -138,7 +139,8 @@ public:
private:
AudioDriver *audioDriver = nullptr;
const std::string &deviceId;
const std::string &inputDeviceId;
const std::string &outputDeviceId;
ChannelsT inputChannels;
ChannelsT outputChannels;
uint32_t sampleRate;
@@ -147,11 +149,13 @@ private:
public:
AlsaTester(
const std::string &deviceId,
const std::string &inputDeviceId,
const std::string &outputDeviceId,
const ChannelsT &inputChannels,
const ChannelsT &outputChannels,
uint32_t sampleRate, int bufferSize, int buffers)
: deviceId(deviceId),
: inputDeviceId(inputDeviceId),
outputDeviceId(outputDeviceId),
sampleRate(sampleRate),
inputChannels(inputChannels),
outputChannels(outputChannels),
@@ -186,7 +190,7 @@ public:
TestResult result;
try
{
JackServerSettings serverSettings(deviceId, sampleRate, bufferSize, buffers);
JackServerSettings serverSettings(inputDeviceId, outputDeviceId, sampleRate, bufferSize, buffers);
JackConfiguration jackConfiguration;
jackConfiguration.AlsaInitialize(serverSettings);
@@ -403,12 +407,13 @@ public:
};
TestResult RunLatencyTest(
const std::string deviceId,
const std::string inputDeviceId,
const std::string outputDeviceId,
const ChannelsT &inputChannels,
const ChannelsT &outputChannels,
uint32_t sampleRate, int bufferSize, int buffers)
{
AlsaTester tester(deviceId, inputChannels, outputChannels, sampleRate, bufferSize, buffers);
AlsaTester tester(inputDeviceId, outputDeviceId, inputChannels, outputChannels, sampleRate, bufferSize, buffers);
return tester.Test();
}
@@ -428,13 +433,14 @@ static std::string overheadDisplay(float value)
}
void RunLatencyTest(
const std::string &deviceId,
const std::string &inputDeviceId,
const std::string &outputDeviceId,
const ChannelsT &inputChannels,
const ChannelsT &outputChannels,
uint32_t sampleRate)
{
PrettyPrinter pp;
pp << "Device: " << deviceId << " Rate: " << sampleRate << "\n\n";
pp << "Input: " << inputDeviceId << " Output: " << outputDeviceId << " Rate: " << sampleRate << "\n\n";
const int SIZE_COLUMN_WIDTH = 8;
const int BUFFERS_COLUMN_WIDTH = 20;
@@ -461,7 +467,7 @@ void RunLatencyTest(
for (auto bufferCount : bufferCounts)
{
auto result = RunLatencyTest(deviceId, inputChannels,outputChannels, sampleRate, bufferSize, bufferCount);
auto result = RunLatencyTest(inputDeviceId, outputDeviceId, inputChannels,outputChannels, sampleRate, bufferSize, bufferCount);
pp.Column(column);
column += BUFFERS_COLUMN_WIDTH;
@@ -556,11 +562,14 @@ std:
{
ListDevices();
}
else if (parser.Arguments().size() == 1)
else if (parser.Arguments().size() >= 1 && parser.Arguments().size() <= 2)
{
inputChannels = ParseChannels(strInputChannels);
outputChannels = ParseChannels(strInputChannels);
RunLatencyTest(parser.Arguments()[0], inputChannels, outputChannels, sampleRate);
outputChannels = ParseChannels(strOutputChannels);
std::string inDev = parser.Arguments()[0];
std::string outDev = parser.Arguments().size() == 2 ? parser.Arguments()[1] : inDev;
RunLatencyTest(inDev, outDev, inputChannels, outputChannels, sampleRate);
}
else
{
+55 -16
View File
@@ -22,6 +22,7 @@
#include "alsa/asoundlib.h"
#include "Lv2Log.hpp"
#include <mutex>
#include <algorithm>
using namespace pipedal;
@@ -111,6 +112,7 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
}
if (err == 0)
{
snd_pcm_t *hDevice = captureOk ? captureDevice : playbackDevice; // xxx: HECK NO!
snd_pcm_hw_params_t *params = nullptr;
err = snd_pcm_hw_params_malloc(&params);
if (err == 0)
@@ -121,29 +123,42 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
unsigned int minRate = 0, maxRate = 0;
snd_pcm_uframes_t minBufferSize = 0, maxBufferSize = 0;
int dir;
err = snd_pcm_hw_params_get_rate_min(params, &minRate, &dir);
if (err == 0)
{
err = snd_pcm_hw_params_get_rate_max(params, &maxRate, &dir);
if (err == 0)
{
for (size_t i = 0; i < sizeof(RATES) / sizeof(RATES[0]); ++i)
{
uint32_t rate = RATES[i];
if (rate >= minRate && rate <= maxRate)
{
info.sampleRates_.push_back(rate);
}
}
}
else
{
Lv2Log::warning(SS("Failed to get maximum sample rate for device '" << info.name_ << "'."));
}
}
else
{
Lv2Log::warning(SS("Failed to get minimum sample rate for device '" << info.name_ << "'."));
}
if (err == 0)
{
err = snd_pcm_hw_params_get_buffer_size_min(params, &minBufferSize);
}
if (err == 0)
{
err = snd_pcm_hw_params_get_buffer_size_max(params, &maxBufferSize);
}
if (err == 0)
{
for (size_t i = 0; i < sizeof(RATES) / sizeof(RATES[0]); ++i)
if (err == 0)
{
uint32_t rate = RATES[i];
if (rate >= minRate && rate <= maxRate)
{
info.sampleRates_.push_back(rate);
}
err = snd_pcm_hw_params_get_buffer_size_max(params, &maxBufferSize);
}
}
if (err == 0)
{
if (minBufferSize < 16)
{
minBufferSize = 16;
@@ -158,7 +173,19 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
}
if (params != nullptr)
snd_pcm_hw_params_free(params);
snd_pcm_close(hDevice);
if (captureOk) // HECK NO!! REVIEW THIS!
snd_pcm_close(captureDevice);
if (playbackOk && playbackDevice != captureDevice)
snd_pcm_close(playbackDevice);
if (err == 0)
{
cacheDevice(info.name_, info);
result.push_back(info);
}
else if (getCachedDevice(info.name_, &info))
{
result.push_back(info);
}
}
else
{
@@ -174,12 +201,24 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
}
snd_config_update_free_global();
auto isFiltered = [](const AlsaDeviceInfo &d) {
std::string name = d.name_ + " " + d.longName_;
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c){return std::tolower(c);});
return name.find("hdmi") != std::string::npos || name.find("bcm2835") != std::string::npos;
};
std::vector<AlsaDeviceInfo> filtered;
for (auto &d : result)
{
if (!isFiltered(d)) filtered.push_back(d);
}
Lv2Log::debug("GetAlsaDevices --");
for (auto &device : result)
for (auto &device : filtered)
{
Lv2Log::debug(SS(" " << device.name_ << " " << device.longName_ << " " << device.cardId_));
}
return result;
return filtered;
}
static void AddMidiCardDevicesToList(snd_ctl_t *ctl, int card, int device, AlsaMidiDeviceInfo::Direction direction, std::vector<AlsaMidiDeviceInfo> *result)
+2
View File
@@ -31,6 +31,8 @@ namespace pipedal {
std::string longName_;
std::vector<uint32_t> sampleRates_;
uint32_t minBufferSize_ = 0,maxBufferSize_ = 0;
bool supportsCapture_ = false;
bool supportsPlayback_ = false;
bool isDummyDevice() const {
return id_.starts_with("dummy:");
+8
View File
@@ -1750,6 +1750,14 @@ pipedal::JackServerSettings Storage::GetJackServerSettings()
{
json_reader reader(f);
reader.read(&result);
if (!result.GetLegacyAlsaDevice().empty() &&
result.GetAlsaInputDevice().empty() &&
result.GetAlsaOutputDevice().empty())
{
result.SetAlsaInputDevice(result.GetLegacyAlsaDevice());
result.SetAlsaOutputDevice(result.GetLegacyAlsaDevice());
result.SetLegacyAlsaDevice("");
}
}
#if JACK_HOST
result.Initialize();