From e68953141016336cd8e571aa60034b422b92073f Mon Sep 17 00:00:00 2001 From: amerhifi Date: Mon, 16 Sep 2019 15:31:44 -0700 Subject: [PATCH] added unique identifier to device for comparison. Because a default device had a different name, but same underlying device. So comparing with device name is not necessarily the same device. Possibly fixed select issue with multiple devices same name --- interface/src/scripting/AudioDevices.cpp | 13 +-- libraries/audio-client/src/AudioClient.cpp | 87 ++++++++----------- libraries/audio-client/src/AudioClient.h | 6 +- .../audio-client/src/HifiAudioDeviceInfo.h | 17 ++-- .../audio-client/src/HifiAudioDeviceinfo.cpp | 9 +- 5 files changed, 62 insertions(+), 70 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index dbdd0c4852..7e31d36f7d 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -200,9 +200,10 @@ void AudioDeviceList::onDeviceChanged(const HifiAudioDeviceInfo& device, bool is for (auto i = 0; i < _devices.size(); ++i) { std::shared_ptr device = _devices[i]; bool& isSelected = isHMD ? device->selectedHMD : device->selectedDesktop; - if (isSelected && device->info != selectedDevice) { - isSelected = false; - } else if (device->info == selectedDevice) { + HifiAudioDeviceInfo devInfo = device->info; + isSelected = false; + + if (devInfo == selectedDevice) { isSelected = true; } } @@ -401,7 +402,7 @@ void AudioDevices::onContextChanged(const QString& context) { void AudioDevices::onDeviceSelected(QAudio::Mode mode, const HifiAudioDeviceInfo& device, const HifiAudioDeviceInfo& previousDevice, bool isHMD) { - QString deviceName = device.getDevice().isNull() ? QString() : device.deviceName(); + QString deviceName = device.deviceName(); auto& setting = getSetting(isHMD, mode); @@ -512,7 +513,7 @@ void AudioDevices::chooseInputDevice(const HifiAudioDeviceInfo& device, bool isH _requestedInputDevice = device; QMetaObject::invokeMethod(client, "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), - Q_ARG(const QAudioDeviceInfo&, device.getDevice())); + Q_ARG(const HifiAudioDeviceInfo&, device)); } else { //context is different. just save device in settings onDeviceSelected(QAudio::AudioInput, device, @@ -529,7 +530,7 @@ void AudioDevices::chooseOutputDevice(const HifiAudioDeviceInfo& device, bool is _requestedOutputDevice = device; QMetaObject::invokeMethod(client, "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioOutput), - Q_ARG(const QAudioDeviceInfo&, device.getDevice())); + Q_ARG(const HifiAudioDeviceInfo&, device)); } else { //context is different. just save device in settings onDeviceSelected(QAudio::AudioOutput, device, diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 8609b9585a..4f5edef1b8 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -90,7 +90,7 @@ using Mutex = std::mutex; using Lock = std::unique_lock; Mutex _deviceMutex; Mutex _recordMutex; -QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode); +HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode); // thread-safe QList getAvailableDevices(QAudio::Mode mode) { @@ -337,24 +337,22 @@ AudioClient::AudioClient() : this, &AudioClient::processReceivedSamples, Qt::DirectConnection); connect(this, &AudioClient::changeDevice, this, [=](const HifiAudioDeviceInfo& outputDeviceInfo) { qCDebug(audioclient)<< "got AudioClient::changeDevice signal, about to call switchOutputToAudioDevice() outputDeviceInfo: ["<< outputDeviceInfo.deviceName() << "]"; - switchOutputToAudioDevice(outputDeviceInfo.getDevice()); + switchOutputToAudioDevice(outputDeviceInfo); }); connect(&_receivedAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioClient::handleMismatchAudioFormat); - _defaultOutputDevice = HifiAudioDeviceInfo(); - _defaultOutputDevice.setDevice(defaultAudioDeviceForMode(QAudio::AudioOutput)); + _defaultOutputDevice = defaultAudioDeviceForMode(QAudio::AudioOutput); _defaultOutputDevice.setDeviceName("Default audio (recommended)"); _defaultOutputDevice.setIsDefault(true); _defaultOutputDevice.setMode(QAudio::AudioOutput); - _defaultInputDevice = HifiAudioDeviceInfo(); - _defaultInputDevice.setDevice(defaultAudioDeviceForMode(QAudio::AudioInput)); + _defaultInputDevice = defaultAudioDeviceForMode(QAudio::AudioInput); _defaultInputDevice.setDeviceName("Default microphone (recommended)"); _defaultInputDevice.setIsDefault(true); - _defaultInputDevice.setMode(QAudio::AudioOutput); + _defaultInputDevice.setMode(QAudio::AudioInput); // initialize wasapi; if getAvailableDevices is called from the CheckDevicesThread before this, it will crash @@ -459,30 +457,14 @@ void AudioClient::setAudioPaused(bool pause) { } } -void AudioClient::setDefaultDevice(QList& devices ,QAudio::Mode mode) { - QAudioDeviceInfo defDevice = defaultAudioDeviceForMode(mode); - for (auto& device : devices) { - if (device.getDevice() == defDevice) { - if (!device.isDefault()) { - device.setIsDefault(true); - } - } else { - if (device.isDefault()) { - device.setIsDefault(false); - } - } - } -} - -QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { - QAudioDeviceInfo result; +HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { + HifiAudioDeviceInfo result; foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) { - result = audioDevice.getDevice(); + result = audioDevice; break; } } - return result; } @@ -530,7 +512,7 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) { #endif -QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { +HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #ifdef __APPLE__ if (getAvailableDevices(mode).size() > 1) { AudioDeviceID defaultDeviceID = 0; @@ -562,7 +544,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { if (!getPropertyError && propertySize) { // find a device in the list that matches the name we have and return it - foreach (QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { + foreach (AudioDeviceInfo audioDevice, getAvailableDevices(mode)) { if (audioDevice.deviceName() == CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman)) { return audioDevice; } @@ -634,7 +616,8 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { } #endif // fallback for failed lookup is the default device - return (mode == QAudio::AudioInput) ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice(); + return (mode == QAudio::AudioInput) ? HifiAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice(), false, QAudio::AudioInput) : + HifiAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice(), false, QAudio::AudioOutput); } bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) { @@ -801,22 +784,22 @@ void AudioClient::start() { _desiredOutputFormat = _desiredInputFormat; _desiredOutputFormat.setChannelCount(OUTPUT_CHANNEL_COUNT); - QAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput); + HifiAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput); qCDebug(audioclient) << "The default audio input device is" << inputDeviceInfo.deviceName(); bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo); - QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); + HifiAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); qCDebug(audioclient) << "The default audio output device is" << outputDeviceInfo.deviceName(); bool outputFormatSupported = switchOutputToAudioDevice(outputDeviceInfo); if (!inputFormatSupported) { qCDebug(audioclient) << "Unable to set up audio input because of a problem with input format."; - qCDebug(audioclient) << "The closest format available is" << inputDeviceInfo.nearestFormat(_desiredInputFormat); + qCDebug(audioclient) << "The closest format available is" << inputDeviceInfo.getDevice().nearestFormat(_desiredInputFormat); } if (!outputFormatSupported) { qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format."; - qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat); + qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.getDevice().nearestFormat(_desiredOutputFormat); } #if defined(Q_OS_ANDROID) connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout); @@ -826,10 +809,10 @@ void AudioClient::start() { void AudioClient::stop() { qCDebug(audioclient) << "AudioClient::stop(), requesting switchInputToAudioDevice() to shut down"; - switchInputToAudioDevice(QAudioDeviceInfo(), true); + switchInputToAudioDevice(HifiAudioDeviceInfo(), true); qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down"; - switchOutputToAudioDevice(QAudioDeviceInfo(), true); + switchOutputToAudioDevice(HifiAudioDeviceInfo(), true); // Stop triggering the checks QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr); @@ -1021,11 +1004,11 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) { } -bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo) { +bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo) { auto device = deviceInfo; - if (device.isNull()) { - device = defaultAudioDeviceForMode(mode); + if (device.getDevice().isNull()) { + device=defaultAudioDeviceForMode(mode); } if (mode == QAudio::AudioInput) { @@ -1799,7 +1782,7 @@ bool AudioClient::setIsStereoInput(bool isStereoInput) { qCDebug(audioclient) << "Reset Codec:" << _selectedCodecName << "isStereoInput:" << _isStereoInput; // restart the input device - switchInputToAudioDevice(_inputDeviceInfo.getDevice()); + switchInputToAudioDevice(_inputDeviceInfo); emit isStereoInputChanged(_isStereoInput); } @@ -1841,10 +1824,10 @@ void AudioClient::outputFormatChanged() { _receivedAudioStream.outputFormatChanged(_outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT); } -bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) { +bool AudioClient::switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) { Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread"); - qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]"; + qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.getDevice().deviceName() << "]"; bool supportedFormat = false; // NOTE: device start() uses the Qt internal device list @@ -1897,13 +1880,12 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf return true; } - if (!inputDeviceInfo.isNull()) { + if (!inputDeviceInfo.getDevice().isNull()) { qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; - _inputDeviceInfo = HifiAudioDeviceInfo(); - _inputDeviceInfo.setDevice(inputDeviceInfo); + _inputDeviceInfo = inputDeviceInfo; emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo); - if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { + if (adjustedFormatForAudioDevice(inputDeviceInfo.getDevice(), _desiredInputFormat, _inputFormat)) { qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat; // we've got the best we can get for input @@ -1928,7 +1910,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf // if the user wants stereo but this device can't provide then bail if (!_isStereoInput || _inputFormat.channelCount() == 2) { - _audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this); + _audioInput = new QAudioInput(inputDeviceInfo.getDevice(), _inputFormat, this); _numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat); _audioInput->setBufferSize(_numInputCallbackBytes); // different audio input devices may have different volumes @@ -2070,7 +2052,7 @@ void AudioClient::outputNotify() { } } -bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) { +bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) { Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread"); qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]"; @@ -2106,7 +2088,6 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI delete[] _localOutputMixBuffer; _localOutputMixBuffer = NULL; - //ctor call needed? _outputDeviceInfo = HifiAudioDeviceInfo(); _outputDeviceInfo.setDevice(QAudioDeviceInfo()); } @@ -2132,12 +2113,12 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI return true; } - if (!outputDeviceInfo.isNull()) { + if (!outputDeviceInfo.getDevice().isNull()) { qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; - _outputDeviceInfo.setDevice(outputDeviceInfo); + _outputDeviceInfo = outputDeviceInfo; emit deviceChanged(QAudio::AudioOutput, _outputDeviceInfo); - if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { + if (adjustedFormatForAudioDevice(outputDeviceInfo.getDevice(), _desiredOutputFormat, _outputFormat)) { qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat; // we've got the best we can get for input @@ -2159,7 +2140,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI outputFormatChanged(); // setup our general output device for audio-mixer audio - _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); + _audioOutput = new QAudioOutput(outputDeviceInfo.getDevice(), _outputFormat, this); int deviceChannelCount = _outputFormat.channelCount(); int frameSize = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * deviceChannelCount * _outputFormat.sampleRate()) / _desiredOutputFormat.sampleRate(); @@ -2211,7 +2192,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI localAudioLock.unlock(); // setup a loopback audio output device - _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); + _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo.getDevice(), _outputFormat, this); _timeSinceLastReceived.start(); diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index fabf83c53f..bbc22ba93d 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -236,7 +236,7 @@ public slots: bool shouldLoopbackInjectors() override { return _shouldEchoToServer; } // calling with a null QAudioDevice will use the system default - bool switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo = QAudioDeviceInfo()); + bool switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo = HifiAudioDeviceInfo()); bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName); // Qt opensles plugin is not able to detect when the headset is plugged in @@ -438,8 +438,8 @@ private: void processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate); #endif - bool switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false); - bool switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false); + bool switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false); + bool switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false); // Callback acceleration dependent calculations int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const; diff --git a/libraries/audio-client/src/HifiAudioDeviceInfo.h b/libraries/audio-client/src/HifiAudioDeviceInfo.h index d2a349ed8c..e044562a35 100644 --- a/libraries/audio-client/src/HifiAudioDeviceInfo.h +++ b/libraries/audio-client/src/HifiAudioDeviceInfo.h @@ -1,5 +1,6 @@ #ifndef hifi_audiodeviceinfo_h #define hifi_audiodeviceinfo_h +#pragma once #include #include @@ -14,26 +15,29 @@ public: HifiAudioDeviceInfo(const HifiAudioDeviceInfo &deviceInfo){ _audioDeviceInfo = deviceInfo.getDevice(); _mode = deviceInfo.getMode(); - _deviceName = deviceInfo.deviceName(); _isDefault = deviceInfo.isDefault(); + + setDeviceName(deviceInfo.deviceName()); } HifiAudioDeviceInfo(QAudioDeviceInfo deviceInfo, bool isDefault, QAudio::Mode mode) : _isDefault(isDefault), _mode(mode), - _audioDeviceInfo(deviceInfo), - _deviceName(deviceInfo.deviceName()){ + _audioDeviceInfo(deviceInfo){ + + setDeviceName(deviceInfo.deviceName()); } void setMode(QAudio::Mode mode) { _mode = mode; } void setIsDefault(bool isDefault = false) { _isDefault = isDefault; } - void setDeviceName(QString name) { _deviceName = name; + setId(name); } - void setDevice(QAudioDeviceInfo devInfo); - + void setId(QString name); + + QString getId() const { return _uniqueId; } QAudioDeviceInfo getDevice() const { return _audioDeviceInfo; } QString deviceName() const { return _deviceName; } bool isDefault() const { return _isDefault; } @@ -48,6 +52,7 @@ private: QString _deviceName{ "" }; bool _isDefault { false }; QAudio::Mode _mode { QAudio::AudioInput }; + QString _uniqueId; }; #endif \ No newline at end of file diff --git a/libraries/audio-client/src/HifiAudioDeviceinfo.cpp b/libraries/audio-client/src/HifiAudioDeviceinfo.cpp index 91a6324c26..0c677a2027 100644 --- a/libraries/audio-client/src/HifiAudioDeviceinfo.cpp +++ b/libraries/audio-client/src/HifiAudioDeviceinfo.cpp @@ -1,4 +1,5 @@ #include "HifiAudioDeviceInfo.h" +#include void HifiAudioDeviceInfo::setDevice(QAudioDeviceInfo devInfo) { _audioDeviceInfo = devInfo; @@ -9,14 +10,18 @@ HifiAudioDeviceInfo& HifiAudioDeviceInfo::operator=(const HifiAudioDeviceInfo& o _deviceName = other.deviceName(); _mode = other.getMode(); _isDefault = other.isDefault(); + _uniqueId = other.getId(); return *this; } bool HifiAudioDeviceInfo::operator==(const HifiAudioDeviceInfo& rhs) const { - return _audioDeviceInfo == rhs.getDevice(); + return _audioDeviceInfo == rhs.getDevice() && getId() == rhs.getId(); } bool HifiAudioDeviceInfo::operator!=(const HifiAudioDeviceInfo& rhs) const { - return _audioDeviceInfo != rhs.getDevice(); + return _audioDeviceInfo != rhs.getDevice() && getId() != rhs.getId(); } +void HifiAudioDeviceInfo::setId(QString name) { + _uniqueId=QString(QCryptographicHash::hash(name.toUtf8().constData(), QCryptographicHash::Md5).toHex()); +}