Jack Settings bug fixes.

This commit is contained in:
Robin Davies
2021-08-30 04:34:07 -04:00
parent 57ecc0d9ef
commit 6cb1300cc9
7 changed files with 135 additions and 39 deletions
+33 -37
View File
@@ -107,15 +107,18 @@ void DisableService()
} }
} }
void StopService() void StopService(bool excludeShutdownService = false)
{ {
if (SysExec(SYSTEMCTL_BIN " stop " NATIVE_SERVICE ".service") != EXIT_SUCCESS) if (SysExec(SYSTEMCTL_BIN " stop " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
{ {
cout << "Error: Failed to stop the " NATIVE_SERVICE " service."; cout << "Error: Failed to stop the " NATIVE_SERVICE " service.";
} }
if (SysExec(SYSTEMCTL_BIN " stop " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS) if (!excludeShutdownService)
{ {
cout << "Error: Failed to stop the " SHUTDOWN_SERVICE " service."; if (SysExec(SYSTEMCTL_BIN " stop " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
{
cout << "Error: Failed to stop the " SHUTDOWN_SERVICE " service.";
}
} }
if (SysExec(SYSTEMCTL_BIN " stop " JACK_SERVICE ".service") != EXIT_SUCCESS) if (SysExec(SYSTEMCTL_BIN " stop " JACK_SERVICE ".service") != EXIT_SUCCESS)
{ {
@@ -123,20 +126,24 @@ void StopService()
} }
} }
void Uninstall() { void Uninstall()
{
StopService(); StopService();
DisableService(); DisableService();
system(SYSTEMCTL_BIN " stop jack"); system(SYSTEMCTL_BIN " stop jack");
system(SYSTEMCTL_BIN " disable jack"); system(SYSTEMCTL_BIN " disable jack");
} }
void StartService() void StartService(bool excludeShutdownService = false)
{ {
SilentSysExec("/usr/bin/pulseaudio --kill"); // interferes with Jack audio service startup. SilentSysExec("/usr/bin/pulseaudio --kill"); // interferes with Jack audio service startup.
if (SysExec(SYSTEMCTL_BIN " start " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS) if (!excludeShutdownService)
{ {
throw PiPedalException("Failed to start the " SHUTDOWN_SERVICE " service."); if (SysExec(SYSTEMCTL_BIN " start " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
{
throw PiPedalException("Failed to start the " SHUTDOWN_SERVICE " service.");
}
} }
if (SysExec(SYSTEMCTL_BIN " start " NATIVE_SERVICE ".service") != EXIT_SUCCESS) if (SysExec(SYSTEMCTL_BIN " start " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
{ {
@@ -152,11 +159,11 @@ void StartService()
} }
} }
} }
void RestartService() void RestartService(bool excludeShutdownService)
{ {
StopService(); StopService(excludeShutdownService);
StartService(); StartService(excludeShutdownService);
} }
static bool userExists(const char *userName) static bool userExists(const char *userName)
@@ -202,16 +209,18 @@ void InstallLimits()
output << "@audio - rtprio 95" << endl; output << "@audio - rtprio 95" << endl;
output << "@audio - memlock unlimited" << endl; output << "@audio - memlock unlimited" << endl;
} }
} }
void MaybeStartJackService() { void MaybeStartJackService()
{
std::filesystem::path drcFile = "/etc/jackdrc"; std::filesystem::path drcFile = "/etc/jackdrc";
if (std::filesystem::exists(drcFile) && std::filesystem::file_size(drcFile) != 0) { if (std::filesystem::exists(drcFile) && std::filesystem::file_size(drcFile) != 0)
{
system(SYSTEMCTL_BIN " start jack"); system(SYSTEMCTL_BIN " start jack");
} else { }
else
{
system(SYSTEMCTL_BIN " mask jack"); system(SYSTEMCTL_BIN " mask jack");
} }
} }
@@ -237,16 +246,13 @@ void InstallJackService()
SysExec(USERMOD_BIN " -a -G" AUDIO_SERVICE_GROUP_NAME " " JACK_SERVICE_ACCOUNT_NAME); SysExec(USERMOD_BIN " -a -G" AUDIO_SERVICE_GROUP_NAME " " JACK_SERVICE_ACCOUNT_NAME);
// deploy the systemd service file // deploy the systemd service file
std::map<std::string,std::string> map; // nothing to customize. std::map<std::string, std::string> map; // nothing to customize.
WriteTemplateFile(map, std::filesystem::path("/etc/pipedal/templateJack.service"), GetServiceFileName(JACK_SERVICE)); WriteTemplateFile(map, std::filesystem::path("/etc/pipedal/templateJack.service"), GetServiceFileName(JACK_SERVICE));
MaybeStartJackService(); MaybeStartJackService();
} }
void Install(const std::filesystem::path &programPrefix, const std::string endpointAddress) void Install(const std::filesystem::path &programPrefix, const std::string endpointAddress)
{ {
@@ -391,7 +397,7 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
SysExec(SYSTEMCTL_BIN " daemon-reload"); SysExec(SYSTEMCTL_BIN " daemon-reload");
cout << "Starting service" << endl; cout << "Starting service" << endl;
RestartService(); RestartService(false);
EnableService(); EnableService();
cout << "Complete" << endl; cout << "Complete" << endl;
@@ -426,6 +432,7 @@ int main(int argc, char **argv)
bool enable = false, disable = false, restart = false; bool enable = false, disable = false, restart = false;
bool enable_ap = false, disable_ap = false; bool enable_ap = false, disable_ap = false;
bool nopkexec = false; bool nopkexec = false;
bool excludeShutdownService = false;
std::string prefixOption; std::string prefixOption;
std::string portOption; std::string portOption;
@@ -443,6 +450,7 @@ int main(int argc, char **argv)
parser.AddOption("--port", &portOption); parser.AddOption("--port", &portOption);
parser.AddOption("--enable_ap", &enable_ap); parser.AddOption("--enable_ap", &enable_ap);
parser.AddOption("--disable_ap", &disable_ap); parser.AddOption("--disable_ap", &disable_ap);
parser.AddOption("--excludeShutdownService", &excludeShutdownService); // private (unstable) option used by shutdown service.
try try
{ {
parser.Parse(argc, (const char **)argv); parser.Parse(argc, (const char **)argv);
@@ -540,30 +548,18 @@ int main(int argc, char **argv)
auto uid = getuid(); auto uid = getuid();
if (uid != 0 && !nopkexec) if (uid != 0 && !nopkexec)
{ {
// re-execute with PKEXEC in order to prompt form SUDO credentials. // re-execute with PKEXEC in order to prompt for SUDO credentials once only.
std::vector<char *> args; std::vector<char *> args;
std::string pkexec = "/usr/bin/pkexec"; // staged because "ISO C++ forbids converting a string constant to std::vector<char*>::value_type"(!) std::string pkexec = "/usr/bin/pkexec"; // staged because "ISO C++ forbids converting a string constant to std::vector<char*>::value_type"(!)
args.push_back((char *)(pkexec.c_str())); args.push_back((char *)(pkexec.c_str()));
std::filesystem::path path = std::filesystem::absolute(argv[0]); std::string sPath = GetSelfExePath();
std::string sPath = path; args.push_back(const_cast<char*>(sPath.c_str()));
args.push_back((char *)path.c_str());
for (int arg = 1; arg < argc; ++arg) for (int arg = 1; arg < argc; ++arg)
{ {
args.push_back((char *)argv[arg]); args.push_back(const_cast<char *>(argv[arg]));
} }
std::string prefixArg; // lifetime management for the prefix arguments
std::string prefixOptionArg;
if (prefixOption.length() == 0)
{
std::filesystem::path prefix = std::filesystem::path(argv[0]).parent_path().parent_path();
prefixOptionArg = "-prefix";
args.push_back((char *)(prefixOptionArg.c_str()));
prefixArg = prefix;
args.push_back((char *)prefixArg.c_str());
}
args.push_back(nullptr); args.push_back(nullptr);
char **rawArgv = &args[0]; char **rawArgv = &args[0];
@@ -616,7 +612,7 @@ int main(int argc, char **argv)
} }
else if (restart) else if (restart)
{ {
RestartService(); RestartService(excludeShutdownService);
} }
else if (enable) else if (enable)
{ {
+15 -1
View File
@@ -76,6 +76,11 @@ void PiPedalModel::Close()
PiPedalModel::~PiPedalModel() PiPedalModel::~PiPedalModel()
{ {
CurrentPreset currentPreset;
currentPreset.modified_ = this->hasPresetChanged;
currentPreset.preset_ = this->pedalBoard;
storage.SaveCurrentPreset(currentPreset);
if (jackHost) if (jackHost)
{ {
jackHost->Close(); jackHost->Close();
@@ -109,7 +114,15 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
} }
lv2Host.Load(configuration.GetLv2Path().c_str()); lv2Host.Load(configuration.GetLv2Path().c_str());
this->pedalBoard = storage.GetCurrentPreset(); this->pedalBoard = storage.GetCurrentPreset(); // the current *saved* preset.
// the current edited preset, saved only across orderly shutdowns.
CurrentPreset currentPreset;
if (storage.RestoreCurrentPreset(&currentPreset))
{
this->pedalBoard = currentPreset.preset_;
this->hasPresetChanged = currentPreset.modified_;
}
updateDefaults(&this->pedalBoard); updateDefaults(&this->pedalBoard);
std::unique_ptr<JackHost> p{JackHost::CreateInstance(lv2Host.asIHost())}; std::unique_ptr<JackHost> p{JackHost::CreateInstance(lv2Host.asIHost())};
@@ -373,6 +386,7 @@ void PiPedalModel::firePresetsChanged(int64_t clientId)
} }
} }
void PiPedalModel::saveCurrentPreset(int64_t clientId) void PiPedalModel::saveCurrentPreset(int64_t clientId)
{ {
std::lock_guard(this->mutex); std::lock_guard(this->mutex);
+17 -1
View File
@@ -30,6 +30,7 @@
#include <iostream> #include <iostream>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <memory> #include <memory>
#include <thread>
#include <stdlib.h> #include <stdlib.h>
#include "JackServerSettings.hpp" #include "JackServerSettings.hpp"
#include <cstdlib> #include <cstdlib>
@@ -38,6 +39,7 @@
#include "WifiConfigSettings.hpp" #include "WifiConfigSettings.hpp"
#include "SetWifiConfig.hpp" #include "SetWifiConfig.hpp"
#include "SysExec.hpp" #include "SysExec.hpp"
#include <filesystem>
using namespace std; using namespace std;
@@ -48,6 +50,8 @@ using ip::tcp;
const size_t MAX_LENGTH = 128; const size_t MAX_LENGTH = 128;
static bool startsWith(const std::string&s, const char*text) static bool startsWith(const std::string&s, const char*text)
{ {
if (s.length() < strlen(text)) return false; if (s.length() < strlen(text)) return false;
@@ -79,12 +83,24 @@ static void ReleaseAccessPoint(const std::string gatewayAddress)
{ {
} }
void delayedRestartProc()
{
sleep(1); // give a chance for websocket messages to propagate.
std::string pipedalConfigPath = std::filesystem::path(GetSelfExePath()).parent_path() / "pipedalConfig";
std::stringstream s;
s << pipedalConfigPath.c_str() << " --restart --excludeShutdownService";
::system(s.str().c_str());
}
bool setJackConfiguration(JackServerSettings serverSettings) bool setJackConfiguration(JackServerSettings serverSettings)
{ {
bool success = true; bool success = true;
serverSettings.Write(); serverSettings.Write();
std::thread delayedRestartThread(delayedRestartProc);
delayedRestartThread.detach();
return true; return true;
@@ -319,9 +335,9 @@ void runServer(uint16_t port)
} }
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Lv2Log::set_logger(MakeLv2SystemdLogger()); Lv2Log::set_logger(MakeLv2SystemdLogger());
CommandLineParser parser; CommandLineParser parser;
+44
View File
@@ -205,6 +205,11 @@ std::filesystem::path Storage::GetPresetsDirectory() const
{ {
return this->dataRoot / "presets"; return this->dataRoot / "presets";
} }
std::filesystem::path Storage::GetCurrentPresetPath() const
{
return this->dataRoot / "currentPreset.json";
}
std::filesystem::path Storage::GetChannelSelectionFileName() std::filesystem::path Storage::GetChannelSelectionFileName()
{ {
@@ -821,3 +826,42 @@ WifiConfigSettings Storage::GetWifiConfigSettings()
} }
void Storage::SaveCurrentPreset(const CurrentPreset &currentPreset)
{
try {
std::filesystem::path path = GetCurrentPresetPath();
std::ofstream f(path);
json_writer writer(f);
writer.write(currentPreset);
} catch (std::exception&)
{
// called from destructor. Must be nothrow().
}
}
bool Storage::RestoreCurrentPreset(CurrentPreset*pResult)
{
std::filesystem::path path = GetCurrentPresetPath();
if (std::filesystem::exists(path)) {
try {
std::ifstream f(path);
json_reader reader(f);
reader.read(pResult);
std::filesystem::remove(path); // one-shot only, restore the state from the last *orderly* shutdown.
} catch (const std::exception&)
{
return false;
}
return true;
} else {
return false;
}
}
JSON_MAP_BEGIN(CurrentPreset)
JSON_MAP_REFERENCE(CurrentPreset,modified)
JSON_MAP_REFERENCE(CurrentPreset,preset)
JSON_MAP_END()
+14
View File
@@ -30,6 +30,14 @@
namespace pipedal { namespace pipedal {
class CurrentPreset {
public:
bool modified_ = false;
PedalBoard preset_;
DECLARE_JSON_MAP(CurrentPreset);
};
// controls user-defined storage. Implmentation hidden to allow to later migration to a database (perhaps) // controls user-defined storage. Implmentation hidden to allow to later migration to a database (perhaps)
class Storage { class Storage {
@@ -45,6 +53,8 @@ private:
std::filesystem::path GetIndexFileName() const; std::filesystem::path GetIndexFileName() const;
std::filesystem::path GetBankFileName(const std::string & name) const; std::filesystem::path GetBankFileName(const std::string & name) const;
std::filesystem::path GetChannelSelectionFileName(); std::filesystem::path GetChannelSelectionFileName();
std::filesystem::path GetCurrentPresetPath() const;
void LoadBankIndex(); void LoadBankIndex();
void SaveBankIndex(); void SaveBankIndex();
@@ -104,6 +114,10 @@ public:
void SetWifiConfigSettings(const WifiConfigSettings & wifiConfigSettings); void SetWifiConfigSettings(const WifiConfigSettings & wifiConfigSettings);
WifiConfigSettings GetWifiConfigSettings(); WifiConfigSettings GetWifiConfigSettings();
void SaveCurrentPreset(const CurrentPreset &currentPreset);
bool RestoreCurrentPreset(CurrentPreset*pResult);
}; };
+11
View File
@@ -24,6 +24,7 @@
#include "PiPedalException.hpp" #include "PiPedalException.hpp"
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <linux/limits.h> // for PATH_MAX
using namespace pipedal; using namespace pipedal;
using namespace std; using namespace std;
@@ -129,4 +130,14 @@ int pipedal::SysExec(const char *szCommand)
int exitStatus = WEXITSTATUS(returnValue); int exitStatus = WEXITSTATUS(returnValue);
return exitStatus; return exitStatus;
} }
}
std::string pipedal::GetSelfExePath()
{
char result[PATH_MAX+1];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
if (count < 0) throw PiPedalException("Can't find EXE path.");
result[count] = 0;
return result;
} }
+1
View File
@@ -27,4 +27,5 @@ int SysExec(const char*szCommand);
// execute a command, suppressing output. // execute a command, suppressing output.
void SilentSysExec(const char *szCommand); void SilentSysExec(const char *szCommand);
std::string GetSelfExePath();
} }