Manifest.json, Channel Router Sync. Alsa device enumeration.
This commit is contained in:
+17
-1
@@ -1895,8 +1895,14 @@ namespace pipedal
|
||||
std::vector<float*> &channelBuffers
|
||||
) {
|
||||
size_t nChannels = channelSelection.size();
|
||||
channelBuffers.resize(nChannels);
|
||||
if (nChannels == 0)
|
||||
{
|
||||
channelBuffers.resize(1);
|
||||
channelBuffers[0] = zeroInputBuffer;
|
||||
return;
|
||||
}
|
||||
|
||||
channelBuffers.resize(nChannels);
|
||||
for (size_t i = 0; i < nChannels; ++i)
|
||||
{
|
||||
int64_t deviceChannel = channelSelection[i];
|
||||
@@ -1932,6 +1938,16 @@ namespace pipedal
|
||||
) {
|
||||
size_t nChannels = channelSelection.size();
|
||||
|
||||
if (nChannels == 0)
|
||||
{
|
||||
channelBuffers.resize(1);
|
||||
if (discardOutputBuffer != nullptr)
|
||||
{
|
||||
discardOutputBuffer = AllocateAudioBuffer();
|
||||
}
|
||||
channelBuffers[0] = discardOutputBuffer;
|
||||
return;
|
||||
}
|
||||
channelBuffers.resize(nChannels);
|
||||
for (size_t i = 0; i < nChannels; ++i)
|
||||
{
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
|
||||
AlsaFormatEncodeDecodeTest(this);
|
||||
|
||||
JackServerSettings serverSettings("hw:M2", "hw:M2", 48000, 32, 3);
|
||||
JackServerSettings serverSettings("hw:M2","hw:M2", 48000, 32, 3);
|
||||
|
||||
JackConfiguration jackConfiguration;
|
||||
jackConfiguration.AlsaInitialize(serverSettings);
|
||||
|
||||
@@ -533,6 +533,7 @@ private:
|
||||
|
||||
std::vector<std::shared_ptr<Lv2Pedalboard>> activePedalboards; // pedalboards that have been sent to the audio queue.
|
||||
Lv2Pedalboard *realtimeActivePedalboard = nullptr;
|
||||
Lv2RoutingInserts realtimeRoutingInserts;
|
||||
|
||||
uint32_t sampleRate = 0;
|
||||
uint64_t currentSample = 0;
|
||||
@@ -894,6 +895,47 @@ private:
|
||||
|
||||
return false; // signal to caller that the effect has been replaced, and processing needs to start again.
|
||||
}
|
||||
case RingBufferCommand::ReplaceRoutingInserts:
|
||||
{
|
||||
Lv2RoutingInserts body;
|
||||
realtimeReader.readComplete(&body);
|
||||
|
||||
auto oldValue = this->realtimeRoutingInserts;
|
||||
this->realtimeRoutingInserts = body;
|
||||
|
||||
realtimeWriter.RoutingInsertsReplaced(oldValue);
|
||||
|
||||
// invalidate the possibly no-good subscriptions. Model will update them shortly.
|
||||
freeRealtimeVuConfiguration();
|
||||
freeRealtimeMonitorPortSubscriptions();
|
||||
cancelParameterRequests();
|
||||
|
||||
Lv2Pedalboard *mainInserts = body.mainInserts;
|
||||
if (mainInserts)
|
||||
{
|
||||
mainInserts->ResetAtomBuffers();
|
||||
// issue patch gets for all writable path properties.
|
||||
for (auto pEffect : mainInserts->GetEffects())
|
||||
{
|
||||
pEffect->RequestAllPathPatchProperties();
|
||||
}
|
||||
mainInserts->UpdateAudioPorts();
|
||||
}
|
||||
Lv2Pedalboard *auxInserts = body.auxInserts;
|
||||
if (auxInserts)
|
||||
{
|
||||
auxInserts->ResetAtomBuffers();
|
||||
// issue patch gets for all writable path properties.
|
||||
for (auto pEffect : auxInserts->GetEffects())
|
||||
{
|
||||
pEffect->RequestAllPathPatchProperties();
|
||||
}
|
||||
auxInserts->UpdateAudioPorts();
|
||||
}
|
||||
reEntered = false;
|
||||
|
||||
return false; // signal to caller that the effect has been replaced, and processing needs to start again.
|
||||
}
|
||||
default:
|
||||
throw PiPedalStateException("Unknown Ringbuffer command.");
|
||||
}
|
||||
@@ -1549,6 +1591,20 @@ public:
|
||||
hostReader.read(&body);
|
||||
OnActivePedalboardReleased(body.oldEffect);
|
||||
}
|
||||
else if (command == RingBufferCommand::RoutingInsertsReplaced)
|
||||
{
|
||||
Lv2RoutingInserts body;
|
||||
hostReader.read(&body);
|
||||
if (body.mainInserts)
|
||||
{
|
||||
OnActivePedalboardReleased(body.mainInserts);
|
||||
}
|
||||
if (body.auxInserts)
|
||||
{
|
||||
OnActivePedalboardReleased(body.auxInserts);
|
||||
}
|
||||
|
||||
}
|
||||
else if (command == RingBufferCommand::FreeSnapshot)
|
||||
{
|
||||
IndexedSnapshot *snapshot;
|
||||
@@ -1782,6 +1838,25 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetChannelRoutingInserts(
|
||||
const std::shared_ptr<Lv2Pedalboard> &mainInserts,
|
||||
const std::shared_ptr<Lv2Pedalboard> &auxInserts
|
||||
) override {
|
||||
if (active && mainInserts)
|
||||
{
|
||||
mainInserts->Activate();
|
||||
this->activePedalboards.push_back(mainInserts);
|
||||
}
|
||||
if (active && auxInserts)
|
||||
{
|
||||
auxInserts->Activate();
|
||||
this->activePedalboards.push_back(auxInserts);
|
||||
}
|
||||
Lv2RoutingInserts routingInserts { mainInserts: mainInserts.get(), auxInserts: auxInserts.get()};
|
||||
hostWriter.ReplaceRoutingInserts(routingInserts);
|
||||
}
|
||||
|
||||
|
||||
virtual void SetBypass(uint64_t instanceId, bool enabled)
|
||||
{
|
||||
std::lock_guard guard(mutex);
|
||||
|
||||
@@ -238,6 +238,12 @@ namespace pipedal
|
||||
|
||||
virtual void SetPedalboard(const std::shared_ptr<Lv2Pedalboard> &pedalboard) = 0;
|
||||
|
||||
virtual void SetChannelRoutingInserts(
|
||||
const std::shared_ptr<Lv2Pedalboard> &mainInserts,
|
||||
const std::shared_ptr<Lv2Pedalboard> &auxInserts
|
||||
) = 0;
|
||||
|
||||
|
||||
virtual void SetControlValue(uint64_t instanceId, const std::string &symbol, float value) = 0;
|
||||
virtual void SetInputVolume(float value) = 0;
|
||||
virtual void SetOutputVolume(float value) = 0;
|
||||
|
||||
+3
-1
@@ -740,6 +740,7 @@ add_executable(pipedalconfig
|
||||
ModFileTypes.cpp ModFileTypes.hpp
|
||||
MimeTypes.cpp MimeTypes.hpp
|
||||
PiPedalConfiguration.hpp PiPedalConfiguration.cpp
|
||||
PiPedalAlsa.hpp PiPedalAlsa.cpp
|
||||
JackServerSettings.hpp JackServerSettings.cpp
|
||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||
WifiChannelSelectors.cpp WifiChannelSelectors.hpp
|
||||
@@ -817,6 +818,7 @@ add_executable(pipedaladmind AdminMain.cpp CommandLineParser.hpp
|
||||
|
||||
SetWifiConfig.cpp SetWifiConfig.hpp
|
||||
JackServerSettings.hpp JackServerSettings.cpp
|
||||
PiPedalAlsa.hpp PiPedalAlsa.cpp
|
||||
Lv2SystemdLogger.hpp Lv2SystemdLogger.cpp
|
||||
|
||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||
@@ -824,7 +826,7 @@ add_executable(pipedaladmind AdminMain.cpp CommandLineParser.hpp
|
||||
asan_options.cpp
|
||||
|
||||
)
|
||||
target_link_libraries(pipedaladmind PRIVATE PiPedalCommon pthread atomic stdc++fs systemd )
|
||||
target_link_libraries(pipedaladmind PRIVATE PiPedalCommon pthread atomic stdc++fs systemd asound)
|
||||
|
||||
add_executable(processcopyrights copyrightMain.cpp
|
||||
CommandLineParser.hpp
|
||||
|
||||
@@ -135,9 +135,20 @@ ChannelRouterSettings::ChannelRouterSettings()
|
||||
|
||||
}
|
||||
|
||||
std::vector<ChannelRouterPresetIndexEntry> ChannelRouterPresetBank::getIndexEntries()
|
||||
{
|
||||
std::vector<ChannelRouterPresetIndexEntry> result;
|
||||
for (auto &entry: entries_)
|
||||
{
|
||||
result.push_back(ChannelRouterPresetIndexEntry{entry->id(), entry->name()});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterSettings)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, configured)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, changed)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, channelRouterPresetId)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, mainInputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, mainOutputChannels)
|
||||
@@ -149,3 +160,22 @@ JSON_MAP_REFERENCE(ChannelRouterSettings, sendInputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, sendOutputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, controlValues)
|
||||
JSON_MAP_END()
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetIndexEntry)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetIndexEntry, id)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetIndexEntry, name)
|
||||
JSON_MAP_END()
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetBankEntry)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, id)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, name)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, channelRouterSettings)
|
||||
JSON_MAP_END()
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetBank)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, nextId)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, version)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, entries)
|
||||
JSON_MAP_END()
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace pipedal
|
||||
|
||||
bool configured_ = false;
|
||||
int64_t channelRouterPresetId_ = -1;
|
||||
bool changed_ = false;
|
||||
|
||||
std::vector<int64_t> mainInputChannels_ = {1, 1};
|
||||
std::vector<int64_t> mainOutputChannels_ = {0, 1};
|
||||
@@ -60,6 +61,7 @@ namespace pipedal
|
||||
|
||||
JSON_GETTER_SETTER(configured)
|
||||
JSON_GETTER_SETTER(channelRouterPresetId)
|
||||
JSON_GETTER_SETTER(changed)
|
||||
JSON_GETTER_SETTER_REF(mainInputChannels)
|
||||
JSON_GETTER_SETTER_REF(mainOutputChannels)
|
||||
JSON_GETTER_SETTER_REF(mainInserts)
|
||||
@@ -110,4 +112,56 @@ namespace pipedal
|
||||
std::vector<int64_t> sendOutputChannels_;
|
||||
};
|
||||
|
||||
class ChannelRouterPresetIndexEntry {
|
||||
private:
|
||||
int64_t id_ = -1;
|
||||
std::string name_;
|
||||
public:
|
||||
ChannelRouterPresetIndexEntry() = default;
|
||||
ChannelRouterPresetIndexEntry(const ChannelRouterPresetIndexEntry&other) = default;
|
||||
ChannelRouterPresetIndexEntry(ChannelRouterPresetIndexEntry&&other) = default;
|
||||
ChannelRouterPresetIndexEntry&operator=(const ChannelRouterPresetIndexEntry&other) = default;
|
||||
ChannelRouterPresetIndexEntry&operator=(ChannelRouterPresetIndexEntry&&other) = default;
|
||||
|
||||
ChannelRouterPresetIndexEntry(int64_t id, const std::string&name)
|
||||
: id_(id),name_(name) { }
|
||||
|
||||
|
||||
JSON_GETTER_SETTER(id)
|
||||
JSON_GETTER_SETTER_REF(name)
|
||||
|
||||
DECLARE_JSON_MAP(ChannelRouterPresetIndexEntry);
|
||||
};
|
||||
|
||||
|
||||
class ChannelRouterPresetBankEntry {
|
||||
private:
|
||||
int64_t id_;
|
||||
std::string name_;
|
||||
ChannelRouterSettings channelRouterSettings_;
|
||||
public:
|
||||
JSON_GETTER_SETTER(id)
|
||||
JSON_GETTER_SETTER_REF(name)
|
||||
JSON_GETTER_SETTER_REF(channelRouterSettings)
|
||||
|
||||
DECLARE_JSON_MAP(ChannelRouterPresetBankEntry);
|
||||
|
||||
};
|
||||
|
||||
class ChannelRouterPresetBank {
|
||||
private:
|
||||
int64_t nextId_ = 1;
|
||||
int64_t version_ = 1;
|
||||
std::vector<std::shared_ptr<ChannelRouterPresetBankEntry>> entries_;
|
||||
public:
|
||||
|
||||
JSON_GETTER_SETTER(nextId)
|
||||
JSON_GETTER_SETTER(version)
|
||||
JSON_GETTER_SETTER_REF(entries)
|
||||
|
||||
std::vector<ChannelRouterPresetIndexEntry> getIndexEntries();
|
||||
|
||||
DECLARE_JSON_MAP(ChannelRouterPresetBank);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -149,6 +149,8 @@ void JackConfiguration::AlsaInitialize(
|
||||
}
|
||||
} catch (const std::exception& /*ignore*/)
|
||||
{
|
||||
this->isValid_ = false;
|
||||
this->errorStatus_ = "Not configured.";
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
+53
-144
@@ -28,6 +28,7 @@
|
||||
#include <filesystem>
|
||||
#include "Lv2Log.hpp"
|
||||
#include "SysExec.hpp"
|
||||
#include "PiPedalAlsa.hpp"
|
||||
|
||||
#define DRC_FILENAME "/etc/jackdrc"
|
||||
|
||||
@@ -60,33 +61,41 @@ static std::vector<std::string> SplitArgs(const char *szBuff)
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string GetJackStringArg(const std::vector<std::string> &args, const std::string&shortOption, const std::string&longOption)
|
||||
static std::string GetJackStringArg(const std::vector<std::string> &args, const std::string &shortOption, const std::string &longOption)
|
||||
{
|
||||
std::string strVal;
|
||||
for (size_t i = 1; i < args.size(); ++i)
|
||||
{
|
||||
auto pos = args[i].rfind(longOption,0);
|
||||
if (pos != std::string::npos) {
|
||||
auto pos = args[i].rfind(longOption, 0);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (args[i].length() == longOption.length())
|
||||
{
|
||||
if (i == args.size()-1) {
|
||||
throw PiPedalException("Can't read Jack configuration.");
|
||||
if (i == args.size() - 1)
|
||||
{
|
||||
throw PiPedalException("Can't read Jack configuration.");
|
||||
}
|
||||
strVal = args[i+1];
|
||||
} else {
|
||||
strVal = args[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
strVal = args[i].substr(longOption.length());
|
||||
}
|
||||
break;
|
||||
}
|
||||
pos = args[i].rfind(shortOption,0);
|
||||
if (pos != std::string::npos) {
|
||||
pos = args[i].rfind(shortOption, 0);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (args[i].length() == shortOption.length())
|
||||
{
|
||||
if (i == args.size()-1) {
|
||||
throw PiPedalException("Can't read Jack configuration.");
|
||||
if (i == args.size() - 1)
|
||||
{
|
||||
throw PiPedalException("Can't read Jack configuration.");
|
||||
}
|
||||
strVal = args[i+1];
|
||||
} else {
|
||||
strVal = args[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
strVal = args[i].substr(shortOption.length());
|
||||
}
|
||||
break;
|
||||
@@ -94,9 +103,9 @@ static std::string GetJackStringArg(const std::vector<std::string> &args, const
|
||||
}
|
||||
return strVal;
|
||||
}
|
||||
static std::int32_t GetJackArg(const std::vector<std::string> &args, const std::string&shortOption, const std::string&longOption)
|
||||
static std::int32_t GetJackArg(const std::vector<std::string> &args, const std::string &shortOption, const std::string &longOption)
|
||||
{
|
||||
std::string strVal = GetJackStringArg(args,shortOption,longOption);
|
||||
std::string strVal = GetJackStringArg(args, shortOption, longOption);
|
||||
try
|
||||
{
|
||||
unsigned long value = std::stoul(strVal);
|
||||
@@ -108,144 +117,42 @@ static std::int32_t GetJackArg(const std::vector<std::string> &args, const std::
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JackServerSettings::ReadJackDaemonConfiguration()
|
||||
static std::string GetAlsaDeviceName(const std::vector<AlsaDeviceInfo> &availableDevices, const std::string &id)
|
||||
{
|
||||
#if !JACK_HOST
|
||||
return;
|
||||
#endif
|
||||
this->valid_ = false;
|
||||
|
||||
std::string lastLine;
|
||||
if (id.empty())
|
||||
return "";
|
||||
std::string name;
|
||||
for (const auto &availableDevice : availableDevices)
|
||||
{
|
||||
ifstream input(DRC_FILENAME);
|
||||
|
||||
if (!input.is_open())
|
||||
if (availableDevice.id_ == id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(input,line);
|
||||
if (line.length() != 0) {
|
||||
lastLine = line;
|
||||
}
|
||||
if (input.eof()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
std::vector<std::string> argv = SplitArgs(lastLine.c_str());
|
||||
for (auto i = argv.begin(); i != argv.end(); ++i)
|
||||
{
|
||||
if ((*i) == "-dalsa") {
|
||||
argv.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->bufferSize_ = GetJackArg(argv, "-p", "--period");
|
||||
this->numberOfBuffers_ = (uint32_t)GetJackArg(argv, "-n", "--nperiods");
|
||||
this->sampleRate_ = (uint32_t)GetJackArg(argv, "-r", "--rate");
|
||||
// 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 &)
|
||||
{
|
||||
//Lv2Log::error("Can't parse " DRC_FILENAME);
|
||||
name = availableDevice.name_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name.empty())
|
||||
{
|
||||
auto pos = id.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
name = id.substr(pos + 1);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void JackServerSettings::WriteDaemonConfig()
|
||||
void JackServerSettings::FixUpDeviceNames()
|
||||
{
|
||||
#if JACK_HOST
|
||||
this->valid_ = false;
|
||||
|
||||
std::vector<std::string> precedingLines;
|
||||
std::vector<std::string> argv;
|
||||
std::string lastLine;
|
||||
|
||||
if (std::filesystem::exists(DRC_FILENAME)) {
|
||||
ifstream input(DRC_FILENAME);
|
||||
|
||||
if (!input.is_open())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (input.eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::getline(input,lastLine);
|
||||
precedingLines.push_back(lastLine);
|
||||
if (input.eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// erase blank lines at the end.
|
||||
while (precedingLines.size() != 0 && precedingLines[precedingLines.size()-1] == "")
|
||||
{
|
||||
precedingLines.erase(precedingLines.begin()+precedingLines.size()-1);
|
||||
}
|
||||
// erase the last line, which should contain the command invocation.
|
||||
if (precedingLines.size() != 0)
|
||||
{
|
||||
precedingLines.erase(precedingLines.begin()+precedingLines.size()-1);
|
||||
}
|
||||
}
|
||||
// write to the output.
|
||||
try
|
||||
if (
|
||||
((!this->alsaInputDevice_.empty()) && this->alsaInputDeviceName_.empty()) ||
|
||||
(!this->alsaOutputDevice_.empty()) && this->alsaOutputDeviceName_.empty())
|
||||
{
|
||||
ofstream output(DRC_FILENAME);
|
||||
if (!output.is_open())
|
||||
{
|
||||
throw PiPedalException("Can't write " DRC_FILENAME);
|
||||
}
|
||||
if (precedingLines.size() == 0)
|
||||
{
|
||||
// jack1 incantation for promiscuous servers.
|
||||
output << "#!/bin/sh" <<endl;
|
||||
output << "export JACK_PROMISCUOUS_SERVER=audio" << endl;
|
||||
output << "export JACK_NO_AUDIO_RESERVATION=1" << endl;
|
||||
output << "umask 0" << endl;
|
||||
}
|
||||
for (auto line : precedingLines)
|
||||
{
|
||||
output << line << endl;
|
||||
}
|
||||
// the style used by qjackctl. :-/
|
||||
// Lower to -P70 in order to allow the USB soft-irq to run at higher priority than JACK (it runs at 80).
|
||||
output << "/usr/bin/jackd "
|
||||
<< "-R -P70 --silent"
|
||||
<< " -dalsa -d" << this->alsaDevice_
|
||||
<< " -r" << this->sampleRate_
|
||||
<< " -p" << this->bufferSize_
|
||||
<< " -n" << this->numberOfBuffers_ << " -Xseq"
|
||||
<< endl;
|
||||
if (silentSysExec("/usr/bin/chmod 755 " DRC_FILENAME) != 0)
|
||||
{
|
||||
Lv2Log::error("Failed to set permissions on /etc/jackdrc");
|
||||
}
|
||||
|
||||
PiPedalAlsaDevices& alsaDevices = PiPedalAlsaDevices::instance();
|
||||
std::vector<AlsaDeviceInfo> availableDevices = alsaDevices.GetAlsaDevices();
|
||||
|
||||
this->alsaInputDeviceName_ = GetAlsaDeviceName(availableDevices, this->alsaInputDevice_);
|
||||
this->alsaOutputDeviceName_ = GetAlsaDeviceName(availableDevices, this->alsaOutputDevice_);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
}
|
||||
#else
|
||||
throw PiPedalStateException("JACK_HOST not enabled at compile time.");
|
||||
#endif
|
||||
}
|
||||
|
||||
JSON_MAP_BEGIN(JackServerSettings)
|
||||
@@ -256,6 +163,8 @@ JSON_MAP_REFERENCE(JackServerSettings, isJackAudio)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, alsaDevice) // legacy field
|
||||
JSON_MAP_REFERENCE(JackServerSettings, alsaInputDevice)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, alsaOutputDevice)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, alsaInputDeviceName)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, alsaOutputDeviceName)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, sampleRate)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, bufferSize)
|
||||
JSON_MAP_REFERENCE(JackServerSettings, numberOfBuffers)
|
||||
|
||||
@@ -33,7 +33,9 @@ namespace pipedal
|
||||
bool isJackAudio_ = JACK_HOST ? true : false;
|
||||
bool rebootRequired_ = false;
|
||||
std::string alsaInputDevice_;
|
||||
std::string alsaInputDeviceName_;
|
||||
std::string alsaOutputDevice_;
|
||||
std::string alsaOutputDeviceName_;
|
||||
std::string alsaDevice_; // legacy
|
||||
uint64_t sampleRate_ = 0;
|
||||
uint32_t bufferSize_ = 64;
|
||||
@@ -44,6 +46,7 @@ namespace pipedal
|
||||
JackServerSettings(
|
||||
const std::string &alsaInputDevice,
|
||||
const std::string &alsaOutputDevice,
|
||||
|
||||
uint64_t sampleRate,
|
||||
uint32_t bufferSize,
|
||||
uint32_t numberOfBuffers)
|
||||
@@ -55,6 +58,7 @@ namespace pipedal
|
||||
numberOfBuffers_(numberOfBuffers),
|
||||
isOnboarding_(false)
|
||||
{
|
||||
FixUpDeviceNames();
|
||||
}
|
||||
|
||||
uint64_t GetSampleRate() const { return sampleRate_; }
|
||||
@@ -62,11 +66,13 @@ namespace pipedal
|
||||
uint32_t GetBufferSize() const { return bufferSize_; }
|
||||
uint32_t GetNumberOfBuffers() const { return numberOfBuffers_; }
|
||||
const std::string &GetAlsaInputDevice() const { return alsaInputDevice_; }
|
||||
const std::string &GetAlsaInputDeviceName() const { return alsaInputDeviceName_; }
|
||||
const std::string &GetAlsaOutputDevice() const { return alsaOutputDevice_; }
|
||||
const std::string &GetAlsaOutputDeviceName() const { return alsaOutputDeviceName_; }
|
||||
const std::string &GetLegacyAlsaDevice() const { return alsaDevice_; } //legacy
|
||||
|
||||
void SetAlsaInputDevice(const std::string &d){ alsaInputDevice_ = d; }
|
||||
void SetAlsaOutputDevice(const std::string &d){ alsaOutputDevice_ = d; }
|
||||
void SetAlsaInputDevice(const std::string &id, const std::string&name){ alsaInputDevice_ = id; alsaInputDeviceName_ = name; }
|
||||
void SetAlsaOutputDevice(const std::string &id, const std::string&name){ alsaOutputDevice_ = id; alsaOutputDeviceName_ = name; }
|
||||
void SetLegacyAlsaDevice(const std::string &d) { alsaDevice_ = d; }
|
||||
|
||||
void UseDummyAudioDevice() {
|
||||
@@ -74,7 +80,9 @@ namespace pipedal
|
||||
if (sampleRate_ == 0) sampleRate_ = 48000;
|
||||
this->alsaDevice_ = "dummy:channels_2";
|
||||
this->alsaInputDevice_ = "dummy:channels_2";
|
||||
this->alsaInputDeviceName_ = "Stopped";
|
||||
this->alsaOutputDevice_ = "dummy:channels_2";
|
||||
this->alsaOutputDeviceName_ = "Stopped";
|
||||
}
|
||||
bool IsDummyAudioDevice() const {
|
||||
return
|
||||
@@ -83,11 +91,8 @@ namespace pipedal
|
||||
|| this->alsaInputDevice_.starts_with("dummy:");
|
||||
}
|
||||
|
||||
void ReadJackDaemonConfiguration();
|
||||
|
||||
bool IsValid() const { return valid_; }
|
||||
|
||||
void WriteDaemonConfig(); // requires root perms.
|
||||
void SetRebootRequired(bool value)
|
||||
{
|
||||
rebootRequired_ = value;
|
||||
@@ -106,6 +111,7 @@ namespace pipedal
|
||||
this->bufferSize_ == other.bufferSize_ &&
|
||||
this->numberOfBuffers_ == other.numberOfBuffers_;
|
||||
}
|
||||
void FixUpDeviceNames();
|
||||
|
||||
DECLARE_JSON_MAP(JackServerSettings);
|
||||
};
|
||||
|
||||
@@ -103,8 +103,7 @@ void PrintHelp()
|
||||
|
||||
void ListDevices()
|
||||
{
|
||||
PiPedalAlsaDevices alsaDevices;
|
||||
auto devices = alsaDevices.GetAlsaDevices();
|
||||
auto devices = PiPedalAlsaDevices::instance().GetAlsaDevices();
|
||||
|
||||
PrettyPrinter pp;
|
||||
if (devices.size() == 0)
|
||||
@@ -199,7 +198,7 @@ public:
|
||||
TestResult result;
|
||||
try
|
||||
{
|
||||
JackServerSettings serverSettings(inputDeviceId, outputDeviceId, sampleRate, bufferSize, buffers);
|
||||
JackServerSettings serverSettings(inputDeviceId,outputDeviceId, sampleRate, bufferSize, buffers);
|
||||
|
||||
JackConfiguration jackConfiguration;
|
||||
jackConfiguration.AlsaInitialize(serverSettings);
|
||||
|
||||
+67
-3
@@ -160,11 +160,14 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
||||
|
||||
std::vector<AlsaDeviceInfo> result;
|
||||
|
||||
int cardNum = -1; // Start with first card
|
||||
int err;
|
||||
|
||||
std::vector<ProcAlsaDevice> procAlsaDevices = getProcAlsaDevices();
|
||||
|
||||
|
||||
snd_pcm_info_t *pcminfo = nullptr;
|
||||
snd_pcm_info_alloca(&pcminfo);
|
||||
|
||||
for (const auto &procAlsaDevice: procAlsaDevices)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -198,13 +201,60 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
||||
err = snd_ctl_card_info(hDevice, alsaInfo);
|
||||
if (err == 0)
|
||||
{
|
||||
|
||||
AlsaDeviceInfo info;
|
||||
info.cardId_ = cardNum;
|
||||
info.cardId_ = procAlsaDevice.cardId;
|
||||
info.id_ = std::string("hw:") + snd_ctl_card_info_get_id(alsaInfo);
|
||||
const char *driver = snd_ctl_card_info_get_driver(alsaInfo);
|
||||
(void)driver;
|
||||
|
||||
info.name_ = snd_ctl_card_info_get_name(alsaInfo);
|
||||
snd_pcm_info_set_device(pcminfo, procAlsaDevice.subdeviceId);
|
||||
snd_pcm_info_set_subdevice(pcminfo, 0);
|
||||
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
|
||||
|
||||
if ((err = snd_ctl_pcm_info(hDevice, pcminfo)) < 0) {
|
||||
snd_pcm_info_set_device(pcminfo, procAlsaDevice.subdeviceId);
|
||||
snd_pcm_info_set_subdevice(pcminfo, 0);
|
||||
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
|
||||
|
||||
if ((err = snd_ctl_pcm_info(hDevice, pcminfo)) < 0) {
|
||||
if (err != -ENOENT)
|
||||
Lv2Log::warning("control digital audio info (%i): %s", info.cardId_, snd_strerror(err));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Names and IDs are f-ed up in ALSA. id seems to be vaguely reliable. names are garbage!
|
||||
Sample data from Unbuntu 24.04.
|
||||
|
||||
snd_ctl_card_info_get_id(info) snd_ctl_card_info_get_name(alsaInfo) subdevice snd_pcm_info_get_id(pcminfo) snd_pcm_info_get_name(pcminfo)
|
||||
Generic HD-Audio Generic 3 HDMI 0 Acer S231HL
|
||||
Generic HD-Audio Generic 3 HDMI 0 ASUS MG28U
|
||||
Generic_1 HD-Audio Generic 0 CX11970 Analog CX11970 Analog
|
||||
M2 M2 USB Audio USB Audio
|
||||
CODEC USB AUDIO CODEC USB Audio USB Audio
|
||||
|
||||
*/
|
||||
std::string name;
|
||||
{
|
||||
// let's assume (without evidence) that names get localized, but ids do not. :-/
|
||||
std::string cardId = snd_ctl_card_info_get_id(alsaInfo);
|
||||
std::string cardName = snd_ctl_card_info_get_name(alsaInfo);
|
||||
std::string pcmId = snd_pcm_info_get_id(pcminfo);
|
||||
std::string pcmName = snd_pcm_info_get_name(pcminfo);
|
||||
std::string driver = snd_ctl_card_info_get_driver(alsaInfo);
|
||||
if (driver == "USB-Audio")
|
||||
{
|
||||
name = SS("USB - " << cardId);
|
||||
}
|
||||
else if (pcmId == pcmName)
|
||||
{
|
||||
name = pcmId;
|
||||
} else {
|
||||
name = SS(pcmId << '[' << pcmName << ']');
|
||||
}
|
||||
}
|
||||
info.name_ = name;
|
||||
info.longName_ = snd_ctl_card_info_get_longname(alsaInfo);
|
||||
|
||||
// we can't read our own device if it's open so use data that gets
|
||||
@@ -219,6 +269,8 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
||||
result.push_back(cachedInfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
snd_pcm_t *captureDevice = nullptr;
|
||||
snd_pcm_t *playbackDevice = nullptr;
|
||||
auto rc = snd_pcm_open(&captureDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
|
||||
@@ -248,6 +300,7 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
||||
|
||||
if (captureOk || playbackOk)
|
||||
{
|
||||
|
||||
snd_pcm_t *hDevice = captureOk ? captureDevice : playbackDevice;
|
||||
snd_pcm_hw_params_t *params = nullptr;
|
||||
err = snd_pcm_hw_params_malloc(¶ms);
|
||||
@@ -637,6 +690,17 @@ AlsaMidiDeviceInfo::AlsaMidiDeviceInfo(const char *name, const char *description
|
||||
this->subdevice_ = subdevice;
|
||||
}
|
||||
|
||||
std::unique_ptr<PiPedalAlsaDevices> PiPedalAlsaDevices::instance_;
|
||||
|
||||
PiPedalAlsaDevices&PiPedalAlsaDevices::instance() {
|
||||
if (!instance_)
|
||||
{
|
||||
instance_ = std::unique_ptr<PiPedalAlsaDevices>(new PiPedalAlsaDevices());
|
||||
}
|
||||
return (*instance_);
|
||||
}
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(AlsaDeviceInfo)
|
||||
JSON_MAP_REFERENCE(AlsaDeviceInfo, cardId)
|
||||
JSON_MAP_REFERENCE(AlsaDeviceInfo, id)
|
||||
|
||||
+5
-1
@@ -71,12 +71,16 @@ namespace pipedal {
|
||||
};
|
||||
|
||||
class PiPedalAlsaDevices {
|
||||
|
||||
private:
|
||||
static std::unique_ptr<PiPedalAlsaDevices> instance_;
|
||||
PiPedalAlsaDevices() { }
|
||||
std::map<std::string,AlsaDeviceInfo> cachedDevices;
|
||||
|
||||
bool getCachedDevice(const std::string&name, AlsaDeviceInfo*pResult);
|
||||
void cacheDevice(const std::string&name, const AlsaDeviceInfo&deviceInfo);
|
||||
|
||||
public:
|
||||
static PiPedalAlsaDevices&instance();
|
||||
|
||||
std::vector<AlsaDeviceInfo> GetAlsaDevices();
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ using namespace std;
|
||||
static void DiscoveryTest()
|
||||
{
|
||||
cout << "--- Discovery" << endl;
|
||||
PiPedalAlsaDevices devices;
|
||||
PiPedalAlsaDevices &devices = PiPedalAlsaDevices::instance();
|
||||
auto result = devices.GetAlsaDevices();
|
||||
std::cout << result.size() << " ALSA devices found." << std::endl;
|
||||
|
||||
|
||||
+66
-62
@@ -83,12 +83,9 @@ PiPedalModel::PiPedalModel()
|
||||
this->updater->Start();
|
||||
this->currentUpdateStatus = updater->GetCurrentStatus();
|
||||
this->pedalboard = Pedalboard::MakeDefault(Pedalboard::PedalboardType::MainPedalboard);
|
||||
#if JACK_HOST
|
||||
this->jackServerSettings = this->storage.GetJackServerSettings(); // to get onboarding flag.
|
||||
this->jackServerSettings.ReadJackDaemonConfiguration();
|
||||
#else
|
||||
|
||||
this->jackServerSettings = this->storage.GetJackServerSettings();
|
||||
#endif
|
||||
|
||||
updater->SetUpdateListener(
|
||||
[this](const UpdateStatus &updateStatus)
|
||||
{
|
||||
@@ -224,21 +221,22 @@ void PiPedalModel::Init(const PiPedalConfiguration &configuration)
|
||||
|
||||
this->systemMidiBindings = storage.GetSystemMidiBindings();
|
||||
|
||||
#if JACK_HOST
|
||||
this->jackConfiguration = this->jackConfiguration.JackInitialize();
|
||||
#else
|
||||
this->jackServerSettings = storage.GetJackServerSettings();
|
||||
this->jackConfiguration.AlsaInitialize(jackServerSettings);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
this->jackConfiguration.AlsaInitialize(jackServerSettings);
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
this->channelRouterSettings = storage.GetChannelRouterSettings();
|
||||
pluginHost.OnConfigurationChanged(
|
||||
jackConfiguration,
|
||||
storage.GetChannelSelection());
|
||||
|
||||
}
|
||||
|
||||
|
||||
int64_t PiPedalModel::DownloadModelsFromTone3000(
|
||||
int64_t clientId,
|
||||
Tone3000DownloadType downloadType,
|
||||
@@ -253,7 +251,7 @@ int64_t PiPedalModel::DownloadModelsFromTone3000(
|
||||
{
|
||||
throw PiPedalException("Invalid path: not in uploads directory.");
|
||||
}
|
||||
|
||||
|
||||
// Check for ".." in path components (security check)
|
||||
for (const auto &component : path)
|
||||
{
|
||||
@@ -271,14 +269,12 @@ int64_t PiPedalModel::DownloadModelsFromTone3000(
|
||||
return tone3000Downloader->RequestDownload(
|
||||
downloadType,
|
||||
downloadPath,
|
||||
tone3000Url
|
||||
);
|
||||
tone3000Url);
|
||||
}
|
||||
|
||||
void PiPedalModel::CancelTone3000Download(
|
||||
int64_t clientId,
|
||||
int64_t downloadHandle
|
||||
)
|
||||
int64_t downloadHandle)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
|
||||
@@ -307,12 +303,12 @@ void PiPedalModel::OnTone3000Progress(const Tone3000DownloadProgress &progress)
|
||||
}
|
||||
}
|
||||
|
||||
void PiPedalModel::OnTone3000DownloadComplete(int64_t handle, const std::string&resultPath)
|
||||
void PiPedalModel::OnTone3000DownloadComplete(int64_t handle, const std::string &resultPath)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
for (auto subscriber : this->subscribers)
|
||||
{
|
||||
subscriber->OnTone3000DownloadComplete(handle,resultPath);
|
||||
subscriber->OnTone3000DownloadComplete(handle, resultPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,20 +354,21 @@ void PiPedalModel::LoadLv2PluginInfo()
|
||||
{
|
||||
PluginPresets pluginPresets = pluginHost.GetFactoryPluginPresets(plugin->uri());
|
||||
storage.SavePluginPresets(plugin->uri(), pluginPresets);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pluginPresetIndexVersion == 0)
|
||||
{
|
||||
if (plugin->uri() == "http://two-play.com/plugins/toob-convolution-reverb" || plugin->uri() == "http://two-play.com/plugins/toob-convolution-reverb-stereo")
|
||||
{
|
||||
// overwrite previous factory presets!
|
||||
PluginPresets pluginPresets = pluginHost.GetFactoryPluginPresets(plugin->uri());
|
||||
for (auto & pluginPreset: pluginPresets.presets_)
|
||||
for (auto &pluginPreset : pluginPresets.presets_)
|
||||
{
|
||||
storage.SavePluginPreset(
|
||||
plugin->uri(),
|
||||
pluginPreset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -772,16 +769,20 @@ void PiPedalModel::SetPedalboardItemEnable(int64_t clientId, int64_t pedalItemId
|
||||
std::lock_guard<std::recursive_mutex> guard{mutex};
|
||||
{
|
||||
this->pedalboard.SetItemEnabled(pedalItemId, enabled);
|
||||
PedalboardItem * pPedalboardItem = this->pedalboard.GetItem(pedalItemId);
|
||||
if (pPedalboardItem) {
|
||||
PedalboardItem *pPedalboardItem = this->pedalboard.GetItem(pedalItemId);
|
||||
if (pPedalboardItem)
|
||||
{
|
||||
Lv2PluginInfo::ptr pluginInfo = GetPluginInfo(pPedalboardItem->uri());
|
||||
if (pluginInfo) {
|
||||
for (auto &port: pluginInfo->ports()) {
|
||||
if (port->is_bypass()) {
|
||||
pPedalboardItem->SetControlValue(port->symbol(), enabled? 1.0: 0.0f);
|
||||
if (pluginInfo)
|
||||
{
|
||||
for (auto &port : pluginInfo->ports())
|
||||
{
|
||||
if (port->is_bypass())
|
||||
{
|
||||
pPedalboardItem->SetControlValue(port->symbol(), enabled ? 1.0 : 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify clients.
|
||||
@@ -999,7 +1000,7 @@ int64_t PiPedalModel::SavePluginPresetAs(int64_t instanceId, const std::string &
|
||||
return presetId;
|
||||
}
|
||||
|
||||
int64_t PiPedalModel::SaveCurrentPresetAs(int64_t clientId, int64_t bankInstanceId,const std::string &name, int64_t saveAfterInstanceId)
|
||||
int64_t PiPedalModel::SaveCurrentPresetAs(int64_t clientId, int64_t bankInstanceId, const std::string &name, int64_t saveAfterInstanceId)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard{mutex};
|
||||
|
||||
@@ -1523,7 +1524,7 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
|
||||
throw std::runtime_error("Audio configuration not valid.");
|
||||
}
|
||||
|
||||
const auto & channelSelection = this->storage.GetChannelSelection();
|
||||
const auto &channelSelection = this->storage.GetChannelSelection();
|
||||
|
||||
this->audioHost->Open(jackServerSettings, channelSelection);
|
||||
|
||||
@@ -1625,7 +1626,6 @@ std::vector<AlsaSequencerPortSelection> PiPedalModel::GetAlsaSequencerPorts()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void PiPedalModel::FireChannelRouterSettingsChanged(int64_t clientId)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard{mutex};
|
||||
@@ -1838,7 +1838,7 @@ void PiPedalModel::SendSetPatchProperty(
|
||||
{
|
||||
std::shared_ptr<Lv2PluginInfo> pluginInfo = GetPluginInfo(pedalboardItem->uri_);
|
||||
auto pipedalUi = pluginInfo->piPedalUI();
|
||||
if (pipedalUi)
|
||||
if (pipedalUi)
|
||||
{
|
||||
auto fileProperty = pipedalUi->GetFileProperty(propertyUri);
|
||||
if (fileProperty)
|
||||
@@ -2129,8 +2129,7 @@ std::shared_ptr<Lv2PluginInfo> PiPedalModel::GetPluginInfo(const std::string &ur
|
||||
return pluginHost.GetPluginInfo(uri);
|
||||
}
|
||||
|
||||
|
||||
void PiPedalModel::UpdateDefaults(SnapshotValue&snapshotValue, const PedalboardItem*pedalboardItem_)
|
||||
void PiPedalModel::UpdateDefaults(SnapshotValue &snapshotValue, const PedalboardItem *pedalboardItem_)
|
||||
{
|
||||
std::shared_ptr<Lv2PluginInfo> pPlugin = pluginHost.GetPluginInfo(pedalboardItem_->uri());
|
||||
if (!pPlugin)
|
||||
@@ -2145,11 +2144,11 @@ void PiPedalModel::UpdateDefaults(SnapshotValue&snapshotValue, const PedalboardI
|
||||
// Fix incorrect bypass settings presint in Pipedal < 1.5.96
|
||||
for (size_t i = 0; i < pPlugin->ports().size(); ++i)
|
||||
{
|
||||
auto& port = pPlugin->ports()[i];
|
||||
auto &port = pPlugin->ports()[i];
|
||||
if (port->is_bypass() && port->is_control_port() && port->is_input())
|
||||
{
|
||||
ControlValue* pValue = snapshotValue.GetControlValue(port->symbol());
|
||||
float value = snapshotValue.isEnabled_ ? 1.0f : 0.0f;
|
||||
ControlValue *pValue = snapshotValue.GetControlValue(port->symbol());
|
||||
float value = snapshotValue.isEnabled_ ? 1.0f : 0.0f;
|
||||
|
||||
if (pValue == nullptr)
|
||||
{
|
||||
@@ -2166,7 +2165,8 @@ void PiPedalModel::UpdateDefaults(SnapshotValue&snapshotValue, const PedalboardI
|
||||
if (pPlugin->uri() == "http://two-play.com/plugins/toob-nam")
|
||||
{
|
||||
ControlValue *pVersion = snapshotValue.GetControlValue("version");
|
||||
if (pVersion == nullptr) {
|
||||
if (pVersion == nullptr)
|
||||
{
|
||||
ControlValue *pValue = snapshotValue.GetControlValue("inputCalibrationMode");
|
||||
if (pValue == nullptr)
|
||||
{
|
||||
@@ -2175,13 +2175,16 @@ void PiPedalModel::UpdateDefaults(SnapshotValue&snapshotValue, const PedalboardI
|
||||
}
|
||||
// convert old gate threshold to new gate threshold.
|
||||
ControlValue *pGateValue = snapshotValue.GetControlValue("gate");
|
||||
if (pGateValue) {
|
||||
if (pGateValue)
|
||||
{
|
||||
float value = pGateValue->value();
|
||||
// Is the gate disabled?
|
||||
if (value <= -100.0f)
|
||||
{
|
||||
value = -120.0f; // "disabled in new range."
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
value = value * 0.5; // correct the bug in original implementation.
|
||||
}
|
||||
snapshotValue.SetControlValue("gate", value);
|
||||
@@ -2245,7 +2248,8 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
|
||||
if (pPlugin->uri() == "http://two-play.com/plugins/toob-nam")
|
||||
{
|
||||
ControlValue *pVersion = pedalboardItem->GetControlValue("version");
|
||||
if (pVersion == nullptr) {
|
||||
if (pVersion == nullptr)
|
||||
{
|
||||
ControlValue *pValue = pedalboardItem->GetControlValue("inputCalibrationMode");
|
||||
if (pValue == nullptr)
|
||||
{
|
||||
@@ -2254,13 +2258,16 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
|
||||
}
|
||||
// convert old gate threshold to new gate threshold.
|
||||
ControlValue *pGateValue = pedalboardItem->GetControlValue("gate");
|
||||
if (pGateValue) {
|
||||
if (pGateValue)
|
||||
{
|
||||
float value = pGateValue->value();
|
||||
// Is the gate disabled?
|
||||
if (value <= -100.0f)
|
||||
{
|
||||
value = -120.0f; // "disabled in new range."
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
value = value * 0.5; // correct the bug in original implementation.
|
||||
}
|
||||
pedalboardItem->SetControlValue("gate", value);
|
||||
@@ -2278,18 +2285,20 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
|
||||
{
|
||||
// retroactively correct bug in version of PiPedal prior to 1.5.96.
|
||||
ControlValue *pValue = pedalboardItem->GetControlValue(port->symbol());
|
||||
float value = pedalboardItem->isEnabled() ? 1.0f: 0.0f;
|
||||
float value = pedalboardItem->isEnabled() ? 1.0f : 0.0f;
|
||||
|
||||
if (pValue == nullptr)
|
||||
{
|
||||
pedalboardItem->controlValues().push_back(
|
||||
pipedal::ControlValue(port->symbol().c_str(), value));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pValue->value(value);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlValue *pValue = pedalboardItem->GetControlValue(port->symbol());
|
||||
if (pValue == nullptr)
|
||||
{
|
||||
@@ -2357,7 +2366,9 @@ void PiPedalModel::UpdateDefaults(Snapshot *snapshot, std::unordered_map<int64_t
|
||||
// plugin is no longer present. Remove from the snapshot.
|
||||
snapshot->values_.erase(snapshot->values_.begin() + i);
|
||||
--i;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateDefaults(value, f->second);
|
||||
}
|
||||
}
|
||||
@@ -2387,7 +2398,7 @@ void PiPedalModel::UpdateDefaults(Pedalboard *pedalboard)
|
||||
|
||||
PluginPresets PiPedalModel::GetPluginPresets(const std::string &pluginUri)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
|
||||
return storage.GetPluginPresets(pluginUri);
|
||||
}
|
||||
@@ -3376,34 +3387,30 @@ std::vector<PresetIndexEntry> PiPedalModel::RequestBankPresets(int64_t bankInsta
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
|
||||
return storage.RequestBankPresets(bankInstanceId);
|
||||
|
||||
}
|
||||
|
||||
int64_t PiPedalModel::ImportPresetsFromBank(int64_t bankInstanceId, const std::vector<int64_t> &presets)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
uint64_t lastAdded = storage.ImportPresetsFromBank(bankInstanceId, presets);
|
||||
uint64_t lastAdded = storage.ImportPresetsFromBank(bankInstanceId, presets);
|
||||
|
||||
FirePresetsChanged(-1);
|
||||
return lastAdded;
|
||||
|
||||
}
|
||||
int64_t PiPedalModel::CopyPresetsToBank(int64_t bankInstanceId, const std::vector<int64_t> &presets)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
uint64_t lastAdded = storage.CopyPresetsToBank(bankInstanceId, presets);
|
||||
uint64_t lastAdded = storage.CopyPresetsToBank(bankInstanceId, presets);
|
||||
return lastAdded;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ChannelRouterSettings::ptr PiPedalModel::GetChannelRouterSettings()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
return this->channelRouterSettings;
|
||||
}
|
||||
|
||||
void PiPedalModel::SetChannelRouterSettings(int64_t clientId,ChannelRouterSettings::ptr &settings)
|
||||
void PiPedalModel::SetChannelRouterSettings(int64_t clientId, ChannelRouterSettings::ptr &settings)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
@@ -3415,12 +3422,9 @@ void PiPedalModel::SetChannelRouterSettings(int64_t clientId,ChannelRouterSettin
|
||||
RestartAudio(); // no lock to avoid mutex deadlock when reader thread is sending notifications..
|
||||
|
||||
this->FireChannelRouterSettingsChanged(clientId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string PiPedalModel::Tone3000ThumbnailDirectory()
|
||||
std::string PiPedalModel::Tone3000ThumbnailDirectory()
|
||||
{
|
||||
return "/var/pipedal/tone3000_thumbnails";
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace pipedal
|
||||
std::unique_ptr<AvahiService> avahiService;
|
||||
uint16_t webPort;
|
||||
|
||||
PiPedalAlsaDevices alsaDevices;
|
||||
PiPedalAlsaDevices &alsaDevices = PiPedalAlsaDevices::instance();
|
||||
std::recursive_mutex mutex;
|
||||
|
||||
AdminClient adminClient;
|
||||
|
||||
+918
-737
File diff suppressed because it is too large
Load Diff
@@ -45,11 +45,19 @@ namespace pipedal
|
||||
uint8_t cc2_;
|
||||
};
|
||||
|
||||
struct Lv2RoutingInserts {
|
||||
|
||||
Lv2Pedalboard*mainInserts = nullptr;
|
||||
Lv2Pedalboard*auxInserts = nullptr;;
|
||||
};
|
||||
|
||||
enum class RingBufferCommand : int64_t
|
||||
{
|
||||
Invalid = 0,
|
||||
ReplaceEffect,
|
||||
EffectReplaced,
|
||||
ReplaceRoutingInserts,
|
||||
RoutingInsertsReplaced,
|
||||
SetValue,
|
||||
SetBypass,
|
||||
// AudioStopped,
|
||||
@@ -539,16 +547,28 @@ namespace pipedal
|
||||
write(RingBufferCommand::ReplaceEffect, pedalboard);
|
||||
}
|
||||
|
||||
void EffectReplaced(Lv2Pedalboard *pedalboard)
|
||||
{
|
||||
write(RingBufferCommand::EffectReplaced, pedalboard);
|
||||
}
|
||||
|
||||
void ReplaceRoutingInserts(Lv2RoutingInserts routingInserts)
|
||||
{
|
||||
write(RingBufferCommand::ReplaceRoutingInserts, routingInserts);
|
||||
}
|
||||
|
||||
void RoutingInsertsReplaced(Lv2RoutingInserts routingInserts)
|
||||
{
|
||||
write(RingBufferCommand::ReplaceRoutingInserts, routingInserts);
|
||||
}
|
||||
|
||||
|
||||
void AudioTerminatedAbnormally()
|
||||
{
|
||||
AudioStoppedBody body;
|
||||
write(RingBufferCommand::AudioTerminatedAbnormally, body);
|
||||
}
|
||||
|
||||
void EffectReplaced(Lv2Pedalboard *pedalboard)
|
||||
{
|
||||
write(RingBufferCommand::EffectReplaced, pedalboard);
|
||||
}
|
||||
|
||||
void FreeSnapshot(IndexedSnapshot *snapshot)
|
||||
{
|
||||
|
||||
+4
-8
@@ -1931,14 +1931,13 @@ pipedal::JackServerSettings Storage::GetJackServerSettings()
|
||||
result.GetAlsaInputDevice().empty() &&
|
||||
result.GetAlsaOutputDevice().empty())
|
||||
{
|
||||
result.SetAlsaInputDevice(result.GetLegacyAlsaDevice());
|
||||
result.SetAlsaOutputDevice(result.GetLegacyAlsaDevice());
|
||||
std::string legacyDeviceId = result.GetLegacyAlsaDevice();
|
||||
result.SetAlsaInputDevice(legacyDeviceId, "");
|
||||
result.SetAlsaOutputDevice(legacyDeviceId, "");
|
||||
result.SetLegacyAlsaDevice("");
|
||||
}
|
||||
result.FixUpDeviceNames();
|
||||
}
|
||||
#if JACK_HOST
|
||||
result.Initialize();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1952,9 +1951,6 @@ void Storage::SetJackServerSettings(const pipedal::JackServerSettings &jackConfi
|
||||
json_writer writer(f, false);
|
||||
writer.write(jackConfiguration);
|
||||
}
|
||||
#if JACK_HOST
|
||||
jackConfiguration.Write();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Storage::SetSystemMidiBindings(const std::vector<MidiBinding> &bindings)
|
||||
|
||||
@@ -206,6 +206,7 @@ static void print_device_info(snd_ctl_t* handle, int card, int device) {
|
||||
// Print basic info
|
||||
std::cout << "\n Subdevice: " << name << " - " << device_name << std::endl;
|
||||
std::cout << " ID: " << snd_pcm_info_get_id(pcminfo) << std::endl;
|
||||
std::cout << " Name: " << snd_pcm_info_get_name(pcminfo) << std::endl;
|
||||
std::cout << " Capabilities:";
|
||||
if (has_playback) std::cout << " PLAYBACK";
|
||||
if (has_capture) std::cout << " CAPTURE";
|
||||
|
||||
Reference in New Issue
Block a user