expose Audio.devices.input/output

This commit is contained in:
Zach Pomerantz 2017-05-31 19:39:53 -04:00
parent 4a3f2e1d09
commit 954e4979f8
8 changed files with 322 additions and 79 deletions

View file

@ -13,6 +13,7 @@
#define hifi_scripting_Audio_h #define hifi_scripting_Audio_h
#include "AudioScriptingInterface.h" #include "AudioScriptingInterface.h"
#include "AudioDevices.h"
namespace scripting { namespace scripting {
@ -22,14 +23,21 @@ class Audio : public AudioScriptingInterface {
// TODO: Q_PROPERTY(bool mute) // TODO: Q_PROPERTY(bool mute)
// TODO: Q_PROPERTY(bool noiseReduction) // TODO: Q_PROPERTY(bool noiseReduction)
// TODO: Q_PROPERTY(bool reverb)
// TODO: Q_PROPERTY(float inputVolume)
// TODO: Q_PROPERTY(bool showMicLevel) // TODO: Q_PROPERTY(bool showMicLevel)
// TODO: Q_PROPERTY(? devices) // TODO: Q_PROPERTY(QString context)
Q_PROPERTY(AudioDevices* devices READ getDevices)
public: public:
virtual ~Audio() {} virtual ~Audio() {}
protected: protected:
Audio() {} Audio() {}
private:
AudioDevices* getDevices() { return &_devices; }
AudioDevices _devices;
}; };
}; };

View file

@ -10,6 +10,7 @@
// //
#include "AudioClient.h" #include "AudioClient.h"
/*
#include "AudioDeviceScriptingInterface.h" #include "AudioDeviceScriptingInterface.h"
#include "SettingsScriptingInterface.h" #include "SettingsScriptingInterface.h"
@ -269,3 +270,4 @@ void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString& name, QAu
} }
} }
} }
*/

View file

@ -12,6 +12,7 @@
#ifndef hifi_AudioDeviceScriptingInterface_h #ifndef hifi_AudioDeviceScriptingInterface_h
#define hifi_AudioDeviceScriptingInterface_h #define hifi_AudioDeviceScriptingInterface_h
/*
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QVector> #include <QVector>
@ -103,5 +104,6 @@ private:
QString _currentInputDevice; QString _currentInputDevice;
QString _currentOutputDevice; QString _currentOutputDevice;
}; };
*/
#endif // hifi_AudioDeviceScriptingInterface_h #endif // hifi_AudioDeviceScriptingInterface_h

View file

@ -0,0 +1,146 @@
//
// AudioDevices.cpp
// interface/src/scripting
//
// Created by Zach Pomerantz on 28/5/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AudioDevices.h"
#include "AudioClient.h"
using namespace scripting;
QHash<int, QByteArray> AudioDeviceList::_roles {
{ Qt::DisplayRole, "display" },
{ Qt::CheckStateRole, "selected" }
};
Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled };
AudioDeviceList::AudioDeviceList(QAudio::Mode mode) : _mode(mode) {
}
int AudioDeviceList::rowCount(const QModelIndex& parent) const {
Q_UNUSED(parent);
return _devices.size();
}
QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
if (!index.isValid() || index.row() >= _devices.size()) {
return QVariant();
}
if (role == Qt::DisplayRole) {
return _devices.at(index.row()).name;
} else if (role == Qt::CheckStateRole) {
return _devices.at(index.row()).selected;
} else {
return QVariant();
}
}
QHash<int, QByteArray> AudioDeviceList::roleNames() const {
return _roles;
}
Qt::ItemFlags AudioDeviceList::flags(const QModelIndex& index) const {
return _flags;
}
bool AudioDeviceList::setData(const QModelIndex& index, const QVariant &value, int role) {
if (!index.isValid() || index.row() >= _devices.size()) {
return false;
}
bool success = false;
if (role == Qt::CheckStateRole) {
auto selected = value.toBool();
auto& device = _devices[index.row()];
// only allow switching to a new device, not deactivating an in-use device
if (selected
// skip if already selected
&& selected != device.selected) {
auto client = DependencyManager::get<AudioClient>();
bool success;
QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, success),
Q_ARG(QAudio::Mode, _mode),
Q_ARG(const QAudioDeviceInfo&, device.info));
if (success) {
device.selected = true;
emit dataChanged(index, index, { Qt::CheckStateRole });
}
}
}
return success;
}
void AudioDeviceList::setDevice(const QAudioDeviceInfo& device) {
_selectedDevice = device;
for (auto i = 0; i < _devices.size(); ++i) {
AudioDevice& device = _devices[i];
if (device.selected && device.info != _selectedDevice) {
device.selected = false;
auto index = createIndex(i , 0);
emit dataChanged(index, index, { Qt::CheckStateRole });
} else if (!device.selected && device.info == _selectedDevice) {
device.selected = true;
auto index = createIndex(i , 0);
emit dataChanged(index, index, { Qt::CheckStateRole });
}
}
}
void AudioDeviceList::populate(const QList<QAudioDeviceInfo>& devices) {
beginResetModel();
_devices.clear();
foreach(const QAudioDeviceInfo& deviceInfo, devices) {
AudioDevice device;
device.info = deviceInfo;
device.name = device.info.deviceName();
device.selected = (device.info == _selectedDevice);
_devices.push_back(device);
}
endResetModel();
}
AudioDevices::AudioDevices() {
auto client = DependencyManager::get<AudioClient>();
// connections are made after client is initialized, so we must also fetch the devices
connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection);
_inputs.setDevice(client->getActiveAudioDevice(QAudio::AudioInput));
_outputs.setDevice(client->getActiveAudioDevice(QAudio::AudioOutput));
connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection);
_inputs.populate(client->getAudioDevices(QAudio::AudioInput));
_outputs.populate(client->getAudioDevices(QAudio::AudioOutput));
}
void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device) {
if (mode == QAudio::AudioInput) {
_inputs.setDevice(device);
} else { // if (mode == QAudio::AudioOutput)
_outputs.setDevice(device);
}
}
void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices) {
if (mode == QAudio::AudioInput) {
_inputs.populate(devices);
} else { // if (mode == QAudio::AudioOutput)
_outputs.populate(devices);
}
}

View file

@ -0,0 +1,76 @@
//
// AudioDeviceScriptingInterface.h
// interface/src/scripting
//
// Created by Zach Pomerantz on 28/5/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_scripting_AudioDevices_h
#define hifi_scripting_AudioDevices_h
#include <QObject>
#include <QAbstractListModel>
#include <QAudioDeviceInfo>
namespace scripting {
class AudioDevice {
public:
QAudioDeviceInfo info;
QString name;
bool selected { false };
};
class AudioDeviceList : public QAbstractListModel {
Q_OBJECT
public:
AudioDeviceList(QAudio::Mode mode);
int rowCount(const QModelIndex& parent) const override;
QVariant data(const QModelIndex& index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
bool setData(const QModelIndex& index, const QVariant &value, int role) override;
void setDevice(const QAudioDeviceInfo& device);
void populate(const QList<QAudioDeviceInfo>& devices);
private:
static QHash<int, QByteArray> _roles;
static Qt::ItemFlags _flags;
QAudio::Mode _mode;
QAudioDeviceInfo _selectedDevice;
QList<AudioDevice> _devices;
};
class AudioDevices : public QObject {
Q_OBJECT
Q_PROPERTY(AudioDeviceList* input READ getInputList)
Q_PROPERTY(AudioDeviceList* output READ getOutputList)
public:
AudioDevices();
private slots:
void onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device);
void onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices);
private:
AudioDeviceList* getInputList() { return &_inputs; }
AudioDeviceList* getOutputList() { return &_outputs; }
AudioDeviceList _inputs { QAudio::AudioInput };
AudioDeviceList _outputs { QAudio::AudioOutput };
bool tester;
};
};
#endif // hifi_scripting_AudioDevices_h

View file

@ -76,6 +76,13 @@ using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>; using Lock = std::unique_lock<Mutex>;
static Mutex _deviceMutex; static Mutex _deviceMutex;
// thread-safe
QList<QAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
// NOTE: availableDevices() clobbers the Qt internal device list
Lock lock(_deviceMutex);
return QAudioDeviceInfo::availableDevices(mode);
}
class BackgroundThread : public QThread { class BackgroundThread : public QThread {
public: public:
BackgroundThread(AudioClient* client) : QThread((QObject*)client), _client(client) {} BackgroundThread(AudioClient* client) : QThread((QObject*)client), _client(client) {}
@ -115,6 +122,45 @@ private:
std::condition_variable _joinCondition; std::condition_variable _joinCondition;
}; };
// now called from a background thread, to keep blocking operations off the audio thread
void AudioClient::checkDevices() {
auto inputDevices = getAvailableDevices(QAudio::AudioInput);
auto outputDevices = getAvailableDevices(QAudio::AudioOutput);
Lock lock(_deviceMutex);
if (inputDevices != _inputDevices) {
_inputDevices.swap(inputDevices);
emit devicesChanged(QAudio::AudioInput, _inputDevices);
}
if (outputDevices != _outputDevices) {
_outputDevices.swap(outputDevices);
emit devicesChanged(QAudio::AudioOutput, _outputDevices);
}
}
QAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {
Lock lock(_deviceMutex);
if (mode == QAudio::AudioInput) {
return _inputDeviceInfo;
} else { // if (mode == QAudio::AudioOutput)
return _outputDeviceInfo;
}
}
QList<QAudioDeviceInfo> AudioClient::getAudioDevices(QAudio::Mode mode) const {
Lock lock(_deviceMutex);
if (mode == QAudio::AudioInput) {
return _inputDevices;
} else { // if (mode == QAudio::AudioOutput)
return _outputDevices;
}
}
// background thread buffering local injectors // background thread buffering local injectors
class LocalInjectorsThread : public BackgroundThread { class LocalInjectorsThread : public BackgroundThread {
Q_OBJECT Q_OBJECT
@ -220,8 +266,9 @@ AudioClient::AudioClient() :
connect(&_receivedAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioClient::handleMismatchAudioFormat); connect(&_receivedAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioClient::handleMismatchAudioFormat);
_inputDevices = getDeviceNames(QAudio::AudioInput); // initialize wasapi; if getAvailableDevices is called from the CheckDevicesThread before this, it will crash
_outputDevices = getDeviceNames(QAudio::AudioOutput); getAvailableDevices(QAudio::AudioInput);
getAvailableDevices(QAudio::AudioOutput);
// start a thread to detect any device changes // start a thread to detect any device changes
_checkDevicesThread = new CheckDevicesThread(this); _checkDevicesThread = new CheckDevicesThread(this);
@ -295,13 +342,6 @@ void AudioClient::audioMixerKilled() {
emit disconnected(); emit disconnected();
} }
// thread-safe
QList<QAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
// NOTE: availableDevices() clobbers the Qt internal device list
Lock lock(_deviceMutex);
return QAudioDeviceInfo::availableDevices(mode);
}
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
QAudioDeviceInfo result; QAudioDeviceInfo result;
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
@ -315,7 +355,7 @@ QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& de
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString friendlyNameForAudioDevice(IMMDevice* pEndpoint) { QString getWinDeviceName(IMMDevice* pEndpoint) {
QString deviceName; QString deviceName;
IPropertyStore* pPropertyStore; IPropertyStore* pPropertyStore;
pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore); pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore);
@ -336,7 +376,7 @@ QString friendlyNameForAudioDevice(IMMDevice* pEndpoint) {
return deviceName; return deviceName;
} }
QString AudioClient::friendlyNameForAudioDevice(wchar_t* guid) { QString AudioClient::getWinDeviceName(wchar_t* guid) {
QString deviceName; QString deviceName;
HRESULT hr = S_OK; HRESULT hr = S_OK;
CoInitialize(nullptr); CoInitialize(nullptr);
@ -348,7 +388,7 @@ QString AudioClient::friendlyNameForAudioDevice(wchar_t* guid) {
printf("Audio Error: device not found\n"); printf("Audio Error: device not found\n");
deviceName = QString("NONE"); deviceName = QString("NONE");
} else { } else {
deviceName = ::friendlyNameForAudioDevice(pEndpoint); deviceName = ::getWinDeviceName(pEndpoint);
} }
pMMDeviceEnumerator->Release(); pMMDeviceEnumerator->Release();
pMMDeviceEnumerator = nullptr; pMMDeviceEnumerator = nullptr;
@ -431,7 +471,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
printf("Audio Error: device not found\n"); printf("Audio Error: device not found\n");
deviceName = QString("NONE"); deviceName = QString("NONE");
} else { } else {
deviceName = friendlyNameForAudioDevice(pEndpoint); deviceName = getWinDeviceName(pEndpoint);
} }
pMMDeviceEnumerator->Release(); pMMDeviceEnumerator->Release();
pMMDeviceEnumerator = NULL; pMMDeviceEnumerator = NULL;
@ -791,29 +831,12 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
} }
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo) {
QString AudioClient::getDefaultDeviceName(QAudio::Mode mode) { if (mode == QAudio::AudioInput) {
QAudioDeviceInfo deviceInfo = defaultAudioDeviceForMode(mode); return switchInputToAudioDevice(deviceInfo);
return deviceInfo.deviceName(); } else { // if (mode == QAudio::AudioOutput)
} return switchOutputToAudioDevice(deviceInfo);
QVector<QString> AudioClient::getDeviceNames(QAudio::Mode mode) {
QVector<QString> deviceNames;
const QList<QAudioDeviceInfo> &availableDevice = getAvailableDevices(mode);
foreach(const QAudioDeviceInfo &audioDevice, availableDevice) {
deviceNames << audioDevice.deviceName().trimmed();
} }
return deviceNames;
}
bool AudioClient::switchInputToAudioDevice(const QString& inputDeviceName) {
qCDebug(audioclient) << "[" << inputDeviceName << "] [" << getNamedAudioDeviceForMode(QAudio::AudioInput, inputDeviceName).deviceName() << "]";
return switchInputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioInput, inputDeviceName));
}
bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
qCDebug(audioclient) << "[" << outputDeviceName << "] [" << getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName).deviceName() << "]";
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
} }
void AudioClient::configureReverb() { void AudioClient::configureReverb() {
@ -1357,7 +1380,7 @@ void AudioClient::setIsStereoInput(bool isStereoInput) {
} }
// change in channel count for desired input format, restart the input device // change in channel count for desired input format, restart the input device
switchInputToAudioDevice(_inputAudioDeviceName); switchInputToAudioDevice(_inputDeviceInfo);
} }
} }
@ -1397,6 +1420,9 @@ void AudioClient::outputFormatChanged() {
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) { bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
bool supportedFormat = false; bool supportedFormat = false;
// NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex);
// cleanup any previously initialized device // cleanup any previously initialized device
if (_audioInput) { if (_audioInput) {
// The call to stop() causes _inputDevice to be destructed. // The call to stop() causes _inputDevice to be destructed.
@ -1409,7 +1435,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
_audioInput = NULL; _audioInput = NULL;
_numInputCallbackBytes = 0; _numInputCallbackBytes = 0;
_inputAudioDeviceName = ""; _inputDeviceInfo = QAudioDeviceInfo();
} }
if (_inputToNetworkResampler) { if (_inputToNetworkResampler) {
@ -1424,8 +1450,8 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
if (!inputDeviceInfo.isNull()) { if (!inputDeviceInfo.isNull()) {
qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available.";
_inputAudioDeviceName = inputDeviceInfo.deviceName().trimmed(); _inputDeviceInfo = inputDeviceInfo;
emit currentInputDeviceChanged(_inputAudioDeviceName); emit deviceChanged(QAudio::AudioInput, inputDeviceInfo);
if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) {
qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat; qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat;
@ -1460,10 +1486,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes); int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes);
_inputRingBuffer.resizeForFrameSize(numFrameSamples); _inputRingBuffer.resizeForFrameSize(numFrameSamples);
// NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex);
_inputDevice = _audioInput->start(); _inputDevice = _audioInput->start();
lock.unlock();
if (_inputDevice) { if (_inputDevice) {
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleMicAudioInput())); connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleMicAudioInput()));
@ -1511,6 +1534,9 @@ void AudioClient::outputNotify() {
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) { bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) {
bool supportedFormat = false; bool supportedFormat = false;
// NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex);
Lock localAudioLock(_localAudioMutex); Lock localAudioLock(_localAudioMutex);
_localSamplesAvailable.exchange(0, std::memory_order_release); _localSamplesAvailable.exchange(0, std::memory_order_release);
@ -1536,6 +1562,8 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
delete[] _localOutputMixBuffer; delete[] _localOutputMixBuffer;
_localOutputMixBuffer = NULL; _localOutputMixBuffer = NULL;
_outputDeviceInfo = QAudioDeviceInfo();
} }
if (_networkToOutputResampler) { if (_networkToOutputResampler) {
@ -1549,8 +1577,8 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
if (!outputDeviceInfo.isNull()) { if (!outputDeviceInfo.isNull()) {
qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available.";
_outputAudioDeviceName = outputDeviceInfo.deviceName().trimmed(); _outputDeviceInfo = outputDeviceInfo;
emit currentOutputDeviceChanged(_outputAudioDeviceName); emit deviceChanged(QAudio::AudioOutput, outputDeviceInfo);
if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) {
qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat; qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat;
@ -1625,10 +1653,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
_audioOutputIODevice.start(); _audioOutputIODevice.start();
// NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex);
_audioOutput->start(&_audioOutputIODevice); _audioOutput->start(&_audioOutputIODevice);
lock.unlock();
// setup a loopback audio output device // setup a loopback audio output device
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
@ -1821,19 +1846,6 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
return bytesWritten; return bytesWritten;
} }
// now called from a background thread, to keep blocking operations off the audio thread
void AudioClient::checkDevices() {
QVector<QString> inputDevices = getDeviceNames(QAudio::AudioInput);
QVector<QString> outputDevices = getDeviceNames(QAudio::AudioOutput);
if (inputDevices != _inputDevices || outputDevices != _outputDevices) {
_inputDevices = inputDevices;
_outputDevices = outputDevices;
emit deviceChanged();
}
}
void AudioClient::loadSettings() { void AudioClient::loadSettings() {
_receivedAudioStream.setDynamicJitterBufferEnabled(dynamicJitterBufferEnabled.get()); _receivedAudioStream.setDynamicJitterBufferEnabled(dynamicJitterBufferEnabled.get());
_receivedAudioStream.setStaticJitterBufferFrames(staticJitterBufferFrames.get()); _receivedAudioStream.setStaticJitterBufferFrames(staticJitterBufferFrames.get());

View file

@ -146,10 +146,13 @@ public:
bool outputLocalInjector(AudioInjector* injector) override; bool outputLocalInjector(AudioInjector* injector) override;
QAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const;
QList<QAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const;
static const float CALLBACK_ACCELERATOR_RATIO; static const float CALLBACK_ACCELERATOR_RATIO;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
static QString friendlyNameForAudioDevice(wchar_t* guid); static QString getWinDeviceName(wchar_t* guid);
#endif #endif
public slots: public slots:
@ -185,12 +188,7 @@ public slots:
bool shouldLoopbackInjectors() override { return _shouldEchoToServer; } bool shouldLoopbackInjectors() override { return _shouldEchoToServer; }
bool switchInputToAudioDevice(const QString& inputDeviceName); bool switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo);
bool switchOutputToAudioDevice(const QString& outputDeviceName);
QString getDeviceName(QAudio::Mode mode) const { return (mode == QAudio::AudioInput) ?
_inputAudioDeviceName : _outputAudioDeviceName; }
QString getDefaultDeviceName(QAudio::Mode mode);
QVector<QString> getDeviceNames(QAudio::Mode mode);
float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; } float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; }
void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); } void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); }
@ -212,7 +210,9 @@ signals:
void noiseGateClosed(); void noiseGateClosed();
void changeDevice(const QAudioDeviceInfo& outputDeviceInfo); void changeDevice(const QAudioDeviceInfo& outputDeviceInfo);
void deviceChanged();
void deviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device);
void devicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices);
void receivedFirstPacket(); void receivedFirstPacket();
void disconnected(); void disconnected();
@ -221,9 +221,6 @@ signals:
void muteEnvironmentRequested(glm::vec3 position, float radius); void muteEnvironmentRequested(glm::vec3 position, float radius);
void currentOutputDeviceChanged(const QString& name);
void currentInputDeviceChanged(const QString& name);
protected: protected:
AudioClient(); AudioClient();
~AudioClient(); ~AudioClient();
@ -290,9 +287,6 @@ private:
MixedProcessedAudioStream _receivedAudioStream; MixedProcessedAudioStream _receivedAudioStream;
bool _isStereoInput; bool _isStereoInput;
QString _inputAudioDeviceName;
QString _outputAudioDeviceName;
quint64 _outputStarveDetectionStartTimeMsec; quint64 _outputStarveDetectionStartTimeMsec;
int _outputStarveDetectionCount; int _outputStarveDetectionCount;
@ -368,8 +362,11 @@ private:
glm::vec3 avatarBoundingBoxCorner; glm::vec3 avatarBoundingBoxCorner;
glm::vec3 avatarBoundingBoxScale; glm::vec3 avatarBoundingBoxScale;
QVector<QString> _inputDevices; QAudioDeviceInfo _inputDeviceInfo;
QVector<QString> _outputDevices; QAudioDeviceInfo _outputDeviceInfo;
QList<QAudioDeviceInfo> _inputDevices;
QList<QAudioDeviceInfo> _outputDevices;
bool _hasReceivedFirstPacket { false }; bool _hasReceivedFirstPacket { false };

View file

@ -244,7 +244,7 @@ QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
if (!OVR_SUCCESS(ovr_GetAudioDeviceInGuidStr(buffer))) { if (!OVR_SUCCESS(ovr_GetAudioDeviceInGuidStr(buffer))) {
return QString(); return QString();
} }
return AudioClient::friendlyNameForAudioDevice(buffer); return AudioClient::getWinDeviceName(buffer);
} }
QString OculusDisplayPlugin::getPreferredAudioOutDevice() const { QString OculusDisplayPlugin::getPreferredAudioOutDevice() const {
@ -252,7 +252,7 @@ QString OculusDisplayPlugin::getPreferredAudioOutDevice() const {
if (!OVR_SUCCESS(ovr_GetAudioDeviceOutGuidStr(buffer))) { if (!OVR_SUCCESS(ovr_GetAudioDeviceOutGuidStr(buffer))) {
return QString(); return QString();
} }
return AudioClient::friendlyNameForAudioDevice(buffer); return AudioClient::getWinDeviceName(buffer);
} }
OculusDisplayPlugin::~OculusDisplayPlugin() { OculusDisplayPlugin::~OculusDisplayPlugin() {