mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 10:07:58 +02:00
Merge pull request #10337 from vladest/audio-source-sync
Audio source sync
This commit is contained in:
commit
9d63113e62
9 changed files with 301 additions and 160 deletions
|
@ -35,11 +35,6 @@ Rectangle {
|
||||||
property string title: "Audio Options"
|
property string title: "Audio Options"
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
|
|
||||||
//set models after Components is shown
|
|
||||||
Component.onCompleted: {
|
|
||||||
refreshTimer.start()
|
|
||||||
refreshTimerOutput.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: separator
|
id: separator
|
||||||
|
@ -84,7 +79,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: AvatarInputs
|
target: AvatarInputs !== undefined ? AvatarInputs : null
|
||||||
onShowAudioToolsChanged: {
|
onShowAudioToolsChanged: {
|
||||||
audioTools.checkbox.checked = showAudioTools
|
audioTools.checkbox.checked = showAudioTools
|
||||||
}
|
}
|
||||||
|
@ -105,10 +100,12 @@ Rectangle {
|
||||||
id: audioTools
|
id: audioTools
|
||||||
width: parent.width
|
width: parent.width
|
||||||
anchors { left: parent.left; right: parent.right; leftMargin: 30 }
|
anchors { left: parent.left; right: parent.right; leftMargin: 30 }
|
||||||
checkbox.checked: AvatarInputs.showAudioTools
|
checkbox.checked: AvatarInputs !== undefined ? AvatarInputs.showAudioTools : false
|
||||||
text.text: qsTr("Show audio level meter")
|
text.text: qsTr("Show audio level meter")
|
||||||
onCheckBoxClicked: {
|
onCheckBoxClicked: {
|
||||||
AvatarInputs.showAudioTools = checked
|
if (AvatarInputs !== undefined) {
|
||||||
|
AvatarInputs.showAudioTools = checked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,30 +135,34 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
Timer {
|
|
||||||
id: refreshTimer
|
|
||||||
interval: 1
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
//refresh model
|
|
||||||
inputAudioListView.model = undefined
|
|
||||||
inputAudioListView.model = AudioDevice.inputAudioDevices
|
|
||||||
}
|
|
||||||
}
|
|
||||||
id: inputAudioListView
|
id: inputAudioListView
|
||||||
anchors { left: parent.left; right: parent.right; leftMargin: 70 }
|
anchors { left: parent.left; right: parent.right; leftMargin: 70 }
|
||||||
height: 125
|
height: 125
|
||||||
spacing: 16
|
spacing: 0
|
||||||
clip: true
|
clip: true
|
||||||
snapMode: ListView.SnapToItem
|
snapMode: ListView.SnapToItem
|
||||||
delegate: AudioCheckbox {
|
model: AudioDevice
|
||||||
|
delegate: Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
checkbox.checked: (modelData === AudioDevice.getInputDevice())
|
visible: devicemode === 0
|
||||||
text.text: modelData
|
height: visible ? 36 : 0
|
||||||
onCheckBoxClicked: {
|
|
||||||
if (checked) {
|
AudioCheckbox {
|
||||||
AudioDevice.setInputDevice(modelData)
|
id: cbin
|
||||||
refreshTimer.start()
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Binding {
|
||||||
|
target: cbin.checkbox
|
||||||
|
property: 'checked'
|
||||||
|
value: devicechecked
|
||||||
|
}
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
cbchecked: devicechecked
|
||||||
|
text.text: devicename
|
||||||
|
onCheckBoxClicked: {
|
||||||
|
if (checked) {
|
||||||
|
AudioDevice.setInputDeviceAsync(devicename)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,31 +192,33 @@ Rectangle {
|
||||||
text: qsTr("CHOOSE OUTPUT DEVICE")
|
text: qsTr("CHOOSE OUTPUT DEVICE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: outputAudioListView
|
id: outputAudioListView
|
||||||
Timer {
|
|
||||||
id: refreshTimerOutput
|
|
||||||
interval: 1
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
//refresh model
|
|
||||||
outputAudioListView.model = undefined
|
|
||||||
outputAudioListView.model = AudioDevice.outputAudioDevices
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors { left: parent.left; right: parent.right; leftMargin: 70 }
|
anchors { left: parent.left; right: parent.right; leftMargin: 70 }
|
||||||
height: 250
|
height: 250
|
||||||
spacing: 16
|
spacing: 0
|
||||||
clip: true
|
clip: true
|
||||||
snapMode: ListView.SnapToItem
|
snapMode: ListView.SnapToItem
|
||||||
delegate: AudioCheckbox {
|
model: AudioDevice
|
||||||
|
delegate: Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
checkbox.checked: (modelData === AudioDevice.getOutputDevice())
|
visible: devicemode === 1
|
||||||
text.text: modelData
|
height: visible ? 36 : 0
|
||||||
onCheckBoxClicked: {
|
AudioCheckbox {
|
||||||
if (checked) {
|
id: cbout
|
||||||
AudioDevice.setOutputDevice(modelData)
|
width: parent.width
|
||||||
refreshTimerOutput.start()
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Binding {
|
||||||
|
target: cbout.checkbox
|
||||||
|
property: 'checked'
|
||||||
|
value: devicechecked
|
||||||
|
}
|
||||||
|
text.text: devicename
|
||||||
|
onCheckBoxClicked: {
|
||||||
|
if (checked) {
|
||||||
|
AudioDevice.setOutputDeviceAsync(devicename)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ Row {
|
||||||
id: row
|
id: row
|
||||||
spacing: 16
|
spacing: 16
|
||||||
property alias checkbox: cb
|
property alias checkbox: cb
|
||||||
|
property alias cbchecked: cb.checked
|
||||||
property alias text: txt
|
property alias text: txt
|
||||||
signal checkBoxClicked(bool checked)
|
signal checkBoxClicked(bool checked)
|
||||||
|
|
||||||
|
|
|
@ -2053,6 +2053,8 @@ void Application::initializeUi() {
|
||||||
|
|
||||||
rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
||||||
|
|
||||||
|
rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||||
|
|
||||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||||
rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,21 +11,19 @@
|
||||||
|
|
||||||
#include "AudioClient.h"
|
#include "AudioClient.h"
|
||||||
#include "AudioDeviceScriptingInterface.h"
|
#include "AudioDeviceScriptingInterface.h"
|
||||||
|
#include "SettingsScriptingInterface.h"
|
||||||
|
|
||||||
AudioDeviceScriptingInterface* AudioDeviceScriptingInterface::getInstance() {
|
AudioDeviceScriptingInterface* AudioDeviceScriptingInterface::getInstance() {
|
||||||
static AudioDeviceScriptingInterface sharedInstance;
|
static AudioDeviceScriptingInterface sharedInstance;
|
||||||
return &sharedInstance;
|
return &sharedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList AudioDeviceScriptingInterface::inputAudioDevices() const
|
QStringList AudioDeviceScriptingInterface::inputAudioDevices() const {
|
||||||
{
|
return _inputAudioDevices;
|
||||||
return DependencyManager::get<AudioClient>()->getDeviceNames(QAudio::AudioInput).toList();;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList AudioDeviceScriptingInterface::outputAudioDevices() const
|
QStringList AudioDeviceScriptingInterface::outputAudioDevices() const {
|
||||||
{
|
return _outputAudioDevices;
|
||||||
return DependencyManager::get<AudioClient>()->getDeviceNames(QAudio::AudioOutput).toList();;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioDeviceScriptingInterface::muted()
|
bool AudioDeviceScriptingInterface::muted()
|
||||||
|
@ -33,11 +31,27 @@ bool AudioDeviceScriptingInterface::muted()
|
||||||
return getMuted();
|
return getMuted();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDeviceScriptingInterface::AudioDeviceScriptingInterface() {
|
AudioDeviceScriptingInterface::AudioDeviceScriptingInterface(): QAbstractListModel(nullptr) {
|
||||||
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::muteToggled,
|
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::muteToggled,
|
||||||
this, &AudioDeviceScriptingInterface::muteToggled);
|
this, &AudioDeviceScriptingInterface::muteToggled);
|
||||||
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged,
|
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged,
|
||||||
this, &AudioDeviceScriptingInterface::deviceChanged);
|
this, &AudioDeviceScriptingInterface::onDeviceChanged, Qt::QueuedConnection);
|
||||||
|
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::currentInputDeviceChanged,
|
||||||
|
this, &AudioDeviceScriptingInterface::onCurrentInputDeviceChanged, Qt::QueuedConnection);
|
||||||
|
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::currentOutputDeviceChanged,
|
||||||
|
this, &AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged, Qt::QueuedConnection);
|
||||||
|
//fill up model
|
||||||
|
onDeviceChanged();
|
||||||
|
//set up previously saved device
|
||||||
|
SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance();
|
||||||
|
const QString inDevice = settings->getValue("audio_input_device").toString();
|
||||||
|
if (inDevice != _currentInputDevice) {
|
||||||
|
setInputDeviceAsync(inDevice);
|
||||||
|
}
|
||||||
|
const QString outDevice = settings->getValue("audio_output_device").toString();
|
||||||
|
if (outDevice != _currentOutputDevice) {
|
||||||
|
setOutputDeviceAsync(outDevice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) {
|
bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) {
|
||||||
|
@ -58,6 +72,43 @@ bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AudioDeviceScriptingInterface::setDeviceFromMenu(const QString& deviceMenuName) {
|
||||||
|
QAudio::Mode mode;
|
||||||
|
|
||||||
|
if (deviceMenuName.indexOf("for Output") != -1) {
|
||||||
|
mode = QAudio::AudioOutput;
|
||||||
|
} else if (deviceMenuName.indexOf("for Input") != -1) {
|
||||||
|
mode = QAudio::AudioInput;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ScriptingAudioDeviceInfo di: _devices) {
|
||||||
|
if (mode == di.mode && deviceMenuName.contains(di.name)) {
|
||||||
|
if (mode == QAudio::AudioOutput) {
|
||||||
|
setOutputDeviceAsync(di.name);
|
||||||
|
} else {
|
||||||
|
setInputDeviceAsync(di.name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::setInputDeviceAsync(const QString& deviceName) {
|
||||||
|
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "switchInputToAudioDevice",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
Q_ARG(const QString&, deviceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::setOutputDeviceAsync(const QString& deviceName) {
|
||||||
|
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "switchOutputToAudioDevice",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
Q_ARG(const QString&, deviceName));
|
||||||
|
}
|
||||||
|
|
||||||
QString AudioDeviceScriptingInterface::getInputDevice() {
|
QString AudioDeviceScriptingInterface::getInputDevice() {
|
||||||
return DependencyManager::get<AudioClient>()->getDeviceName(QAudio::AudioInput);
|
return DependencyManager::get<AudioClient>()->getDeviceName(QAudio::AudioInput);
|
||||||
}
|
}
|
||||||
|
@ -116,3 +167,105 @@ void AudioDeviceScriptingInterface::setMuted(bool muted)
|
||||||
bool AudioDeviceScriptingInterface::getMuted() {
|
bool AudioDeviceScriptingInterface::getMuted() {
|
||||||
return DependencyManager::get<AudioClient>()->isMuted();
|
return DependencyManager::get<AudioClient>()->isMuted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant AudioDeviceScriptingInterface::data(const QModelIndex& index, int role) const {
|
||||||
|
//sanity
|
||||||
|
if (!index.isValid() || index.row() >= _devices.size())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole || role == DisplayNameRole) {
|
||||||
|
return _devices.at(index.row()).name;
|
||||||
|
} else if (role == SelectedRole) {
|
||||||
|
return _devices.at(index.row()).selected;
|
||||||
|
} else if (role == AudioModeRole) {
|
||||||
|
return (int)_devices.at(index.row()).mode;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AudioDeviceScriptingInterface::rowCount(const QModelIndex& parent) const {
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return _devices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> AudioDeviceScriptingInterface::roleNames() const {
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(DisplayNameRole, "devicename");
|
||||||
|
roles.insert(SelectedRole, "devicechecked");
|
||||||
|
roles.insert(AudioModeRole, "devicemode");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::onDeviceChanged()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
_outputAudioDevices.clear();
|
||||||
|
_devices.clear();
|
||||||
|
_currentOutputDevice = getOutputDevice();
|
||||||
|
for (QString name: getOutputDevices()) {
|
||||||
|
ScriptingAudioDeviceInfo di;
|
||||||
|
di.name = name;
|
||||||
|
di.selected = (name == _currentOutputDevice);
|
||||||
|
di.mode = QAudio::AudioOutput;
|
||||||
|
_devices.append(di);
|
||||||
|
_outputAudioDevices.append(name);
|
||||||
|
}
|
||||||
|
emit outputAudioDevicesChanged(_outputAudioDevices);
|
||||||
|
|
||||||
|
_inputAudioDevices.clear();
|
||||||
|
_currentInputDevice = getInputDevice();
|
||||||
|
for (QString name: getInputDevices()) {
|
||||||
|
ScriptingAudioDeviceInfo di;
|
||||||
|
di.name = name;
|
||||||
|
di.selected = (name == _currentInputDevice);
|
||||||
|
di.mode = QAudio::AudioInput;
|
||||||
|
_devices.append(di);
|
||||||
|
_inputAudioDevices.append(name);
|
||||||
|
}
|
||||||
|
emit inputAudioDevicesChanged(_inputAudioDevices);
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
emit deviceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged(const QString& name)
|
||||||
|
{
|
||||||
|
currentDeviceUpdate(name, QAudio::AudioInput);
|
||||||
|
//we got a signal that device changed. Save it now
|
||||||
|
SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance();
|
||||||
|
settings->setValue("audio_input_device", name);
|
||||||
|
emit currentInputDeviceChanged(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged(const QString& name)
|
||||||
|
{
|
||||||
|
currentDeviceUpdate(name, QAudio::AudioOutput);
|
||||||
|
//we got a signal that device changed. Save it now
|
||||||
|
SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance();
|
||||||
|
settings->setValue("audio_output_device", name);
|
||||||
|
emit currentOutputDeviceChanged(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString& name, QAudio::Mode mode)
|
||||||
|
{
|
||||||
|
QVector<int> role;
|
||||||
|
role.append(SelectedRole);
|
||||||
|
|
||||||
|
for (int i = 0; i < _devices.size(); i++) {
|
||||||
|
ScriptingAudioDeviceInfo di = _devices.at(i);
|
||||||
|
if (di.mode != mode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (di.selected && di.name != name ) {
|
||||||
|
di.selected = false;
|
||||||
|
_devices[i] = di;
|
||||||
|
emit dataChanged(index(i, 0), index(i, 0), role);
|
||||||
|
}
|
||||||
|
if (di.name == name) {
|
||||||
|
di.selected = true;
|
||||||
|
_devices[i] = di;
|
||||||
|
emit dataChanged(index(i, 0), index(i, 0), role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,10 +15,18 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QAudio>
|
||||||
|
|
||||||
class AudioEffectOptions;
|
class AudioEffectOptions;
|
||||||
|
|
||||||
class AudioDeviceScriptingInterface : public QObject {
|
struct ScriptingAudioDeviceInfo {
|
||||||
|
QString name;
|
||||||
|
bool selected;
|
||||||
|
QAudio::Mode mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioDeviceScriptingInterface : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(QStringList inputAudioDevices READ inputAudioDevices NOTIFY inputAudioDevicesChanged)
|
Q_PROPERTY(QStringList inputAudioDevices READ inputAudioDevices NOTIFY inputAudioDevicesChanged)
|
||||||
|
@ -32,9 +40,26 @@ public:
|
||||||
QStringList outputAudioDevices() const;
|
QStringList outputAudioDevices() const;
|
||||||
bool muted();
|
bool muted();
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
enum Roles {
|
||||||
|
DisplayNameRole = Qt::UserRole,
|
||||||
|
SelectedRole,
|
||||||
|
AudioModeRole
|
||||||
|
};
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDeviceChanged();
|
||||||
|
void onCurrentInputDeviceChanged(const QString& name);
|
||||||
|
void onCurrentOutputDeviceChanged(const QString& name);
|
||||||
|
void currentDeviceUpdate(const QString& name, QAudio::Mode mode);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool setInputDevice(const QString& deviceName);
|
bool setInputDevice(const QString& deviceName);
|
||||||
bool setOutputDevice(const QString& deviceName);
|
bool setOutputDevice(const QString& deviceName);
|
||||||
|
bool setDeviceFromMenu(const QString& deviceMenuName);
|
||||||
|
|
||||||
QString getInputDevice();
|
QString getInputDevice();
|
||||||
QString getOutputDevice();
|
QString getOutputDevice();
|
||||||
|
@ -55,15 +80,28 @@ public slots:
|
||||||
|
|
||||||
void setMuted(bool muted);
|
void setMuted(bool muted);
|
||||||
|
|
||||||
|
void setInputDeviceAsync(const QString& deviceName);
|
||||||
|
void setOutputDeviceAsync(const QString& deviceName);
|
||||||
private:
|
private:
|
||||||
AudioDeviceScriptingInterface();
|
AudioDeviceScriptingInterface();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void muteToggled();
|
void muteToggled();
|
||||||
void deviceChanged();
|
void deviceChanged();
|
||||||
|
void currentInputDeviceChanged(const QString& name);
|
||||||
|
void currentOutputDeviceChanged(const QString& name);
|
||||||
void mutedChanged(bool muted);
|
void mutedChanged(bool muted);
|
||||||
void inputAudioDevicesChanged(QStringList inputAudioDevices);
|
void inputAudioDevicesChanged(QStringList inputAudioDevices);
|
||||||
void outputAudioDevicesChanged(QStringList outputAudioDevices);
|
void outputAudioDevicesChanged(QStringList outputAudioDevices);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<ScriptingAudioDeviceInfo> _devices;
|
||||||
|
|
||||||
|
QStringList _inputAudioDevices;
|
||||||
|
QStringList _outputAudioDevices;
|
||||||
|
|
||||||
|
QString _currentInputDevice;
|
||||||
|
QString _currentOutputDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioDeviceScriptingInterface_h
|
#endif // hifi_AudioDeviceScriptingInterface_h
|
||||||
|
|
|
@ -799,7 +799,8 @@ QString AudioClient::getDefaultDeviceName(QAudio::Mode mode) {
|
||||||
|
|
||||||
QVector<QString> AudioClient::getDeviceNames(QAudio::Mode mode) {
|
QVector<QString> AudioClient::getDeviceNames(QAudio::Mode mode) {
|
||||||
QVector<QString> deviceNames;
|
QVector<QString> deviceNames;
|
||||||
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
const QList<QAudioDeviceInfo> &availableDevice = getAvailableDevices(mode);
|
||||||
|
foreach(const QAudioDeviceInfo &audioDevice, availableDevice) {
|
||||||
deviceNames << audioDevice.deviceName().trimmed();
|
deviceNames << audioDevice.deviceName().trimmed();
|
||||||
}
|
}
|
||||||
return deviceNames;
|
return deviceNames;
|
||||||
|
@ -1402,7 +1403,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
||||||
_audioInput->stop();
|
_audioInput->stop();
|
||||||
_inputDevice = NULL;
|
_inputDevice = NULL;
|
||||||
|
|
||||||
delete _audioInput;
|
_audioInput->deleteLater();
|
||||||
_audioInput = NULL;
|
_audioInput = NULL;
|
||||||
_numInputCallbackBytes = 0;
|
_numInputCallbackBytes = 0;
|
||||||
|
|
||||||
|
@ -1418,6 +1419,7 @@ 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();
|
_inputAudioDeviceName = inputDeviceInfo.deviceName().trimmed();
|
||||||
|
emit currentInputDeviceChanged(_inputAudioDeviceName);
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1506,11 +1508,13 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
|
||||||
if (_audioOutput) {
|
if (_audioOutput) {
|
||||||
_audioOutput->stop();
|
_audioOutput->stop();
|
||||||
|
|
||||||
delete _audioOutput;
|
//must be deleted in next eventloop cycle when its called from notify()
|
||||||
|
_audioOutput->deleteLater();
|
||||||
_audioOutput = NULL;
|
_audioOutput = NULL;
|
||||||
|
|
||||||
_loopbackOutputDevice = NULL;
|
_loopbackOutputDevice = NULL;
|
||||||
delete _loopbackAudioOutput;
|
//must be deleted in next eventloop cycle when its called from notify()
|
||||||
|
_loopbackAudioOutput->deleteLater();
|
||||||
_loopbackAudioOutput = NULL;
|
_loopbackAudioOutput = NULL;
|
||||||
|
|
||||||
delete[] _outputMixBuffer;
|
delete[] _outputMixBuffer;
|
||||||
|
@ -1535,6 +1539,7 @@ 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();
|
_outputAudioDeviceName = outputDeviceInfo.deviceName().trimmed();
|
||||||
|
emit currentOutputDeviceChanged(_outputAudioDeviceName);
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -222,6 +222,9 @@ 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();
|
||||||
|
|
|
@ -24,6 +24,7 @@ class AudioScriptingInterface : public QObject, public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~AudioScriptingInterface() {}
|
||||||
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
|
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -17,32 +17,22 @@
|
||||||
|
|
||||||
const INPUT = "Input";
|
const INPUT = "Input";
|
||||||
const OUTPUT = "Output";
|
const OUTPUT = "Output";
|
||||||
function parseMenuItem(item) {
|
const SELECT_AUDIO_SCRIPT_STARTUP_TIMEOUT = 300;
|
||||||
const USE = "Use ";
|
|
||||||
const FOR_INPUT = " for " + INPUT;
|
|
||||||
const FOR_OUTPUT = " for " + OUTPUT;
|
|
||||||
if (item.slice(0, USE.length) == USE) {
|
|
||||||
if (item.slice(-FOR_INPUT.length) == FOR_INPUT) {
|
|
||||||
return { device: item.slice(USE.length, -FOR_INPUT.length), mode: INPUT };
|
|
||||||
} else if (item.slice(-FOR_OUTPUT.length) == FOR_OUTPUT) {
|
|
||||||
return { device: item.slice(USE.length, -FOR_OUTPUT.length), mode: OUTPUT };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// VAR DEFINITIONS
|
// VAR DEFINITIONS
|
||||||
//
|
//
|
||||||
var debugPrintStatements = true;
|
var debugPrintStatements = true;
|
||||||
const INPUT_DEVICE_SETTING = "audio_input_device";
|
const INPUT_DEVICE_SETTING = "audio_input_device";
|
||||||
const OUTPUT_DEVICE_SETTING = "audio_output_device";
|
const OUTPUT_DEVICE_SETTING = "audio_output_device";
|
||||||
var audioDevicesList = [];
|
var audioDevicesList = []; // placeholder for menu items
|
||||||
var wasHmdActive = false; // assume it's not active to start
|
var wasHmdActive = false; // assume it's not active to start
|
||||||
var switchedAudioInputToHMD = false;
|
var switchedAudioInputToHMD = false;
|
||||||
var switchedAudioOutputToHMD = false;
|
var switchedAudioOutputToHMD = false;
|
||||||
var previousSelectedInputAudioDevice = "";
|
var previousSelectedInputAudioDevice = "";
|
||||||
var previousSelectedOutputAudioDevice = "";
|
var previousSelectedOutputAudioDevice = "";
|
||||||
var skipMenuEvents = true;
|
|
||||||
|
var interfaceInputDevice = "";
|
||||||
|
var interfaceOutputDevice = "";
|
||||||
|
|
||||||
//
|
//
|
||||||
// BEGIN FUNCTION DEFINITIONS
|
// BEGIN FUNCTION DEFINITIONS
|
||||||
|
@ -56,56 +46,37 @@ function debug() {
|
||||||
|
|
||||||
function setupAudioMenus() {
|
function setupAudioMenus() {
|
||||||
// menu events can be triggered asynchronously; skip them for 200ms to avoid recursion and false switches
|
// menu events can be triggered asynchronously; skip them for 200ms to avoid recursion and false switches
|
||||||
skipMenuEvents = true;
|
|
||||||
Script.setTimeout(function() { skipMenuEvents = false; }, 200);
|
|
||||||
|
|
||||||
removeAudioMenus();
|
removeAudioMenus();
|
||||||
|
|
||||||
// Setup audio input devices
|
// Setup audio input devices
|
||||||
Menu.addSeparator("Audio", "Input Audio Device");
|
Menu.addSeparator("Audio", "Input Audio Device");
|
||||||
var inputDevices = AudioDevice.getInputDevices();
|
var currentInputDevice = AudioDevice.getInputDevice()
|
||||||
for (var i = 0; i < inputDevices.length; i++) {
|
for (var i = 0; i < AudioDevice.inputAudioDevices.length; i++) {
|
||||||
var audioDeviceMenuString = "Use " + inputDevices[i] + " for Input";
|
var audioDeviceMenuString = "Use " + AudioDevice.inputAudioDevices[i] + " for Input";
|
||||||
Menu.addMenuItem({
|
Menu.addMenuItem({
|
||||||
menuName: "Audio",
|
menuName: "Audio",
|
||||||
menuItemName: audioDeviceMenuString,
|
menuItemName: audioDeviceMenuString,
|
||||||
isCheckable: true,
|
isCheckable: true,
|
||||||
isChecked: inputDevices[i] == AudioDevice.getInputDevice()
|
isChecked: AudioDevice.inputAudioDevices[i] == currentInputDevice
|
||||||
});
|
});
|
||||||
audioDevicesList.push(audioDeviceMenuString);
|
audioDevicesList.push(audioDeviceMenuString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup audio output devices
|
// Setup audio output devices
|
||||||
Menu.addSeparator("Audio", "Output Audio Device");
|
Menu.addSeparator("Audio", "Output Audio Device");
|
||||||
var outputDevices = AudioDevice.getOutputDevices();
|
var currentOutputDevice = AudioDevice.getOutputDevice()
|
||||||
for (var i = 0; i < outputDevices.length; i++) {
|
for (var i = 0; i < AudioDevice.outputAudioDevices.length; i++) {
|
||||||
var audioDeviceMenuString = "Use " + outputDevices[i] + " for Output";
|
var audioDeviceMenuString = "Use " + AudioDevice.outputAudioDevices[i] + " for Output";
|
||||||
Menu.addMenuItem({
|
Menu.addMenuItem({
|
||||||
menuName: "Audio",
|
menuName: "Audio",
|
||||||
menuItemName: audioDeviceMenuString,
|
menuItemName: audioDeviceMenuString,
|
||||||
isCheckable: true,
|
isCheckable: true,
|
||||||
isChecked: outputDevices[i] == AudioDevice.getOutputDevice()
|
isChecked: AudioDevice.outputAudioDevices[i] == currentOutputDevice
|
||||||
});
|
});
|
||||||
audioDevicesList.push(audioDeviceMenuString);
|
audioDevicesList.push(audioDeviceMenuString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDeviceMismatch() {
|
|
||||||
var inputDeviceSetting = Settings.getValue(INPUT_DEVICE_SETTING);
|
|
||||||
var interfaceInputDevice = AudioDevice.getInputDevice();
|
|
||||||
if (interfaceInputDevice != inputDeviceSetting) {
|
|
||||||
debug("Input Setting & Device mismatch! Input SETTING: " + inputDeviceSetting + "Input DEVICE IN USE: " + interfaceInputDevice);
|
|
||||||
switchAudioDevice("Use " + inputDeviceSetting + " for Input");
|
|
||||||
}
|
|
||||||
|
|
||||||
var outputDeviceSetting = Settings.getValue(OUTPUT_DEVICE_SETTING);
|
|
||||||
var interfaceOutputDevice = AudioDevice.getOutputDevice();
|
|
||||||
if (interfaceOutputDevice != outputDeviceSetting) {
|
|
||||||
debug("Output Setting & Device mismatch! Output SETTING: " + outputDeviceSetting + "Output DEVICE IN USE: " + interfaceOutputDevice);
|
|
||||||
switchAudioDevice("Use " + outputDeviceSetting + " for Output");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeAudioMenus() {
|
function removeAudioMenus() {
|
||||||
Menu.removeSeparator("Audio", "Input Audio Device");
|
Menu.removeSeparator("Audio", "Input Audio Device");
|
||||||
Menu.removeSeparator("Audio", "Output Audio Device");
|
Menu.removeSeparator("Audio", "Output Audio Device");
|
||||||
|
@ -124,67 +95,28 @@ function removeAudioMenus() {
|
||||||
function onDevicechanged() {
|
function onDevicechanged() {
|
||||||
debug("System audio devices changed. Removing and replacing Audio Menus...");
|
debug("System audio devices changed. Removing and replacing Audio Menus...");
|
||||||
setupAudioMenus();
|
setupAudioMenus();
|
||||||
checkDeviceMismatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMenuEvent(audioDeviceMenuString) {
|
function onMenuEvent(audioDeviceMenuString) {
|
||||||
if (!skipMenuEvents) {
|
if (Menu.isOptionChecked(audioDeviceMenuString) &&
|
||||||
switchAudioDevice(audioDeviceMenuString);
|
(audioDeviceMenuString !== interfaceInputDevice &&
|
||||||
|
audioDeviceMenuString !== interfaceOutputDevice)) {
|
||||||
|
AudioDevice.setDeviceFromMenu(audioDeviceMenuString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchAudioDevice(audioDeviceMenuString) {
|
function onCurrentDeviceChanged() {
|
||||||
// if the device is not plugged in, short-circuit
|
debug("System audio device switched. ");
|
||||||
if (!~audioDevicesList.indexOf(audioDeviceMenuString)) {
|
interfaceInputDevice = "Use " + AudioDevice.getInputDevice() + " for Input";
|
||||||
return;
|
interfaceOutputDevice = "Use " + AudioDevice.getOutputDevice() + " for Output";
|
||||||
}
|
for (var index = 0; index < audioDevicesList.length; index++) {
|
||||||
|
if (audioDevicesList[index] === interfaceInputDevice ||
|
||||||
var selection = parseMenuItem(audioDeviceMenuString);
|
audioDevicesList[index] === interfaceOutputDevice) {
|
||||||
if (!selection) {
|
if (Menu.isOptionChecked(audioDevicesList[index]) === false)
|
||||||
debug("Invalid Audio audioDeviceMenuString! Doesn't end with 'for Input' or 'for Output'");
|
Menu.setIsOptionChecked(audioDevicesList[index], true);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// menu events can be triggered asynchronously; skip them for 200ms to avoid recursion and false switches
|
|
||||||
skipMenuEvents = true;
|
|
||||||
Script.setTimeout(function() { skipMenuEvents = false; }, 200);
|
|
||||||
|
|
||||||
var selectedDevice = selection.device;
|
|
||||||
if (selection.mode == INPUT) {
|
|
||||||
var currentInputDevice = AudioDevice.getInputDevice();
|
|
||||||
if (selectedDevice != currentInputDevice) {
|
|
||||||
debug("Switching audio INPUT device from " + currentInputDevice + " to " + selectedDevice);
|
|
||||||
Menu.setIsOptionChecked("Use " + currentInputDevice + " for Input", false);
|
|
||||||
if (AudioDevice.setInputDevice(selectedDevice)) {
|
|
||||||
Settings.setValue(INPUT_DEVICE_SETTING, selectedDevice);
|
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, true);
|
|
||||||
} else {
|
|
||||||
debug("Error setting audio input device!")
|
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, false);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debug("Selected input device is the same as the current input device!")
|
if (Menu.isOptionChecked(audioDevicesList[index]) === true)
|
||||||
Settings.setValue(INPUT_DEVICE_SETTING, selectedDevice);
|
Menu.setIsOptionChecked(audioDevicesList[index], false);
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, true);
|
|
||||||
AudioDevice.setInputDevice(selectedDevice); // Still try to force-set the device (in case the user's trying to forcefully debug an issue)
|
|
||||||
}
|
|
||||||
} else if (selection.mode == OUTPUT) {
|
|
||||||
var currentOutputDevice = AudioDevice.getOutputDevice();
|
|
||||||
if (selectedDevice != currentOutputDevice) {
|
|
||||||
debug("Switching audio OUTPUT device from " + currentOutputDevice + " to " + selectedDevice);
|
|
||||||
Menu.setIsOptionChecked("Use " + currentOutputDevice + " for Output", false);
|
|
||||||
if (AudioDevice.setOutputDevice(selectedDevice)) {
|
|
||||||
Settings.setValue(OUTPUT_DEVICE_SETTING, selectedDevice);
|
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, true);
|
|
||||||
} else {
|
|
||||||
debug("Error setting audio output device!")
|
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug("Selected output device is the same as the current output device!")
|
|
||||||
Settings.setValue(OUTPUT_DEVICE_SETTING, selectedDevice);
|
|
||||||
Menu.setIsOptionChecked(audioDeviceMenuString, true);
|
|
||||||
AudioDevice.setOutputDevice(selectedDevice); // Still try to force-set the device (in case the user's trying to forcefully debug an issue)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,12 +124,12 @@ function switchAudioDevice(audioDeviceMenuString) {
|
||||||
function restoreAudio() {
|
function restoreAudio() {
|
||||||
if (switchedAudioInputToHMD) {
|
if (switchedAudioInputToHMD) {
|
||||||
debug("Switching back from HMD preferred audio input to: " + previousSelectedInputAudioDevice);
|
debug("Switching back from HMD preferred audio input to: " + previousSelectedInputAudioDevice);
|
||||||
switchAudioDevice("Use " + previousSelectedInputAudioDevice + " for Input");
|
AudioDevice.setInputDeviceAsync(previousSelectedInputAudioDevice)
|
||||||
switchedAudioInputToHMD = false;
|
switchedAudioInputToHMD = false;
|
||||||
}
|
}
|
||||||
if (switchedAudioOutputToHMD) {
|
if (switchedAudioOutputToHMD) {
|
||||||
debug("Switching back from HMD preferred audio output to: " + previousSelectedOutputAudioDevice);
|
debug("Switching back from HMD preferred audio output to: " + previousSelectedOutputAudioDevice);
|
||||||
switchAudioDevice("Use " + previousSelectedOutputAudioDevice + " for Output");
|
AudioDevice.setOutputDeviceAsync(previousSelectedOutputAudioDevice)
|
||||||
switchedAudioOutputToHMD = false;
|
switchedAudioOutputToHMD = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +156,7 @@ function checkHMDAudio() {
|
||||||
debug("previousSelectedInputAudioDevice: " + previousSelectedInputAudioDevice);
|
debug("previousSelectedInputAudioDevice: " + previousSelectedInputAudioDevice);
|
||||||
if (hmdPreferredAudioInput != previousSelectedInputAudioDevice) {
|
if (hmdPreferredAudioInput != previousSelectedInputAudioDevice) {
|
||||||
switchedAudioInputToHMD = true;
|
switchedAudioInputToHMD = true;
|
||||||
switchAudioDevice("Use " + hmdPreferredAudioInput + " for Input");
|
AudioDevice.setInputDeviceAsync(hmdPreferredAudioInput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hmdPreferredAudioOutput !== "") {
|
if (hmdPreferredAudioOutput !== "") {
|
||||||
|
@ -233,7 +165,7 @@ function checkHMDAudio() {
|
||||||
debug("previousSelectedOutputAudioDevice: " + previousSelectedOutputAudioDevice);
|
debug("previousSelectedOutputAudioDevice: " + previousSelectedOutputAudioDevice);
|
||||||
if (hmdPreferredAudioOutput != previousSelectedOutputAudioDevice) {
|
if (hmdPreferredAudioOutput != previousSelectedOutputAudioDevice) {
|
||||||
switchedAudioOutputToHMD = true;
|
switchedAudioOutputToHMD = true;
|
||||||
switchAudioDevice("Use " + hmdPreferredAudioOutput + " for Output");
|
AudioDevice.setOutputDeviceAsync(hmdPreferredAudioOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,14 +187,15 @@ function checkHMDAudio() {
|
||||||
Script.setTimeout(function () {
|
Script.setTimeout(function () {
|
||||||
debug("Connecting deviceChanged(), displayModeChanged(), and switchAudioDevice()...");
|
debug("Connecting deviceChanged(), displayModeChanged(), and switchAudioDevice()...");
|
||||||
AudioDevice.deviceChanged.connect(onDevicechanged);
|
AudioDevice.deviceChanged.connect(onDevicechanged);
|
||||||
|
AudioDevice.currentInputDeviceChanged.connect(onCurrentDeviceChanged);
|
||||||
|
AudioDevice.currentOutputDeviceChanged.connect(onCurrentDeviceChanged);
|
||||||
HMD.displayModeChanged.connect(checkHMDAudio);
|
HMD.displayModeChanged.connect(checkHMDAudio);
|
||||||
Menu.menuItemEvent.connect(onMenuEvent);
|
Menu.menuItemEvent.connect(onMenuEvent);
|
||||||
debug("Setting up Audio I/O menu for the first time...");
|
debug("Setting up Audio I/O menu for the first time...");
|
||||||
setupAudioMenus();
|
setupAudioMenus();
|
||||||
checkDeviceMismatch();
|
|
||||||
debug("Checking HMD audio status...")
|
debug("Checking HMD audio status...")
|
||||||
checkHMDAudio();
|
checkHMDAudio();
|
||||||
}, 3000);
|
}, SELECT_AUDIO_SCRIPT_STARTUP_TIMEOUT);
|
||||||
|
|
||||||
debug("Connecting scriptEnding()");
|
debug("Connecting scriptEnding()");
|
||||||
Script.scriptEnding.connect(function () {
|
Script.scriptEnding.connect(function () {
|
||||||
|
@ -270,6 +203,8 @@ Script.scriptEnding.connect(function () {
|
||||||
removeAudioMenus();
|
removeAudioMenus();
|
||||||
Menu.menuItemEvent.disconnect(onMenuEvent);
|
Menu.menuItemEvent.disconnect(onMenuEvent);
|
||||||
HMD.displayModeChanged.disconnect(checkHMDAudio);
|
HMD.displayModeChanged.disconnect(checkHMDAudio);
|
||||||
|
AudioDevice.currentInputDeviceChanged.disconnect(onCurrentDeviceChanged);
|
||||||
|
AudioDevice.currentOutputDeviceChanged.disconnect(onCurrentDeviceChanged);
|
||||||
AudioDevice.deviceChanged.disconnect(onDevicechanged);
|
AudioDevice.deviceChanged.disconnect(onDevicechanged);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue