diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 055d59efe3..b0ea8226e8 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -9,18 +9,30 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "AudioDevices.h" #include "Application.h" #include "AudioClient.h" #include "Audio.h" +#include "UserActivityLogger.h" + using namespace scripting; -Setting::Handle inputDeviceDesktop { QStringList { Audio::AUDIO, Audio::DESKTOP, "INPUT" }}; -Setting::Handle outputDeviceDesktop { QStringList { Audio::AUDIO, Audio::DESKTOP, "OUTPUT" }}; -Setting::Handle inputDeviceHMD { QStringList { Audio::AUDIO, Audio::HMD, "INPUT" }}; -Setting::Handle outputDeviceHMD { QStringList { Audio::AUDIO, Audio::HMD, "OUTPUT" }}; +static Setting::Handle desktopInputDeviceSetting { QStringList { Audio::AUDIO, Audio::DESKTOP, "INPUT" }}; +static Setting::Handle desktopOutputDeviceSetting { QStringList { Audio::AUDIO, Audio::DESKTOP, "OUTPUT" }}; +static Setting::Handle hmdInputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "INPUT" }}; +static Setting::Handle hmdOutputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "OUTPUT" }}; + +Setting::Handle& getSetting(bool contextIsHMD, QAudio::Mode mode) { + if (mode == QAudio::AudioInput) { + return contextIsHMD ? hmdInputDeviceSetting : desktopInputDeviceSetting; + } else { // if (mode == QAudio::AudioOutput) + return contextIsHMD ? hmdOutputDeviceSetting : desktopOutputDeviceSetting; + } +} QHash AudioDeviceList::_roles { { Qt::DisplayRole, "display" }, @@ -43,32 +55,37 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { } bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.row() >= _devices.size()) { + if (!index.isValid() || index.row() >= _devices.size() || role != Qt::CheckStateRole) { return false; } + // only allow switching to a new device, not deactivating an in-use device + auto selected = value.toBool(); + if (!selected) { + return false; + } + + return setDevice(index.row(), true); +} + +bool AudioDeviceList::setDevice(int row, bool fromUser) { bool success = false; + auto& device = _devices[row]; - if (role == Qt::CheckStateRole) { - auto selected = value.toBool(); - auto& device = _devices[index.row()]; + // skip if already selected + if (!device.selected) { + auto client = DependencyManager::get(); + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), + Q_ARG(QAudio::Mode, _mode), + Q_ARG(const QAudioDeviceInfo&, device.info)); - // 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(); - 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 deviceSelected(device.info); - emit deviceChanged(device.info); + if (success) { + device.selected = true; + if (fromUser) { + emit deviceSelected(device.info, _selectedDevice); } + emit deviceChanged(device.info); } } @@ -88,12 +105,12 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { } } if (i < rowCount()) { - success = setData(createIndex(i, 0), true, Qt::CheckStateRole); + success = setDevice(i, false); } // the selection failed - reset it if (!success) { - emit deviceSelected(QAudioDeviceInfo()); + emit deviceSelected(); } } @@ -167,48 +184,55 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { _inputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioInput)); _outputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioOutput)); - connect(&_inputs, &AudioDeviceList::deviceSelected, this, &AudioDevices::onInputDeviceSelected); - connect(&_outputs, &AudioDeviceList::deviceSelected, this, &AudioDevices::onOutputDeviceSelected); + connect(&_inputs, &AudioDeviceList::deviceSelected, [&](const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { + onDeviceSelected(QAudio::AudioInput, device, previousDevice); + }); + connect(&_outputs, &AudioDeviceList::deviceSelected, [&](const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { + onDeviceSelected(QAudio::AudioOutput, device, previousDevice); + }); } void AudioDevices::onContextChanged(const QString& context) { - QString input; - QString output; - if (_contextIsHMD) { - input = inputDeviceHMD.get(); - output = outputDeviceHMD.get(); - } else { - input = inputDeviceDesktop.get(); - output = outputDeviceDesktop.get(); - } + auto input = getSetting(_contextIsHMD, QAudio::AudioInput).get(); + auto output = getSetting(_contextIsHMD, QAudio::AudioOutput).get(); _inputs.resetDevice(_contextIsHMD, input); _outputs.resetDevice(_contextIsHMD, output); } -void AudioDevices::onInputDeviceSelected(const QAudioDeviceInfo& device) { - QString deviceName; +void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { + QString deviceName = device.isNull() ? QString() : device.deviceName(); + + auto& setting = getSetting(_contextIsHMD, mode); + + // check for a previous device + auto wasDefault = setting.get().isNull(); + + // store the selected device + setting.set(deviceName); + + // log the selected device if (!device.isNull()) { - deviceName = device.deviceName(); - } + QJsonObject data; - if (_contextIsHMD) { - inputDeviceHMD.set(deviceName); - } else { - inputDeviceDesktop.set(deviceName); - } -} + const QString MODE = "audio_mode"; + const QString INPUT = "INPUT"; + const QString OUTPUT = "OUTPUT"; data[MODE] = mode == QAudio::AudioInput ? INPUT : OUTPUT; -void AudioDevices::onOutputDeviceSelected(const QAudioDeviceInfo& device) { - QString deviceName; - if (!device.isNull()) { - deviceName = device.deviceName(); - } + const QString CONTEXT = "display_mode"; + data[CONTEXT] = _contextIsHMD ? Audio::HMD : Audio::DESKTOP; - if (_contextIsHMD) { - outputDeviceHMD.set(deviceName); - } else { - outputDeviceDesktop.set(deviceName); + const QString DISPLAY = "display_device"; + data[DISPLAY] = qApp->getActiveDisplayPlugin()->getName(); + + const QString DEVICE = "device"; + const QString PREVIOUS_DEVICE = "previous_device"; + const QString WAS_DEFAULT = "was_default"; + data[DEVICE] = deviceName; + data[PREVIOUS_DEVICE] = previousDevice.deviceName(); + data[WAS_DEFAULT] = wasDefault; + + UserActivityLogger::getInstance().logAction("selected_audio_device", data); } } @@ -239,4 +263,4 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList _roles; static Qt::ItemFlags _flags; @@ -76,8 +79,7 @@ signals: private slots: void onContextChanged(const QString& context); - void onInputDeviceSelected(const QAudioDeviceInfo& device); - void onOutputDeviceSelected(const QAudioDeviceInfo& device); + void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice); void onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device); void onDevicesChanged(QAudio::Mode mode, const QList& devices);