diff --git a/src/DummyAudioDriver.cpp b/src/DummyAudioDriver.cpp index a03e034..de8a9dd 100644 --- a/src/DummyAudioDriver.cpp +++ b/src/DummyAudioDriver.cpp @@ -517,6 +517,8 @@ namespace pipedal result.sampleRates_.push_back(48000); result.minBufferSize_ = 16; result.maxBufferSize_ = 1024; + result.supportsCapture_ = true; + result.supportsPlayback_ = true; return result; } diff --git a/src/PiPedalAlsa.cpp b/src/PiPedalAlsa.cpp index af1be7e..b2f7f1a 100644 --- a/src/PiPedalAlsa.cpp +++ b/src/PiPedalAlsa.cpp @@ -97,20 +97,16 @@ std::vector PiPedalAlsaDevices::GetAlsaDevices() info.name_ = snd_ctl_card_info_get_name(alsaInfo); info.longName_ = snd_ctl_card_info_get_longname(alsaInfo); - snd_pcm_t *hDevice = nullptr; + snd_pcm_t *captureDevice = nullptr; + snd_pcm_t *playbackDevice = nullptr; + bool captureOk = snd_pcm_open(&captureDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, 0) == 0; + bool playbackOk = snd_pcm_open(&playbackDevice, cardId.c_str(), SND_PCM_STREAM_PLAYBACK, 0) == 0; + info.supportsCapture_ = captureOk; + info.supportsPlayback_ = playbackOk; - // must support capture AND playback - err = snd_pcm_open(&hDevice, cardId.c_str(), SND_PCM_STREAM_CAPTURE, 0); - if (err == 0) - { - snd_pcm_close(hDevice); - } - if (err == 0) - { - err = snd_pcm_open(&hDevice, cardId.c_str(), SND_PCM_STREAM_PLAYBACK, 0); - } - if (err == 0) + if (captureOk || playbackOk) { + snd_pcm_t *hDevice = captureOk ? captureDevice : playbackDevice; snd_pcm_hw_params_t *params = nullptr; err = snd_pcm_hw_params_malloc(¶ms); if (err == 0) @@ -151,15 +147,25 @@ std::vector PiPedalAlsaDevices::GetAlsaDevices() info.minBufferSize_ = (uint32_t)minBufferSize; info.maxBufferSize_ = (uint32_t)maxBufferSize; - cacheDevice(info.name_, info); - result.push_back(info); } } } if (params != nullptr) snd_pcm_hw_params_free(params); - snd_pcm_close(hDevice); - } + if (captureOk) + snd_pcm_close(captureDevice); + if (playbackOk && playbackDevice != captureDevice) + snd_pcm_close(playbackDevice); + if (err == 0) + { + cacheDevice(info.name_, info); + result.push_back(info); + } + else if (getCachedDevice(info.name_, &info)) + { + result.push_back(info); + } + } else { if (getCachedDevice(info.name_, &info)) @@ -480,6 +486,8 @@ JSON_MAP_REFERENCE(AlsaDeviceInfo, longName) JSON_MAP_REFERENCE(AlsaDeviceInfo, sampleRates) JSON_MAP_REFERENCE(AlsaDeviceInfo, minBufferSize) JSON_MAP_REFERENCE(AlsaDeviceInfo, maxBufferSize) +JSON_MAP_REFERENCE(AlsaDeviceInfo, supportsCapture) +JSON_MAP_REFERENCE(AlsaDeviceInfo, supportsPlayback) JSON_MAP_END() JSON_MAP_BEGIN(AlsaMidiDeviceInfo) diff --git a/src/PiPedalAlsa.hpp b/src/PiPedalAlsa.hpp index cf602b2..5259837 100644 --- a/src/PiPedalAlsa.hpp +++ b/src/PiPedalAlsa.hpp @@ -31,6 +31,8 @@ namespace pipedal { std::string longName_; std::vector sampleRates_; uint32_t minBufferSize_ = 0,maxBufferSize_ = 0; + bool supportsCapture_ = false; + bool supportsPlayback_ = false; bool isDummyDevice() const { return id_.starts_with("dummy:"); diff --git a/vite/src/pipedal/AlsaDeviceInfo.tsx b/vite/src/pipedal/AlsaDeviceInfo.tsx index 0cd10ff..d1f97e0 100644 --- a/vite/src/pipedal/AlsaDeviceInfo.tsx +++ b/vite/src/pipedal/AlsaDeviceInfo.tsx @@ -9,6 +9,8 @@ export default class AlsaDeviceInfo { this.sampleRates = input.sampleRates as number[]; this.minBufferSize = input.minBufferSize; this.maxBufferSize = input.maxBufferSize; + this.supportsCapture = input.supportsCapture ? true : false; + this.supportsPlayback = input.supportsPlayback ? true : false; return this; } static deserialize_array(input: any): AlsaDeviceInfo[] @@ -62,5 +64,7 @@ export default class AlsaDeviceInfo { longName: string = ""; sampleRates: number[] = []; minBufferSize: number = 0; - maxBufferSize: number = 0; + maxBufferSize: number = 0; + supportsCapture: boolean = false; + supportsPlayback: boolean = false; }; \ No newline at end of file diff --git a/vite/src/pipedal/JackServerSettingsDialog.tsx b/vite/src/pipedal/JackServerSettingsDialog.tsx index c35a442..a295bb5 100644 --- a/vite/src/pipedal/JackServerSettingsDialog.tsx +++ b/vite/src/pipedal/JackServerSettingsDialog.tsx @@ -220,8 +220,8 @@ function isOkEnabled(jackServerSettings: JackServerSettings, alsaDevices?: AlsaD { if (!jackServerSettings.valid) return false; if (!alsaDevices) return false; - const inDevice = alsaDevices.find(d => d.id === jackServerSettings.alsaInputDevice); - const outDevice = alsaDevices.find(d => d.id === jackServerSettings.alsaOutputDevice); + const inDevice = alsaDevices.find(d => d.id === jackServerSettings.alsaInputDevice && d.supportsCapture); + const outDevice = alsaDevices.find(d => d.id === jackServerSettings.alsaOutputDevice && d.supportsPlayback); if (!inDevice || !outDevice) return false; const deviceBufferSize = jackServerSettings.bufferSize * jackServerSettings.numberOfBuffers; @@ -289,15 +289,24 @@ const JackServerSettingsDialog = withStyles( return result; } - let inDevice = alsaDevices.find(d => d.id === result.alsaInputDevice); - let outDevice = alsaDevices.find(d => d.id === result.alsaOutputDevice); + let inDevice = alsaDevices.find(d => d.id === result.alsaInputDevice && d.supportsCapture); + let outDevice = alsaDevices.find(d => d.id === result.alsaOutputDevice && d.supportsPlayback); if (!inDevice) { - inDevice = alsaDevices[0]; - result.alsaInputDevice = inDevice.id; + inDevice = alsaDevices.find(d => d.supportsCapture); + if (inDevice) { + result.alsaInputDevice = inDevice.id; + } } if (!outDevice) { - outDevice = alsaDevices[0]; - result.alsaOutputDevice = outDevice.id; + outDevice = alsaDevices.find(d => d.supportsPlayback); + if (outDevice) { + result.alsaOutputDevice = outDevice.id; + } + } + + if (!inDevice || !outDevice) { + result.valid = false; + return result; } if (result.sampleRate === 0) result.sampleRate = 48000; @@ -467,9 +476,9 @@ const JackServerSettingsDialog = withStyles( disabled={!this.state.alsaDevices || this.state.alsaDevices.length === 0} style={{ width: 220 }} > - {this.state.alsaDevices?.map(d => ( - {d.name} - )) || Loading...} + {this.state.alsaDevices?.filter(d => d.supportsCapture).map(d => ( + {d.name} + )) || Loading...} @@ -483,8 +492,8 @@ const JackServerSettingsDialog = withStyles( disabled={!this.state.alsaDevices || this.state.alsaDevices.length === 0} style={{ width: 220 }} > - {this.state.alsaDevices?.map(d => ( - {d.name} + {this.state.alsaDevices?.filter(d => d.supportsPlayback).map(d => ( + {d.name} )) || Loading...}