Skip to content
Snippets Groups Projects
Commit 754f17df authored by Andreas Traczyk's avatar Andreas Traczyk Committed by Kateryna Kostiuk
Browse files

portaudio: expose seperate indexes for input/output devices

- Portaudio enumerates all input and output devices in a single
  list, but we split them up in the selection models in lrc. This
  patch exposes device indexes based on device type, converts them
  to an Portaudio index for saving to preferences.

- This patch also catches out of range values incoming from the
  saved preferences. This can happen if we decide to switch default
  host APIs in portaudio, or if someone's cat walks on their laptop
  while they edit their config.

Change-Id: I350f283588745fe4186ae11a8410d7c9374b72ee
parent 3dcfb098
Branches
No related tags found
No related merge requests found
......@@ -45,7 +45,9 @@ struct PortAudioLayer::PortAudioLayerImpl
void terminate() const;
void initStream(PortAudioLayer&);
std::vector<std::string> getDeviceByType(bool) const;
std::vector<std::string> getDeviceByType(DeviceType type) const;
int getIndexByType(DeviceType type);
int getInternalIndexByType(const int index, DeviceType type);
PaDeviceIndex indexIn_;
PaDeviceIndex indexOut_;
......@@ -89,13 +91,13 @@ PortAudioLayer::PortAudioLayer(const AudioPreference& pref)
std::vector<std::string>
PortAudioLayer::getCaptureDeviceList() const
{
return pimpl_->getDeviceByType(false);
return pimpl_->getDeviceByType(DeviceType::CAPTURE);
}
std::vector<std::string>
PortAudioLayer::getPlaybackDeviceList() const
{
return pimpl_->getDeviceByType(true);
return pimpl_->getDeviceByType(DeviceType::PLAYBACK);
}
int
......@@ -131,19 +133,20 @@ PortAudioLayer::getAudioDeviceName(int index, DeviceType type) const
int
PortAudioLayer::getIndexCapture() const
{
return pimpl_->indexIn_;
return pimpl_->getIndexByType(DeviceType::CAPTURE);
}
int
PortAudioLayer::getIndexPlayback() const
{
return pimpl_->indexOut_;
auto index = pimpl_->getIndexByType(DeviceType::PLAYBACK);
return index;
}
int
PortAudioLayer::getIndexRingtone() const
{
return pimpl_->indexRing_;
return pimpl_->getIndexByType(DeviceType::RINGTONE);
}
void
......@@ -195,33 +198,19 @@ PortAudioLayer::stopStream()
void
PortAudioLayer::updatePreference(AudioPreference& preference, int index, DeviceType type)
{
auto internalIndex = pimpl_->getInternalIndexByType(index, type);
switch (type) {
case DeviceType::PLAYBACK:
{
auto playbackList = pimpl_->getDeviceByType(true);
if (playbackList.size() > (size_t) index) {
auto realIdx = getAudioDeviceIndex(playbackList.at(index), type);
preference.setAlsaCardout(realIdx);
}
}
break;
preference.setAlsaCardout(internalIndex);
break;
case DeviceType::CAPTURE:
{
auto captureList = pimpl_->getDeviceByType(false);
if (captureList.size() > (size_t) index) {
auto realIdx = getAudioDeviceIndex(captureList.at(index), type);
preference.setAlsaCardin(realIdx);
}
}
break;
preference.setAlsaCardin(internalIndex);
break;
case DeviceType::RINGTONE:
preference.setAlsaCardring(index);
break;
preference.setAlsaCardring(internalIndex);
break;
default:
break;
break;
}
}
......@@ -243,7 +232,7 @@ PortAudioLayer::PortAudioLayerImpl::~PortAudioLayerImpl()
}
std::vector<std::string>
PortAudioLayer::PortAudioLayerImpl::getDeviceByType(bool playback) const
PortAudioLayer::PortAudioLayerImpl::getDeviceByType(DeviceType type) const
{
std::vector<std::string> ret;
int numDevices = 0;
......@@ -254,7 +243,7 @@ PortAudioLayer::PortAudioLayerImpl::getDeviceByType(bool playback) const
else {
for (int i = 0; i < numDevices; i++) {
const auto deviceInfo = Pa_GetDeviceInfo(i);
if (playback) {
if (type == DeviceType::PLAYBACK) {
if (deviceInfo->maxOutputChannels > 0)
ret.push_back(deviceInfo->name);
} else {
......@@ -276,8 +265,16 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent)
terminate();
}
indexRing_ = indexOut_ = indexOut_ == paNoDevice ? Pa_GetDefaultOutputDevice() : indexOut_;
indexIn_ = indexIn_ == paNoDevice ? Pa_GetDefaultInputDevice() : indexIn_;
auto numDevices = Pa_GetDeviceCount();
if (indexOut_ <= paNoDevice || indexOut_ >= numDevices) {
indexRing_ = indexOut_ = Pa_GetDefaultOutputDevice();
} else {
indexRing_ = indexOut_;
}
if (indexIn_ <= paNoDevice || indexIn_ >= numDevices) {
indexIn_ = Pa_GetDefaultInputDevice();
}
if (indexOut_ != paNoDevice) {
if (const auto outputDeviceInfo = Pa_GetDeviceInfo(indexOut_)) {
......@@ -302,6 +299,54 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent)
std::fill(std::begin(streams_), std::end(streams_), nullptr);
}
int
PortAudioLayer::PortAudioLayerImpl::getIndexByType(DeviceType type)
{
int index = indexRing_;
if (type == DeviceType::PLAYBACK) {
index = indexOut_;
} else if (type == DeviceType::CAPTURE) {
index = indexIn_;
}
auto deviceList = getDeviceByType(type);
if (!deviceList.size()) {
return paNoDevice;
}
const PaDeviceInfo *indexedDeviceInfo;
indexedDeviceInfo = Pa_GetDeviceInfo(index);
if (!indexedDeviceInfo) {
return paNoDevice;
}
for (int i = 0; i < deviceList.size(); ++i) {
if (deviceList.at(i) == indexedDeviceInfo->name) {
return i;
}
}
return paNoDevice;
}
int
PortAudioLayer::PortAudioLayerImpl::getInternalIndexByType(const int index, DeviceType type)
{
auto deviceList = getDeviceByType(type);
if (!deviceList.size() || index >= deviceList.size()) {
return paNoDevice;
}
for (int i = 0; i < Pa_GetDeviceCount(); i++) {
const auto deviceInfo = Pa_GetDeviceInfo(i);
if (deviceList.at(index) == deviceInfo->name) {
return i;
}
}
return paNoDevice;
}
void
PortAudioLayer::PortAudioLayerImpl::terminate() const
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment