bug: invalid mono audio device channel selects

This commit is contained in:
Robin Davies
2024-10-12 03:53:57 -04:00
parent 21f5c9e43a
commit b0107d4490
17 changed files with 163 additions and 68 deletions
+21 -4
View File
@@ -20,6 +20,12 @@
import {PiPedalArgumentError} from './PiPedalError'; import {PiPedalArgumentError} from './PiPedalError';
import {AlsaMidiDeviceInfo} from './AlsaMidiDeviceInfo'; import {AlsaMidiDeviceInfo} from './AlsaMidiDeviceInfo';
function getChannelNumber(channelId: string): number {
let pos = channelId.indexOf("_");
let i = Number(channelId.substring(pos+1));
return i;
}
export class JackChannelSelection { export class JackChannelSelection {
deserialize(input: any): JackChannelSelection deserialize(input: any): JackChannelSelection
{ {
@@ -57,7 +63,8 @@ export class JackChannelSelection {
return "Stereo"; return "Stereo";
} }
if (selectedChannels.length === 1) return "Mono"; if (selectedChannels.length === 1) return "Mono";
return "Invalid selection";
return "\u00A0"; // nbsp
} }
if (selectedChannels.length === 0) return "Invalid selection"; if (selectedChannels.length === 0) return "Invalid selection";
@@ -69,12 +76,22 @@ export class JackChannelSelection {
} else if (selectedChannels[0] === availableChannels[1]) { } else if (selectedChannels[0] === availableChannels[1]) {
return "Mono (right channel only)"; return "Mono (right channel only)";
} else { } else {
return "\u00A0"; // nbsp
throw new PiPedalArgumentError("Invalid channel selection."); // should be subset of jackConfiguration. throw new PiPedalArgumentError("Invalid channel selection."); // should be subset of jackConfiguration.
} }
} else { } else {
if (selectedChannels.length === 2) return "Stereo (custom selection)"; if (selectedChannels.length === 2)
if (selectedChannels.length === 1) return "Mono (custom selection)"; {
throw new PiPedalArgumentError("Invalid channel selection."); // should be subset of jackConfiguration. let result: string = "Stereo (" + (getChannelNumber(selectedChannels[0])+1) + "," + (getChannelNumber(selectedChannels[1])+1) + ")";
return result;
}
if (selectedChannels.length === 1)
{
let result: string = "Mono (" + (getChannelNumber(selectedChannels[0])+1) +")";
return result;
}
return "\u00A0"; // nbsp
} }
} }
getAudioInputDisplayValue(jackConfiguration: JackConfiguration): string getAudioInputDisplayValue(jackConfiguration: JackConfiguration): string
+18 -6
View File
@@ -65,12 +65,22 @@ function removePort(selectedChannels: string[], channel: string) {
return result; return result;
} }
function makeChannelName(id: string)
{
let pos = id.lastIndexOf("_");
if (pos === -1)
{
return id;
}
let i = Number(id.substring(pos+1));
return "Channel " + (i+1);
}
function SelectChannelsDialog(props: SelectChannelsDialogProps) { function SelectChannelsDialog(props: SelectChannelsDialogProps) {
//const classes = useStyles(); //const classes = useStyles();
const { onClose, selectedChannels, availableChannels, open } = props; const { onClose, selectedChannels, availableChannels, open } = props;
const [currentSelection, setCurrentSelection] = useState(selectedChannels); const [currentSelection, setCurrentSelection] = useState(selectedChannels);
let showCheckboxes = availableChannels.length > 2; let showCheckboxes = availableChannels.length !== 2;
if (showCheckboxes) { if (showCheckboxes) {
let toggleSelect = (value: string) => { let toggleSelect = (value: string) => {
@@ -85,23 +95,25 @@ function SelectChannelsDialog(props: SelectChannelsDialogProps) {
onClose(null); onClose(null);
}; };
const handleOk = (): void => { const handleOk = (): void => {
if (currentSelection.length >= 1 && currentSelection.length <= 2)
{
onClose(currentSelection); onClose(currentSelection);
}
}; };
return ( return (
<DialogEx tag="audioChannels" onClose={handleClose} aria-labelledby="select-channels-title" open={open} <DialogEx tag="audioChannels" onClose={handleClose} aria-labelledby="select-channels-title" open={open} fullWidth maxWidth="xs"
onEnterKey={handleOk} onEnterKey={handleOk}
> >
<DialogTitle id="simple-dialog-title">Select Channels</DialogTitle> <DialogTitle id="simple-dialog-title">Select Channels</DialogTitle>
<List> <List>
{availableChannels.map((channel) => ( {availableChannels.map((channel) => (
<ListItem button > <ListItem button key={channel}>
<FormControlLabel <FormControlLabel
control={ control={
<Checkbox checked={isChecked(currentSelection, channel)} onClick={() => toggleSelect(channel)} key={channel} /> <Checkbox checked={isChecked(currentSelection, channel)} onClick={() => toggleSelect(channel)} style={{marginLeft: 24}} />
} }
label={channel} label={makeChannelName(channel)}
/> />
</ListItem> </ListItem>
) )
+4 -2
View File
@@ -651,7 +651,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
<ButtonBase className={classes.setting} onClick={() => this.handleInputSelection()} disabled={!isConfigValid} <ButtonBase className={classes.setting} onClick={() => this.handleInputSelection()}
disabled={!isConfigValid || this.state.jackConfiguration.outputAudioPorts.length <= 1}
style={{ opacity: !isConfigValid ? 0.6 : 1.0 }} style={{ opacity: !isConfigValid ? 0.6 : 1.0 }}
> >
@@ -661,7 +662,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
<Typography display="block" variant="caption" color="textSecondary" noWrap>{this.state.jackSettings.getAudioInputDisplayValue(this.state.jackConfiguration)}</Typography> <Typography display="block" variant="caption" color="textSecondary" noWrap>{this.state.jackSettings.getAudioInputDisplayValue(this.state.jackConfiguration)}</Typography>
</div> </div>
</ButtonBase> </ButtonBase>
<ButtonBase className={classes.setting} onClick={() => this.handleOutputSelection()} disabled={!isConfigValid} <ButtonBase className={classes.setting} onClick={() => this.handleOutputSelection()}
disabled={!isConfigValid || this.state.jackConfiguration.outputAudioPorts.length <= 1}
style={{ opacity: !isConfigValid ? 0.6 : 1.0 }} style={{ opacity: !isConfigValid ? 0.6 : 1.0 }}
> >
<SelectHoverBackground selected={false} showHover={true} /> <SelectHoverBackground selected={false} showHover={true} />
+9 -6
View File
@@ -32,6 +32,7 @@
#include <thread> #include <thread>
#include "RtInversionGuard.hpp" #include "RtInversionGuard.hpp"
#include "PiPedalException.hpp" #include "PiPedalException.hpp"
#include "DummyAudioDriver.hpp"
#include "CpuUse.hpp" #include "CpuUse.hpp"
@@ -2022,13 +2023,15 @@ namespace pipedal
{ {
if (jackServerSettings.IsDummyAudioDevice()) if (jackServerSettings.IsDummyAudioDevice())
{ {
inputAudioPorts.clear(); auto nChannels = GetDummyAudioChannels(jackServerSettings.GetAlsaInputDevice());
inputAudioPorts.push_back(std::string("system::capture_0"));
inputAudioPorts.push_back(std::string("system::capture_1"));
outputAudioPorts.clear();
outputAudioPorts.push_back(std::string("system::playback_0"));
outputAudioPorts.push_back(std::string("system::playback_1"));
inputAudioPorts.clear();
outputAudioPorts.clear();
for (uint32_t i = 0; i < nChannels; ++i)
{
inputAudioPorts.push_back(std::string(SS("system::capture_" << i)));
outputAudioPorts.push_back(std::string(SS("system::playback_" << i)));
}
return true; return true;
} }
+3 -3
View File
@@ -75,9 +75,9 @@ public:
} }
JackChannelSelection channelSelection( JackChannelSelection channelSelection(
jackConfiguration.GetInputAudioPorts(), jackConfiguration.inputAudioPorts(),
jackConfiguration.GetOutputAudioPorts(), jackConfiguration.outputAudioPorts(),
jackConfiguration.GetInputMidiDevices()); jackConfiguration.inputMidiDevices());
#if JACK_HOST #if JACK_HOST
if (useJack) if (useJack)
+1 -1
View File
@@ -1636,7 +1636,7 @@ public:
if (jackServerSettings.IsDummyAudioDevice()) if (jackServerSettings.IsDummyAudioDevice())
{ {
this->isDummyAudioDriver = true; this->isDummyAudioDriver = true;
this->audioDriver = std::unique_ptr<AudioDriver>(CreateDummyAudioDriver(this)); this->audioDriver = std::unique_ptr<AudioDriver>(CreateDummyAudioDriver(this,jackServerSettings.GetAlsaInputDevice()));
} }
else else
{ {
+1
View File
@@ -637,6 +637,7 @@ add_executable(pipedal_latency_test
PiPedalAlsa.hpp PiPedalAlsa.cpp PiPedalAlsa.hpp PiPedalAlsa.cpp
asan_options.cpp asan_options.cpp
AlsaDriver.cpp AlsaDriver.hpp AlsaDriver.cpp AlsaDriver.hpp
DummyAudioDriver.cpp DummyAudioDriver.hpp
JackConfiguration.hpp JackConfiguration.cpp JackConfiguration.hpp JackConfiguration.cpp
JackServerSettings.hpp JackServerSettings.cpp JackServerSettings.hpp JackServerSettings.cpp
CpuUse.hpp CpuUse.hpp
+48 -8
View File
@@ -35,6 +35,8 @@
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <stdexcept>
#include "ss.hpp"
#include "CpuUse.hpp" #include "CpuUse.hpp"
@@ -91,11 +93,16 @@ namespace pipedal
uint8_t *rawPlaybackBuffer = nullptr; uint8_t *rawPlaybackBuffer = nullptr;
AudioDriverHost *driverHost = nullptr; AudioDriverHost *driverHost = nullptr;
uint32_t channels = 2;
public: public:
DummyDriverImpl(AudioDriverHost *driverHost) DummyDriverImpl(AudioDriverHost *driverHost,const std::string&deviceName)
: driverHost(driverHost) : driverHost(driverHost)
, channels(GetDummyAudioChannels(deviceName))
{ {
captureChannels = channels;
playbackChannels = channels;
} }
virtual ~DummyDriverImpl() virtual ~DummyDriverImpl()
{ {
@@ -201,8 +208,8 @@ namespace pipedal
this->numberOfBuffers = jackServerSettings.GetNumberOfBuffers(); this->numberOfBuffers = jackServerSettings.GetNumberOfBuffers();
this->bufferSize = jackServerSettings.GetBufferSize(); this->bufferSize = jackServerSettings.GetBufferSize();
AllocateBuffers(captureBuffers, 2); AllocateBuffers(captureBuffers, channels);
AllocateBuffers(playbackBuffers, 2); AllocateBuffers(playbackBuffers, channels);
} }
@@ -299,7 +306,7 @@ namespace pipedal
this->activeCaptureBuffers.resize(channelSelection.GetInputAudioPorts().size()); this->activeCaptureBuffers.resize(channelSelection.GetInputAudioPorts().size());
playbackBuffers.resize(2); playbackBuffers.resize(channels);
int ix = 0; int ix = 0;
for (auto &x : channelSelection.GetInputAudioPorts()) for (auto &x : channelSelection.GetInputAudioPorts())
@@ -419,14 +426,15 @@ namespace pipedal
} }
}; };
AudioDriver *CreateDummyAudioDriver(AudioDriverHost *driverHost) AudioDriver *CreateDummyAudioDriver(AudioDriverHost *driverHost,const std::string&deviceName)
{ {
return new DummyDriverImpl(driverHost); return new DummyDriverImpl(driverHost,deviceName);
} }
bool GetDummyChannels(const JackServerSettings &jackServerSettings, bool GetDummyChannels(const JackServerSettings &jackServerSettings,
std::vector<std::string> &inputAudioPorts, std::vector<std::string> &inputAudioPorts,
std::vector<std::string> &outputAudioPorts) std::vector<std::string> &outputAudioPorts,
uint32_t channels)
{ {
bool result = false; bool result = false;
@@ -434,7 +442,7 @@ namespace pipedal
try try
{ {
unsigned int playbackChannels = 2, captureChannels = 2; uint32_t playbackChannels = channels, captureChannels = channels;
inputAudioPorts.clear(); inputAudioPorts.clear();
for (unsigned int i = 0; i < captureChannels; ++i) for (unsigned int i = 0; i < captureChannels; ++i)
@@ -457,4 +465,36 @@ namespace pipedal
return result; return result;
} }
AlsaDeviceInfo MakeDummyDeviceInfo(uint32_t channels)
{
AlsaDeviceInfo result;
constexpr int DUMMY_DEVICE_ID_OFFSET = 100974;
result.cardId_ = DUMMY_DEVICE_ID_OFFSET+channels;
result.id_ = SS("dummy:channels_" << channels);
result.name_ = SS("Dummy Device (" << channels << " channels)");
result.longName_ = result.name_;
result.sampleRates_.push_back(44100);
result.sampleRates_.push_back(48000);
result.minBufferSize_ = 16;
result.maxBufferSize_ = 1024;
return result;
}
} // namespace } // namespace
uint32_t pipedal::GetDummyAudioChannels(const std::string &deviceName)
{
uint32_t channels;
int pos = deviceName.find_last_of('_');
if (pos == std::string::npos)
{
throw std::runtime_error("Invalid dummy device name");
}
std::istringstream ss(deviceName.substr(pos+1));
ss >> channels;
return channels;
}
+4 -1
View File
@@ -29,7 +29,10 @@
namespace pipedal { namespace pipedal {
AudioDriver* CreateDummyAudioDriver(AudioDriverHost*driverHost); AlsaDeviceInfo MakeDummyDeviceInfo(uint32_t channels);
uint32_t GetDummyAudioChannels(const std::string &deviceName);
AudioDriver* CreateDummyAudioDriver(AudioDriverHost*driverHost,const std::string&deviceId);
} }
+17 -7
View File
@@ -199,14 +199,14 @@ void JackConfiguration::JackInitialize()
JackChannelSelection JackChannelSelection::MakeDefault(const JackConfiguration&config){ JackChannelSelection JackChannelSelection::MakeDefault(const JackConfiguration&config){
JackChannelSelection result; JackChannelSelection result;
for (size_t i = 0; i < std::min((size_t)2,config.GetInputAudioPorts().size()); ++i) for (size_t i = 0; i < std::min((size_t)2,config.inputAudioPorts().size()); ++i)
{ {
result.inputAudioPorts_.push_back(config.GetInputAudioPorts()[i]); result.inputAudioPorts_.push_back(config.inputAudioPorts()[i]);
} }
for (size_t i = 0; i < std::min((size_t)2,config.GetOutputAudioPorts().size()); ++i) for (size_t i = 0; i < std::min((size_t)2,config.outputAudioPorts().size()); ++i)
{ {
result.outputAudioPorts_.push_back(config.GetOutputAudioPorts()[i]); result.outputAudioPorts_.push_back(config.outputAudioPorts()[i]);
} }
return result; return result;
@@ -232,6 +232,16 @@ static std::vector<std::string> makeValid(const std::vector<std::string> & selec
result.push_back(t); result.push_back(t);
} }
} }
// if the result is empty, generate a default selection.
if (result.size() == 0)
{
size_t n = std::min(available.size(),(size_t)2);
for (size_t i = 0; i < n; ++i)
{
result.push_back(available[i]);
}
}
return result; return result;
} }
static std::vector<AlsaMidiDeviceInfo> makeValid(const std::vector<AlsaMidiDeviceInfo> & selected, const std::vector<AlsaMidiDeviceInfo> &available) static std::vector<AlsaMidiDeviceInfo> makeValid(const std::vector<AlsaMidiDeviceInfo> & selected, const std::vector<AlsaMidiDeviceInfo> &available)
@@ -284,9 +294,9 @@ static std::vector<AlsaMidiDeviceInfo> makeValid(const std::vector<AlsaMidiDevic
JackChannelSelection JackChannelSelection::RemoveInvalidChannels(const JackConfiguration&config) const JackChannelSelection JackChannelSelection::RemoveInvalidChannels(const JackConfiguration&config) const
{ {
JackChannelSelection result; JackChannelSelection result;
result.inputAudioPorts_ = makeValid(this->inputAudioPorts_,config.GetInputAudioPorts()); result.inputAudioPorts_ = makeValid(this->inputAudioPorts_,config.inputAudioPorts());
result.outputAudioPorts_ = makeValid(this->outputAudioPorts_,config.GetOutputAudioPorts()); result.outputAudioPorts_ = makeValid(this->outputAudioPorts_,config.outputAudioPorts());
result.inputMidiDevices_ = makeValid(this->inputMidiDevices_, config.GetInputMidiDevices()); result.inputMidiDevices_ = makeValid(this->inputMidiDevices_, config.inputMidiDevices());
if (!result.isValid()) if (!result.isValid())
{ {
return this->MakeDefault(config); return this->MakeDefault(config);
+4 -4
View File
@@ -50,7 +50,7 @@ namespace pipedal
public: public:
JackConfiguration(); JackConfiguration();
void AlsaInitialize(const JackServerSettings &jackServerSettings); // from also config settings. void AlsaInitialize(const JackServerSettings &jackServerSettings); // from alsa config settings.
void JackInitialize(); // from jack server instance. void JackInitialize(); // from jack server instance.
~JackConfiguration(); ~JackConfiguration();
@@ -67,9 +67,9 @@ namespace pipedal
double maxAllowedMidiDelta() const { return maxAllowedMidiDelta_; } double maxAllowedMidiDelta() const { return maxAllowedMidiDelta_; }
void setErrorStatus(const std::string&message) { this->errorStatus_ = message; } void setErrorStatus(const std::string&message) { this->errorStatus_ = message; }
const std::vector<std::string> &GetInputAudioPorts() const { return inputAudioPorts_; } const std::vector<std::string> &inputAudioPorts() const { return inputAudioPorts_; }
const std::vector<std::string> &GetOutputAudioPorts() const { return outputAudioPorts_; } const std::vector<std::string> &outputAudioPorts() const { return outputAudioPorts_; }
const std::vector<AlsaMidiDeviceInfo> &GetInputMidiDevices() const { return inputMidiDevices_; } const std::vector<AlsaMidiDeviceInfo> &inputMidiDevices() const { return inputMidiDevices_; }
DECLARE_JSON_MAP(JackConfiguration); DECLARE_JSON_MAP(JackConfiguration);
+4 -2
View File
@@ -57,10 +57,12 @@ namespace pipedal
void UseDummyAudioDevice() { void UseDummyAudioDevice() {
this->valid_ = true; this->valid_ = true;
if (sampleRate_ == 0) sampleRate_ = 48000; if (sampleRate_ == 0) sampleRate_ = 48000;
this->alsaDevice_ = "__DUMMY_AUDIO__"; this->alsaDevice_ = "dummy:channels_2";
} }
bool IsDummyAudioDevice() const { bool IsDummyAudioDevice() const {
return this->alsaDevice_ == "__DUMMY_AUDIO__"; return
this->alsaDevice_.starts_with("__DUMMY_AUDIO__")
|| this->alsaDevice_.starts_with("dummy:");
} }
void ReadJackDaemonConfiguration(); void ReadJackDaemonConfiguration();
+2 -2
View File
@@ -183,8 +183,8 @@ public:
JackConfiguration jackConfiguration; JackConfiguration jackConfiguration;
jackConfiguration.AlsaInitialize(serverSettings); jackConfiguration.AlsaInitialize(serverSettings);
auto & availableInputs = jackConfiguration.GetInputAudioPorts(); auto & availableInputs = jackConfiguration.inputAudioPorts();
auto & availableOutputs = jackConfiguration.GetOutputAudioPorts(); auto & availableOutputs = jackConfiguration.outputAudioPorts();
std::vector<std::string> inputAudioPorts, outputAudioPorts; std::vector<std::string> inputAudioPorts, outputAudioPorts;
+5
View File
@@ -22,6 +22,7 @@
#include "json.hpp" #include "json.hpp"
namespace pipedal { namespace pipedal {
class AlsaDeviceInfo { class AlsaDeviceInfo {
public: public:
int cardId_ = -1; int cardId_ = -1;
@@ -31,6 +32,10 @@ namespace pipedal {
std::vector<uint32_t> sampleRates_; std::vector<uint32_t> sampleRates_;
uint32_t minBufferSize_ = 0,maxBufferSize_ = 0; uint32_t minBufferSize_ = 0,maxBufferSize_ = 0;
bool isDummyDevice() const {
return id_.starts_with("dummy:");
}
DECLARE_JSON_MAP(AlsaDeviceInfo); DECLARE_JSON_MAP(AlsaDeviceInfo);
}; };
+17 -16
View File
@@ -42,6 +42,7 @@
#include "util.hpp" #include "util.hpp"
#include "DBusLog.hpp" #include "DBusLog.hpp"
#include "AvahiService.hpp" #include "AvahiService.hpp"
#include "DummyAudioDriver.hpp"
#ifndef NO_MLOCK #ifndef NO_MLOCK
#include <sys/mman.h> #include <sys/mman.h>
@@ -481,6 +482,8 @@ void PiPedalModel::SetControl(int64_t clientId, int64_t pedalItemId, const std::
void PiPedalModel::FireJackConfigurationChanged(const JackConfiguration &jackConfiguration) void PiPedalModel::FireJackConfigurationChanged(const JackConfiguration &jackConfiguration)
{ {
// noify subscribers. // noify subscribers.
std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()}; std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
for (auto &subscriber : t) for (auto &subscriber : t)
{ {
@@ -1319,12 +1322,7 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
auto jackConfiguration = this->jackConfiguration; auto jackConfiguration = this->jackConfiguration;
jackConfiguration.AlsaInitialize(jackServerSettings); jackConfiguration.AlsaInitialize(jackServerSettings);
if (jackConfiguration.isValid()) if (!jackConfiguration.isValid())
{
JackChannelSelection selection = storage.GetJackChannelSelection(jackConfiguration);
selection = selection.RemoveInvalidChannels(jackConfiguration);
}
else
{ {
jackConfiguration.setErrorStatus("Error"); jackConfiguration.setErrorStatus("Error");
} }
@@ -1339,11 +1337,8 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
throw std::runtime_error("Audio configuration not valid."); throw std::runtime_error("Audio configuration not valid.");
} }
JackChannelSelection channelSelection = this->storage.GetJackChannelSelection(jackConfiguration); auto channelSelection = this->storage.GetJackChannelSelection(jackConfiguration);
if (this->jackConfiguration.isValid())
{
channelSelection.RemoveInvalidChannels(this->jackConfiguration);
}
if (!channelSelection.isValid()) if (!channelSelection.isValid())
{ {
throw std::runtime_error("Audio configuration not valid."); throw std::runtime_error("Audio configuration not valid.");
@@ -1352,6 +1347,7 @@ void PiPedalModel::RestartAudio(bool useDummyAudioDriver)
this->pluginHost.OnConfigurationChanged(jackConfiguration, channelSelection); this->pluginHost.OnConfigurationChanged(jackConfiguration, channelSelection);
FireChannelSelectionChanged(-1);
LoadCurrentPedalboard(); LoadCurrentPedalboard();
this->UpdateRealtimeVuSubscriptions(); this->UpdateRealtimeVuSubscriptions();
@@ -1408,10 +1404,7 @@ JackChannelSelection PiPedalModel::GetJackChannelSelection()
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> lock(mutex);
JackChannelSelection t = this->storage.GetJackChannelSelection(this->jackConfiguration); JackChannelSelection t = this->storage.GetJackChannelSelection(this->jackConfiguration);
if (this->jackConfiguration.isValid())
{
t = t.RemoveInvalidChannels(this->jackConfiguration);
}
return t; return t;
} }
@@ -2235,7 +2228,15 @@ void PiPedalModel::CancelMonitorPatchProperty(int64_t clientId, int64_t clientHa
} }
std::vector<AlsaDeviceInfo> PiPedalModel::GetAlsaDevices() std::vector<AlsaDeviceInfo> PiPedalModel::GetAlsaDevices()
{ {
return this->alsaDevices.GetAlsaDevices(); std::vector<AlsaDeviceInfo> result = this->alsaDevices.GetAlsaDevices();
#ifdef JUNK
// Useful for debugging non-stereo device configurations
result.push_back(MakeDummyDeviceInfo(1));
result.push_back(MakeDummyDeviceInfo(2));
result.push_back(MakeDummyDeviceInfo(8));
#endif
return result;
} }
const std::filesystem::path &PiPedalModel::GetWebRoot() const const std::filesystem::path &PiPedalModel::GetWebRoot() const
+2 -3
View File
@@ -683,7 +683,7 @@ void Storage::SetJackChannelSelection(const JackChannelSelection &channelSelecti
this->isJackChannelSelectionValid = true; this->isJackChannelSelectionValid = true;
SaveChannelSelection(); SaveChannelSelection();
} }
const JackChannelSelection &Storage::GetJackChannelSelection(const JackConfiguration &jackConfiguration) JackChannelSelection Storage::GetJackChannelSelection(const JackConfiguration &jackConfiguration)
{ {
if (!this->isJackChannelSelectionValid) if (!this->isJackChannelSelectionValid)
{ {
@@ -691,10 +691,9 @@ const JackChannelSelection &Storage::GetJackChannelSelection(const JackConfigura
{ {
auto defaultSelection = JackChannelSelection::MakeDefault(jackConfiguration); auto defaultSelection = JackChannelSelection::MakeDefault(jackConfiguration);
SetJackChannelSelection(defaultSelection); SetJackChannelSelection(defaultSelection);
return this->jackChannelSelection;
} }
} }
return jackChannelSelection; return jackChannelSelection.RemoveInvalidChannels(jackConfiguration);
} }
void Storage::LoadChannelSelection() void Storage::LoadChannelSelection()
+1 -1
View File
@@ -156,7 +156,7 @@ public:
void SetJackChannelSelection(const JackChannelSelection&channelSelection); void SetJackChannelSelection(const JackChannelSelection&channelSelection);
const JackChannelSelection&GetJackChannelSelection(const JackConfiguration &jackConfiguration); JackChannelSelection GetJackChannelSelection(const JackConfiguration &jackConfiguration);
// returns true if services needs to be updated. // returns true if services needs to be updated.
bool SetWifiConfigSettings(const WifiConfigSettings & wifiConfigSettings); bool SetWifiConfigSettings(const WifiConfigSettings & wifiConfigSettings);