Re-order service startup (Jack Server Settings)
This commit is contained in:
@@ -25,6 +25,6 @@
|
|||||||
|
|
||||||
/* Provide access point capture redirects on this gateway. */
|
/* Provide access point capture redirects on this gateway. */
|
||||||
"accessPointGateway": "192.168.0.0/24",
|
"accessPointGateway": "192.168.0.0/24",
|
||||||
"accessPointServerAddress" : "192.168.0.23:8080"
|
"accessPointServerAddress" : "192.168.0.26:8080"
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,6 @@ import FormControl from '@material-ui/core/FormControl';
|
|||||||
import Select from '@material-ui/core/Select';
|
import Select from '@material-ui/core/Select';
|
||||||
import DialogContent from '@material-ui/core/DialogContent';
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
import MenuItem from '@material-ui/core/MenuItem';
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
import { nullCast } from './Utility';
|
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||||
|
|
||||||
@@ -178,7 +177,7 @@ const JackServerSettingsDialog = withStyles(styles)(
|
|||||||
let settings = this.state.jackServerSettings.clone();
|
let settings = this.state.jackServerSettings.clone();
|
||||||
settings.alsaDevice = device;
|
settings.alsaDevice = device;
|
||||||
settings.sampleRate = selectedDevice.closestSampleRate(settings.sampleRate);
|
settings.sampleRate = selectedDevice.closestSampleRate(settings.sampleRate);
|
||||||
settings.bufferSize = selectedDevice.closestSampleRate(settings.bufferSize);
|
settings.bufferSize = selectedDevice.closestBufferSize(settings.bufferSize);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
jackServerSettings: settings,
|
jackServerSettings: settings,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
import React, { SyntheticEvent, Component } from 'react';
|
import React, { SyntheticEvent, Component } from 'react';
|
||||||
import IconButton from '@material-ui/core/IconButton';
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel';
|
||||||
import ButtonBase from "@material-ui/core/ButtonBase";
|
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||||
import { TransitionProps } from '@material-ui/core/transitions/transition';
|
import { TransitionProps } from '@material-ui/core/transitions/transition';
|
||||||
import Slide from '@material-ui/core/Slide';
|
import Slide from '@material-ui/core/Slide';
|
||||||
@@ -159,9 +159,20 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
|||||||
this.handleJackSettingsChanged = this.handleJackSettingsChanged.bind(this);
|
this.handleJackSettingsChanged = this.handleJackSettingsChanged.bind(this);
|
||||||
this.handleJackServerSettingsChanged = this.handleJackServerSettingsChanged.bind(this);
|
this.handleJackServerSettingsChanged = this.handleJackServerSettingsChanged.bind(this);
|
||||||
this.handleWifiConfigSettingsChanged = this.handleWifiConfigSettingsChanged.bind(this);
|
this.handleWifiConfigSettingsChanged = this.handleWifiConfigSettingsChanged.bind(this);
|
||||||
|
this.handleConnectionStateChanged = this.handleConnectionStateChanged.bind(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleConnectionStateChanged() : void {
|
||||||
|
if (this.model.state.get() === State.Ready)
|
||||||
|
{
|
||||||
|
if (this.state.shuttingDown || this.state.restarting)
|
||||||
|
{
|
||||||
|
this.setState({shuttingDown: false, restarting: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleApplyWifiConfig(wifiConfigSettings: WifiConfigSettings): void {
|
handleApplyWifiConfig(wifiConfigSettings: WifiConfigSettings): void {
|
||||||
this.setState({showWifiConfigDialog: false});
|
this.setState({showWifiConfigDialog: false});
|
||||||
this.model.setWifiConfigSettings(wifiConfigSettings)
|
this.model.setWifiConfigSettings(wifiConfigSettings)
|
||||||
@@ -218,6 +229,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
|||||||
if (active !== this.active) {
|
if (active !== this.active) {
|
||||||
this.active = active;
|
this.active = active;
|
||||||
if (active) {
|
if (active) {
|
||||||
|
this.model.state.addOnChangedHandler(this.handleConnectionStateChanged);
|
||||||
this.model.jackSettings.addOnChangedHandler(this.handleJackSettingsChanged);
|
this.model.jackSettings.addOnChangedHandler(this.handleJackSettingsChanged);
|
||||||
this.model.jackConfiguration.addOnChangedHandler(this.handleJackConfigurationChanged);
|
this.model.jackConfiguration.addOnChangedHandler(this.handleJackConfigurationChanged);
|
||||||
this.model.jackServerSettings.addOnChangedHandler(this.handleJackServerSettingsChanged);
|
this.model.jackServerSettings.addOnChangedHandler(this.handleJackServerSettingsChanged);
|
||||||
@@ -235,15 +247,17 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
|||||||
jackStatus: undefined
|
jackStatus: undefined
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
this.handleConnectionStateChanged();
|
||||||
this.handleJackConfigurationChanged();
|
this.handleJackConfigurationChanged();
|
||||||
this.handleJackSettingsChanged();
|
this.handleJackSettingsChanged();
|
||||||
this.handleJackServerSettingsChanged();
|
this.handleJackServerSettingsChanged();
|
||||||
this.handleWifiConfigSettingsChanged();
|
this.handleWifiConfigSettingsChanged();
|
||||||
// xxx UNCOMMENT ME! this.timerHandle = setInterval(() => this.tick(), 1000);
|
this.timerHandle = setInterval(() => this.tick(), 1000);
|
||||||
} else {
|
} else {
|
||||||
if (this.timerHandle) {
|
if (this.timerHandle) {
|
||||||
clearInterval(this.timerHandle);
|
clearInterval(this.timerHandle);
|
||||||
}
|
}
|
||||||
|
this.model.state.removeOnChangedHandler(this.handleConnectionStateChanged);
|
||||||
this.model.jackConfiguration.removeOnChangedHandler(this.handleJackConfigurationChanged);
|
this.model.jackConfiguration.removeOnChangedHandler(this.handleJackConfigurationChanged);
|
||||||
this.model.jackSettings.removeOnChangedHandler(this.handleJackSettingsChanged);
|
this.model.jackSettings.removeOnChangedHandler(this.handleJackSettingsChanged);
|
||||||
this.model.jackServerSettings.removeOnChangedHandler(this.handleJackServerSettingsChanged);
|
this.model.jackServerSettings.removeOnChangedHandler(this.handleJackServerSettingsChanged);
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ add_executable(pipedalconfig json.cpp json.hpp
|
|||||||
PiPedalException.hpp
|
PiPedalException.hpp
|
||||||
ConfigMain.cpp
|
ConfigMain.cpp
|
||||||
WifiConfigSettings.cpp WifiConfigSettings.hpp
|
WifiConfigSettings.cpp WifiConfigSettings.hpp
|
||||||
|
JackServerSettings.hpp JackServerSettings.cpp
|
||||||
SetWifiConfig.hpp SetWifiConfig.cpp
|
SetWifiConfig.hpp SetWifiConfig.cpp
|
||||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||||
SysExec.hpp SysExec.cpp
|
SysExec.hpp SysExec.cpp
|
||||||
|
|||||||
+17
-2
@@ -30,6 +30,7 @@
|
|||||||
#include "SysExec.hpp"
|
#include "SysExec.hpp"
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include "JackServerSettings.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace pipedal;
|
using namespace pipedal;
|
||||||
@@ -116,6 +117,10 @@ void StopService()
|
|||||||
{
|
{
|
||||||
cout << "Error: Failed to stop the " SHUTDOWN_SERVICE " service.";
|
cout << "Error: Failed to stop the " SHUTDOWN_SERVICE " service.";
|
||||||
}
|
}
|
||||||
|
if (SysExec(SYSTEMCTL_BIN " stop " JACK_SERVICE ".service") != EXIT_SUCCESS)
|
||||||
|
{
|
||||||
|
throw PiPedalException("Failed to stop the " JACK_SERVICE " service.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Uninstall() {
|
void Uninstall() {
|
||||||
@@ -128,13 +133,23 @@ void Uninstall() {
|
|||||||
void StartService()
|
void StartService()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
SilentSysExec("/usr/bin/pulseaudio --kill"); // interferes with Jack audio service startup.
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
throw PiPedalException("Failed to start the " NATIVE_SERVICE " service.");
|
throw PiPedalException("Failed to start the " NATIVE_SERVICE " service.");
|
||||||
}
|
}
|
||||||
if (SysExec(SYSTEMCTL_BIN " start " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
JackServerSettings serverSettings;
|
||||||
|
serverSettings.ReadJackConfiguration();
|
||||||
|
if (serverSettings.IsValid())
|
||||||
{
|
{
|
||||||
throw PiPedalException("Failed to start the " SHUTDOWN_SERVICE " service.");
|
if (SysExec(SYSTEMCTL_BIN " start " JACK_SERVICE ".service") != EXIT_SUCCESS)
|
||||||
|
{
|
||||||
|
throw PiPedalException("Failed to start the " JACK_SERVICE " service.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RestartService()
|
void RestartService()
|
||||||
|
|||||||
+15
-1
@@ -905,6 +905,8 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jackInstanceId;
|
||||||
|
|
||||||
virtual void Open(const JackChannelSelection &channelSelection)
|
virtual void Open(const JackChannelSelection &channelSelection)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -929,14 +931,24 @@ public:
|
|||||||
jack_status_t status;
|
jack_status_t status;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// need a unique instance name every timme.
|
||||||
|
std::stringstream s;
|
||||||
|
s << "PiPedal";
|
||||||
|
if (jackInstanceId != 0) {
|
||||||
|
s << jackInstanceId;
|
||||||
|
}
|
||||||
|
++jackInstanceId;
|
||||||
|
|
||||||
client = jack_client_open("PiPedal", JackNullOption, &status);
|
std::string instanceName = s.str();
|
||||||
|
|
||||||
|
client = jack_client_open(instanceName.c_str(), JackNullOption, &status);
|
||||||
|
|
||||||
if (client == nullptr || status & JackFailure)
|
if (client == nullptr || status & JackFailure)
|
||||||
{
|
{
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
jack_client_close(client);
|
jack_client_close(client);
|
||||||
|
client = nullptr;
|
||||||
}
|
}
|
||||||
std::string error = GetJackErrorMessage(status);
|
std::string error = GetJackErrorMessage(status);
|
||||||
Lv2Log::error(error);
|
Lv2Log::error(error);
|
||||||
@@ -1389,6 +1401,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int JackHostImpl::jackInstanceId = 0;
|
||||||
|
|
||||||
JackHost *JackHost::CreateInstance(IHost *pHost)
|
JackHost *JackHost::CreateInstance(IHost *pHost)
|
||||||
{
|
{
|
||||||
return new JackHostImpl(pHost);
|
return new JackHostImpl(pHost);
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "Lv2Log.hpp"
|
|
||||||
#include "JackServerSettings.hpp"
|
#include "JackServerSettings.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "PiPedalException.hpp"
|
#include "PiPedalException.hpp"
|
||||||
@@ -117,7 +116,6 @@ void JackServerSettings::ReadJackConfiguration()
|
|||||||
|
|
||||||
if (!input.is_open())
|
if (!input.is_open())
|
||||||
{
|
{
|
||||||
Lv2Log::error("Can't read " DRC_FILENAME);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,11 +144,11 @@ void JackServerSettings::ReadJackConfiguration()
|
|||||||
this->numberOfBuffers_ = (uint32_t)GetJackArg(argv, "-n", "--nperiods");
|
this->numberOfBuffers_ = (uint32_t)GetJackArg(argv, "-n", "--nperiods");
|
||||||
this->sampleRate_ = (uint32_t)GetJackArg(argv, "-r", "--rate");
|
this->sampleRate_ = (uint32_t)GetJackArg(argv, "-r", "--rate");
|
||||||
this->alsaDevice_ = GetJackStringArg(argv,"-d", "--device");
|
this->alsaDevice_ = GetJackStringArg(argv,"-d", "--device");
|
||||||
valid_ = true;
|
this->valid_ = true;
|
||||||
}
|
}
|
||||||
catch (std::exception &)
|
catch (std::exception &)
|
||||||
{
|
{
|
||||||
Lv2Log::error("Can't parse " DRC_FILENAME);
|
//Lv2Log::error("Can't parse " DRC_FILENAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,7 +166,6 @@ void JackServerSettings::Write()
|
|||||||
|
|
||||||
if (!input.is_open())
|
if (!input.is_open())
|
||||||
{
|
{
|
||||||
Lv2Log::error("Can't read " DRC_FILENAME);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +173,6 @@ void JackServerSettings::Write()
|
|||||||
{
|
{
|
||||||
if (input.eof())
|
if (input.eof())
|
||||||
{
|
{
|
||||||
Lv2Log::error("Premature end of file in " DRC_FILENAME);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::getline(input,lastLine);
|
std::getline(input,lastLine);
|
||||||
@@ -209,8 +205,8 @@ void JackServerSettings::Write()
|
|||||||
{
|
{
|
||||||
// jack1 incantation for promiscuous servers.
|
// jack1 incantation for promiscuous servers.
|
||||||
output << "#!/bin/sh" <<endl;
|
output << "#!/bin/sh" <<endl;
|
||||||
output << "export JACK_PROMISCUOUS_SERVER=" << endl;
|
output << "export JACK_PROMISCUOUS_SERVER=jack" << endl;
|
||||||
output << "export JACK_NO_AUDIO_RESERVATION=" << endl;
|
output << "export JACK_NO_AUDIO_RESERVATION=1" << endl;
|
||||||
output << "umask 0" << endl;
|
output << "umask 0" << endl;
|
||||||
}
|
}
|
||||||
for (auto line : precedingLines)
|
for (auto line : precedingLines)
|
||||||
@@ -220,7 +216,7 @@ void JackServerSettings::Write()
|
|||||||
// the style used by qjackctl. :-/
|
// the style used by qjackctl. :-/
|
||||||
output << "/usr/bin/jackd "
|
output << "/usr/bin/jackd "
|
||||||
<< "-R -P90"
|
<< "-R -P90"
|
||||||
<< " -driver alsa -d" << this->alsaDevice_
|
<< " -dalsa -d" << this->alsaDevice_
|
||||||
<< " -r" << this->sampleRate_
|
<< " -r" << this->sampleRate_
|
||||||
<< " -p" << this->bufferSize_
|
<< " -p" << this->bufferSize_
|
||||||
<< " -n" << this->numberOfBuffers_ << " -Xseq"
|
<< " -n" << this->numberOfBuffers_ << " -Xseq"
|
||||||
@@ -235,9 +231,6 @@ void JackServerSettings::Write()
|
|||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
stringstream s;
|
|
||||||
s << "jack - " << e.what();
|
|
||||||
Lv2Log::error(s.str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-53
@@ -26,12 +26,26 @@
|
|||||||
using namespace pipedal;
|
using namespace pipedal;
|
||||||
|
|
||||||
static uint32_t RATES[] = {
|
static uint32_t RATES[] = {
|
||||||
44100, 48000, 44100 * 2, 48000 * 2, 44100 * 4, 48000 * 4};
|
22050, 24000, 44100, 48000, 44100 * 2, 48000 * 2, 44100 * 4, 48000 * 4};
|
||||||
|
|
||||||
|
|
||||||
std::mutex alsaMutex;
|
std::mutex alsaMutex;
|
||||||
|
|
||||||
std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
bool PiPedalAlsaDevices::getCachedDevice(const std::string &name, AlsaDeviceInfo *pResult)
|
||||||
|
{
|
||||||
|
auto it = cachedDevices.find(name);
|
||||||
|
if (it != cachedDevices.end())
|
||||||
|
{
|
||||||
|
*pResult = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void PiPedalAlsaDevices::cacheDevice(const std::string &name, const AlsaDeviceInfo &deviceInfo)
|
||||||
|
{
|
||||||
|
cachedDevices[name] = deviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
||||||
{
|
{
|
||||||
std::lock_guard guard{alsaMutex};
|
std::lock_guard guard{alsaMutex};
|
||||||
|
|
||||||
@@ -50,7 +64,7 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
if (cardNum < 0)
|
if (cardNum < 0)
|
||||||
// No more cards
|
// No more cards
|
||||||
break;
|
break;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "hw:" << cardNum;
|
ss << "hw:" << cardNum;
|
||||||
@@ -77,17 +91,17 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
AlsaDeviceInfo info;
|
AlsaDeviceInfo info;
|
||||||
info.cardId_ = cardNum;
|
info.cardId_ = cardNum;
|
||||||
info.id_ = std::string("hw:") + snd_ctl_card_info_get_id(alsaInfo);
|
info.id_ = std::string("hw:") + snd_ctl_card_info_get_id(alsaInfo);
|
||||||
const char* driver = snd_ctl_card_info_get_driver(alsaInfo);
|
const char *driver = snd_ctl_card_info_get_driver(alsaInfo);
|
||||||
|
|
||||||
info.name_ = snd_ctl_card_info_get_name(alsaInfo);
|
info.name_ = snd_ctl_card_info_get_name(alsaInfo);
|
||||||
info.longName_ = snd_ctl_card_info_get_longname(alsaInfo);
|
info.longName_ = snd_ctl_card_info_get_longname(alsaInfo);
|
||||||
|
|
||||||
|
|
||||||
snd_pcm_t *hDevice = nullptr;
|
snd_pcm_t *hDevice = nullptr;
|
||||||
|
|
||||||
// must support capture AND playback
|
// must support capture AND playback
|
||||||
err = snd_pcm_open(&hDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, 0);
|
err = snd_pcm_open(&hDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, 0);
|
||||||
if (err == 0) {
|
if (err == 0)
|
||||||
|
{
|
||||||
snd_pcm_close(hDevice);
|
snd_pcm_close(hDevice);
|
||||||
}
|
}
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
@@ -104,7 +118,7 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
unsigned int minRate = 0, maxRate = 0;
|
unsigned int minRate = 0, maxRate = 0;
|
||||||
snd_pcm_uframes_t minBufferSize,maxBufferSize;
|
snd_pcm_uframes_t minBufferSize, maxBufferSize;
|
||||||
int dir;
|
int dir;
|
||||||
err = snd_pcm_hw_params_get_rate_min(params, &minRate, &dir);
|
err = snd_pcm_hw_params_get_rate_min(params, &minRate, &dir);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
@@ -113,11 +127,11 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
}
|
}
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
err = snd_pcm_hw_params_get_buffer_size_min(params,&minBufferSize);
|
err = snd_pcm_hw_params_get_buffer_size_min(params, &minBufferSize);
|
||||||
}
|
}
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
err = snd_pcm_hw_params_get_buffer_size_max(params,&maxBufferSize);
|
err = snd_pcm_hw_params_get_buffer_size_max(params, &maxBufferSize);
|
||||||
}
|
}
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
@@ -131,7 +145,8 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
}
|
}
|
||||||
info.minBufferSize_ = (uint32_t)minBufferSize;
|
info.minBufferSize_ = (uint32_t)minBufferSize;
|
||||||
info.maxBufferSize_ = (uint32_t)maxBufferSize;
|
info.maxBufferSize_ = (uint32_t)maxBufferSize;
|
||||||
result.push_back(std::move(info));
|
cacheDevice(info.name_, info);
|
||||||
|
result.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,6 +154,13 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
snd_pcm_hw_params_free(params);
|
snd_pcm_hw_params_free(params);
|
||||||
snd_pcm_close(hDevice);
|
snd_pcm_close(hDevice);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (getCachedDevice(info.name_, &info))
|
||||||
|
{
|
||||||
|
result.push_back(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
snd_ctl_card_info_free(alsaInfo);
|
snd_ctl_card_info_free(alsaInfo);
|
||||||
snd_ctl_close(hDevice);
|
snd_ctl_close(hDevice);
|
||||||
@@ -148,47 +170,6 @@ std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAvailableAlsaDevices()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PiPedalAlsaDevices::PreLoadJackDevice(const std::string&deviceName)
|
|
||||||
{
|
|
||||||
// save the device info before we start the jack server, because
|
|
||||||
// we won't be able to do it later.
|
|
||||||
std::vector<AlsaDeviceInfo> devices = GetAvailableAlsaDevices();
|
|
||||||
this->hasJackDevice = false;
|
|
||||||
for (auto &device : devices)
|
|
||||||
{
|
|
||||||
if (device.id_ == deviceName) {
|
|
||||||
this->currentJackDevice = device;
|
|
||||||
this->hasJackDevice = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<AlsaDeviceInfo> PiPedalAlsaDevices::GetAlsaDevices()
|
|
||||||
{
|
|
||||||
std::vector<AlsaDeviceInfo> devices = GetAvailableAlsaDevices();
|
|
||||||
if (this->hasJackDevice)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (auto &device: devices)
|
|
||||||
{
|
|
||||||
if (device.id_ == this->currentJackDevice.id_)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
devices.push_back(this->currentJackDevice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
JSON_MAP_BEGIN(AlsaDeviceInfo)
|
JSON_MAP_BEGIN(AlsaDeviceInfo)
|
||||||
JSON_MAP_REFERENCE(AlsaDeviceInfo, cardId)
|
JSON_MAP_REFERENCE(AlsaDeviceInfo, cardId)
|
||||||
JSON_MAP_REFERENCE(AlsaDeviceInfo, id)
|
JSON_MAP_REFERENCE(AlsaDeviceInfo, id)
|
||||||
|
|||||||
+5
-5
@@ -37,12 +37,12 @@ namespace pipedal {
|
|||||||
|
|
||||||
class PiPedalAlsaDevices {
|
class PiPedalAlsaDevices {
|
||||||
|
|
||||||
bool hasJackDevice = false;
|
std::map<std::string,AlsaDeviceInfo> cachedDevices;
|
||||||
AlsaDeviceInfo currentJackDevice;
|
|
||||||
std::vector<AlsaDeviceInfo> GetAvailableAlsaDevices();
|
|
||||||
public:
|
|
||||||
void PreLoadJackDevice(const std::string&deviceName);
|
|
||||||
|
|
||||||
|
bool getCachedDevice(const std::string&name, AlsaDeviceInfo*pResult);
|
||||||
|
void cacheDevice(const std::string&name, const AlsaDeviceInfo&deviceInfo);
|
||||||
|
public:
|
||||||
|
|
||||||
std::vector<AlsaDeviceInfo> GetAlsaDevices();
|
std::vector<AlsaDeviceInfo> GetAlsaDevices();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,8 @@ std::string AtomToJson(int length, uint8_t *pData)
|
|||||||
PiPedalModel::PiPedalModel()
|
PiPedalModel::PiPedalModel()
|
||||||
{
|
{
|
||||||
this->pedalBoard = PedalBoard::MakeDefault();
|
this->pedalBoard = PedalBoard::MakeDefault();
|
||||||
|
this->jackServerSettings.ReadJackConfiguration();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PiPedalModel::Close()
|
void PiPedalModel::Close()
|
||||||
@@ -87,7 +89,6 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
|
|||||||
|
|
||||||
this->jackServerSettings.ReadJackConfiguration();
|
this->jackServerSettings.ReadJackConfiguration();
|
||||||
|
|
||||||
alsaDevices.PreLoadJackDevice(this->jackServerSettings.GetAlsaDevice());
|
|
||||||
|
|
||||||
storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
|
storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
|
||||||
storage.Initialize();
|
storage.Initialize();
|
||||||
@@ -862,10 +863,6 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
|
|||||||
throw PiPedalException("Can't change server settings when running a debug server.");
|
throw PiPedalException("Can't change server settings when running a debug server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->jackServerSettings.GetAlsaDevice() != jackServerSettings.GetAlsaDevice())
|
|
||||||
{
|
|
||||||
this->alsaDevices.PreLoadJackDevice(jackServerSettings.GetAlsaDevice());
|
|
||||||
}
|
|
||||||
this->jackServerSettings = jackServerSettings;
|
this->jackServerSettings = jackServerSettings;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+31
-14
@@ -28,7 +28,6 @@
|
|||||||
using namespace pipedal;
|
using namespace pipedal;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
// find on path, but ONLY /usr/bin and /usr/sbin
|
// find on path, but ONLY /usr/bin and /usr/sbin
|
||||||
|
|
||||||
static std::filesystem::path findOnSystemPath(const std::string &command)
|
static std::filesystem::path findOnSystemPath(const std::string &command)
|
||||||
@@ -60,23 +59,42 @@ static std::filesystem::path findOnSystemPath(const std::string &command)
|
|||||||
throw PiPedalException(s.str());
|
throw PiPedalException(s.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pipedal::SilentSysExec(const char *szCommand)
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << szCommand << " 2>&1";
|
||||||
|
|
||||||
|
FILE *output = popen(s.str().c_str(), "r");
|
||||||
|
char buffer[512];
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
while (!feof(output))
|
||||||
|
{
|
||||||
|
fgets(buffer, sizeof(buffer), output);
|
||||||
|
}
|
||||||
|
pclose(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int pipedal::SysExec(const char*szCommand) {
|
int pipedal::SysExec(const char *szCommand)
|
||||||
char*args = strdup(szCommand);
|
{
|
||||||
|
char *args = strdup(szCommand);
|
||||||
int argc;
|
int argc;
|
||||||
std::vector<char*> argv;
|
std::vector<char *> argv;
|
||||||
|
|
||||||
char *p = args;
|
char *p = args;
|
||||||
while (*p) {
|
while (*p)
|
||||||
|
{
|
||||||
argv.push_back(p);
|
argv.push_back(p);
|
||||||
|
|
||||||
while (*p && *p != ' ') {
|
while (*p && *p != ' ')
|
||||||
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (*p) {
|
if (*p)
|
||||||
|
{
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
while (*p && *p == ' ')
|
while (*p && *p == ' ')
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -91,12 +109,11 @@ int pipedal::SysExec(const char*szCommand) {
|
|||||||
}
|
}
|
||||||
if (!std::filesystem::exists(execPath))
|
if (!std::filesystem::exists(execPath))
|
||||||
{
|
{
|
||||||
throw PiPedalException( SS("Path does not exist: " << execPath << "."));
|
throw PiPedalException(SS("Path does not exist: " << execPath << "."));
|
||||||
}
|
}
|
||||||
argv[0] = (char*)(execPath.c_str());
|
argv[0] = (char *)(execPath.c_str());
|
||||||
|
|
||||||
|
char **rawArgv = &argv[0];
|
||||||
char**rawArgv = &argv[0];
|
|
||||||
int pbPid;
|
int pbPid;
|
||||||
int returnValue = 0;
|
int returnValue = 0;
|
||||||
|
|
||||||
@@ -107,7 +124,7 @@ int pipedal::SysExec(const char*szCommand) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free((void*)args);
|
free((void *)args);
|
||||||
waitpid(pbPid, &returnValue, 0);
|
waitpid(pbPid, &returnValue, 0);
|
||||||
int exitStatus = WEXITSTATUS(returnValue);
|
int exitStatus = WEXITSTATUS(returnValue);
|
||||||
return exitStatus;
|
return exitStatus;
|
||||||
|
|||||||
@@ -24,4 +24,7 @@ namespace pipedal {
|
|||||||
// exec a command, returning the actual exit code (unlike execXX() or system() )
|
// exec a command, returning the actual exit code (unlike execXX() or system() )
|
||||||
int SysExec(const char*szCommand);
|
int SysExec(const char*szCommand);
|
||||||
|
|
||||||
|
// execute a command, suppressing output.
|
||||||
|
void SilentSysExec(const char *szCommand);
|
||||||
|
|
||||||
}
|
}
|
||||||
+102
-23
@@ -37,6 +37,8 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
|
||||||
using namespace pipedal;
|
using namespace pipedal;
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
|
|
||||||
@@ -45,6 +47,16 @@ using namespace boost::beast;
|
|||||||
|
|
||||||
sem_t signalSemaphore;
|
sem_t signalSemaphore;
|
||||||
|
|
||||||
|
bool HasAlsaDevice(const std::vector<AlsaDeviceInfo> devices, const std::string &deviceId)
|
||||||
|
{
|
||||||
|
for (auto &device : devices)
|
||||||
|
{
|
||||||
|
if (device.id_ == deviceId)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class application_category : public boost::system::error_category
|
class application_category : public boost::system::error_category
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -52,13 +64,14 @@ public:
|
|||||||
std::string message(int ev) const { return "error message"; }
|
std::string message(int ev) const { return "error message"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static volatile bool g_SigBreak = false;
|
||||||
void sig_handler(int signo)
|
void sig_handler(int signo)
|
||||||
{
|
{
|
||||||
|
g_SigBreak = true;
|
||||||
sem_post(&signalSemaphore);
|
sem_post(&signalSemaphore);
|
||||||
}
|
}
|
||||||
using namespace boost::system;
|
using namespace boost::system;
|
||||||
|
|
||||||
|
|
||||||
class DownloadIntercept : public RequestHandler
|
class DownloadIntercept : public RequestHandler
|
||||||
{
|
{
|
||||||
PiPedalModel *model;
|
PiPedalModel *model;
|
||||||
@@ -81,7 +94,8 @@ public:
|
|||||||
std::string strInstanceId = request_uri.query("id");
|
std::string strInstanceId = request_uri.query("id");
|
||||||
if (strInstanceId != "")
|
if (strInstanceId != "")
|
||||||
return true;
|
return true;
|
||||||
} else if (request_uri.segment(1) == "uploadPreset")
|
}
|
||||||
|
else if (request_uri.segment(1) == "uploadPreset")
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -90,19 +104,19 @@ public:
|
|||||||
std::string strInstanceId = request_uri.query("id");
|
std::string strInstanceId = request_uri.query("id");
|
||||||
if (strInstanceId != "")
|
if (strInstanceId != "")
|
||||||
return true;
|
return true;
|
||||||
} else if (request_uri.segment(1) == "uploadBank")
|
}
|
||||||
|
else if (request_uri.segment(1) == "uploadBank")
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string GetContentDispositionHeader(const std::string &name, const std::string &extension)
|
std::string GetContentDispositionHeader(const std::string &name, const std::string &extension)
|
||||||
{
|
{
|
||||||
std::string fileName = name.substr(0,64) + extension;
|
std::string fileName = name.substr(0, 64) + extension;
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
|
||||||
s << "attachment; filename*=" << HtmlHelper::Rfc5987EncodeFileName(fileName) << "; filename=\"" << HtmlHelper::SafeFileName(fileName) << "\"";
|
s << "attachment; filename*=" << HtmlHelper::Rfc5987EncodeFileName(fileName) << "; filename=\"" << HtmlHelper::SafeFileName(fileName) << "\"";
|
||||||
std::string result = s.str();
|
std::string result = s.str();
|
||||||
return result;
|
return result;
|
||||||
@@ -131,11 +145,10 @@ public:
|
|||||||
std::string strInstanceId = request_uri.query("id");
|
std::string strInstanceId = request_uri.query("id");
|
||||||
int64_t instanceId = std::stol(strInstanceId);
|
int64_t instanceId = std::stol(strInstanceId);
|
||||||
BankFile bank;
|
BankFile bank;
|
||||||
model->getBank(instanceId,&bank);
|
model->getBank(instanceId, &bank);
|
||||||
|
|
||||||
|
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
json_writer writer(s,true); // do what we can to reduce the file size.
|
json_writer writer(s, true); // do what we can to reduce the file size.
|
||||||
writer.write(bank);
|
writer.write(bank);
|
||||||
*pContent = s.str();
|
*pContent = s.str();
|
||||||
*pName = bank.name();
|
*pName = bank.name();
|
||||||
@@ -160,7 +173,7 @@ public:
|
|||||||
res.set(http::field::content_length, content.length());
|
res.set(http::field::content_length, content.length());
|
||||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (request_uri.segment(1) == "downloadBank")
|
if (request_uri.segment(1) == "downloadBank")
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -172,7 +185,7 @@ public:
|
|||||||
res.set(http::field::content_length, content.length());
|
res.set(http::field::content_length, content.length());
|
||||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw PiPedalException("Not found.");
|
throw PiPedalException("Not found.");
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
@@ -207,7 +220,8 @@ public:
|
|||||||
res.set(http::field::content_length, content.length());
|
res.set(http::field::content_length, content.length());
|
||||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||||
res.body() = content;
|
res.body() = content;
|
||||||
} else if (request_uri.segment(1) == "downloadBank")
|
}
|
||||||
|
else if (request_uri.segment(1) == "downloadBank")
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string content;
|
std::string content;
|
||||||
@@ -218,7 +232,9 @@ public:
|
|||||||
res.set(http::field::content_length, content.length());
|
res.set(http::field::content_length, content.length());
|
||||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||||
res.body() = content;
|
res.body() = content;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
throw PiPedalException("Not found");
|
throw PiPedalException("Not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +274,7 @@ public:
|
|||||||
BankFile bankFile;
|
BankFile bankFile;
|
||||||
reader.read(&bankFile);
|
reader.read(&bankFile);
|
||||||
|
|
||||||
uint64_t instanceId = model->uploadPreset(bankFile,uploadAfter);
|
uint64_t instanceId = model->uploadPreset(bankFile, uploadAfter);
|
||||||
|
|
||||||
res.set(http::field::content_type, "application/json");
|
res.set(http::field::content_type, "application/json");
|
||||||
res.set(http::field::cache_control, "no-cache");
|
res.set(http::field::cache_control, "no-cache");
|
||||||
@@ -268,8 +284,8 @@ public:
|
|||||||
res.set(http::field::content_length, result.length());
|
res.set(http::field::content_length, result.length());
|
||||||
|
|
||||||
res.body() = result;
|
res.body() = result;
|
||||||
}
|
}
|
||||||
else if (request_uri.segment(1) == "uploadBank" )
|
else if (request_uri.segment(1) == "uploadBank")
|
||||||
{
|
{
|
||||||
std::string presetBody = req.body();
|
std::string presetBody = req.body();
|
||||||
std::stringstream s(presetBody);
|
std::stringstream s(presetBody);
|
||||||
@@ -285,7 +301,7 @@ public:
|
|||||||
BankFile bankFile;
|
BankFile bankFile;
|
||||||
reader.read(&bankFile);
|
reader.read(&bankFile);
|
||||||
|
|
||||||
uint64_t instanceId = model->uploadBank(bankFile,uploadAfter);
|
uint64_t instanceId = model->uploadBank(bankFile, uploadAfter);
|
||||||
|
|
||||||
res.set(http::field::content_type, "application/json");
|
res.set(http::field::content_type, "application/json");
|
||||||
res.set(http::field::cache_control, "no-cache");
|
res.set(http::field::cache_control, "no-cache");
|
||||||
@@ -296,7 +312,8 @@ public:
|
|||||||
|
|
||||||
res.body() = result;
|
res.body() = result;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
throw PiPedalException("Not found");
|
throw PiPedalException("Not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,7 +329,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* When hosting a react app, replace /var/config.json with
|
/* When hosting a react app, replace /var/config.json with
|
||||||
@@ -326,7 +342,7 @@ private:
|
|||||||
uint64_t maxUploadSize;
|
uint64_t maxUploadSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InterceptConfig(int portNumber,uint64_t maxUploadSize)
|
InterceptConfig(int portNumber, uint64_t maxUploadSize)
|
||||||
: RequestHandler("/var/config.json"),
|
: RequestHandler("/var/config.json"),
|
||||||
maxUploadSize(maxUploadSize)
|
maxUploadSize(maxUploadSize)
|
||||||
{
|
{
|
||||||
@@ -414,11 +430,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool isJackServiceRunning()
|
||||||
|
{
|
||||||
|
// look for the jack shmem .
|
||||||
|
std::filesystem::path path = "/dev/shm/jack_default_0";
|
||||||
|
return std::filesystem::exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t g_ShutdownPort = 0;
|
uint16_t g_ShutdownPort = 0;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
sem_init(&signalSemaphore, 0, 0);
|
sem_init(&signalSemaphore, 0, 0);
|
||||||
|
|
||||||
@@ -471,7 +493,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
std::cout << "Usage: pipedal <doc_root> [<web_root>] [options...]\n\n"
|
std::cout << "Usage: pipedal <doc_root> [<web_root>] [options...]\n\n"
|
||||||
<< "Options:\n"
|
<< "Options:\n"
|
||||||
<< " -systemd: Log to systemd journals.\n"
|
<< " -systemd: Log to systemd journals, wait for jack service.\n"
|
||||||
<< " -port: Port to listen on e.g. 0.0.0.0:80\n"
|
<< " -port: Port to listen on e.g. 0.0.0.0:80\n"
|
||||||
<< " -shutdownPort: Port for the shutdown service.\n"
|
<< " -shutdownPort: Port for the shutdown service.\n"
|
||||||
<< "Example:\n"
|
<< "Example:\n"
|
||||||
@@ -556,13 +578,65 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
PiPedalModel model;
|
PiPedalModel model;
|
||||||
|
|
||||||
|
// Pre-populate ALSA device info,wait for jackd service (daemon only)
|
||||||
|
if (systemd)
|
||||||
|
{
|
||||||
|
auto devices = model.GetAlsaDevices();
|
||||||
|
|
||||||
|
auto serverSettings = model.GetJackServerSettings();
|
||||||
|
if (serverSettings.IsValid())
|
||||||
|
{
|
||||||
|
// wait up to 15 seconds for the midi device to come online.
|
||||||
|
if (!HasAlsaDevice(devices, serverSettings.GetAlsaDevice()))
|
||||||
|
{
|
||||||
|
Lv2Log::info("Waiting for ALSA device " + serverSettings.GetAlsaDevice());
|
||||||
|
for (int i = 0; i < 15; ++i)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
devices = model.GetAlsaDevices();
|
||||||
|
if (HasAlsaDevice(devices, serverSettings.GetAlsaDevice()))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (g_SigBreak)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Lv2Log::info("Waiting for jack service.");
|
||||||
|
|
||||||
|
// pre-cache device info.
|
||||||
|
model.GetAlsaDevices();
|
||||||
|
sd_notify(0, "READY=1");
|
||||||
|
|
||||||
|
if (!isJackServiceRunning())
|
||||||
|
{
|
||||||
|
Lv2Log::info("Waiting for Jack service.");
|
||||||
|
// wait up to 15 seconds for the jack service to come online.
|
||||||
|
for (int i = 0; i < 15; ++i)
|
||||||
|
{
|
||||||
|
// use the time to prepopulate ALSA device cache before jack
|
||||||
|
// opens the device and we can't read properties.
|
||||||
|
model.GetAlsaDevices();
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
if (isJackServiceRunning())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Lv2Log::info("Found Jack service.");
|
||||||
|
}
|
||||||
|
sleep(3); // jack needs a little time to get up to speed.
|
||||||
|
}
|
||||||
|
|
||||||
model.Load(configuration);
|
model.Load(configuration);
|
||||||
|
|
||||||
auto pipedalSocketFactory = MakePiPedalSocketFactory(model);
|
auto pipedalSocketFactory = MakePiPedalSocketFactory(model);
|
||||||
|
|
||||||
server->AddSocketFactory(pipedalSocketFactory);
|
server->AddSocketFactory(pipedalSocketFactory);
|
||||||
|
|
||||||
std::shared_ptr<RequestHandler> interceptConfig{new InterceptConfig(port,configuration.GetMaxUploadSize())};
|
std::shared_ptr<RequestHandler> interceptConfig{new InterceptConfig(port, configuration.GetMaxUploadSize())};
|
||||||
server->AddRequestHandler(interceptConfig);
|
server->AddRequestHandler(interceptConfig);
|
||||||
|
|
||||||
std::shared_ptr<DownloadIntercept> downloadIntercept = std::make_shared<DownloadIntercept>(&model);
|
std::shared_ptr<DownloadIntercept> downloadIntercept = std::make_shared<DownloadIntercept>(&model);
|
||||||
@@ -572,6 +646,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
sem_wait(&signalSemaphore);
|
sem_wait(&signalSemaphore);
|
||||||
|
|
||||||
|
if (systemd)
|
||||||
|
{
|
||||||
|
sd_notify(0, "STOPPING=1");
|
||||||
|
}
|
||||||
|
|
||||||
Lv2Log::info("Shutting down gracefully.");
|
Lv2Log::info("Shutting down gracefully.");
|
||||||
model.Close();
|
model.Close();
|
||||||
Lv2Log::info("Stopping web server.");
|
Lv2Log::info("Stopping web server.");
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=${DESCRIPTION}
|
Description=${DESCRIPTION}
|
||||||
After=jack.service
|
Before=jack.service
|
||||||
After=network.target
|
After=network.target
|
||||||
BindsTo=jack.service
|
After=sound.target
|
||||||
|
After=local-fs.target
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
Type=notify
|
||||||
LimitMEMLOCK=infinity
|
LimitMEMLOCK=infinity
|
||||||
LimitRTPRIO=95
|
LimitRTPRIO=95
|
||||||
ExecStart=${COMMAND}
|
ExecStart=${COMMAND}
|
||||||
@@ -16,8 +18,8 @@ Restart=always
|
|||||||
RestartSec=25
|
RestartSec=25
|
||||||
TimeoutStopSec=10
|
TimeoutStopSec=10
|
||||||
WorkingDirectory=/var/pipedal
|
WorkingDirectory=/var/pipedal
|
||||||
Environment=JACK_PROMISCUOUS_SERVER=
|
Environment=JACK_PROMISCUOUS_SERVER=jack
|
||||||
Environment=JACK_STJACK_NO_START_SERVER=
|
Environment=JACK_NO_START_SERVER=1
|
||||||
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|||||||
Reference in New Issue
Block a user