1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-31 03:00:05 +00:00
This commit is contained in:
jules 2008-07-02 20:10:02 +00:00
parent ad56914057
commit 3b59053b2c
15 changed files with 4828 additions and 1574 deletions

View file

@ -78,7 +78,7 @@ static void getDeviceSampleRates (snd_pcm_t* handle, Array <int>& rates)
if (snd_pcm_hw_params_any (handle, hwParams) >= 0
&& snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0)
{
rates.add (ratesToTry[i]);
rates.addIfNotAlreadyThere (ratesToTry[i]);
}
}
}
@ -102,6 +102,9 @@ static void getDeviceProperties (const String& id,
unsigned int& maxChansIn,
Array <int>& rates)
{
if (id.isEmpty())
return;
snd_ctl_t* handle;
if (snd_ctl_open (&handle, id.upToLastOccurrenceOf (T(","), false, false), SND_CTL_NONBLOCK) >= 0)
@ -149,7 +152,7 @@ static void getDeviceProperties (const String& id,
class ALSADevice
{
public:
ALSADevice (const String& deviceName,
ALSADevice (const String& id,
const bool forInput)
: handle (0),
bitDepth (16),
@ -157,7 +160,7 @@ public:
isInput (forInput),
sampleFormat (AudioDataConverters::int16LE)
{
failed (snd_pcm_open (&handle, deviceName,
failed (snd_pcm_open (&handle, id,
forInput ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
SND_PCM_ASYNC));
}
@ -364,12 +367,14 @@ private:
class ALSAThread : public Thread
{
public:
ALSAThread (const String& deviceName_)
ALSAThread (const String& inputId_,
const String& outputId_)
: Thread ("Juce ALSA"),
sampleRate (0),
bufferSize (0),
callback (0),
deviceName (deviceName_),
inputId (inputId_),
outputId (outputId_),
outputDevice (0),
inputDevice (0),
numCallbacks (0),
@ -402,16 +407,9 @@ public:
currentInputChans.clear();
currentOutputChans.clear();
numChannelsRunning = jmax (inputChannels.getHighestBit(),
outputChannels.getHighestBit()) + 1;
numChannelsRunning = jmin (maxNumChans, jlimit ((int) minChansIn,
(int) maxChansIn,
numChannelsRunning));
if (inputChannels.getHighestBit() >= 0)
{
for (int i = 0; i < numChannelsRunning; ++i)
for (int i = 0; i <= inputChannels.getHighestBit(); ++i)
{
inputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize);
@ -425,7 +423,7 @@ public:
if (outputChannels.getHighestBit() >= 0)
{
for (int i = 0; i < numChannelsRunning; ++i)
for (int i = 0; i <= outputChannels.getHighestBit(); ++i)
{
outputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize);
@ -437,9 +435,9 @@ public:
}
}
if (totalNumOutputChannels > 0)
if (totalNumOutputChannels > 0 && outputId.isNotEmpty())
{
outputDevice = new ALSADevice (deviceName, false);
outputDevice = new ALSADevice (outputId, false);
if (outputDevice->error.isNotEmpty())
{
@ -448,7 +446,9 @@ public:
return;
}
if (! outputDevice->setParameters ((unsigned int) sampleRate, numChannelsRunning, bufferSize))
if (! outputDevice->setParameters ((unsigned int) sampleRate,
currentOutputChans.getHighestBit() + 1,
bufferSize))
{
error = outputDevice->error;
deleteAndZero (outputDevice);
@ -456,9 +456,9 @@ public:
}
}
if (totalNumInputChannels > 0)
if (totalNumInputChannels > 0 && inputId.isNotEmpty())
{
inputDevice = new ALSADevice (deviceName, true);
inputDevice = new ALSADevice (inputId, true);
if (inputDevice->error.isNotEmpty())
{
@ -467,7 +467,9 @@ public:
return;
}
if (! inputDevice->setParameters ((unsigned int) sampleRate, numChannelsRunning, bufferSize))
if (! inputDevice->setParameters ((unsigned int) sampleRate,
currentInputChans.getHighestBit() + 1,
bufferSize))
{
error = inputDevice->error;
deleteAndZero (inputDevice);
@ -527,7 +529,6 @@ public:
zeromem (inputChannelDataForCallback, sizeof (inputChannelDataForCallback));
totalNumOutputChannels = 0;
totalNumInputChannels = 0;
numChannelsRunning = 0;
numCallbacks = 0;
}
@ -544,8 +545,6 @@ public:
{
if (inputDevice != 0)
{
jassert (numChannelsRunning >= inputDevice->numChannelsRunning);
if (! inputDevice->read (inputChannelData, bufferSize))
{
DBG ("ALSA: read failure");
@ -584,7 +583,6 @@ public:
failed (snd_pcm_avail_update (outputDevice->handle));
jassert (numChannelsRunning >= outputDevice->numChannelsRunning);
if (! outputDevice->write (outputChannelData, bufferSize))
{
DBG ("ALSA: write failure");
@ -619,7 +617,7 @@ public:
private:
//==============================================================================
const String deviceName;
const String inputId, outputId;
ALSADevice* outputDevice;
ALSADevice* inputDevice;
int numCallbacks;
@ -632,7 +630,6 @@ private:
float* inputChannelData [maxNumChans];
float* inputChannelDataForCallback [maxNumChans];
int totalNumOutputChannels;
int numChannelsRunning;
unsigned int minChansOut, maxChansOut;
unsigned int minChansIn, maxChansIn;
@ -656,8 +653,10 @@ private:
maxChansOut = 0;
minChansIn = 0;
maxChansIn = 0;
unsigned int dummy = 0;
getDeviceProperties (deviceName, minChansOut, maxChansOut, minChansIn, maxChansIn, sampleRates);
getDeviceProperties (inputId, dummy, dummy, minChansIn, maxChansIn, sampleRates);
getDeviceProperties (outputId, minChansOut, maxChansOut, dummy, dummy, sampleRates);
unsigned int i;
for (i = 0; i < maxChansOut; ++i)
@ -674,13 +673,16 @@ class ALSAAudioIODevice : public AudioIODevice
{
public:
ALSAAudioIODevice (const String& deviceName,
const String& deviceId)
const String& inputId_,
const String& outputId_)
: AudioIODevice (deviceName, T("ALSA")),
inputId (inputId_),
outputId (outputId_),
isOpen_ (false),
isStarted (false),
internal (0)
{
internal = new ALSAThread (deviceId);
internal = new ALSAThread (inputId, outputId);
}
~ALSAAudioIODevice()
@ -839,6 +841,8 @@ public:
return internal->error;
}
String inputId, outputId;
private:
bool isOpen_, isStarted;
ALSAThread* internal;
@ -863,10 +867,14 @@ public:
//==============================================================================
void scanForDevices()
{
hasScanned = true;
if (hasScanned)
return;
names.clear();
ids.clear();
hasScanned = true;
inputNames.clear();
inputIds.clear();
outputNames.clear();
outputIds.clear();
snd_ctl_t* handle;
snd_ctl_card_info_t* info;
@ -874,7 +882,7 @@ public:
int cardNum = -1;
while (ids.size() <= 24)
while (outputIds.size() + inputIds.size() <= 32)
{
snd_card_next (&cardNum);
@ -900,18 +908,26 @@ public:
String id, name;
id << "hw:" << cardId << ',' << device;
if (testDevice (id))
bool isInput, isOutput;
if (testDevice (id, isInput, isOutput))
{
name << snd_ctl_card_info_get_name (info);
if (name.isEmpty())
name = id;
if (device > 0)
name << " (" << (device + 1) << ')';
if (isInput)
{
inputNames.add (name);
inputIds.add (id);
}
ids.add (id);
names.add (name);
if (isOutput)
{
outputNames.add (name);
outputIds.add (id);
}
}
}
}
@ -919,35 +935,54 @@ public:
snd_ctl_close (handle);
}
}
inputNames.appendNumbersToDuplicates (false, true);
outputNames.appendNumbersToDuplicates (false, true);
}
const StringArray getDeviceNames (const bool /*preferInputNames*/) const
const StringArray getDeviceNames (const bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
StringArray namesCopy (names);
namesCopy.removeDuplicates (true);
return namesCopy;
return wantInputNames ? inputNames : outputNames;
}
const String getDefaultDeviceName (const bool /*preferInputNames*/,
const int /*numInputChannelsNeeded*/,
const int /*numOutputChannelsNeeded*/) const
int getDefaultDeviceIndex (const bool forInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
}
bool hasSeparateInputsAndOutputs() const { return true; }
int getIndexOfDevice (AudioIODevice* device, const bool asInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return names[0];
ALSAAudioIODevice* const d = dynamic_cast <ALSAAudioIODevice*> (device);
if (d == 0)
return -1;
return asInput ? inputIds.indexOf (d->inputId)
: outputIds.indexOf (d->outputId);
}
AudioIODevice* createDevice (const String& deviceName)
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this
const int index = names.indexOf (deviceName);
const int inputIndex = inputNames.indexOf (inputDeviceName);
const int outputIndex = outputNames.indexOf (outputDeviceName);
String deviceName (outputDeviceName);
if (deviceName.isEmpty())
deviceName = inputDeviceName;
if (index >= 0)
return new ALSAAudioIODevice (deviceName, ids [index]);
return new ALSAAudioIODevice (deviceName,
inputIds [inputIndex],
outputIds [outputIndex]);
return 0;
}
@ -956,10 +991,10 @@ public:
juce_UseDebuggingNewOperator
private:
StringArray names, ids;
StringArray inputNames, outputNames, inputIds, outputIds;
bool hasScanned;
static bool testDevice (const String& id)
static bool testDevice (const String& id, bool& isInput, bool& isOutput)
{
unsigned int minChansOut = 0, maxChansOut = 0;
unsigned int minChansIn = 0, maxChansIn = 0;
@ -972,7 +1007,10 @@ private:
+ T(" ins=") + String ((int) minChansIn) + T("-") + String ((int) maxChansIn)
+ T(" rates=") + String (rates.size()));
return (maxChansOut > 0 || maxChansIn > 0) && rates.size() > 0;
isInput = maxChansIn > 0;
isOutput = maxChansOut > 0;
return (isInput || isOutput) && rates.size() > 0;
}
ALSAAudioIODeviceType (const ALSAAudioIODeviceType&);