diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index fccba12a8a..eef339b854 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -375,14 +375,14 @@ Rectangle { x: margins.paddings interactive: false; height: contentHeight; - spacing: 4; + clip: true; model: AudioScriptingInterface.devices.input; delegate: Item { width: rightMostInputLevelPos - margins.paddings*2 - height: margins.sizeCheckBox > checkBoxInput.implicitHeight ? - margins.sizeCheckBox : checkBoxInput.implicitHeight - + height: ((type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)) ? + (margins.sizeCheckBox > checkBoxInput.implicitHeight ? margins.sizeCheckBox + 4 : checkBoxInput.implicitHeight + 4) : 0 + visible: (type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1) AudioControls.CheckBox { id: checkBoxInput anchors.left: parent.left @@ -470,13 +470,13 @@ Rectangle { height: contentHeight; anchors.top: outputDeviceHeader.bottom; anchors.topMargin: 10; - spacing: 4; clip: true; model: AudioScriptingInterface.devices.output; delegate: Item { width: rightMostInputLevelPos - height: margins.sizeCheckBox > checkBoxOutput.implicitHeight ? - margins.sizeCheckBox : checkBoxOutput.implicitHeight + height: ((type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)) ? + (margins.sizeCheckBox > checkBoxOutput.implicitHeight ? margins.sizeCheckBox + 4 : checkBoxOutput.implicitHeight + 4) : 0 + visible: (type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1) AudioControls.CheckBox { id: checkBoxOutput diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 76c871fa5c..688b4df8cd 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include "Application.h" @@ -68,6 +69,27 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) { return deviceName; } +static void checkHmdDefaultsChange(QAudio::Mode mode) { + QString name; + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getAllDisplayPlugins()) { + if (displayPlugin && displayPlugin->isHmd()) { + if (mode == QAudio::AudioInput) { + name = displayPlugin->getPreferredAudioInDevice(); + } else { + name = displayPlugin->getPreferredAudioOutDevice(); + } + break; + } + } + + if (!name.isEmpty()) { + auto client = DependencyManager::get().data(); + QMetaObject::invokeMethod(client, "setHmdAudioName", + Q_ARG(QAudio::Mode, mode), + Q_ARG(const QString&, name)); + } +} + Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled }; AudioDeviceList::AudioDeviceList(QAudio::Mode mode) : _mode(mode) { @@ -256,13 +278,15 @@ std::shared_ptr getSimilarDevice(const QString& deviceNa return devices[minDistanceIndex]; } -void AudioDeviceList::onDevicesChanged(const QList& devices) { + +void AudioDeviceList::onDevicesChanged(QAudio::Mode mode, const QList& devices) { beginResetModel(); QList> newDevices; bool hmdIsSelected = false; bool desktopIsSelected = false; - + + checkHmdDefaultsChange(mode); if (!_backupSelectedDesktopDeviceName.isEmpty() && !_backupSelectedHMDDeviceName.isEmpty()) { foreach(const HifiAudioDeviceInfo& deviceInfo, devices) { for (bool isHMD : {false, true}) { @@ -275,7 +299,6 @@ void AudioDeviceList::onDevicesChanged(const QList& devices _selectedDesktopDevice = deviceInfo; backupSelectedDeviceName.clear(); } - } } } @@ -417,6 +440,9 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { connect(client, &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection); connect(client, &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection); connect(client, &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection); + + checkHmdDefaultsChange(QAudio::AudioInput); + checkHmdDefaultsChange(QAudio::AudioOutput); _inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput), contextIsHMD); _outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD); @@ -425,9 +451,11 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { const QList& devicesInput = client->getAudioDevices(QAudio::AudioInput); const QList& devicesOutput = client->getAudioDevices(QAudio::AudioOutput); - //setup devices - _inputs.onDevicesChanged(devicesInput); - _outputs.onDevicesChanged(devicesOutput); + if (devicesInput.size() > 0 && devicesOutput.size() > 0) { + //setup devices + _inputs.onDevicesChanged(QAudio::AudioInput, devicesInput); + _outputs.onDevicesChanged(QAudio::AudioOutput, devicesOutput); + } } AudioDevices::~AudioDevices() {} @@ -526,14 +554,14 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList& devices); + void onDevicesChanged(QAudio::Mode mode, const QList& devices); protected: friend class AudioDevices; diff --git a/libraries/audio-client/CMakeLists.txt b/libraries/audio-client/CMakeLists.txt index e1d90334ff..6b88292dd4 100644 --- a/libraries/audio-client/CMakeLists.txt +++ b/libraries/audio-client/CMakeLists.txt @@ -6,7 +6,6 @@ setup_hifi_library(Network Multimedia ${PLATFORM_QT_COMPONENTS}) link_hifi_libraries(audio plugins) include_hifi_library_headers(shared) include_hifi_library_headers(networking) -include_hifi_library_headers(gpu) if (ANDROID) else () diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 9f28a61ed8..d8741e4aa7 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include "AudioClientLogging.h" #include "AudioLogging.h" @@ -83,24 +82,32 @@ Mutex _recordMutex; QString defaultAudioDeviceName(QAudio::Mode mode); +void AudioClient::setHmdAudioName(QAudio::Mode mode, const QString& name) { + QWriteLocker lock(&_hmdNameLock); + if (mode == QAudio::AudioInput) { + _hmdInputName = name; + } else { + _hmdOutputName = name; + } +} + // thread-safe -QList getAvailableDevices(QAudio::Mode mode) { +QList getAvailableDevices(QAudio::Mode mode, const QString& hmdName) { //get hmd device name prior to locking device mutex. in case of shutdown, this thread will be locked and audio client //cannot properly shut down. - QString hmdDeviceName = QString(); QString defDeviceName = defaultAudioDeviceName(mode); // NOTE: availableDevices() clobbers the Qt internal device list Lock lock(_deviceMutex); auto devices = QAudioDeviceInfo::availableDevices(mode); - + HifiAudioDeviceInfo defaultDesktopDevice; QList newDevices; for (auto& device : devices) { newDevices.push_back(HifiAudioDeviceInfo(device, false, mode)); if (device.deviceName() == defDeviceName.trimmed()) { defaultDesktopDevice = HifiAudioDeviceInfo(device, true, mode, HifiAudioDeviceInfo::desktop); - } + } } if (defaultDesktopDevice.getDevice().isNull()) { @@ -109,11 +116,11 @@ QList getAvailableDevices(QAudio::Mode mode) { defaultDesktopDevice = HifiAudioDeviceInfo(devices.first(), true, mode, HifiAudioDeviceInfo::desktop); } newDevices.push_front(defaultDesktopDevice); - - if (!hmdDeviceName.isNull() && !hmdDeviceName.isEmpty()) { + + if (!hmdName.isNull()) { HifiAudioDeviceInfo hmdDevice; foreach(auto device, newDevices) { - if (device.getDevice().deviceName() == hmdDeviceName) { + if (device.getDevice().deviceName() == hmdName) { hmdDevice = HifiAudioDeviceInfo(device.getDevice(), true, mode, HifiAudioDeviceInfo::hmd); break; } @@ -135,9 +142,17 @@ void AudioClient::checkDevices() { return; } - auto inputDevices = getAvailableDevices(QAudio::AudioInput); - auto outputDevices = getAvailableDevices(QAudio::AudioOutput); - + QString hmdInputName; + QString hmdOutputName; + { + QReadLocker readLock(&_hmdNameLock); + hmdInputName = _hmdInputName; + hmdOutputName = _hmdOutputName; + } + + auto inputDevices = getAvailableDevices(QAudio::AudioInput, hmdInputName); + auto outputDevices = getAvailableDevices(QAudio::AudioOutput, hmdOutputName); + checkDefaultChanges(inputDevices); checkDefaultChanges(outputDevices); @@ -320,10 +335,12 @@ AudioClient::AudioClient() { connect(&_receivedAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioClient::handleMismatchAudioFormat); - // initialize wasapi; if getAvailableDevices is called from the CheckDevicesThread before this, it will crash - getAvailableDevices(QAudio::AudioInput); - getAvailableDevices(QAudio::AudioOutput); - + { + QReadLocker readLock(&_hmdNameLock); + // initialize wasapi; if getAvailableDevices is called from the CheckDevicesThread before this, it will crash + getAvailableDevices(QAudio::AudioInput, _hmdInputName); + getAvailableDevices(QAudio::AudioOutput, _hmdOutputName); + } // start a thread to detect any device changes _checkDevicesTimer = new QTimer(this); const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; @@ -422,9 +439,9 @@ void AudioClient::setAudioPaused(bool pause) { } } -HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName, bool isHmd=false) { +HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName, const QString& hmdName, bool isHmd=false) { HifiAudioDeviceInfo result; - foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { + foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode,hmdName)) { if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) { if ((!isHmd && audioDevice.getDeviceType() != HifiAudioDeviceInfo::hmd) || (isHmd && audioDevice.getDeviceType() != HifiAudioDeviceInfo::desktop)) { result = audioDevice; @@ -479,7 +496,7 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) { #endif -HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { +HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode, const QString& hmdName) { QString deviceName = defaultAudioDeviceName(mode); #if defined (Q_OS_ANDROID) if (mode == QAudio::AudioInput) { @@ -495,7 +512,7 @@ HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { } } #endif - return getNamedAudioDeviceForMode(mode, deviceName); + return getNamedAudioDeviceForMode(mode, deviceName, hmdName); } QString defaultAudioDeviceName(QAudio::Mode mode) { @@ -601,7 +618,9 @@ QString defaultAudioDeviceName(QAudio::Mode mode) { } bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) { - return (getNamedAudioDeviceForMode(mode, deviceName).deviceName() == deviceName); + QReadLocker readLock(&_hmdNameLock); + QString hmdName = mode == QAudio::AudioInput ? _hmdInputName : _hmdOutputName; + return (getNamedAudioDeviceForMode(mode, deviceName, hmdName).deviceName() == deviceName); } @@ -763,24 +782,16 @@ void AudioClient::start() { _desiredOutputFormat = _desiredInputFormat; _desiredOutputFormat.setChannelCount(OUTPUT_CHANNEL_COUNT); - - HifiAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput); - qCDebug(audioclient) << "The default audio input device is" << inputDeviceInfo.deviceName(); - bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo); - - 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.getDevice().nearestFormat(_desiredInputFormat); + + QString inputName; + QString outputName; + { + QReadLocker readLock(&_hmdNameLock); + inputName = _hmdInputName; + outputName = _hmdOutputName; } - 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.getDevice().nearestFormat(_desiredOutputFormat); - } + #if defined(Q_OS_ANDROID) connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout); _checkInputTimer.start(CHECK_INPUT_READS_MSECS); @@ -1007,7 +1018,12 @@ bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo } bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QString& deviceName, bool isHmd) { - return switchAudioDevice(mode, getNamedAudioDeviceForMode(mode, deviceName, isHmd)); + QString hmdName; + { + QReadLocker readLock(&_hmdNameLock); + hmdName = mode == QAudio::AudioInput ? _hmdInputName : _hmdOutputName; + } + return switchAudioDevice(mode, getNamedAudioDeviceForMode(mode, deviceName, hmdName, isHmd)); } void AudioClient::configureReverb() { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index ce63c43cff..dafa81081c 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -243,6 +243,7 @@ public slots: // calling with a null QAudioDevice will use the system default bool switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo = HifiAudioDeviceInfo()); bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName, bool isHmd); + void setHmdAudioName(QAudio::Mode mode, const QString& name); // Qt opensles plugin is not able to detect when the headset is plugged in void setHeadsetPluggedIn(bool pluggedIn); @@ -481,6 +482,9 @@ private: QList _inputDevices; QList _outputDevices; + QString _hmdInputName { QString() }; + QString _hmdOutputName{ QString() }; + AudioFileWav _audioFileWav; bool _hasReceivedFirstPacket { false }; @@ -505,6 +509,7 @@ private: AudioSolo _solo; + QReadWriteLock _hmdNameLock; Mutex _checkDevicesMutex; QTimer* _checkDevicesTimer { nullptr }; Mutex _checkPeakValuesMutex; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 660159d9bd..784de6bdea 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -224,13 +224,7 @@ const OculusPlatformPluginPointer PluginManager::getOculusPlatformPlugin() { } DisplayPluginList PluginManager::getAllDisplayPlugins() { - if (thread() != QThread::currentThread()) { - DisplayPluginList list; - QMetaObject::invokeMethod(this, "getAllDisplayPlugins", Qt::BlockingQueuedConnection, Q_RETURN_ARG(DisplayPluginList, list)); - return list; - } else { - return _displayPlugins; - } + return _displayPlugins; } const DisplayPluginList& PluginManager::getDisplayPlugins() {