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

This commit is contained in:
Robin Davies
2021-09-01 05:39:33 -04:00
18 changed files with 188 additions and 88 deletions
+68 -47
View File
@@ -1,15 +1,15 @@
# PiPedal
PiPedal is a multi-effect guitar pedal that provides a clean compact web interface that's suitable for use on small-format devices
like phones and tablets, although it works gloriously with desktop browers as well.
PiPedal is a multi-effect guitar pedal for Raspberry Pi devices. You will need a suitable audio input/output device to use PiPedal, which can be either an external USB audio adapter, or a Raspberry Pi ADC/DAC hat, providing at least one input and one output audio channel.
PiPedal uses LV2 audio plugins. There are currently a wide variety of sources for excellent LV2 guitar plugins. You can add as many
plugins to your patch as your CPU will support (well over a dozen on a Raspberry Pi 4+). Audio signal chains
PiPedal is controlled via a clean compact web app that's suitable for use on small-form devices, like phones and tablets, although it works gloriously with desktop browers as well. You should not have to carry around a laptop to control your PiPedal when you're out gigging; and the web interface for PiPedal has been designed with that scenario specifically in mind. PiPedal has been designed with compact display formats, and touch user-interfaces in mind. Just connect to the PiPedal Wi-Fi access point with your phone, and you have complete control over your PiPedal.
PiPedal effects are LV2 audio plugins. There are currently a wide variety of sources for excellent LV2 guitar plugins.
You can add as many plugins to your patch as your CPU will support (well over a dozen on a Raspberry Pi 4+). Signal chains
can have an arbitrary number of split chains, which maybe A/B-selected or mixed if you wish.
If you have a USB Midi Controller, you can bind Midi controls and notes to LV2 plugin controls using the Midi Bindings dialog.
This particularly useful if you have a USB Midi footccontroller or a small USB Midi controller such as the Korg Nano or AKAI \
midi controllers.
PiPedal allows you to easily bind Midi controls and notes to LV2 plugin controls using the Midi Bindings dialog. USB micro controllers such as the Korg nano series of MIDI controllers, or the AKAI pad controllers are perfectly suited for selecting and tweaking patches while performing; or you can connect regular MIDI controllers and pedalboards via the MIDI ports on your USB Audio device, if it supports MIDI.
## Configuring PiPedal After Installation
@@ -19,71 +19,81 @@ Raspberry Pi, if you are connected from an Android device (which does not curren
To complete the initial configuration, you must either connect an Ethernet cable to your Raspberry pi so you can connect to the Web App (after which you should be able to connect to http://pipedal.local); or you must launch a web browser on your Raspberry pi device while logged in interactively.
Once connected, you can activate a WiFi hotspot on your Rasberry Pi which can be used to connect to PiPedal while it is not connected to an Ethernet network.
Once connected, select the Settings menu item on the Hamburger menu at the top left corner of the display. Click on Audio Device Settings to select and configure the audio device you want to use.
You can also activate PiPedal's Wi-Fi hotspot connection from the Settings dialog. Click on the Wifi Hotspot menu item in the Settings dialog.
IMPORTANT NOTE: Activating the WiFi hotspot will DISABLE outbound Wi-Fi connections from the Raspberry Pi.
You will be able to access the PiPedal web interface through the hotspot connection, and make ssh and VNC
connections to the Raspberry Pi through the hotspot connection; but your Raspberry Pi will not have outbound access
to the Internet.
connections to the Raspberry Pi through the hotspot connection; but your Raspberry Pi will not have
outbound access to the Internet, unless an Ethernet cable is connected to the Raspberry Pi.
If you need access to the internet once the hotspot has been enabled, connect an Ethernet cable to
the Raspberry Pi.
Settings to configure the WiFi hotspot are available in the hamburger menu/Settings dialog.
There are a number of other useful settings in the hamburger menu/Settings dialog. For example, most USB audio devices route instrument
input onto the right channel of the USB audio inputs. So you probably want to configure PiPedal to use only the right USB audio input channel.
input onto the right channel of the USB audio inputs. So you probably want to configure PiPedal to use only the right USB audio input channel.
You can choose how to bind USB audio input and output channels (stereo, left only, right only) in the settings dialog. If you are using a Audio
device that has more than two channels, you will be offered a list of channels to choose from instead.
You can choose how to bind USB audio input and output channels (stereo, left only, right only) in the settings dialog.
## Command Line Configuration of PiPedal
The pipedalconfig program can be used to modify configuration of PiPedal from a shell command line. Run 'pipedalconfig --help' to view
available configuration commands, some of which are not avaialbe from the web interface. (For example, you can change the port number
of the Web App HTTP server if you need to, uusing pipedalconfig).
available configuration commands, some of which are not avaialbe from the web interface. For example, you can change the port number
of the Web App HTTP server if you need to, using pipedalconfig.
## LV2 PLugins
PiPedal uses standard LV2 audio plugins for effects. There are currently a wide variety of available LV2 guitar effect plugins, foremost of
which is the Guitarix plugin collection: https://guitarix.org/
PiPedal uses standard LV2 audio plugins for effects. There are currently a wide variety of available LV2 guitar effect plugins, and among
these are a number of LV2 plugin collections that are specifically meant for use as guitar effects.
To get started, install the Guitarix LV2 plugin collection.
Foremost among these is the Guitarix plugin collection: https://guitarix.org/. You should definitely install Guitarix:
sudo apt install guitarix-lv2
The Guitarix amp modelling plugins are on par with the best amp modelling effects anywhere.
Other highly recommended guitar effect collections:L
sudo apt install zam-plugins # http://www.zamaudio.com/
sudo apt install mda-lv2 # http://drobilla.net/software/mda-lv2/
sudo apt install calf-plugins # http://calf-studio-gear.org/
sudo apt install fomp # http://drobilla.net/software/fomp/
sudo apt install jackd
sudo apt install guitarix-lv2
sudo apt install zam-plugins
sudo apt install mda-lv2
sudo apt install fomp
But there are hundreds of other high-quality LV2 plugins that are suitable for use with PiPedal.
- Zam Plugins. http://www.zamaudio.com/
Visit https://lv2plug.in/pages/projects.html for a more suggestions.
- Calf Plugins. http://calf-studio-gear.org/
Or visit https://lv2plug.in/pages/projects.html for a more complete list.
There is also a set of supplementary Gx effect plugins which did not make it into the main Guitarix distribution. You
have to build these plugins yourself, but the effort is well worthwhile.
There is also a set of supplementary Gx effect plugins which did not make it into the main Guitarix distribution. You will
have to compile these plugins yourself, as they are not currently avaiable via apt. But if you are comfortable building
packages on Raspbian, the effort is well worthwhile. The GxPlugins collection provides a number of boutique amp emulations,
as well as emulations of famous distortion effect pedals.
- https://github.com/brummer10/GxPlugins.lv2
PiPedal will automatically detect installed LV2 plugins and make them selectable from the web app interface, as long as they meet the
following conditions:
- Must have mono or stereo audio inputs and outputs.
- Must not have MIDI or CV inputs.
- Must not be MIDI instruments or have CV (Control Voltage) inputs or outputs.
- Must be remotely controllable (no hard dependency on GUI-only controls), which is true of the vast majority of LV2 plugins.
- Must be remotely controllable (no hard dependency on GUI-only controls), which is true of the vast majority of LV2 plugins).
Most LV2 plugins have GUI interfaces, which are not used by PiPedal; but the LV2 plugin standard allows almost all LV2 plugins to
be controlled via PiPedal's web interface.
Althouhg most LV2 plugins provide GUI interfaces, when running on a LINUX desktop, the LV2 plugin standard is specifically designed to allow remote control
without using the provided desktop GUI interface. And all but a tiny minority of LV2 plugins support this.
### Building and Installing PiPedal
## Building and Installing PiPedal
PiPedal has only been tested on Raspbian. But we will gladly accept pull requests to correct problems with other versions of Linux.
PiPedal has only been tested on Raspbian. But we pull requests to correct problems with building PiPedal on other versions of Linux are welcome.
To build PiPedal, a Raspberry Pi 4B, with at least 4GB of memory is recommended. You should be able to cross-compile PiPedal easily enough,
but we do not currently provide support for this. Consult CMake documentation on how to cross-compile source.
@@ -99,7 +109,7 @@ Run the following commands to install build tools required by the PiPedal build.
sudo apt-get install -y nodejs
Run the following commands to install dependent components required by the PiPedal build.
Run the following commands to install dependent libraries required by the PiPedal build.
sudo apt update
sudo apt install liblilv-dev libboost-dev libjack-jackd2-dev libnl-3-dev libnl-genl-3-dev libsystemd-dev catch
@@ -112,21 +122,32 @@ of `node.js` installed already. Otherwise run the following commands as root to
apt-get install -y nodejs
### Building PiPedal.ini
### Building PiPedal
PiPedal was developed using Visual Studio Code. If you open the PiPedal project as a folder in VS Code, Code will
detect the CMake configuration files, and automatically configure itself. Once the VS Code CMake plugin has configured
itself, build commands should appear on the bottom line of the Visual Studio Code interface.
detect the CMake configuration files, and automatically configure itself. Once the VS Code CMake plugin (written by Microsoft,
available through the plugins store) has configured itself, build commands should appear on the bottom line of Visual Studio
Code. Visual Studio Code will take care of automatically configuring the project.
To install PiPedal, run a full non-debug build using Visual Studio Code, and then run the following command
in the root project directory:
If you are not using Visual Studio Code, you can configure, build and install PiPedal using CMake build tools. For your convenience,
the following shell scripts have been provided in the root of the project.
sudo ,./init
sudo ./init # Configure the CMake build
If you are using a different development environment, you can build the project by running the following
command in the root project directory.
./mk # Build all targets.
sudo ./install # Deploy all targets
./pkg # Build a .deb file for distribution.
If you are using a development environment other than Visual Studio Code, it should be fairly straightforward to figure out how
to incorporate the PiPedal build procedure into your IDE workflow by examining the contents of the build shell scripts.
./mk
The CMake toolchain can be used to generate build scripts for other build environments as well (e.g. Visuual Studio .csproj files, Ant, or Linux
Makefiles); and can be configured to perform cross-compiled builds as well. Consult documentation for CMake for instructions on how to
do that if you're interested. Visual Studio Code also provides quite painless procedures for cross-compiling CMake projects, and for
remote building, and debugging. If you need to build for platforms other than Raspbian, or build on platforms other than Rasbian,
you make want to investigate what Visual Studio Code's CMake integration provides in that regard.
### How to Debug PiPedal.
+4 -2
View File
@@ -188,7 +188,9 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
return (
<DialogEx tag="AboutDlg" fullScreen open={this.props.open}
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}>
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}
style={{userSelect: "none"}}
>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
@@ -206,7 +208,7 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
</div>
<div style={{
flex: "1 1 auto", position: "relative", overflow: "hidden",
overflowX: "hidden", overflowY: "auto"
overflowX: "hidden", overflowY: "auto" , userSelect: "text"
}}
>
<div style={{margin: 24}}>
+5 -2
View File
@@ -407,7 +407,9 @@ const BankDialog = withStyles(styles, { withTheme: true })(
return (
<DialogEx tag="BankDialog" fullScreen open={this.props.show}
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}>
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}
style={{userSelect: "none"}}
>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
<AppBar className={classes.dialogAppBar} style={{ display: this.isEditMode() ? "none" : "block" }} >
@@ -539,7 +541,8 @@ const BankDialog = withStyles(styles, { withTheme: true })(
style={{ display: "none" }}
/>
<DialogEx tag="deletePrompt" open={this.state.showDeletePrompt} onClose={() => this.handleDeletePromptClose()}>
<DialogEx tag="deletePrompt" open={this.state.showDeletePrompt} onClose={() => this.handleDeletePromptClose()}
style={{userSelect: "none"}}>
<DialogContent>
<Typography>Are you sure you want to delete bank '{this.getSelectedBankName()}'?</Typography>
</DialogContent>
+3 -1
View File
@@ -51,7 +51,9 @@ export default class JackServerSettings {
getSummaryText() {
if (this.valid) {
return this.alsaDevice + " Sample Rate: " + this.sampleRate + " BufferSize: " + this.bufferSize + " Number of Buffers: " + this.numberOfBuffers;
let device = this.alsaDevice;
if (device.startsWith("hw:")) device = device.substr(3);
return device + " - Rate: " + this.sampleRate + " BufferSize: " + this.bufferSize + " Buffers: " + this.numberOfBuffers;
} else {
return "Not configured";
}
+2 -8
View File
@@ -408,9 +408,9 @@ class PiPedalModelImpl implements PiPedalModel {
this.onSocketReconnected = this.onSocketReconnected.bind(this);
}
onSocketReconnecting(retry: number, maxRetries: number): void {
if (retry !== 0) {
//if (retry !== 0) {
this.setState(State.Reconnecting);
}
//}
}
@@ -455,14 +455,10 @@ class PiPedalModelImpl implements PiPedalModel {
);
} else if (message === "onPedalBoardChanged") {
let pedalChangedBody = body as PedalBoardChangedBody;
// xxx: do we want to optimize for messages we went ourselves??
// we could actually protect against preview collisions in the model.
this.pedalBoard.set(new PedalBoard().deserialize(pedalChangedBody.pedalBoard));
} else if (message === "onMidiValueChanged") {
let controlChangedBody = body as ControlChangedBody;
// xxx: do we want to optimize for messages we went ourselves??
// we could actually protect against preview collisions in the model.
this._setPedalBoardControlValue(
controlChangedBody.instanceId,
controlChangedBody.symbol,
@@ -480,8 +476,6 @@ class PiPedalModelImpl implements PiPedalModel {
this.handleNotifyMidiListener(clientHandle, isNote, noteOrControl);
} else if (message === "onControlChanged") {
let controlChangedBody = body as ControlChangedBody;
// xxx: do we want to optimize for messages we went ourselves??
// we could actually protect against preview collisions in the model.
this._setPedalBoardControlValue(
controlChangedBody.instanceId,
controlChangedBody.symbol,
+2 -1
View File
@@ -335,7 +335,8 @@ const PresetDialog = withStyles(styles, { withTheme: true })(
return (
<DialogEx tag="PresetDialog" fullScreen open={this.props.show}
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}>
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}
style={{userSelect: "none"}}>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
<AppBar className={classes.dialogAppBar} style={{ display: this.isEditMode() ? "none" : "block" }} >
+2 -1
View File
@@ -96,8 +96,9 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
}
};
return (
<DialogEx tag="RenameDialog" open={open} fullWidth onClose={handleClose} aria-labelledby="Rename-dialog-title" style={{}}
<DialogEx tag="RenameDialog" open={open} fullWidth onClose={handleClose} aria-labelledby="Rename-dialog-title"
fullScreen={this.state.fullScreen}
style={{userSelect: "none"}}
>
<DialogContent>
<TextField
+15 -5
View File
@@ -393,7 +393,9 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
return (
<DialogEx tag="SettingsDialog" fullScreen open={this.props.open}
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}>
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}
style={{userSelect: "none"}}
>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
@@ -426,11 +428,19 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
JackHostStatus.getDisplayView("Status:\u00A0", this.state.jackStatus)
}
</div>
{ this.state.jackConfiguration.errorState !== "" &&
(
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
<Typography variant="caption" color="textSecondary"><span style={{color: "#F00"}}>{this.state.jackConfiguration.errorState }</span></Typography>
</div>
)
}
<ButtonBase className={classes.setting} onClick={() => this.handleJackServerSettings()}
>
<SelectHoverBackground selected={false} showHover={true} />
<div style={{ width: "100%" }}>
<Typography display="block" variant="body2" noWrap>Jack Server Settings</Typography>
<Typography display="block" variant="body2" noWrap>Audio device</Typography>
<Typography display="block" variant="caption" noWrap color="textSecondary">{this.state.jackServerSettings.getSummaryText()}</Typography>
</div>
</ButtonBase>
@@ -454,7 +464,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
>
<SelectHoverBackground selected={false} showHover={true} />
<div style={{ width: "100%" }}>
<Typography display="block" variant="body2" noWrap>Input Channels</Typography>
<Typography display="block" variant="body2" noWrap>Input channels</Typography>
<Typography display="block" variant="caption" color="textSecondary" noWrap>{this.state.jackSettings.getAudioInputDisplayValue(this.state.jackConfiguration)}</Typography>
</div>
</ButtonBase>
@@ -473,7 +483,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
<ButtonBase className={classes.setting} disabled={!isConfigValid} onClick={() => this.handleMidiSelection()} >
<SelectHoverBackground selected={false} showHover={true} />
<div style={{ width: "100%" }}>
<Typography className={classes.primaryItem} display="block" variant="body2" noWrap>Select MIDI Input Channels</Typography>
<Typography className={classes.primaryItem} display="block" variant="body2" noWrap>Select MIDI input channels</Typography>
<Typography className={classes.secondaryItem} display="block" variant="caption" color="textSecondary" noWrap>{this.midiSummary()}</Typography>
</div>
@@ -488,7 +498,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
<SelectHoverBackground selected={false} showHover={true} />
<div style={{ width: "100%" }}>
<Typography className={classes.primaryItem} display="block" variant="body2" color="textPrimary" noWrap>
Configure Wi-fi Hotspot</Typography>
Configure Wi-Fi hotspot</Typography>
<Typography display="block" variant="caption" noWrap color="textSecondary">
{this.state.wifiConfigSettings.getSummaryText()}
</Typography>
+2 -1
View File
@@ -153,8 +153,9 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
return (
<DialogEx tag="UploadDialog" open={this.props.open} fullWidth onClose={() => this.handleClose()} style={{}}
<DialogEx tag="UploadDialog" open={this.props.open} fullWidth onClose={() => this.handleClose()}
fullScreen={this.state.fullScreen}
style={{userSelect: "none"}}
>
<DialogTitle>Upload preset</DialogTitle>
<DialogContent>
+3 -2
View File
@@ -250,7 +250,7 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
};
return (
<DialogEx tag="WifiConfigDialog" open={open} fullWidth onClose={handleClose} style={{}}
<DialogEx tag="WifiConfigDialog" open={open} fullWidth onClose={handleClose} style={{userSelect: "none"}}
fullScreen={this.state.fullScreen}
>
{ this.state.fullScreen && (
@@ -335,7 +335,8 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
OK
</Button>
</DialogActions>
<DialogEx open={this.state.showWifiWarningDialog} tag="wifiConfirm" >
<DialogEx open={this.state.showWifiWarningDialog} tag="wifiConfirm"
style={{userSelect: "none"}}>
<DialogContent>
<Typography className={classes.pgraph} variant="body2" color="textPrimary">
Enabling the Wi-Fi hotspot will disable regular Wi-Fi network access on the PiPedal device. Once
+5 -1
View File
@@ -813,7 +813,11 @@ public:
void
do_read()
{
// Set the timer
// make the request empty before reading
// otherwise the operation behavour is undefined.
req_ = {};
// Set the time
timer_.expires_after(std::chrono::seconds(15));
// Read a request
+55 -1
View File
@@ -193,6 +193,59 @@ static bool userExists(const char *userName)
return true;
}
void InstallPamEnv()
{
std::string newLine = "JACK_PROMISCOUS_SERVER DEFAULT=jack";
std::vector<std::string> lines;
std::filesystem::path path = "/etc/security/pam_env.conf";
try
{
if (std::filesystem::exists(path))
{
{
ifstream f(path);
if (!f.is_open())
{
throw PiPedalException("Can't open pam_env.conf");
}
while (true)
{
std::string line;
if (f.eof())
break;
std::getline(f, line);
lines.push_back(line);
}
}
for (auto &line : lines)
{
if (line == newLine)
{
return;
}
}
lines.push_back(newLine);
{
std::ofstream f(path);
if (!f.is_open())
{
throw PiPedalException("Can't write to file.");
}
for (auto&line: lines)
{
f << line << endl;
}
}
}
}
catch (const std::exception &e)
{
cout << "Failed to update " << path << ". " << e.what();
}
}
void InstallLimits()
{
if (SysExec(GROUPADD_BIN " -f " AUDIO_SERVICE_GROUP_NAME) != EXIT_SUCCESS)
@@ -227,6 +280,7 @@ void MaybeStartJackService()
void InstallJackService()
{
InstallLimits();
InstallPamEnv();
if (SysExec(GROUPADD_BIN " -f " JACK_SERVICE_GROUP_NAME) != EXIT_SUCCESS)
{
throw PiPedalException("Failed to create jack service group.");
@@ -554,7 +608,7 @@ int main(int argc, char **argv)
args.push_back((char *)(pkexec.c_str()));
std::string sPath = GetSelfExePath();
args.push_back(const_cast<char*>(sPath.c_str()));
args.push_back(const_cast<char *>(sPath.c_str()));
for (int arg = 1; arg < argc; ++arg)
{
args.push_back(const_cast<char *>(argv[arg]));
+2 -2
View File
@@ -1275,10 +1275,10 @@ private:
void ThreadProc()
{
this_->restarting = true;
this_->Close();
// this_->Close(); (JackServerConfiguration now does a service restart.)
try {
ShutdownClient::SetJackServerConfiguration(jackServerSettings);
this_->Open(this_->channelSelection);
//this_->Open(this_->channelSelection);
this_->restarting = false;
onComplete(true, "");
isComplete = true;
+3 -6
View File
@@ -214,20 +214,17 @@ void JackServerSettings::Write()
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 -P90"
<< "-R -P70 --silent"
<< " -dalsa -d" << this->alsaDevice_
<< " -r" << this->sampleRate_
<< " -p" << this->bufferSize_
<< " -n" << this->numberOfBuffers_ << " -Xseq"
<< endl;
system("/usr/bin/chmod 755 " DRC_FILENAME);
system("pulseaudio --kill");
system("/usr/bin/systemctl unmask jack");
system("/usr/bin/systemctl enable jack");
if (system("/usr/bin/systemctl restart jack") != 0)
{
throw PiPedalException("Failed to start jack audio service.");
}
}
catch (const std::exception &e)
{
+6 -1
View File
@@ -910,13 +910,17 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
Lv2Log::error(s.str().c_str());
}
// Update jack server status.
this->jackConfiguration.SetIsRestarting(false);
if (!success)
{
this->jackConfiguration.SetIsRestarting(false);
this->jackConfiguration.SetErrorStatus(errorMessage);
fireJackConfigurationChanged(this->jackConfiguration);
}
else
{
// we now do a complete restart of the services,
// so just sit tight and wait for the restart.
#ifdef JUNK
this->jackConfiguration.SetErrorStatus("");
fireJackConfigurationChanged(this->jackConfiguration);
@@ -927,6 +931,7 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
jackHost->SetPedalBoard(lv2PedalBoard);
updateRealtimeVuSubscriptions();
updateRealtimeMonitorPortSubscriptions();
#endif
}
});
}
+7 -4
View File
@@ -86,11 +86,16 @@ 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";
Lv2Log::error("Delayed Restart");
std::string pipedalConfigPath = std::filesystem::path(GetSelfExePath()).parent_path() / "pipedalconfig";
std::stringstream s;
s << pipedalConfigPath.c_str() << " --restart --excludeShutdownService";
::system(s.str().c_str());
if (::system(s.str().c_str())!= EXIT_SUCCESS)
{
Lv2Log::error("Delayed Restart failed.");
}
}
bool setJackConfiguration(JackServerSettings serverSettings)
@@ -247,8 +252,6 @@ private:
{
auto remainder = s.substr(strlen("setJackConfiguration "));
// xxx delete me
Lv2Log::error("setJackConfiguration: " + remainder);
std::stringstream input(remainder);
JackServerSettings serverSettings;
+1 -1
View File
@@ -60,7 +60,7 @@ void json_writer::write(string_view v,bool enforceValidUtf8Encoding)
{
// convert to utf-32.
// convert utf-32 to normalized utf-16.
// write non-7-bit and unsafe characters as \uxxxx.
// write non-7-bit and unsafe characters as \uHHHH.
auto p = v.begin();
os << '"';
+3 -2
View File
@@ -579,9 +579,10 @@ int main(int argc, char *argv[])
PiPedalModel model;
// Pre-populate ALSA device info,wait for jackd service (daemon only)
model.GetAlsaDevices(); // pre-cache ALSA devices.
if (systemd)
{
auto devices = model.GetAlsaDevices();
auto devices = model.GetAlsaDevices(); // pre-cache ALSA devices (most especially, the one which Jack will open, that we can no longer read)
auto serverSettings = model.GetJackServerSettings();
if (serverSettings.IsValid())
@@ -590,7 +591,7 @@ int main(int argc, char *argv[])
if (!HasAlsaDevice(devices, serverSettings.GetAlsaDevice()))
{
Lv2Log::info("Waiting for ALSA device " + serverSettings.GetAlsaDevice());
for (int i = 0; i < 15; ++i)
for (int i = 0; i < 10; ++i)
{
sleep(1);
devices = model.GetAlsaDevices();