mirror of
https://github.com/got-feedBack/feedBack-desktop.git
synced 2026-09-11 03:04:10 +00:00
fix(audio): reuse live ASIO device capabilities
This commit is contained in:
@@ -131,6 +131,43 @@ DeviceOptions DeviceSetup::probeDual(const juce::String& inputTypeName,
|
|||||||
|
|
||||||
if (isDuplex)
|
if (isDuplex)
|
||||||
{
|
{
|
||||||
|
// ASIO drivers commonly allow only one live device object. If
|
||||||
|
// this exact duplex endpoint is already open, constructing a
|
||||||
|
// second object can succeed but report zero channel names (the
|
||||||
|
// settings UI then incorrectly falls back to Inputs 1-2). Reuse
|
||||||
|
// the live device's immutable capability lists instead. The
|
||||||
|
// endpoint checks keep a newly selected device on the normal
|
||||||
|
// temporary-probe path.
|
||||||
|
auto* liveDevice = inMgr.getCurrentAudioDevice();
|
||||||
|
auto* liveType = inMgr.getCurrentDeviceTypeObject();
|
||||||
|
const auto liveSetup = inMgr.getAudioDeviceSetup();
|
||||||
|
const bool requestedEndpointIsLive =
|
||||||
|
liveDevice != nullptr
|
||||||
|
&& liveDevice->isOpen()
|
||||||
|
&& liveType != nullptr
|
||||||
|
&& liveType->getTypeName() == options.inputType
|
||||||
|
&& liveSetup.inputDeviceName == probeInputName
|
||||||
|
&& liveSetup.outputDeviceName == probeOutputName;
|
||||||
|
|
||||||
|
if (requestedEndpointIsLive)
|
||||||
|
{
|
||||||
|
options.inputChannels = liveDevice->getInputChannelNames();
|
||||||
|
options.outputChannels = liveDevice->getOutputChannelNames();
|
||||||
|
for (auto rate : liveDevice->getAvailableSampleRates())
|
||||||
|
options.sampleRates.addIfNotAlreadyThere(rate);
|
||||||
|
for (auto size : liveDevice->getAvailableBufferSizes())
|
||||||
|
options.bufferSizes.addIfNotAlreadyThere(size);
|
||||||
|
|
||||||
|
fprintf(stderr, "[AudioEngine] Probed live device options: "
|
||||||
|
"inType='%s' outType='%s' in='%s' out='%s' "
|
||||||
|
"inputs=%d outputs=%d rates=%d buffers=%d compatible=1\n",
|
||||||
|
options.inputType.toRawUTF8(), options.outputType.toRawUTF8(),
|
||||||
|
options.input.toRawUTF8(), options.output.toRawUTF8(),
|
||||||
|
options.inputChannels.size(), options.outputChannels.size(),
|
||||||
|
options.sampleRates.size(), options.bufferSizes.size());
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioIODevice> dev(
|
std::unique_ptr<juce::AudioIODevice> dev(
|
||||||
inputType->createDevice(probeOutputName, probeInputName));
|
inputType->createDevice(probeOutputName, probeInputName));
|
||||||
if (dev)
|
if (dev)
|
||||||
|
|||||||
@@ -20,6 +20,27 @@ const end = source.indexOf('DeviceConfigResult DeviceSetup::applySplit', start);
|
|||||||
// a bad slice would otherwise make every assertion below fail confusingly.
|
// a bad slice would otherwise make every assertion below fail confusingly.
|
||||||
assert.ok(start >= 0 && end > start, 'could not locate applyDuplex in DeviceSetup.cpp');
|
assert.ok(start >= 0 && end > start, 'could not locate applyDuplex in DeviceSetup.cpp');
|
||||||
const applyDuplex = source.slice(start, end);
|
const applyDuplex = source.slice(start, end);
|
||||||
|
const probeStart = source.indexOf('DeviceOptions DeviceSetup::probeDual');
|
||||||
|
const probeEnd = source.indexOf('juce::String DeviceSetup::applyDuplex', probeStart);
|
||||||
|
const probeDual = source.slice(probeStart, probeEnd);
|
||||||
|
|
||||||
|
test('duplex probe reuses an exact live endpoint before constructing a competing device', () => {
|
||||||
|
assert.ok(probeStart >= 0 && probeEnd > probeStart, 'could not locate probeDual');
|
||||||
|
|
||||||
|
const inspectLive = probeDual.indexOf('inMgr.getCurrentAudioDevice()');
|
||||||
|
const exactEndpoint = probeDual.indexOf('const bool requestedEndpointIsLive');
|
||||||
|
const requireOpen = probeDual.indexOf('liveDevice->isOpen()', exactEndpoint);
|
||||||
|
const reuseChannels = probeDual.indexOf(
|
||||||
|
'options.inputChannels = liveDevice->getInputChannelNames()');
|
||||||
|
const temporaryProbe = probeDual.indexOf(
|
||||||
|
'inputType->createDevice(probeOutputName, probeInputName)');
|
||||||
|
|
||||||
|
assert.ok(inspectLive >= 0 && exactEndpoint > inspectLive,
|
||||||
|
'the probe must inspect and identity-check the live endpoint');
|
||||||
|
assert.ok(requireOpen > exactEndpoint && reuseChannels > requireOpen
|
||||||
|
&& temporaryProbe > reuseChannels,
|
||||||
|
'matching live capabilities must be returned before a temporary device is created');
|
||||||
|
});
|
||||||
|
|
||||||
test('duplex setup closes Windows ASIO before constructing its channel probe', () => {
|
test('duplex setup closes Windows ASIO before constructing its channel probe', () => {
|
||||||
assert.match(
|
assert.match(
|
||||||
|
|||||||
Reference in New Issue
Block a user