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
No related branches found
No related tags found
No related merge requests found
...@@ -45,7 +45,9 @@ struct PortAudioLayer::PortAudioLayerImpl ...@@ -45,7 +45,9 @@ struct PortAudioLayer::PortAudioLayerImpl
void terminate() const; void terminate() const;
void initStream(PortAudioLayer&); 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 indexIn_;
PaDeviceIndex indexOut_; PaDeviceIndex indexOut_;
...@@ -89,13 +91,13 @@ PortAudioLayer::PortAudioLayer(const AudioPreference& pref) ...@@ -89,13 +91,13 @@ PortAudioLayer::PortAudioLayer(const AudioPreference& pref)
std::vector<std::string> std::vector<std::string>
PortAudioLayer::getCaptureDeviceList() const PortAudioLayer::getCaptureDeviceList() const
{ {
return pimpl_->getDeviceByType(false); return pimpl_->getDeviceByType(DeviceType::CAPTURE);
} }
std::vector<std::string> std::vector<std::string>
PortAudioLayer::getPlaybackDeviceList() const PortAudioLayer::getPlaybackDeviceList() const
{ {
return pimpl_->getDeviceByType(true); return pimpl_->getDeviceByType(DeviceType::PLAYBACK);
} }
int int
...@@ -131,19 +133,20 @@ PortAudioLayer::getAudioDeviceName(int index, DeviceType type) const ...@@ -131,19 +133,20 @@ PortAudioLayer::getAudioDeviceName(int index, DeviceType type) const
int int
PortAudioLayer::getIndexCapture() const PortAudioLayer::getIndexCapture() const
{ {
return pimpl_->indexIn_; return pimpl_->getIndexByType(DeviceType::CAPTURE);
} }
int int
PortAudioLayer::getIndexPlayback() const PortAudioLayer::getIndexPlayback() const
{ {
return pimpl_->indexOut_; auto index = pimpl_->getIndexByType(DeviceType::PLAYBACK);
return index;
} }
int int
PortAudioLayer::getIndexRingtone() const PortAudioLayer::getIndexRingtone() const
{ {
return pimpl_->indexRing_; return pimpl_->getIndexByType(DeviceType::RINGTONE);
} }
void void
...@@ -195,31 +198,17 @@ PortAudioLayer::stopStream() ...@@ -195,31 +198,17 @@ PortAudioLayer::stopStream()
void void
PortAudioLayer::updatePreference(AudioPreference& preference, int index, DeviceType type) PortAudioLayer::updatePreference(AudioPreference& preference, int index, DeviceType type)
{ {
auto internalIndex = pimpl_->getInternalIndexByType(index, type);
switch (type) { switch (type) {
case DeviceType::PLAYBACK: case DeviceType::PLAYBACK:
{ preference.setAlsaCardout(internalIndex);
auto playbackList = pimpl_->getDeviceByType(true);
if (playbackList.size() > (size_t) index) {
auto realIdx = getAudioDeviceIndex(playbackList.at(index), type);
preference.setAlsaCardout(realIdx);
}
}
break; break;
case DeviceType::CAPTURE: case DeviceType::CAPTURE:
{ preference.setAlsaCardin(internalIndex);
auto captureList = pimpl_->getDeviceByType(false);
if (captureList.size() > (size_t) index) {
auto realIdx = getAudioDeviceIndex(captureList.at(index), type);
preference.setAlsaCardin(realIdx);
}
}
break; break;
case DeviceType::RINGTONE: case DeviceType::RINGTONE:
preference.setAlsaCardring(index); preference.setAlsaCardring(internalIndex);
break; break;
default: default:
break; break;
} }
...@@ -243,7 +232,7 @@ PortAudioLayer::PortAudioLayerImpl::~PortAudioLayerImpl() ...@@ -243,7 +232,7 @@ PortAudioLayer::PortAudioLayerImpl::~PortAudioLayerImpl()
} }
std::vector<std::string> std::vector<std::string>
PortAudioLayer::PortAudioLayerImpl::getDeviceByType(bool playback) const PortAudioLayer::PortAudioLayerImpl::getDeviceByType(DeviceType type) const
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
int numDevices = 0; int numDevices = 0;
...@@ -254,7 +243,7 @@ PortAudioLayer::PortAudioLayerImpl::getDeviceByType(bool playback) const ...@@ -254,7 +243,7 @@ PortAudioLayer::PortAudioLayerImpl::getDeviceByType(bool playback) const
else { else {
for (int i = 0; i < numDevices; i++) { for (int i = 0; i < numDevices; i++) {
const auto deviceInfo = Pa_GetDeviceInfo(i); const auto deviceInfo = Pa_GetDeviceInfo(i);
if (playback) { if (type == DeviceType::PLAYBACK) {
if (deviceInfo->maxOutputChannels > 0) if (deviceInfo->maxOutputChannels > 0)
ret.push_back(deviceInfo->name); ret.push_back(deviceInfo->name);
} else { } else {
...@@ -276,8 +265,16 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent) ...@@ -276,8 +265,16 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent)
terminate(); terminate();
} }
indexRing_ = indexOut_ = indexOut_ == paNoDevice ? Pa_GetDefaultOutputDevice() : indexOut_; auto numDevices = Pa_GetDeviceCount();
indexIn_ = indexIn_ == paNoDevice ? Pa_GetDefaultInputDevice() : indexIn_; if (indexOut_ <= paNoDevice || indexOut_ >= numDevices) {
indexRing_ = indexOut_ = Pa_GetDefaultOutputDevice();
} else {
indexRing_ = indexOut_;
}
if (indexIn_ <= paNoDevice || indexIn_ >= numDevices) {
indexIn_ = Pa_GetDefaultInputDevice();
}
if (indexOut_ != paNoDevice) { if (indexOut_ != paNoDevice) {
if (const auto outputDeviceInfo = Pa_GetDeviceInfo(indexOut_)) { if (const auto outputDeviceInfo = Pa_GetDeviceInfo(indexOut_)) {
...@@ -302,6 +299,54 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent) ...@@ -302,6 +299,54 @@ PortAudioLayer::PortAudioLayerImpl::init(PortAudioLayer& parent)
std::fill(std::begin(streams_), std::end(streams_), nullptr); 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 void
PortAudioLayer::PortAudioLayerImpl::terminate() const 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