From e6de495285952264e6067e7d22d6143bfc4947a6 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Thu, 26 Feb 2015 22:25:15 +0100 Subject: [PATCH] [DEV] add API to open stream with his name (alsa specific) --- airtaudio/Api.cpp | 63 +++++-- airtaudio/Api.h | 12 ++ airtaudio/Interface.cpp | 15 +- airtaudio/Interface.h | 22 ++- airtaudio/StreamParameters.h | 5 +- airtaudio/api/Alsa.cpp | 325 +++++++++-------------------------- airtaudio/api/Alsa.h | 20 ++- 7 files changed, 178 insertions(+), 284 deletions(-) diff --git a/airtaudio/Api.cpp b/airtaudio/Api.cpp index aca7ca8..6e18429 100644 --- a/airtaudio/Api.cpp +++ b/airtaudio/Api.cpp @@ -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(); diff --git a/airtaudio/Api.h b/airtaudio/Api.h index fb55320..2e87e25 100644 --- a/airtaudio/Api.h +++ b/airtaudio/Api.h @@ -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. */ diff --git a/airtaudio/Interface.cpp b/airtaudio/Interface.cpp index ec24bf3..bbd1878 100644 --- a/airtaudio/Interface.cpp +++ b/airtaudio/Interface.cpp @@ -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; } diff --git a/airtaudio/Interface.h b/airtaudio/Interface.h index 2096d2a..de8ea98 100644 --- a/airtaudio/Interface.h +++ b/airtaudio/Interface.h @@ -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. diff --git a/airtaudio/StreamParameters.h b/airtaudio/StreamParameters.h index e1fa9d8..e9317ca 100644 --- a/airtaudio/StreamParameters.h +++ b/airtaudio/StreamParameters.h @@ -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) { } }; diff --git a/airtaudio/api/Alsa.cpp b/airtaudio/api/Alsa.cpp index 75c5831..da044ac 100644 --- a/airtaudio/api/Alsa.cpp +++ b/airtaudio/api/Alsa.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #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 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(¶ms); - // 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::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)]) { diff --git a/airtaudio/api/Alsa.h b/airtaudio/api/Alsa.h index 2c11506..5c88307 100644 --- a/airtaudio/api/Alsa.h +++ b/airtaudio/api/Alsa.h @@ -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(); }; };