Browse Source

ASLA: reversed the order in which input and output devices are opened, in response to reports of flaky drivers which can't handle doing the outputs first.

tags/2021-05-28
jules 7 years ago
parent
commit
92e97624b1
1 changed files with 58 additions and 64 deletions
  1. +58
    -64
      modules/juce_audio_devices/native/juce_linux_ALSA.cpp

+ 58
- 64
modules/juce_audio_devices/native/juce_linux_ALSA.cpp View File

@@ -58,7 +58,7 @@ static void getDeviceSampleRates (snd_pcm_t* handle, Array<double>& rates)
for (int i = 0; ratesToTry[i] != 0; ++i) for (int i = 0; ratesToTry[i] != 0; ++i)
{ {
if (snd_pcm_hw_params_any (handle, hwParams) >= 0 if (snd_pcm_hw_params_any (handle, hwParams) >= 0
&& snd_pcm_hw_params_test_rate (handle, hwParams, (unsigned int) ratesToTry[i], 0) == 0)
&& snd_pcm_hw_params_test_rate (handle, hwParams, (unsigned int) ratesToTry[i], 0) == 0)
{ {
rates.addIfNotAlreadyThere ((double) ratesToTry[i]); rates.addIfNotAlreadyThere ((double) ratesToTry[i]);
} }
@@ -358,7 +358,7 @@ public:
scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false); scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false);
scratch.fillWith (0); // (not clearing this data causes warnings in valgrind) scratch.fillWith (0); // (not clearing this data causes warnings in valgrind)
snd_pcm_sframes_t num = snd_pcm_readi (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples);
auto num = snd_pcm_readi (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples);
if (num < 0) if (num < 0)
{ {
@@ -378,7 +378,7 @@ public:
} }
else else
{ {
snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, (snd_pcm_uframes_t) numSamples);
auto num = snd_pcm_readn (handle, (void**) data, (snd_pcm_uframes_t) numSamples);
if (num < 0) if (num < 0)
{ {
@@ -488,17 +488,8 @@ class ALSAThread : public Thread
public: public:
ALSAThread (const String& inputDeviceID, const String& outputDeviceID) ALSAThread (const String& inputDeviceID, const String& outputDeviceID)
: Thread ("JUCE ALSA"), : Thread ("JUCE ALSA"),
sampleRate (0),
bufferSize (0),
outputLatency (0),
inputLatency (0),
callback (0),
inputId (inputDeviceID), inputId (inputDeviceID),
outputId (outputDeviceID),
numCallbacks (0),
audioIoInProgress (false),
inputChannelBuffer (1, 1),
outputChannelBuffer (1, 1)
outputId (outputDeviceID)
{ {
initialiseRatesAndChannels(); initialiseRatesAndChannels();
} }
@@ -510,8 +501,8 @@ public:
void open (BigInteger inputChannels, void open (BigInteger inputChannels,
BigInteger outputChannels, BigInteger outputChannels,
const double newSampleRate,
const int newBufferSize)
double newSampleRate,
int newBufferSize)
{ {
close(); close();
@@ -549,6 +540,35 @@ public:
outputChannelDataForCallback.clear(); outputChannelDataForCallback.clear();
currentOutputChans.clear(); currentOutputChans.clear();
// Note that the input device is opened before an output, because we've heard
// of drivers where doing it in the reverse order mysteriously fails.. If this
// order also causes problems, let us know and we'll see if we can find a compromise!
if (inputChannelDataForCallback.size() > 0 && inputId.isNotEmpty())
{
inputDevice.reset (new ALSADevice (inputId, true));
if (inputDevice->error.isNotEmpty())
{
error = inputDevice->error;
inputDevice.reset();
return;
}
ensureMinimumNumBitsSet (currentInputChans, (int) minChansIn);
if (! inputDevice->setParameters ((unsigned int) sampleRate,
jlimit ((int) minChansIn, (int) maxChansIn, currentInputChans.getHighestBit() + 1),
bufferSize))
{
error = inputDevice->error;
inputDevice.reset();
return;
}
inputLatency = inputDevice->latency;
}
if (outputChannels.getHighestBit() >= 0) if (outputChannels.getHighestBit() >= 0)
{ {
for (int i = 0; i < maxOutputsRequested; ++i) for (int i = 0; i < maxOutputsRequested; ++i)
@@ -568,7 +588,7 @@ public:
if (outputDevice->error.isNotEmpty()) if (outputDevice->error.isNotEmpty())
{ {
error = outputDevice->error; error = outputDevice->error;
outputDevice = nullptr;
outputDevice.reset();
return; return;
} }
@@ -578,38 +598,13 @@ public:
bufferSize)) bufferSize))
{ {
error = outputDevice->error; error = outputDevice->error;
outputDevice = nullptr;
outputDevice.reset();
return; return;
} }
outputLatency = outputDevice->latency; outputLatency = outputDevice->latency;
} }
if (inputChannelDataForCallback.size() > 0 && inputId.isNotEmpty())
{
inputDevice.reset (new ALSADevice (inputId, true));
if (inputDevice->error.isNotEmpty())
{
error = inputDevice->error;
inputDevice = nullptr;
return;
}
ensureMinimumNumBitsSet (currentInputChans, (int) minChansIn);
if (! inputDevice->setParameters ((unsigned int) sampleRate,
jlimit ((int) minChansIn, (int) maxChansIn, currentInputChans.getHighestBit() + 1),
bufferSize))
{
error = inputDevice->error;
inputDevice = nullptr;
return;
}
inputLatency = inputDevice->latency;
}
if (outputDevice == nullptr && inputDevice == nullptr) if (outputDevice == nullptr && inputDevice == nullptr)
{ {
error = "no channels"; error = "no channels";
@@ -664,8 +659,8 @@ public:
stopThread (6000); stopThread (6000);
inputDevice = nullptr;
outputDevice = nullptr;
inputDevice.reset();
outputDevice.reset();
inputChannelBuffer.setSize (1, 1); inputChannelBuffer.setSize (1, 1);
outputChannelBuffer.setSize (1, 1); outputChannelBuffer.setSize (1, 1);
@@ -692,7 +687,7 @@ public:
if (threadShouldExit()) if (threadShouldExit())
break; break;
snd_pcm_sframes_t avail = snd_pcm_avail_update (inputDevice->handle);
auto avail = snd_pcm_avail_update (inputDevice->handle);
if (avail < 0) if (avail < 0)
JUCE_ALSA_FAILED (snd_pcm_recover (inputDevice->handle, (int) avail, 0)); JUCE_ALSA_FAILED (snd_pcm_recover (inputDevice->handle, (int) avail, 0));
@@ -738,7 +733,7 @@ public:
if (threadShouldExit()) if (threadShouldExit())
break; break;
snd_pcm_sframes_t avail = snd_pcm_avail_update (outputDevice->handle);
auto avail = snd_pcm_avail_update (outputDevice->handle);
if (avail < 0) if (avail < 0)
JUCE_ALSA_FAILED (snd_pcm_recover (outputDevice->handle, (int) avail, 0)); JUCE_ALSA_FAILED (snd_pcm_recover (outputDevice->handle, (int) avail, 0));
@@ -784,20 +779,20 @@ public:
//============================================================================== //==============================================================================
String error; String error;
double sampleRate;
int bufferSize, outputLatency, inputLatency;
double sampleRate = 0;
int bufferSize = 0, outputLatency = 0, inputLatency = 0;
BigInteger currentInputChans, currentOutputChans; BigInteger currentInputChans, currentOutputChans;
Array<double> sampleRates; Array<double> sampleRates;
StringArray channelNamesOut, channelNamesIn; StringArray channelNamesOut, channelNamesIn;
AudioIODeviceCallback* callback;
AudioIODeviceCallback* callback = nullptr;
private: private:
//============================================================================== //==============================================================================
const String inputId, outputId; const String inputId, outputId;
std::unique_ptr<ALSADevice> outputDevice, inputDevice; std::unique_ptr<ALSADevice> outputDevice, inputDevice;
int numCallbacks;
bool audioIoInProgress;
int numCallbacks = 0;
bool audioIoInProgress = false;
CriticalSection callbackLock; CriticalSection callbackLock;
@@ -805,8 +800,8 @@ private:
Array<const float*> inputChannelDataForCallback; Array<const float*> inputChannelDataForCallback;
Array<float*> outputChannelDataForCallback; Array<float*> outputChannelDataForCallback;
unsigned int minChansOut, maxChansOut;
unsigned int minChansIn, maxChansIn;
unsigned int minChansOut = 0, maxChansOut = 0;
unsigned int minChansIn = 0, maxChansIn = 0;
bool failed (const int errorNum) bool failed (const int errorNum)
{ {
@@ -854,8 +849,6 @@ public:
: AudioIODevice (deviceName, deviceTypeName), : AudioIODevice (deviceName, deviceTypeName),
inputId (inputDeviceID), inputId (inputDeviceID),
outputId (outputDeviceID), outputId (outputDeviceID),
isOpen_ (false),
isStarted (false),
internal (inputDeviceID, outputDeviceID) internal (inputDeviceID, outputDeviceID)
{ {
} }
@@ -958,7 +951,7 @@ public:
void stop() override void stop() override
{ {
AudioIODeviceCallback* const oldCallback = internal.callback;
auto oldCallback = internal.callback;
start (nullptr); start (nullptr);
@@ -969,7 +962,7 @@ public:
String inputId, outputId; String inputId, outputId;
private: private:
bool isOpen_, isStarted;
bool isOpen_ = false, isStarted = false;
ALSAThread internal; ALSAThread internal;
}; };
@@ -1030,7 +1023,7 @@ public:
{ {
jassert (hasScanned); // need to call scanForDevices() before doing this jassert (hasScanned); // need to call scanForDevices() before doing this
const int idx = (forInput ? inputIds : outputIds).indexOf ("default");
auto idx = (forInput ? inputIds : outputIds).indexOf ("default");
return idx >= 0 ? idx : 0; return idx >= 0 ? idx : 0;
} }
@@ -1052,8 +1045,8 @@ public:
{ {
jassert (hasScanned); // need to call scanForDevices() before doing this jassert (hasScanned); // need to call scanForDevices() before doing this
const int inputIndex = inputNames.indexOf (inputDeviceName);
const int outputIndex = outputNames.indexOf (outputDeviceName);
auto inputIndex = inputNames.indexOf (inputDeviceName);
auto outputIndex = outputNames.indexOf (outputDeviceName);
String deviceName (outputIndex >= 0 ? outputDeviceName String deviceName (outputIndex >= 0 ? outputDeviceName
: inputDeviceName); : inputDeviceName);
@@ -1069,7 +1062,8 @@ public:
private: private:
//============================================================================== //==============================================================================
StringArray inputNames, outputNames, inputIds, outputIds; StringArray inputNames, outputNames, inputIds, outputIds;
bool hasScanned = false, listOnlySoundcards;
bool hasScanned = false;
const bool listOnlySoundcards;
bool testDevice (const String& id, const String& outputName, const String& inputName) bool testDevice (const String& id, const String& outputName, const String& inputName)
{ {
@@ -1264,7 +1258,7 @@ private:
testDevice ("pulse", "Pulseaudio output", "Pulseaudio input"); testDevice ("pulse", "Pulseaudio output", "Pulseaudio input");
// make sure the default device is listed first, and followed by the pulse device (if present) // make sure the default device is listed first, and followed by the pulse device (if present)
int idx = outputIds.indexOf ("pulse");
auto idx = outputIds.indexOf ("pulse");
outputIds.move (idx, 0); outputIds.move (idx, 0);
outputNames.move (idx, 0); outputNames.move (idx, 0);
@@ -1283,8 +1277,8 @@ private:
static String hintToString (const void* hints, const char* type) static String hintToString (const void* hints, const char* type)
{ {
char* const hint = snd_device_name_get_hint (hints, type);
const String s (String::fromUTF8 (hint));
char* hint = snd_device_name_get_hint (hints, type);
auto s = String::fromUTF8 (hint);
::free (hint); ::free (hint);
return s; return s;
} }


Loading…
Cancel
Save