[DEV] add API to open stream with his name (alsa specific)

This commit is contained in:
Edouard DUPIN 2015-02-26 22:25:15 +01:00
parent 12342a4ffa
commit e6de495285
7 changed files with 178 additions and 284 deletions

View File

@ -81,7 +81,8 @@ enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oP
ATA_ERROR("a non-nullptr input StreamParameters structure cannot have an nChannels value less than one.");
return airtaudio::error_invalidUse;
}
if (oParams == nullptr && iParams == nullptr) {
if ( oParams == nullptr
&& iParams == nullptr) {
ATA_ERROR("input and output StreamParameters structures are both nullptr!");
return airtaudio::error_invalidUse;
}
@ -93,7 +94,8 @@ enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oP
uint32_t oChannels = 0;
if (oParams) {
oChannels = oParams->nChannels;
if (oParams->deviceId >= nDevices) {
if ( oParams->deviceId >= nDevices
&& oParams->deviceName == "") {
ATA_ERROR("output device parameter value is invalid.");
return airtaudio::error_invalidUse;
}
@ -101,7 +103,8 @@ enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oP
uint32_t iChannels = 0;
if (iParams) {
iChannels = iParams->nChannels;
if (iParams->deviceId >= nDevices) {
if ( iParams->deviceId >= nDevices
&& iParams->deviceName == "") {
ATA_ERROR("input device parameter value is invalid.");
return airtaudio::error_invalidUse;
}
@ -109,28 +112,50 @@ enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oP
clearStreamInfo();
bool result;
if (oChannels > 0) {
result = probeDeviceOpen(oParams->deviceId,
airtaudio::mode_output,
oChannels,
oParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
if (oParams->deviceId == -1) {
result = probeDeviceOpenName(oParams->deviceName,
airtaudio::mode_output,
oChannels,
oParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
} else {
result = probeDeviceOpen(oParams->deviceId,
airtaudio::mode_output,
oChannels,
oParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
}
if (result == false) {
ATA_ERROR("system ERROR");
return airtaudio::error_systemError;
}
}
if (iChannels > 0) {
result = probeDeviceOpen(iParams->deviceId,
airtaudio::mode_input,
iChannels,
iParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
if (iParams->deviceId == -1) {
result = probeDeviceOpenName(iParams->deviceName,
airtaudio::mode_input,
iChannels,
iParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
} else {
result = probeDeviceOpen(iParams->deviceId,
airtaudio::mode_input,
iChannels,
iParams->firstChannel,
sampleRate,
format,
bufferFrames,
options);
}
if (result == false) {
if (oChannels > 0) {
closeStream();

View File

@ -56,6 +56,10 @@ namespace airtaudio {
virtual airtaudio::type getCurrentApi() = 0;
virtual uint32_t getDeviceCount() = 0;
virtual airtaudio::DeviceInfo getDeviceInfo(uint32_t _device) = 0;
// TODO : Check API ...
virtual bool getNamedDeviceInfo(const std::string& _deviceName, airtaudio::DeviceInfo& _info) {
return false;
}
virtual uint32_t getDefaultInputDevice();
virtual uint32_t getDefaultOutputDevice();
enum airtaudio::error openStream(airtaudio::StreamParameters* _outputParameters,
@ -120,6 +124,14 @@ namespace airtaudio {
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
virtual bool probeDeviceOpenName(const std::string& _deviceName,
airtaudio::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) { return false; }
/**
* @brief Increment the stream time.
*/

View File

@ -143,14 +143,13 @@ airtaudio::Interface::~Interface() {
m_rtapi = nullptr;
}
enum airtaudio::error airtaudio::Interface::openStream(
airtaudio::StreamParameters* _outputParameters,
airtaudio::StreamParameters* _inputParameters,
audio::format _format,
uint32_t _sampleRate,
uint32_t* _bufferFrames,
airtaudio::AirTAudioCallback _callback,
airtaudio::StreamOptions* _options) {
enum airtaudio::error airtaudio::Interface::openStream(airtaudio::StreamParameters* _outputParameters,
airtaudio::StreamParameters* _inputParameters,
audio::format _format,
uint32_t _sampleRate,
uint32_t* _bufferFrames,
airtaudio::AirTAudioCallback _callback,
airtaudio::StreamOptions* _options) {
if (m_rtapi == nullptr) {
return airtaudio::error_inputNull;
}

View File

@ -116,6 +116,14 @@ namespace airtaudio {
}
return m_rtapi->getDeviceInfo(_device);
}
airtaudio::DeviceInfo getDeviceInfo(const std::string& _deviceName) {
if (m_rtapi == nullptr) {
return airtaudio::DeviceInfo();
}
airtaudio::DeviceInfo info;
m_rtapi->getNamedDeviceInfo(_deviceName, info);
return info;
}
/**
* @brief A function that returns the index of the default output device.
*
@ -165,7 +173,7 @@ namespace airtaudio {
* 0 and getDeviceCount() - 1.
* @param _format An audio::format specifying the desired sample data format.
* @param _sampleRate The desired sample rate (sample frames per second).
* @param *_bufferFrames A pointer to a value indicating the desired
* @param _bufferFrames A pointer to a value indicating the desired
* internal buffer size in sample frames. The actual value
* used by the device is returned via the same pointer. A
* value of zero can be specified, in which case the lowest
@ -185,12 +193,12 @@ namespace airtaudio {
* when an error has occured.
*/
enum airtaudio::error openStream(airtaudio::StreamParameters *_outputParameters,
airtaudio::StreamParameters *_inputParameters,
enum audio::format _format,
uint32_t _sampleRate,
uint32_t *_bufferFrames,
airtaudio::AirTAudioCallback _callback,
airtaudio::StreamOptions *_options = nullptr);
airtaudio::StreamParameters *_inputParameters,
enum audio::format _format,
uint32_t _sampleRate,
uint32_t* _bufferFrames,
airtaudio::AirTAudioCallback _callback,
airtaudio::StreamOptions *_options = nullptr);
/**
* @brief A function that closes a stream and frees any associated stream memory.

View File

@ -14,12 +14,13 @@ namespace airtaudio {
*/
class StreamParameters {
public:
uint32_t deviceId; //!< Device index (0 to getDeviceCount() - 1).
int32_t deviceId; //!< Device index (-1 to getDeviceCount() - 1).
std::string deviceName; //!< name of the device (if deviceId==-1 this must not be == "", and the oposite ...)
uint32_t nChannels; //!< Number of channels.
uint32_t firstChannel; //!< First channel index on device (default = 0).
// Default constructor.
StreamParameters() :
deviceId(0),
deviceId(-1),
nChannels(0),
firstChannel(0) { }
};

View File

@ -12,6 +12,7 @@
#include <unistd.h>
#include <airtaudio/Interface.h>
#include <airtaudio/debug.h>
#include <etk/stdTools.h>
#include <limits.h>
#undef __class__
@ -62,7 +63,9 @@ airtaudio::api::Alsa::~Alsa() {
uint32_t airtaudio::api::Alsa::getDeviceCount() {
unsigned nDevices = 0;
int32_t result, subdevice, card;
int32_t result= -1;
int32_t subdevice = -1;
int32_t card = -1;
char name[64];
snd_ctl_t *handle;
// Count cards and devices
@ -96,8 +99,9 @@ nextcard:
return nDevices;
}
bool airtaudio::api::Alsa::getDeviceInfo(const std::string& _deviceName, airtaudio::DeviceInfo& _info) {
bool airtaudio::api::Alsa::getNamedDeviceInfoLocal(const std::string& _deviceName, airtaudio::DeviceInfo& _info, int32_t _cardId, int32_t _subdevice, int32_t _localDeviceId) {
int32_t result;
snd_ctl_t *chandle;
int32_t openMode = SND_PCM_ASYNC;
snd_pcm_stream_t stream;
snd_pcm_info_t *pcminfo;
@ -108,9 +112,18 @@ bool airtaudio::api::Alsa::getDeviceInfo(const std::string& _deviceName, airtaud
// First try for playback unless default _device (which has subdev -1)
stream = SND_PCM_STREAM_PLAYBACK;
snd_pcm_info_set_stream(pcminfo, stream);
/*
if (subdevice != -1) {
snd_pcm_info_set_device(pcminfo, subdevice);
std::vector<std::string> listElement = etk::split(_deviceName, ',');
if (listElement.size() == 0) {
ATA_ERROR("can not get control interface = '" << _deviceName << "' Can not plit at ',' ...");
return false;
}
result = snd_ctl_open(&chandle, listElement[0].c_str(), SND_CTL_NONBLOCK);
if (result < 0) {
ATA_ERROR("control open, card = " << listElement[0] << ", " << snd_strerror(result) << ".");
return false;
}
if (_subdevice != -1) {
snd_pcm_info_set_device(pcminfo, _subdevice);
snd_pcm_info_set_subdevice(pcminfo, 0);
result = snd_ctl_pcm_info(chandle, pcminfo);
if (result < 0) {
@ -118,7 +131,6 @@ bool airtaudio::api::Alsa::getDeviceInfo(const std::string& _deviceName, airtaud
goto captureProbe;
}
}
*/
result = snd_pcm_open(&phandle, _deviceName.c_str(), stream, openMode | SND_PCM_NONBLOCK);
if (result < 0) {
ATA_ERROR("snd_pcm_open error for device (" << _deviceName << "), " << snd_strerror(result) << ".");
@ -149,8 +161,7 @@ captureProbe:
stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_info_set_stream(pcminfo, stream);
// Now try for capture unless default device (with subdev = -1)
/*
if (subdevice != -1) {
if (_subdevice != -1) {
result = snd_ctl_pcm_info(chandle, pcminfo);
snd_ctl_close(chandle);
if (result < 0) {
@ -161,7 +172,6 @@ captureProbe:
goto probeParameters;
}
}
*/
result = snd_pcm_open(&phandle, _deviceName.c_str(), stream, openMode | SND_PCM_NONBLOCK);
if (result < 0) {
ATA_ERROR("snd_pcm_open error for device (" << _deviceName << "), " << snd_strerror(result) << ".");
@ -200,20 +210,18 @@ captureProbe:
_info.duplexChannels = (_info.outputChannels > _info.inputChannels) ? _info.inputChannels : _info.outputChannels;
}
// ALSA doesn't provide default devices so we'll use the first available one.
/*
if ( _name == 0
if ( _localDeviceId == 0
&& _info.outputChannels > 0) {
info.isDefaultOutput = true;
_info.isDefaultOutput = true;
}
if ( _device == 0
if ( _localDeviceId == 0
&& _info.inputChannels > 0) {
info.isDefaultInput = true;
_info.isDefaultInput = true;
}
*/
probeParameters:
// At this point, we just need to figure out the supported data
// formats and sample rates. We'll proceed by opening the device in
// formats and sample rates. We'll proceed by opening the device in
// the direction with the maximum number of channels, or playback if
// they are equal. This might limit our sample rate options, but so
// be it.
@ -286,14 +294,17 @@ probeParameters:
return false;
}
// Get the device name
/*
char *cardname;
result = snd_card_get_name(card, &cardname);
if (result >= 0) {
sprintf(name, "hw:%s,%d", cardname, subdevice);
if (_cardId != -1) {
char *cardname;
char name[1024];
result = snd_card_get_name(_cardId, &cardname);
if (result >= 0) {
sprintf(name, "hw:%s,%d", cardname, _subdevice);
}
_info.name = name;
} else {
_info.name = _deviceName;
}
*/
_info.name = _deviceName;
// That's all ... close the device and return
snd_pcm_close(phandle);
_info.probed = true;
@ -302,14 +313,18 @@ probeParameters:
airtaudio::DeviceInfo airtaudio::api::Alsa::getDeviceInfo(uint32_t _device) {
airtaudio::DeviceInfo info;
/*
ATA_WARNING("plop");
getDeviceInfo("hw:0,0,0", info);
info.display();
getDeviceInfo("hw:0,0,1", info);
info.display();
*/
info.probed = false;
unsigned nDevices = 0;
int32_t result, subdevice, card;
int32_t result = -1;
int32_t subdevice = -1;
int32_t card = -1;
char name[64];
snd_ctl_t *chandle;
// Count cards and devices
@ -354,12 +369,12 @@ airtaudio::DeviceInfo airtaudio::api::Alsa::getDeviceInfo(uint32_t _device) {
}
foundDevice:
snd_ctl_close(chandle);
// If a stream is already open, we cannot probe the stream devices.
// Thus, use the saved results.
if ( m_state != airtaudio::state_closed
&& ( m_device[0] == _device
|| m_device[1] == _device)) {
snd_ctl_close(chandle);
if (_device >= m_devices.size()) {
ATA_ERROR("device ID was not present before stream was opened.");
// TODO : return airtaudio::error_warning;
@ -367,204 +382,11 @@ foundDevice:
}
return m_devices[ _device ];
}
bool ret = airtaudio::api::Alsa::getDeviceInfo(name, info);
int32_t openMode = SND_PCM_ASYNC;
snd_pcm_stream_t stream;
snd_pcm_info_t *pcminfo;
snd_pcm_info_alloca(&pcminfo);
snd_pcm_t *phandle;
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(&params);
// First try for playback unless default _device (which has subdev -1)
stream = SND_PCM_STREAM_PLAYBACK;
snd_pcm_info_set_stream(pcminfo, stream);
if (subdevice != -1) {
snd_pcm_info_set_device(pcminfo, subdevice);
snd_pcm_info_set_subdevice(pcminfo, 0);
result = snd_ctl_pcm_info(chandle, pcminfo);
if (result < 0) {
// Device probably doesn't support playback.
goto captureProbe;
}
}
result = snd_pcm_open(&phandle, name, stream, openMode | SND_PCM_NONBLOCK);
if (result < 0) {
ATA_ERROR("snd_pcm_open error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
goto captureProbe;
}
// The device is open ... fill the parameter structure.
result = snd_pcm_hw_params_any(phandle, params);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("snd_pcm_hw_params error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
goto captureProbe;
}
// Get output channel information.
uint32_t value;
result = snd_pcm_hw_params_get_channels_max(params, &value);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error getting device (" << name << ") output channels, " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
goto captureProbe;
}
info.outputChannels = value;
snd_pcm_close(phandle);
captureProbe:
stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_info_set_stream(pcminfo, stream);
// Now try for capture unless default device (with subdev = -1)
if (subdevice != -1) {
result = snd_ctl_pcm_info(chandle, pcminfo);
snd_ctl_close(chandle);
if (result < 0) {
// Device probably doesn't support capture.
if (info.outputChannels == 0) {
return info;
}
goto probeParameters;
}
}
result = snd_pcm_open(&phandle, name, stream, openMode | SND_PCM_NONBLOCK);
if (result < 0) {
ATA_ERROR("snd_pcm_open error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
if (info.outputChannels == 0) {
return info;
}
goto probeParameters;
}
// The device is open ... fill the parameter structure.
result = snd_pcm_hw_params_any(phandle, params);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("snd_pcm_hw_params error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
if (info.outputChannels == 0) {
return info;
}
goto probeParameters;
}
result = snd_pcm_hw_params_get_channels_max(params, &value);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error getting device (" << name << ") input channels, " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
if (info.outputChannels == 0) {
return info;
}
goto probeParameters;
}
info.inputChannels = value;
snd_pcm_close(phandle);
// If device opens for both playback and capture, we determine the channels.
if (info.outputChannels > 0 && info.inputChannels > 0) {
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
}
// ALSA doesn't provide default devices so we'll use the first available one.
if (_device == 0 && info.outputChannels > 0) {
info.isDefaultOutput = true;
}
if (_device == 0 && info.inputChannels > 0) {
info.isDefaultInput = true;
}
probeParameters:
// At this point, we just need to figure out the supported data
// formats and sample rates. We'll proceed by opening the device in
// the direction with the maximum number of channels, or playback if
// they are equal. This might limit our sample rate options, but so
// be it.
if (info.outputChannels >= info.inputChannels) {
stream = SND_PCM_STREAM_PLAYBACK;
} else {
stream = SND_PCM_STREAM_CAPTURE;
}
snd_pcm_info_set_stream(pcminfo, stream);
result = snd_pcm_open(&phandle, name, stream, openMode | SND_PCM_NONBLOCK);
if (result < 0) {
ATA_ERROR("snd_pcm_open error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
bool ret = airtaudio::api::Alsa::getNamedDeviceInfoLocal(name, info, card, subdevice, _device);
if (ret == false) {
// TODO : ...
return info;
}
// The device is open ... fill the parameter structure.
result = snd_pcm_hw_params_any(phandle, params);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("snd_pcm_hw_params error for device (" << name << "), " << snd_strerror(result) << ".");
// TODO : Return airtaudio::error_warning;
return info;
}
// Test our discrete set of sample rate values.
info.sampleRates.clear();
#if __CPP_VERSION__ >= 2011
for (auto &it : airtaudio::genericSampleRate()) {
if (snd_pcm_hw_params_test_rate(phandle, params, it, 0) == 0) {
info.sampleRates.push_back(it);
}
}
#else
for (std::vector<uint32_t>::const_iterator it(airtaudio::genericSampleRate().begin());
it != airtaudio::genericSampleRate().end();
++it ) {
if (snd_pcm_hw_params_test_rate(phandle, params, *it, 0) == 0) {
info.sampleRates.push_back(*it);
}
}
#endif
if (info.sampleRates.size() == 0) {
snd_pcm_close(phandle);
ATA_ERROR("no supported sample rates found for device (" << name << ").");
// TODO : Return airtaudio::error_warning;
return info;
}
// Probe the supported data formats ... we don't care about endian-ness just yet
snd_pcm_format_t format;
info.nativeFormats.clear();
format = SND_PCM_FORMAT_S8;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_int8);
}
format = SND_PCM_FORMAT_S16;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_int16);
}
format = SND_PCM_FORMAT_S24;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_int24);
}
format = SND_PCM_FORMAT_S32;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_int32);
}
format = SND_PCM_FORMAT_FLOAT;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_float);
}
format = SND_PCM_FORMAT_FLOAT64;
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
info.nativeFormats.push_back(audio::format_double);
}
// Check that we have at least one supported format
if (info.nativeFormats.size() == 0) {
ATA_ERROR("pcm device (" << name << ") data format not supported by RtAudio.");
// TODO : Return airtaudio::error_warning;
return info;
}
// Get the device name
char *cardname;
result = snd_card_get_name(card, &cardname);
if (result >= 0) {
sprintf(name, "hw:%s,%d", cardname, subdevice);
}
info.name = name;
// That's all ... close the device and return
snd_pcm_close(phandle);
info.probed = true;
return info;
}
@ -616,14 +438,6 @@ bool airtaudio::api::Alsa::probeDeviceOpen(uint32_t _device,
snd_ctl_close(chandle);
snd_card_next(&card);
}
result = snd_ctl_open(&chandle, "default", SND_CTL_NONBLOCK);
if (result == 0) {
if (nDevices == _device) {
strcpy(name, "default");
goto foundDevice;
}
nDevices++;
}
if (nDevices == 0) {
// This should not happen because a check is made before this function is called.
ATA_ERROR("no devices found!");
@ -637,6 +451,23 @@ bool airtaudio::api::Alsa::probeDeviceOpen(uint32_t _device,
// NOTE : Find the device name : [ END ]
foundDevice:
return probeDeviceOpenName(name, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options);
}
bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
airtaudio::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
// I'm not using the "plug" interface ... too much inconsistent behavior.
unsigned nDevices = 0;
int32_t result, subdevice, card;
char name[64];
snd_ctl_t *chandle;
// The getDeviceInfo() function will not work for a device that is
// already open. Thus, we'll probe the system before opening a
// stream and save the results for use by getDeviceInfo().
@ -654,12 +485,12 @@ foundDevice:
}
snd_pcm_t *phandle;
int32_t openMode = SND_PCM_ASYNC;
result = snd_pcm_open(&phandle, name, stream, openMode);
result = snd_pcm_open(&phandle, _deviceName.c_str(), stream, openMode);
if (result < 0) {
if (_mode == airtaudio::mode_output) {
ATA_ERROR("pcm device (" << name << ") won't open for output.");
ATA_ERROR("pcm device (" << _deviceName << ") won't open for output.");
} else {
ATA_ERROR("pcm device (" << name << ") won't open for input.");
ATA_ERROR("pcm device (" << _deviceName << ") won't open for input.");
}
return false;
}
@ -669,7 +500,7 @@ foundDevice:
result = snd_pcm_hw_params_any(phandle, hw_params);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error getting pcm device (" << name << ") parameters, " << snd_strerror(result) << ".");
ATA_ERROR("error getting pcm device (" << _deviceName << ") parameters, " << snd_strerror(result) << ".");
return false;
}
// Open stream all time in interleave mode (by default): (open in non interleave if we have no choice
@ -682,7 +513,7 @@ foundDevice:
}
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting pcm device (" << name << ") access, " << snd_strerror(result) << ".");
ATA_ERROR("error setting pcm device (" << _deviceName << ") access, " << snd_strerror(result) << ".");
return false;
}
// Determine how to set the device format.
@ -706,14 +537,14 @@ foundDevice:
} else {
// If we get here, no supported format was found.
snd_pcm_close(phandle);
ATA_ERROR("pcm device " << _device << " data format not supported: " << _format);
ATA_ERROR("pcm device " << _deviceName << " data format not supported: " << _format);
// TODO : display list of all supported format ..
return false;
}
result = snd_pcm_hw_params_set_format(phandle, hw_params, deviceFormat);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting pcm device (" << name << ") data format, " << snd_strerror(result) << ".");
ATA_ERROR("error setting pcm device (" << _deviceName << ") data format, " << snd_strerror(result) << ".");
return false;
}
// Determine whether byte-swaping is necessary.
@ -724,7 +555,7 @@ foundDevice:
m_doByteSwap[modeToIdTable(_mode)] = true;
} else if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error getting pcm device (" << name << ") endian-ness, " << snd_strerror(result) << ".");
ATA_ERROR("error getting pcm device (" << _deviceName << ") endian-ness, " << snd_strerror(result) << ".");
return false;
}
}
@ -732,7 +563,7 @@ foundDevice:
result = snd_pcm_hw_params_set_rate_near(phandle, hw_params, (uint32_t*) &_sampleRate, 0);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting sample rate on device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error setting sample rate on device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
// Determine the number of channels for this device. We support a possible
@ -744,13 +575,13 @@ foundDevice:
if ( result < 0
|| deviceChannels < _channels + _firstChannel) {
snd_pcm_close(phandle);
ATA_ERROR("requested channel parameters not supported by device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("requested channel parameters not supported by device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
result = snd_pcm_hw_params_get_channels_min(hw_params, &value);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error getting minimum channels for device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error getting minimum channels for device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
deviceChannels = value;
@ -762,7 +593,7 @@ foundDevice:
result = snd_pcm_hw_params_set_channels(phandle, hw_params, deviceChannels);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting channels for device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error setting channels for device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
// Set the buffer (or period) size.
@ -771,7 +602,7 @@ foundDevice:
result = snd_pcm_hw_params_set_period_size_near(phandle, hw_params, &periodSize, &dir);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting period size for device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error setting period size for device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
*_bufferSize = periodSize;
@ -793,7 +624,7 @@ foundDevice:
result = snd_pcm_hw_params_set_periods_near(phandle, hw_params, &periods, &dir);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error setting periods for device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error setting periods for device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
// If attempting to setup a duplex stream, the bufferSize parameter
@ -802,7 +633,7 @@ foundDevice:
&& _mode == airtaudio::mode_input
&& *_bufferSize != m_bufferSize) {
snd_pcm_close(phandle);
ATA_ERROR("system error setting buffer size for duplex stream on device (" << name << ").");
ATA_ERROR("system error setting buffer size for duplex stream on device (" << _deviceName << ").");
return false;
}
m_bufferSize = *_bufferSize;
@ -819,7 +650,7 @@ foundDevice:
result = snd_pcm_hw_params(phandle, hw_params);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error installing hardware configuration on device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error installing hardware configuration on device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
// Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.
@ -841,7 +672,7 @@ foundDevice:
result = snd_pcm_sw_params(phandle, swParams);
if (result < 0) {
snd_pcm_close(phandle);
ATA_ERROR("error installing software configuration on device (" << name << "), " << snd_strerror(result) << ".");
ATA_ERROR("error installing software configuration on device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false;
}
// Set flags for buffer conversion
@ -893,7 +724,7 @@ foundDevice:
}
m_sampleRate = _sampleRate;
m_nBuffers = periods;
m_device[modeToIdTable(_mode)] = _device;
// TODO : m_device[modeToIdTable(_mode)] = _device;
m_state = airtaudio::state_stopped;
// Setup the buffer conversion information structure.
if (m_doConvertBuffer[modeToIdTable(_mode)]) {

View File

@ -21,7 +21,16 @@ namespace airtaudio {
return airtaudio::type_alsa;
}
uint32_t getDeviceCount();
bool getDeviceInfo(const std::string& _deviceName, airtaudio::DeviceInfo& _info);
private:
bool getNamedDeviceInfoLocal(const std::string& _deviceName,
airtaudio::DeviceInfo& _info,
int32_t _cardId=-1, // Alsa card ID
int32_t _subdevice=-1, // alsa subdevice ID
int32_t _localDeviceId=-1); // local ID of device fined
public:
bool getNamedDeviceInfo(const std::string& _deviceName, airtaudio::DeviceInfo& _info) {
return getNamedDeviceInfoLocal(_deviceName, _info);
}
airtaudio::DeviceInfo getDeviceInfo(uint32_t _device);
enum airtaudio::error closeStream();
enum airtaudio::error startStream();
@ -47,6 +56,15 @@ namespace airtaudio {
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
virtual bool probeDeviceOpenName(const std::string& _deviceName,
airtaudio::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
virtual std11::chrono::system_clock::time_point getStreamTime();
};
};