Merge branch 'master' of github.com:highfidelity/hifi into friction

This commit is contained in:
RebeccaStankus 2019-09-27 09:16:26 -07:00
commit de4e8b9cc4
33 changed files with 475 additions and 240 deletions

View file

@ -433,7 +433,7 @@ void Agent::executeScript() {
using namespace recording; using namespace recording;
static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName()); static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName());
Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) { Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &player, &scriptedAvatar](Frame::ConstPointer frame) {
if (_shouldMuteRecordingAudio) { if (_shouldMuteRecordingAudio) {
return; return;
} }
@ -442,9 +442,18 @@ void Agent::executeScript() {
QByteArray audio(frame->data); QByteArray audio(frame->data);
int16_t* samples = reinterpret_cast<int16_t*>(audio.data());
int numSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL;
auto volume = player->getVolume();
if (volume >= 0.0f && volume < 1.0f) {
int32_t fract = (int32_t)(volume * (float)(1 << 16)); // Q16
for (int i = 0; i < numSamples; i++) {
samples[i] = (fract * (int32_t)samples[i]) >> 16;
}
}
if (_isNoiseGateEnabled) { if (_isNoiseGateEnabled) {
int16_t* samples = reinterpret_cast<int16_t*>(audio.data());
int numSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL;
_audioGate.render(samples, samples, numSamples); _audioGate.render(samples, samples, numSamples);
} }

View file

@ -38,7 +38,7 @@ MixerAvatar::MixerAvatar() {
_pendingEvent = false; _pendingEvent = false;
_verifyState = verificationFailed; _verifyState = verificationFailed;
_needsIdentityUpdate = true; _needsIdentityUpdate = true;
qCDebug(avatars) << "Dynamic verification TIMED-OUT for " << getDisplayName() << getSessionUUID(); qCDebug(avatars) << "Dynamic verification TIMED-OUT for" << getDisplayName() << getSessionUUID();
} else { } else {
qCDebug(avatars) << "Ignoring timeout of avatar challenge"; qCDebug(avatars) << "Ignoring timeout of avatar challenge";
} }
@ -287,7 +287,7 @@ void MixerAvatar::processCertifyEvents() {
<< ":" << _dynamicMarketResponse; << ":" << _dynamicMarketResponse;
} }
} else { } else {
qCDebug(avatars) << "Get owner status failed for " << getDisplayName() << _marketplaceIdFromURL << qCDebug(avatars) << "Get owner status failed for" << getDisplayName() << _marketplaceIdFromURL <<
"message:" << responseJson["message"].toString(); "message:" << responseJson["message"].toString();
_verifyState = error; _verifyState = error;
} }
@ -356,7 +356,7 @@ void MixerAvatar::processChallengeResponse(ReceivedMessage& response) {
_verifyState = challengeResult ? verificationSucceeded : verificationFailed; _verifyState = challengeResult ? verificationSucceeded : verificationFailed;
_needsIdentityUpdate = true; _needsIdentityUpdate = true;
if (_verifyState == verificationFailed) { if (_verifyState == verificationFailed) {
qCDebug(avatars) << "Dynamic verification FAILED for " << getDisplayName() << getSessionUUID(); qCDebug(avatars) << "Dynamic verification FAILED for" << getDisplayName() << getSessionUUID();
} else { } else {
qCDebug(avatars) << "Dynamic verification SUCCEEDED for" << getDisplayName() << getSessionUUID(); qCDebug(avatars) << "Dynamic verification SUCCEEDED for" << getDisplayName() << getSessionUUID();
} }

View file

@ -250,14 +250,14 @@ $(document).ready(function(){
// set focus to the first input in the new row // set focus to the first input in the new row
$target.closest('table').find('tr.inputs input:first').focus(); $target.closest('table').find('tr.inputs input:first').focus();
} } else {
var tableRows = sibling.parent();
var tableBody = tableRows.parent();
var tableRows = sibling.parent(); // if theres no more siblings, we should jump to a new row
var tableBody = tableRows.parent(); if (sibling.next().length == 0 && tableRows.nextAll().length == 1) {
tableBody.find("." + Settings.ADD_ROW_BUTTON_CLASS).click();
// if theres no more siblings, we should jump to a new row }
if (sibling.next().length == 0 && tableRows.nextAll().length == 1) {
tableBody.find("." + Settings.ADD_ROW_BUTTON_CLASS).click();
} }
} }

View file

@ -257,27 +257,26 @@ endif()
def installQt(self): def installQt(self):
qt5InstallPath = self.getQt5InstallPath() qt5InstallPath = self.getQt5InstallPath()
if os.getenv('QT_CMAKE_PREFIX_PATH') == None: if not os.path.isdir(qt5InstallPath):
if not os.path.isdir(qt5InstallPath): print ('Downloading Qt from AWS')
print ('Downloading Qt from AWS') dest, tail = os.path.split(qt5InstallPath)
dest, tail = os.path.split(qt5InstallPath)
url = 'NOT DEFINED' url = 'NOT DEFINED'
if platform.system() == 'Windows': if platform.system() == 'Windows':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz' url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz'
elif platform.system() == 'Darwin': elif platform.system() == 'Darwin':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz' url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz'
elif platform.system() == 'Linux': elif platform.system() == 'Linux':
if platform.linux_distribution()[1][:3] == '16.': if platform.linux_distribution()[1][:3] == '16.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz' url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz'
elif platform.linux_distribution()[1][:3] == '18.': elif platform.linux_distribution()[1][:3] == '18.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz' url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
else:
print('UNKNOWN LINUX VERSION!!!')
else: else:
print('UNKNOWN OPERATING SYSTEM!!!') print('UNKNOWN LINUX VERSION!!!')
print('Extracting ' + url + ' to ' + dest)
hifi_utils.downloadAndExtract(url, dest)
else: else:
print ('Qt has already been downloaded') print('UNKNOWN OPERATING SYSTEM!!!')
print('Extracting ' + url + ' to ' + dest)
hifi_utils.downloadAndExtract(url, dest)
else:
print ('Qt has already been downloaded')

View file

@ -3799,8 +3799,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "reactionPoint", "id": "reactionPoint",
"interpDuration": 18, "interpDuration": 10,
"interpTarget": 18, "interpTarget": 10,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"transitions": [ "transitions": [
{ {
@ -4610,9 +4610,9 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "idle", "id": "idle",
"interpDuration": 30, "interpDuration": 10,
"interpTarget": 30, "interpTarget": 10,
"interpType": "evaluateBoth", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
{ {
"state": "WALKFWD", "state": "WALKFWD",
@ -4742,14 +4742,34 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "idleSettle", "id": "idleSettle",
"interpDuration": 12, "interpDuration": 15,
"interpTarget": 12, "interpTarget": 15,
"interpType": "evaluateBoth", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
{ {
"state": "idle", "state": "idle",
"var": "idleSettleOnDone" "var": "idleSettleOnDone"
}, },
{
"state": "idle",
"var": "reactionPositiveTrigger"
},
{
"state": "idle",
"var": "reactionNegativeTrigger"
},
{
"state": "idle",
"var": "reactionRaiseHandEnabled"
},
{
"state": "idle",
"var": "reactionApplaudEnabled"
},
{
"state": "idle",
"var": "reactionPointEnabled"
},
{ {
"state": "WALKFWD", "state": "WALKFWD",
"var": "isMovingForward" "var": "isMovingForward"
@ -4810,7 +4830,7 @@
}, },
{ {
"id": "WALKFWD", "id": "WALKFWD",
"interpDuration": 10, "interpDuration": 15,
"interpTarget": 35, "interpTarget": 35,
"interpType": "snapshotPrev", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
@ -4874,7 +4894,7 @@
}, },
{ {
"id": "WALKBWD", "id": "WALKBWD",
"interpDuration": 10, "interpDuration": 15,
"interpTarget": 35, "interpTarget": 35,
"interpType": "snapshotPrev", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
@ -4938,7 +4958,7 @@
}, },
{ {
"id": "STRAFERIGHT", "id": "STRAFERIGHT",
"interpDuration": 8, "interpDuration": 15,
"interpTarget": 25, "interpTarget": 25,
"interpType": "snapshotPrev", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
@ -5002,7 +5022,7 @@
}, },
{ {
"id": "STRAFELEFT", "id": "STRAFELEFT",
"interpDuration": 8, "interpDuration": 15,
"interpTarget": 25, "interpTarget": 25,
"interpType": "snapshotPrev", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
@ -5873,7 +5893,6 @@
}, },
"id": "userAnimStateMachine", "id": "userAnimStateMachine",
"type": "stateMachine" "type": "stateMachine"
}, },
"version": "1.1" "version": "1.1"
} }

View file

@ -699,8 +699,8 @@ Item {
spacing: controlsTableRoot.rowPadding spacing: controlsTableRoot.rowPadding
HifiStylesUit.GraphikRegular { HifiStylesUit.GraphikRegular {
id: mirrorText id: selfieText
text: "Mirror Mode" text: "Selfie"
width: paintedWidth width: paintedWidth
height: parent.height height: parent.height
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
@ -710,8 +710,8 @@ Item {
} }
HifiStylesUit.GraphikRegular { HifiStylesUit.GraphikRegular {
text: "See your own avatar" text: "Look at self"
width: parent.width - mirrorText.width - parent.spacing - controlsTableRoot.rowPadding width: parent.width - selfieText.width - parent.spacing - controlsTableRoot.rowPadding
height: parent.height height: parent.height
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter

View file

@ -234,9 +234,19 @@ Flickable {
SimplifiedControls.RadioButton { SimplifiedControls.RadioButton {
id: thirdPerson id: thirdPerson
text: "Third Person View" text: "Third Person View"
checked: Camera.mode === "third person" checked: Camera.mode === "look at"
onClicked: { onClicked: {
Camera.mode = "third person" Camera.mode = "look at"
}
}
SimplifiedControls.RadioButton {
id: selfie
text: "Selfie"
checked: Camera.mode === "selfie"
visible: true
onClicked: {
Camera.mode = "selfie"
} }
} }
@ -246,11 +256,21 @@ Flickable {
onModeUpdated: { onModeUpdated: {
if (Camera.mode === "first person") { if (Camera.mode === "first person") {
firstPerson.checked = true firstPerson.checked = true
} else if (Camera.mode === "third person") { } else if (Camera.mode === "look at") {
thirdPerson.checked = true thirdPerson.checked = true
} else if (Camera.mode === "selfie" && HMD.active) {
selfie.checked = true
} }
} }
} }
Connections {
target: HMD
onDisplayModeChanged: {
selfie.visible = isHMDMode ? false : true
}
}
} }
} }

View file

@ -856,9 +856,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<VirtualPad::Manager>(); DependencyManager::set<VirtualPad::Manager>();
DependencyManager::set<DesktopPreviewProvider>(); DependencyManager::set<DesktopPreviewProvider>();
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
DependencyManager::set<AccountManager>(); // use the default user agent getter DependencyManager::set<AccountManager>(true); // use the default user agent getter
#else #else
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp)); DependencyManager::set<AccountManager>(true, std::bind(&Application::getUserAgent, qApp));
#endif #endif
DependencyManager::set<StatTracker>(); DependencyManager::set<StatTracker>();
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT, defaultScriptsOverrideOption); DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT, defaultScriptsOverrideOption);

View file

@ -4144,6 +4144,7 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition,
_goToOrientation = quatOrientation; _goToOrientation = quatOrientation;
} }
resetLookAtRotation(_goToPosition, _goToOrientation);
emit transformChanged(); emit transformChanged();
} }
@ -5996,6 +5997,7 @@ bool MyAvatar::pinJoint(int index, const glm::vec3& position, const glm::quat& o
} }
slamPosition(position); slamPosition(position);
resetLookAtRotation(position, orientation);
setWorldOrientation(orientation); setWorldOrientation(orientation);
auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index); auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index);
@ -6662,6 +6664,15 @@ void MyAvatar::resetHeadLookAt() {
} }
} }
void MyAvatar::resetLookAtRotation(const glm::vec3& avatarPosition, const glm::quat& avatarOrientation) {
// Align the look at values to the given avatar orientation
float yaw = safeEulerAngles(avatarOrientation).y;
_lookAtYaw = glm::angleAxis(yaw, avatarOrientation * Vectors::UP);
_lookAtPitch = Quaternions::IDENTITY;
_lookAtCameraTarget = avatarPosition + avatarOrientation * Vectors::FRONT;
resetHeadLookAt();
}
void MyAvatar::updateHeadLookAt(float deltaTime) { void MyAvatar::updateHeadLookAt(float deltaTime) {
if (_skeletonModelLoaded) { if (_skeletonModelLoaded) {
glm::vec3 lookAtTarget = _scriptControlsHeadLookAt ? _lookAtScriptTarget : _lookAtCameraTarget; glm::vec3 lookAtTarget = _scriptControlsHeadLookAt ? _lookAtScriptTarget : _lookAtCameraTarget;

View file

@ -2654,11 +2654,6 @@ private:
bool _scriptControlsHeadLookAt { false }; bool _scriptControlsHeadLookAt { false };
float _scriptHeadControlTimer { 0.0f }; float _scriptHeadControlTimer { 0.0f };
// LookAt camera data
float _selfieTriggerAngle { 55.0f };
float _frontLookAtSpeed { 0.15f };
float _backLookAtSpeed { 0.25f };
Setting::Handle<float> _realWorldFieldOfView; Setting::Handle<float> _realWorldFieldOfView;
Setting::Handle<bool> _useAdvancedMovementControls; Setting::Handle<bool> _useAdvancedMovementControls;
Setting::Handle<bool> _showPlayArea; Setting::Handle<bool> _showPlayArea;
@ -2685,6 +2680,7 @@ private:
void initFlowFromFST(); void initFlowFromFST();
void updateHeadLookAt(float deltaTime); void updateHeadLookAt(float deltaTime);
void resetHeadLookAt(); void resetHeadLookAt();
void resetLookAtRotation(const glm::vec3& avatarPosition, const glm::quat& avatarOrientation);
// Avatar Preferences // Avatar Preferences
QUrl _fullAvatarURLFromPreferences; QUrl _fullAvatarURLFromPreferences;

View file

@ -440,13 +440,13 @@ void Audio::handlePushedToTalk(bool enabled) {
} }
} }
void Audio::setInputDevice(const QAudioDeviceInfo& device, bool isHMD) { void Audio::setInputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
withWriteLock([&] { withWriteLock([&] {
_devices.chooseInputDevice(device, isHMD); _devices.chooseInputDevice(device, isHMD);
}); });
} }
void Audio::setOutputDevice(const QAudioDeviceInfo& device, bool isHMD) { void Audio::setOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
withWriteLock([&] { withWriteLock([&] {
_devices.chooseOutputDevice(device, isHMD); _devices.chooseOutputDevice(device, isHMD);
}); });

View file

@ -19,6 +19,7 @@
#include "SettingHandle.h" #include "SettingHandle.h"
#include "AudioFileWav.h" #include "AudioFileWav.h"
#include <shared/ReadWriteLockable.h> #include <shared/ReadWriteLockable.h>
#include <HifiAudioDeviceInfo.h>
using MutedGetter = std::function<bool()>; using MutedGetter = std::function<bool()>;
using MutedSetter = std::function<void(bool)>; using MutedSetter = std::function<void(bool)>;
@ -158,7 +159,7 @@ public:
* @param {boolean} isHMD - Is HMD. * @param {boolean} isHMD - Is HMD.
* @deprecated This function is deprecated and will be removed. * @deprecated This function is deprecated and will be removed.
*/ */
Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device, bool isHMD); Q_INVOKABLE void setInputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
/**jsdoc /**jsdoc
* @function Audio.setOutputDevice * @function Audio.setOutputDevice
@ -166,7 +167,7 @@ public:
* @param {boolean} isHMD - Is HMD. * @param {boolean} isHMD - Is HMD.
* @deprecated This function is deprecated and will be removed. * @deprecated This function is deprecated and will be removed.
*/ */
Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device, bool isHMD); Q_INVOKABLE void setOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
/**jsdoc /**jsdoc
* Enables or disables reverberation. Reverberation is done by the client on the post-mix audio. The reverberation options * Enables or disables reverberation. Reverberation is done by the client on the post-mix audio. The reverberation options

View file

@ -29,6 +29,8 @@ static Setting::Handle<QString> desktopOutputDeviceSetting { QStringList { Audio
static Setting::Handle<QString> hmdInputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "INPUT" }}; static Setting::Handle<QString> hmdInputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "INPUT" }};
static Setting::Handle<QString> hmdOutputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "OUTPUT" }}; static Setting::Handle<QString> hmdOutputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "OUTPUT" }};
Q_DECLARE_METATYPE(HifiAudioDeviceInfo);
Setting::Handle<QString>& getSetting(bool contextIsHMD, QAudio::Mode mode) { Setting::Handle<QString>& getSetting(bool contextIsHMD, QAudio::Mode mode) {
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
return contextIsHMD ? hmdInputDeviceSetting : desktopInputDeviceSetting; return contextIsHMD ? hmdInputDeviceSetting : desktopInputDeviceSetting;
@ -64,6 +66,8 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
} else { // if (_mode == QAudio::AudioOutput) } else { // if (_mode == QAudio::AudioOutput)
deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice(); deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
} }
} else {
deviceName = HifiAudioDeviceInfo::DEFAULT_DEVICE_NAME;
} }
return deviceName; return deviceName;
} }
@ -139,7 +143,7 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
} else if (role == SelectedHMDRole) { } else if (role == SelectedHMDRole) {
return _devices.at(index.row())->selectedHMD; return _devices.at(index.row())->selectedHMD;
} else if (role == InfoRole) { } else if (role == InfoRole) {
return QVariant::fromValue<QAudioDeviceInfo>(_devices.at(index.row())->info); return QVariant::fromValue<HifiAudioDeviceInfo>(_devices.at(index.row())->info);
} else { } else {
return QVariant(); return QVariant();
} }
@ -191,18 +195,13 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) {
#endif #endif
} }
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD) { void AudioDeviceList::onDeviceChanged(const HifiAudioDeviceInfo& device, bool isHMD) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
selectedDevice = device; selectedDevice = device;
for (auto i = 0; i < _devices.size(); ++i) { for (auto i = 0; i < _devices.size(); ++i) {
std::shared_ptr<AudioDevice> device = _devices[i]; std::shared_ptr<AudioDevice> device = _devices[i];
bool& isSelected = isHMD ? device->selectedHMD : device->selectedDesktop; bool& isSelected = isHMD ? device->selectedHMD : device->selectedDesktop;
if (isSelected && device->info != selectedDevice) { isSelected = device->info == selectedDevice;
isSelected = false;
} else if (device->info == selectedDevice) {
isSelected = true;
}
} }
emit deviceChanged(selectedDevice); emit deviceChanged(selectedDevice);
@ -259,37 +258,46 @@ std::shared_ptr<scripting::AudioDevice> getSimilarDevice(const QString& deviceNa
return devices[minDistanceIndex]; return devices[minDistanceIndex];
} }
void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) { void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices) {
beginResetModel(); beginResetModel();
QList<std::shared_ptr<AudioDevice>> newDevices; QList<std::shared_ptr<AudioDevice>> newDevices;
bool hmdIsSelected = false; bool hmdIsSelected = false;
bool desktopIsSelected = false; bool desktopIsSelected = false;
foreach(const QAudioDeviceInfo& deviceInfo, devices) { foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
for (bool isHMD : {false, true}) { for (bool isHMD : {false, true}) {
auto& backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName; auto& backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName;
if (deviceInfo.deviceName() == backupSelectedDeviceName) { if (deviceInfo.deviceName() == backupSelectedDeviceName) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
selectedDevice = deviceInfo; selectedDevice = deviceInfo;
backupSelectedDeviceName.clear(); backupSelectedDeviceName.clear();
} }
} }
} }
foreach(const QAudioDeviceInfo& deviceInfo, devices) { foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
AudioDevice device; AudioDevice device;
device.info = deviceInfo; device.info = deviceInfo;
device.display = device.info.deviceName()
.replace("High Definition", "HD") if (deviceInfo.isDefault()) {
.remove("Device") if (deviceInfo.getMode() == QAudio::AudioInput) {
.replace(" )", ")"); device.display = "Default microphone (recommended)";
} else {
device.display = "Default audio (recommended)";
}
} else {
device.display = device.info.deviceName()
.replace("High Definition", "HD")
.remove("Device")
.replace(" )", ")");
}
for (bool isHMD : {false, true}) { for (bool isHMD : {false, true}) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
bool& isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; bool& isSelected = isHMD ? device.selectedHMD : device.selectedDesktop;
if (!selectedDevice.isNull()) { if (!selectedDevice.getDevice().isNull()) {
isSelected = (device.info == selectedDevice); isSelected = (device.info == selectedDevice);
} }
else { else {
@ -325,13 +333,13 @@ void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
if (!newDevices.isEmpty()) { if (!newDevices.isEmpty()) {
if (!hmdIsSelected) { if (!hmdIsSelected) {
_backupSelectedHMDDeviceName = !_selectedHMDDevice.isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName; _backupSelectedHMDDeviceName = !_selectedHMDDevice.getDevice().isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName;
auto device = getSimilarDevice(_backupSelectedHMDDeviceName, newDevices); auto device = getSimilarDevice(_backupSelectedHMDDeviceName, newDevices);
device->selectedHMD = true; device->selectedHMD = true;
emit selectedDevicePlugged(device->info, true); emit selectedDevicePlugged(device->info, true);
} }
if (!desktopIsSelected) { if (!desktopIsSelected) {
_backupSelectedDesktopDeviceName = !_selectedDesktopDevice.isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName; _backupSelectedDesktopDeviceName = !_selectedDesktopDevice.getDevice().isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName;
auto device = getSimilarDevice(_backupSelectedDesktopDeviceName, newDevices); auto device = getSimilarDevice(_backupSelectedDesktopDeviceName, newDevices);
device->selectedDesktop = true; device->selectedDesktop = true;
emit selectedDevicePlugged(device->info, false); emit selectedDevicePlugged(device->info, false);
@ -382,8 +390,8 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
_outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD); _outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD);
// connections are made after client is initialized, so we must also fetch the devices // connections are made after client is initialized, so we must also fetch the devices
const QList<QAudioDeviceInfo>& devicesInput = client->getAudioDevices(QAudio::AudioInput); const QList<HifiAudioDeviceInfo>& devicesInput = client->getAudioDevices(QAudio::AudioInput);
const QList<QAudioDeviceInfo>& devicesOutput = client->getAudioDevices(QAudio::AudioOutput); const QList<HifiAudioDeviceInfo>& devicesOutput = client->getAudioDevices(QAudio::AudioOutput);
//setup devices //setup devices
_inputs.onDevicesChanged(devicesInput); _inputs.onDevicesChanged(devicesInput);
@ -397,9 +405,9 @@ void AudioDevices::onContextChanged(const QString& context) {
_outputs.resetDevice(_contextIsHMD); _outputs.resetDevice(_contextIsHMD);
} }
void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, void AudioDevices::onDeviceSelected(QAudio::Mode mode, const HifiAudioDeviceInfo& device,
const QAudioDeviceInfo& previousDevice, bool isHMD) { const HifiAudioDeviceInfo& previousDevice, bool isHMD) {
QString deviceName = device.isNull() ? QString() : device.deviceName(); QString deviceName = device.deviceName();
auto& setting = getSetting(isHMD, mode); auto& setting = getSetting(isHMD, mode);
@ -410,7 +418,7 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d
setting.set(deviceName); setting.set(deviceName);
// log the selected device // log the selected device
if (!device.isNull()) { if (!device.getDevice().isNull()) {
QJsonObject data; QJsonObject data;
const QString MODE = "audio_mode"; const QString MODE = "audio_mode";
@ -434,13 +442,13 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d
} }
} }
void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device) { void AudioDevices::onDeviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device) {
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
if (_requestedInputDevice == device) { if (_requestedInputDevice == device) {
onDeviceSelected(QAudio::AudioInput, device, onDeviceSelected(QAudio::AudioInput, device,
_contextIsHMD ? _inputs._selectedHMDDevice : _inputs._selectedDesktopDevice, _contextIsHMD ? _inputs._selectedHMDDevice : _inputs._selectedDesktopDevice,
_contextIsHMD); _contextIsHMD);
_requestedInputDevice = QAudioDeviceInfo(); _requestedInputDevice = HifiAudioDeviceInfo();
} }
_inputs.onDeviceChanged(device, _contextIsHMD); _inputs.onDeviceChanged(device, _contextIsHMD);
} else { // if (mode == QAudio::AudioOutput) } else { // if (mode == QAudio::AudioOutput)
@ -448,13 +456,13 @@ void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& de
onDeviceSelected(QAudio::AudioOutput, device, onDeviceSelected(QAudio::AudioOutput, device,
_contextIsHMD ? _outputs._selectedHMDDevice : _outputs._selectedDesktopDevice, _contextIsHMD ? _outputs._selectedHMDDevice : _outputs._selectedDesktopDevice,
_contextIsHMD); _contextIsHMD);
_requestedOutputDevice = QAudioDeviceInfo(); _requestedOutputDevice = HifiAudioDeviceInfo();
} }
_outputs.onDeviceChanged(device, _contextIsHMD); _outputs.onDeviceChanged(device, _contextIsHMD);
} }
} }
void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices) { void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices) {
static std::once_flag once; static std::once_flag once;
std::call_once(once, [&] { std::call_once(once, [&] {
//readout settings //readout settings
@ -503,14 +511,14 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceI
} }
void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD) { void AudioDevices::chooseInputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
//check if current context equals device to change //check if current context equals device to change
if (_contextIsHMD == isHMD) { if (_contextIsHMD == isHMD) {
auto client = DependencyManager::get<AudioClient>().data(); auto client = DependencyManager::get<AudioClient>().data();
_requestedInputDevice = device; _requestedInputDevice = device;
QMetaObject::invokeMethod(client, "switchAudioDevice", QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(QAudio::Mode, QAudio::AudioInput),
Q_ARG(const QAudioDeviceInfo&, device)); Q_ARG(const HifiAudioDeviceInfo&, device));
} else { } else {
//context is different. just save device in settings //context is different. just save device in settings
onDeviceSelected(QAudio::AudioInput, device, onDeviceSelected(QAudio::AudioInput, device,
@ -520,14 +528,14 @@ void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD)
} }
} }
void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD) { void AudioDevices::chooseOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
//check if current context equals device to change //check if current context equals device to change
if (_contextIsHMD == isHMD) { if (_contextIsHMD == isHMD) {
auto client = DependencyManager::get<AudioClient>().data(); auto client = DependencyManager::get<AudioClient>().data();
_requestedOutputDevice = device; _requestedOutputDevice = device;
QMetaObject::invokeMethod(client, "switchAudioDevice", QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, QAudio::AudioOutput), Q_ARG(QAudio::Mode, QAudio::AudioOutput),
Q_ARG(const QAudioDeviceInfo&, device)); Q_ARG(const HifiAudioDeviceInfo&, device));
} else { } else {
//context is different. just save device in settings //context is different. just save device in settings
onDeviceSelected(QAudio::AudioOutput, device, onDeviceSelected(QAudio::AudioOutput, device,

View file

@ -19,11 +19,13 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QAudioDeviceInfo> #include <QAudioDeviceInfo>
#include <HifiAudioDeviceInfo.h>
namespace scripting { namespace scripting {
class AudioDevice { class AudioDevice {
public: public:
QAudioDeviceInfo info; HifiAudioDeviceInfo info;
QString display; QString display;
bool selectedDesktop { false }; bool selectedDesktop { false };
bool selectedHMD { false }; bool selectedHMD { false };
@ -50,12 +52,12 @@ public:
void resetDevice(bool contextIsHMD); void resetDevice(bool contextIsHMD);
signals: signals:
void deviceChanged(const QAudioDeviceInfo& device); void deviceChanged(const HifiAudioDeviceInfo& device);
void selectedDevicePlugged(const QAudioDeviceInfo& device, bool isHMD); void selectedDevicePlugged(const HifiAudioDeviceInfo& device, bool isHMD);
protected slots: protected slots:
void onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD); void onDeviceChanged(const HifiAudioDeviceInfo& device, bool isHMD);
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices); void onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices);
protected: protected:
friend class AudioDevices; friend class AudioDevices;
@ -63,8 +65,8 @@ protected:
static QHash<int, QByteArray> _roles; static QHash<int, QByteArray> _roles;
static Qt::ItemFlags _flags; static Qt::ItemFlags _flags;
const QAudio::Mode _mode; const QAudio::Mode _mode;
QAudioDeviceInfo _selectedDesktopDevice; HifiAudioDeviceInfo _selectedDesktopDevice;
QAudioDeviceInfo _selectedHMDDevice; HifiAudioDeviceInfo _selectedHMDDevice;
QString _backupSelectedDesktopDeviceName; QString _backupSelectedDesktopDeviceName;
QString _backupSelectedHMDDeviceName; QString _backupSelectedHMDDeviceName;
QList<std::shared_ptr<AudioDevice>> _devices; QList<std::shared_ptr<AudioDevice>> _devices;
@ -124,14 +126,14 @@ signals:
void nop(); void nop();
private slots: private slots:
void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD); void chooseInputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD); void chooseOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
void onContextChanged(const QString& context); void onContextChanged(const QString& context);
void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, void onDeviceSelected(QAudio::Mode mode, const HifiAudioDeviceInfo& device,
const QAudioDeviceInfo& previousDevice, bool isHMD); const HifiAudioDeviceInfo& previousDevice, bool isHMD);
void onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device); void onDeviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device);
void onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices); void onDevicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices);
private: private:
friend class Audio; friend class Audio;
@ -141,8 +143,8 @@ private:
AudioInputDeviceList _inputs; AudioInputDeviceList _inputs;
AudioDeviceList _outputs { QAudio::AudioOutput }; AudioDeviceList _outputs { QAudio::AudioOutput };
QAudioDeviceInfo _requestedOutputDevice; HifiAudioDeviceInfo _requestedOutputDevice;
QAudioDeviceInfo _requestedInputDevice; HifiAudioDeviceInfo _requestedInputDevice;
const bool& _contextIsHMD; const bool& _contextIsHMD;
}; };

View file

@ -50,9 +50,6 @@ ContextOverlayInterface::ContextOverlayInterface() {
_entityPropertyFlags += PROP_OWNING_AVATAR_ID; _entityPropertyFlags += PROP_OWNING_AVATAR_ID;
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
/* REMOVING THIS AS AN EMERGENCY FIX. We will be returning to modify the code so that MP inspection is not intrusive in domains with a lot of certified content.
Jira bug to remove inspection temporarily: https://highfidelity.atlassian.net/browse/DEV-639
Jira bug to modify it and bring it back: https://highfidelity.atlassian.net/browse/DEV-645
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::clickDownOnEntity); connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::clickDownOnEntity);
connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, &ContextOverlayInterface::mouseReleaseOnEntity); connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, &ContextOverlayInterface::mouseReleaseOnEntity);
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, &ContextOverlayInterface::contextOverlays_hoverEnterEntity); connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, &ContextOverlayInterface::contextOverlays_hoverEnterEntity);
@ -60,7 +57,6 @@ ContextOverlayInterface::ContextOverlayInterface() {
connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay); connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay); connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
*/
connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() { connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() {
if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) { if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) {

View file

@ -91,11 +91,23 @@ using Lock = std::unique_lock<Mutex>;
Mutex _deviceMutex; Mutex _deviceMutex;
Mutex _recordMutex; Mutex _recordMutex;
HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode);
// thread-safe // thread-safe
QList<QAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) { QList<HifiAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
// NOTE: availableDevices() clobbers the Qt internal device list // NOTE: availableDevices() clobbers the Qt internal device list
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
return QAudioDeviceInfo::availableDevices(mode); auto devices = QAudioDeviceInfo::availableDevices(mode);
QList<HifiAudioDeviceInfo> newDevices;
for (auto& device : devices) {
newDevices.push_back(HifiAudioDeviceInfo(device, false, mode));
}
newDevices.push_front(defaultAudioDeviceForMode(mode));
return newDevices;
} }
// now called from a background thread, to keep blocking operations off the audio thread // now called from a background thread, to keep blocking operations off the audio thread
@ -109,6 +121,9 @@ void AudioClient::checkDevices() {
auto inputDevices = getAvailableDevices(QAudio::AudioInput); auto inputDevices = getAvailableDevices(QAudio::AudioInput);
auto outputDevices = getAvailableDevices(QAudio::AudioOutput); auto outputDevices = getAvailableDevices(QAudio::AudioOutput);
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, inputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioInput));
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, outputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioOutput));
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
if (inputDevices != _inputDevices) { if (inputDevices != _inputDevices) {
@ -122,22 +137,22 @@ void AudioClient::checkDevices() {
} }
} }
QAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const { HifiAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
return _inputDeviceInfo; return _inputDeviceInfo;
} else { // if (mode == QAudio::AudioOutput) } else {
return _outputDeviceInfo; return _outputDeviceInfo;
} }
} }
QList<QAudioDeviceInfo> AudioClient::getAudioDevices(QAudio::Mode mode) const { QList<HifiAudioDeviceInfo> AudioClient::getAudioDevices(QAudio::Mode mode) const {
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
return _inputDevices; return _inputDevices;
} else { // if (mode == QAudio::AudioOutput) } else {
return _outputDevices; return _outputDevices;
} }
} }
@ -226,7 +241,7 @@ static float computeLoudness(int16_t* samples, int numSamples) {
template <int NUM_CHANNELS> template <int NUM_CHANNELS>
static void applyGainSmoothing(float* buffer, int numFrames, float gain0, float gain1) { static void applyGainSmoothing(float* buffer, int numFrames, float gain0, float gain1) {
// fast path for unity gain // fast path for unity gain
if (gain0 == 1.0f && gain1 == 1.0f) { if (gain0 == 1.0f && gain1 == 1.0f) {
return; return;
@ -241,7 +256,7 @@ static void applyGainSmoothing(float* buffer, int numFrames, float gain0, float
float tStep = 1.0f / numFrames; float tStep = 1.0f / numFrames;
for (int i = 0; i < numFrames; i++) { for (int i = 0; i < numFrames; i++) {
// evaluate poly over t=[0,1) // evaluate poly over t=[0,1)
float gain = (c3 * t + c2) * t * t + c0; float gain = (c3 * t + c2) * t * t + c0;
t += tStep; t += tStep;
@ -321,9 +336,9 @@ AudioClient::AudioClient() :
} }
connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples, connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples,
this, &AudioClient::processReceivedSamples, Qt::DirectConnection); this, &AudioClient::processReceivedSamples, Qt::DirectConnection);
connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) { connect(this, &AudioClient::changeDevice, this, [=](const HifiAudioDeviceInfo& outputDeviceInfo) {
qCDebug(audioclient) << "got AudioClient::changeDevice signal, about to call switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]"; qCDebug(audioclient)<< "got AudioClient::changeDevice signal, about to call switchOutputToAudioDevice() outputDeviceInfo: ["<< outputDeviceInfo.deviceName() << "]";
switchOutputToAudioDevice(outputDeviceInfo); switchOutputToAudioDevice(outputDeviceInfo);
}); });
@ -373,7 +388,7 @@ AudioClient::AudioClient() :
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat"); packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
auto& domainHandler = nodeList->getDomainHandler(); auto& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this] { connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this] {
_solo.reset(); _solo.reset();
}); });
connect(nodeList.data(), &NodeList::nodeActivated, this, [this](SharedNodePointer node) { connect(nodeList.data(), &NodeList::nodeActivated, this, [this](SharedNodePointer node) {
@ -431,15 +446,14 @@ void AudioClient::setAudioPaused(bool pause) {
} }
} }
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
QAudioDeviceInfo result; HifiAudioDeviceInfo result;
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) { if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
result = audioDevice; result = audioDevice;
break; break;
} }
} }
return result; return result;
} }
@ -487,9 +501,11 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) {
#endif #endif
QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(mode);
#ifdef __APPLE__ #ifdef __APPLE__
if (getAvailableDevices(mode).size() > 1) { if (devices.size() > 1) {
AudioDeviceID defaultDeviceID = 0; AudioDeviceID defaultDeviceID = 0;
uint32_t propertySize = sizeof(AudioDeviceID); uint32_t propertySize = sizeof(AudioDeviceID);
AudioObjectPropertyAddress propertyAddress = { AudioObjectPropertyAddress propertyAddress = {
@ -519,9 +535,9 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
if (!getPropertyError && propertySize) { if (!getPropertyError && propertySize) {
// find a device in the list that matches the name we have and return it // find a device in the list that matches the name we have and return it
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { foreach(QAudioDeviceInfo audioDevice, devices){
if (audioDevice.deviceName() == CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman)) { if (audioDevice.deviceName() == CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman)) {
return audioDevice; return HifiAudioDeviceInfo(audioDevice, true, mode);
} }
} }
} }
@ -569,10 +585,18 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
CoUninitialize(); CoUninitialize();
} }
qCDebug(audioclient) << "defaultAudioDeviceForMode mode: " << (mode == QAudio::AudioOutput ? "Output" : "Input") HifiAudioDeviceInfo foundDevice;
<< " [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]"; foreach(QAudioDeviceInfo audioDevice, devices) {
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
foundDevice=HifiAudioDeviceInfo(audioDevice,true,mode);
break;
}
}
qCDebug(audioclient) << "defaultAudioDeviceForMode mode: " << (mode == QAudio::AudioOutput ? "Output" : "Input")
<< " [" << deviceName << "] [" << foundDevice.deviceName() << "]";
return getNamedAudioDeviceForMode(mode, deviceName); return foundDevice;
#endif #endif
#if defined (Q_OS_ANDROID) #if defined (Q_OS_ANDROID)
@ -580,18 +604,18 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
Setting::Handle<bool> enableAEC(SETTING_AEC_KEY, DEFAULT_AEC_ENABLED); Setting::Handle<bool> enableAEC(SETTING_AEC_KEY, DEFAULT_AEC_ENABLED);
bool aecEnabled = enableAEC.get(); bool aecEnabled = enableAEC.get();
auto audioClient = DependencyManager::get<AudioClient>(); auto audioClient = DependencyManager::get<AudioClient>();
bool headsetOn = audioClient? audioClient->isHeadsetPluggedIn() : false; bool headsetOn = audioClient ? audioClient->isHeadsetPluggedIn() : false;
auto inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); for (QAudioDeviceInfo inputDevice : devices) {
for (auto inputDevice : inputDevices) {
if (((headsetOn || !aecEnabled) && inputDevice.deviceName() == VOICE_RECOGNITION) || if (((headsetOn || !aecEnabled) && inputDevice.deviceName() == VOICE_RECOGNITION) ||
((!headsetOn && aecEnabled) && inputDevice.deviceName() == VOICE_COMMUNICATION)) { ((!headsetOn && aecEnabled) && inputDevice.deviceName() == VOICE_COMMUNICATION)) {
return inputDevice; return HifiAudioDeviceInfo(inputDevice, false, QAudio::AudioInput);
} }
} }
} }
#endif #endif
// fallback for failed lookup is the default device // fallback for failed lookup is the default device
return (mode == QAudio::AudioInput) ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice(); return (mode == QAudio::AudioInput) ? HifiAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice(), true,mode) :
HifiAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice(), true, mode);
} }
bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) { bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) {
@ -643,29 +667,29 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
if (IsWindows8OrGreater()) { if (IsWindows8OrGreater()) {
// On Windows using WASAPI shared-mode, returns the internal mix format // On Windows using WASAPI shared-mode, returns the internal mix format
return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat); return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat);
} // else enumerate formats } // else enumerate formats
#endif #endif
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
// Mac OSX returns the preferred CoreAudio format // Mac OSX returns the preferred CoreAudio format
return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat); return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat);
#endif #endif
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
// As of Qt5.6, Android returns the native OpenSLES sample rate when possible, else 48000 // As of Qt5.6, Android returns the native OpenSLES sample rate when possible, else 48000
if (nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat)) { if (nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat)) {
return true; return true;
} // else enumerate formats } // else enumerate formats
#endif #endif
adjustedAudioFormat = desiredAudioFormat; adjustedAudioFormat = desiredAudioFormat;
// //
// Attempt the device sample rate and channel count in decreasing order of preference. // Attempt the device sample rate and channel count in decreasing order of preference.
// //
const int sampleRates[] = { 48000, 44100, 32000, 24000, 16000, 96000, 192000, 88200, 176400 }; const int sampleRates[] = { 48000, 44100, 32000, 24000, 16000, 96000, 192000, 88200, 176400 };
const int inputChannels[] = { 1, 2, 4, 6, 8 }; // prefer mono const int inputChannels[] = { 1, 2, 4, 6, 8 }; // prefer mono
const int outputChannels[] = { 2, 4, 6, 8, 1 }; // prefer stereo, downmix as last resort const int outputChannels[] = { 2, 4, 6, 8, 1 }; // prefer stereo, downmix as last resort
for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) { for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) {
for (int sampleRate : sampleRates) { for (int sampleRate : sampleRates) {
@ -758,22 +782,22 @@ void AudioClient::start() {
_desiredOutputFormat = _desiredInputFormat; _desiredOutputFormat = _desiredInputFormat;
_desiredOutputFormat.setChannelCount(OUTPUT_CHANNEL_COUNT); _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(); qCDebug(audioclient) << "The default audio input device is" << inputDeviceInfo.deviceName();
bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo); bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo);
QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); HifiAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput);
qCDebug(audioclient) << "The default audio output device is" << outputDeviceInfo.deviceName(); qCDebug(audioclient) << "The default audio output device is" << outputDeviceInfo.deviceName();
bool outputFormatSupported = switchOutputToAudioDevice(outputDeviceInfo); bool outputFormatSupported = switchOutputToAudioDevice(outputDeviceInfo);
if (!inputFormatSupported) { if (!inputFormatSupported) {
qCDebug(audioclient) << "Unable to set up audio input because of a problem with input format."; 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) { if (!outputFormatSupported) {
qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format."; 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) #if defined(Q_OS_ANDROID)
connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout); connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout);
@ -783,10 +807,10 @@ void AudioClient::start() {
void AudioClient::stop() { void AudioClient::stop() {
qCDebug(audioclient) << "AudioClient::stop(), requesting switchInputToAudioDevice() to shut down"; qCDebug(audioclient) << "AudioClient::stop(), requesting switchInputToAudioDevice() to shut down";
switchInputToAudioDevice(QAudioDeviceInfo(), true); switchInputToAudioDevice(HifiAudioDeviceInfo(), true);
qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down"; qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down";
switchOutputToAudioDevice(QAudioDeviceInfo(), true); switchOutputToAudioDevice(HifiAudioDeviceInfo(), true);
// Stop triggering the checks // Stop triggering the checks
QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr); QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr);
@ -978,16 +1002,18 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
} }
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo) { void AudioClient::changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode) {
auto device = deviceInfo; HifiAudioDeviceInfo currentDevice = mode == QAudio::AudioInput ? _inputDeviceInfo : _outputDeviceInfo;
if (currentDevice.isDefault() && currentDevice.getDevice() != newDefault.getDevice()) {
if (device.isNull()) { switchAudioDevice(mode, newDefault);
device = defaultAudioDeviceForMode(mode);
} }
}
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo) {
auto device = deviceInfo;
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
return switchInputToAudioDevice(device); return switchInputToAudioDevice(device);
} else { // if (mode == QAudio::AudioOutput) } else {
return switchOutputToAudioDevice(device); return switchOutputToAudioDevice(device);
} }
} }
@ -1030,7 +1056,7 @@ void AudioClient::configureReverb() {
p.wetDryMix = 100.0f; p.wetDryMix = 100.0f;
p.preDelay = 0.0f; p.preDelay = 0.0f;
p.earlyGain = -96.0f; // disable ER p.earlyGain = -96.0f; // disable ER
p.lateGain += _reverbOptions->getWetDryMix() * (24.0f/100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix p.lateGain += _reverbOptions->getWetDryMix() * (24.0f / 100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix
p.lateMixLeft = 0.0f; p.lateMixLeft = 0.0f;
p.lateMixRight = 0.0f; p.lateMixRight = 0.0f;
@ -1414,7 +1440,7 @@ void AudioClient::handleMicAudioInput() {
} else if (_timeSinceLastClip >= 0.0f) { } else if (_timeSinceLastClip >= 0.0f) {
_timeSinceLastClip += AudioConstants::NETWORK_FRAME_SECS; _timeSinceLastClip += AudioConstants::NETWORK_FRAME_SECS;
} }
isClipping = (_timeSinceLastClip >= 0.0f) && (_timeSinceLastClip < 2.0f); // 2 second hold time isClipping = (_timeSinceLastClip >= 0.0f) && (_timeSinceLastClip < 2.0f); // 2 second hold time
#if defined(WEBRTC_ENABLED) #if defined(WEBRTC_ENABLED)
if (_isAECEnabled) { if (_isAECEnabled) {
@ -1453,7 +1479,7 @@ void AudioClient::handleDummyAudioInput() {
? AudioConstants::NETWORK_FRAME_BYTES_STEREO ? AudioConstants::NETWORK_FRAME_BYTES_STEREO
: AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL; : AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
QByteArray audioBuffer(numNetworkBytes, 0); // silent QByteArray audioBuffer(numNetworkBytes, 0); // silent
handleAudioInput(audioBuffer); handleAudioInput(audioBuffer);
} }
@ -1598,7 +1624,7 @@ bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) {
// direct mix into mixBuffer // direct mix into mixBuffer
injector->getLocalHRTF().mixStereo(_localScratchBuffer, mixBuffer, gain, injector->getLocalHRTF().mixStereo(_localScratchBuffer, mixBuffer, gain,
AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
} else { // injector is mono } else { // injector is mono
if (options.positionSet) { if (options.positionSet) {
@ -1736,7 +1762,7 @@ void AudioClient::setAcousticEchoCancellation(bool enable, bool emitSignal) {
bool AudioClient::setIsStereoInput(bool isStereoInput) { bool AudioClient::setIsStereoInput(bool isStereoInput) {
bool stereoInputChanged = false; bool stereoInputChanged = false;
if (isStereoInput != _isStereoInput && _inputDeviceInfo.supportedChannelCounts().contains(2)) { if (isStereoInput != _isStereoInput && _inputDeviceInfo.getDevice().supportedChannelCounts().contains(2)) {
_isStereoInput = isStereoInput; _isStereoInput = isStereoInput;
stereoInputChanged = true; stereoInputChanged = true;
@ -1798,17 +1824,17 @@ void AudioClient::outputFormatChanged() {
_receivedAudioStream.outputFormatChanged(_outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT); _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"); 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.deviceName() <<"----"<<inputDeviceInfo.getDevice().deviceName() << "]";
bool supportedFormat = false; bool supportedFormat = false;
// NOTE: device start() uses the Qt internal device list // NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
_shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged _shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged
#endif #endif
// cleanup any previously initialized device // cleanup any previously initialized device
@ -1822,8 +1848,6 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
_audioInput->deleteLater(); _audioInput->deleteLater();
_audioInput = NULL; _audioInput = NULL;
_numInputCallbackBytes = 0; _numInputCallbackBytes = 0;
_inputDeviceInfo = QAudioDeviceInfo();
} }
if (_dummyAudioInput) { if (_dummyAudioInput) {
@ -1854,12 +1878,16 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
return true; return true;
} }
if (!inputDeviceInfo.isNull()) { if (!inputDeviceInfo.getDevice().isNull()) {
qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available.";
bool doEmit = _inputDeviceInfo.deviceName() != inputDeviceInfo.deviceName();
_inputDeviceInfo = inputDeviceInfo; _inputDeviceInfo = inputDeviceInfo;
emit deviceChanged(QAudio::AudioInput, inputDeviceInfo); if (doEmit) {
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; qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat;
// we've got the best we can get for input // we've got the best we can get for input
@ -1884,7 +1912,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
// if the user wants stereo but this device can't provide then bail // if the user wants stereo but this device can't provide then bail
if (!_isStereoInput || _inputFormat.channelCount() == 2) { if (!_isStereoInput || _inputFormat.channelCount() == 2) {
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this); _audioInput = new QAudioInput(_inputDeviceInfo.getDevice(), _inputFormat, this);
_numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat); _numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat);
_audioInput->setBufferSize(_numInputCallbackBytes); _audioInput->setBufferSize(_numInputCallbackBytes);
// different audio input devices may have different volumes // different audio input devices may have different volumes
@ -1906,7 +1934,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleMicAudioInput())); connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleMicAudioInput()));
supportedFormat = true; supportedFormat = true;
} else { } else {
qCDebug(audioclient) << "Error starting audio input -" << _audioInput->error(); qCDebug(audioclient) << "Error starting audio input -" << _audioInput->error();
_audioInput->deleteLater(); _audioInput->deleteLater();
_audioInput = NULL; _audioInput = NULL;
} }
@ -1919,7 +1947,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
// This enables clients without a mic to still receive an audio stream from the mixer. // This enables clients without a mic to still receive an audio stream from the mixer.
if (!_audioInput) { if (!_audioInput) {
qCDebug(audioclient) << "Audio input device is not available, using dummy input."; qCDebug(audioclient) << "Audio input device is not available, using dummy input.";
_inputDeviceInfo = QAudioDeviceInfo(); _inputDeviceInfo.setDevice(QAudioDeviceInfo());
emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo); emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo);
_inputFormat = _desiredInputFormat; _inputFormat = _desiredInputFormat;
@ -1975,11 +2003,11 @@ void AudioClient::checkInputTimeout() {
void AudioClient::setHeadsetPluggedIn(bool pluggedIn) { void AudioClient::setHeadsetPluggedIn(bool pluggedIn) {
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
if (pluggedIn == !_isHeadsetPluggedIn && !_inputDeviceInfo.isNull()) { if (pluggedIn == !_isHeadsetPluggedIn && !_inputDeviceInfo.getDevice().isNull()) {
QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField<jstring>("android/os/Build", "BRAND"); QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField<jstring>("android/os/Build", "BRAND");
// some samsung phones needs more time to shutdown the previous input device // some samsung phones needs more time to shutdown the previous input device
if (brand.toString().contains("samsung", Qt::CaseInsensitive)) { if (brand.toString().contains("samsung", Qt::CaseInsensitive)) {
switchInputToAudioDevice(QAudioDeviceInfo(), true); switchInputToAudioDevice(HifiAudioDeviceInfo(), true);
QThread::msleep(200); QThread::msleep(200);
} }
@ -2026,7 +2054,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"); Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]"; qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
@ -2061,8 +2089,6 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
delete[] _localOutputMixBuffer; delete[] _localOutputMixBuffer;
_localOutputMixBuffer = NULL; _localOutputMixBuffer = NULL;
_outputDeviceInfo = QAudioDeviceInfo();
} }
// cleanup any resamplers // cleanup any resamplers
@ -2086,12 +2112,15 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
return true; return true;
} }
if (!outputDeviceInfo.isNull()) { if (!outputDeviceInfo.getDevice().isNull()) {
qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available.";
bool doEmit = _outputDeviceInfo.deviceName() != outputDeviceInfo.deviceName();
_outputDeviceInfo = outputDeviceInfo; _outputDeviceInfo = outputDeviceInfo;
emit deviceChanged(QAudio::AudioOutput, outputDeviceInfo); if (doEmit) {
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; qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat;
// we've got the best we can get for input // we've got the best we can get for input
@ -2113,7 +2142,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
outputFormatChanged(); outputFormatChanged();
// setup our general output device for audio-mixer audio // 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 deviceChannelCount = _outputFormat.channelCount();
int frameSize = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * deviceChannelCount * _outputFormat.sampleRate()) / _desiredOutputFormat.sampleRate(); int frameSize = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * deviceChannelCount * _outputFormat.sampleRate()) / _desiredOutputFormat.sampleRate();
@ -2165,7 +2194,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
localAudioLock.unlock(); localAudioLock.unlock();
// setup a loopback audio output device // setup a loopback audio output device
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo.getDevice(), _outputFormat, this);
_timeSinceLastReceived.start(); _timeSinceLastReceived.start();
@ -2239,7 +2268,7 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) {
// produce an oriented angle about the y-axis // produce an oriented angle about the y-axis
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
return (direction.x < 0.0f) ? -angle : angle; return (direction.x < 0.0f) ? -angle : angle;
} else { } else {
@ -2423,4 +2452,4 @@ void AudioClient::setInputVolume(float volume, bool emitSignal) {
emit inputVolumeChanged(_audioInput->volume()); emit inputVolumeChanged(_audioInput->volume());
} }
} }
} }

View file

@ -53,6 +53,7 @@
#include "AudioIOStats.h" #include "AudioIOStats.h"
#include "AudioFileWav.h" #include "AudioFileWav.h"
#include "HifiAudioDeviceInfo.h"
#ifdef _WIN32 #ifdef _WIN32
#pragma warning( push ) #pragma warning( push )
@ -102,8 +103,8 @@ public:
_audio(audio), _unfulfilledReads(0) {} _audio(audio), _unfulfilledReads(0) {}
void start() { open(QIODevice::ReadOnly | QIODevice::Unbuffered); } void start() { open(QIODevice::ReadOnly | QIODevice::Unbuffered); }
qint64 readData(char * data, qint64 maxSize) override; qint64 readData(char* data, qint64 maxSize) override;
qint64 writeData(const char * data, qint64 maxSize) override { return 0; } qint64 writeData(const char* data, qint64 maxSize) override { return 0; }
int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; } int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; }
private: private:
LocalInjectorsStream& _localInjectorsStream; LocalInjectorsStream& _localInjectorsStream;
@ -111,7 +112,7 @@ public:
AudioClient* _audio; AudioClient* _audio;
int _unfulfilledReads; int _unfulfilledReads;
}; };
void startThread(); void startThread();
void negotiateAudioFormat(); void negotiateAudioFormat();
void selectAudioFormat(const QString& selectedCodecName); void selectAudioFormat(const QString& selectedCodecName);
@ -152,12 +153,12 @@ public:
void setIsPlayingBackRecording(bool isPlayingBackRecording) { _isPlayingBackRecording = isPlayingBackRecording; } void setIsPlayingBackRecording(bool isPlayingBackRecording) { _isPlayingBackRecording = isPlayingBackRecording; }
Q_INVOKABLE void setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 scale); Q_INVOKABLE void setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 scale);
bool outputLocalInjector(const AudioInjectorPointer& injector) override; bool outputLocalInjector(const AudioInjectorPointer& injector) override;
QAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const; HifiAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const;
QList<QAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const; QList<HifiAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const;
void enablePeakValues(bool enable) { _enablePeakValues = enable; } void enablePeakValues(bool enable) { _enablePeakValues = enable; }
bool peakValuesAvailable() const; bool peakValuesAvailable() const;
@ -233,11 +234,11 @@ public slots:
int setOutputBufferSize(int numFrames, bool persist = true); int setOutputBufferSize(int numFrames, bool persist = true);
bool shouldLoopbackInjectors() override { return _shouldEchoToServer; } bool shouldLoopbackInjectors() override { return _shouldEchoToServer; }
Q_INVOKABLE void changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode);
// calling with a null QAudioDevice will use the system default // 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); bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
// Qt opensles plugin is not able to detect when the headset is plugged in // Qt opensles plugin is not able to detect when the headset is plugged in
void setHeadsetPluggedIn(bool pluggedIn); void setHeadsetPluggedIn(bool pluggedIn);
@ -269,10 +270,10 @@ signals:
void noiseGateOpened(); void noiseGateOpened();
void noiseGateClosed(); void noiseGateClosed();
void changeDevice(const QAudioDeviceInfo& outputDeviceInfo); void changeDevice(const HifiAudioDeviceInfo& outputDeviceInfo);
void deviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device); void deviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device);
void devicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices); void devicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices);
void peakValueListChanged(const QList<float> peakValueList); void peakValueListChanged(const QList<float> peakValueList);
void receivedFirstPacket(); void receivedFirstPacket();
@ -416,7 +417,7 @@ private:
float* _localOutputMixBuffer { NULL }; float* _localOutputMixBuffer { NULL };
Mutex _localAudioMutex; Mutex _localAudioMutex;
AudioLimiter _audioLimiter; AudioLimiter _audioLimiter;
// Adds Reverb // Adds Reverb
void configureReverb(); void configureReverb();
void updateReverbOptions(); void updateReverbOptions();
@ -437,8 +438,8 @@ private:
void processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate); void processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate);
#endif #endif
bool switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false); bool switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false);
bool switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false); bool switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false);
// Callback acceleration dependent calculations // Callback acceleration dependent calculations
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const; int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
@ -459,11 +460,11 @@ private:
glm::vec3 avatarBoundingBoxCorner; glm::vec3 avatarBoundingBoxCorner;
glm::vec3 avatarBoundingBoxScale; glm::vec3 avatarBoundingBoxScale;
QAudioDeviceInfo _inputDeviceInfo; HifiAudioDeviceInfo _inputDeviceInfo;
QAudioDeviceInfo _outputDeviceInfo; HifiAudioDeviceInfo _outputDeviceInfo;
QList<QAudioDeviceInfo> _inputDevices; QList<HifiAudioDeviceInfo> _inputDevices;
QList<QAudioDeviceInfo> _outputDevices; QList<HifiAudioDeviceInfo> _outputDevices;
AudioFileWav _audioFileWav; AudioFileWav _audioFileWav;
@ -476,7 +477,7 @@ private:
CodecPluginPointer _codec; CodecPluginPointer _codec;
QString _selectedCodecName; QString _selectedCodecName;
Encoder* _encoder { nullptr }; // for outbound mic stream Encoder* _encoder { nullptr }; // for outbound mic stream
RateCounter<> _silentOutbound; RateCounter<> _silentOutbound;
RateCounter<> _audioOutbound; RateCounter<> _audioOutbound;
@ -484,11 +485,11 @@ private:
RateCounter<> _audioInbound; RateCounter<> _audioInbound;
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
bool _shouldRestartInputSetup { true }; // Should we restart the input device because of an unintended stop? bool _shouldRestartInputSetup { true }; // Should we restart the input device because of an unintended stop?
#endif #endif
AudioSolo _solo; AudioSolo _solo;
Mutex _checkDevicesMutex; Mutex _checkDevicesMutex;
QTimer* _checkDevicesTimer { nullptr }; QTimer* _checkDevicesTimer { nullptr };
Mutex _checkPeakValuesMutex; Mutex _checkPeakValuesMutex;
@ -498,4 +499,4 @@ private:
}; };
#endif // hifi_AudioClient_h #endif // hifi_AudioClient_h

View file

@ -0,0 +1,36 @@
//
// HifiAudioDeviceInfo.cpp
// libraries/audio-client/src
//
// Created by Amer Cerkic on 9/14/19.
// Copyright 2019 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 "HifiAudioDeviceInfo.h"
const QString HifiAudioDeviceInfo::DEFAULT_DEVICE_NAME = "default ";
void HifiAudioDeviceInfo::setDevice(QAudioDeviceInfo devInfo) {
_audioDeviceInfo = devInfo;
}
HifiAudioDeviceInfo& HifiAudioDeviceInfo::operator=(const HifiAudioDeviceInfo& other) {
_audioDeviceInfo = other.getDevice();
_mode = other.getMode();
_isDefault = other.isDefault();
return *this;
}
bool HifiAudioDeviceInfo::operator==(const HifiAudioDeviceInfo& rhs) const {
//Does the QAudioDeviceinfo match as well as is this the default device or
return getDevice() == rhs.getDevice() && isDefault() == rhs.isDefault();
}
bool HifiAudioDeviceInfo::operator!=(const HifiAudioDeviceInfo& rhs) const {
return getDevice() != rhs.getDevice() || isDefault() != rhs.isDefault();
}

View file

@ -0,0 +1,69 @@
//
// HifiAudioDeviceInfo.h
// libraries/audio-client/src
//
// Created by Amer Cerkic on 9/14/19.
// Copyright 2019 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
//
#pragma once
#ifndef hifi_audiodeviceinfo_h
#define hifi_audiodeviceinfo_h
#include <QObject>
#include <QAudioDeviceInfo>
#include <QAudio>
#include <QString>
class HifiAudioDeviceInfo : public QObject {
Q_OBJECT
public:
HifiAudioDeviceInfo() : QObject() {}
HifiAudioDeviceInfo(const HifiAudioDeviceInfo &deviceInfo) : QObject(){
_audioDeviceInfo = deviceInfo.getDevice();
_mode = deviceInfo.getMode();
_isDefault = deviceInfo.isDefault();
}
HifiAudioDeviceInfo(QAudioDeviceInfo deviceInfo, bool isDefault, QAudio::Mode mode) :
_audioDeviceInfo(deviceInfo),
_isDefault(isDefault),
_mode(mode){
}
void setMode(QAudio::Mode mode) { _mode = mode; }
void setIsDefault() { _isDefault = true; }
void setDevice(QAudioDeviceInfo devInfo);
QString deviceName() const {
#if defined(Q_OS_ANDROID)
return _audioDeviceInfo.deviceName();
#endif
if (_isDefault) {
return DEFAULT_DEVICE_NAME;
} else {
return _audioDeviceInfo.deviceName();
}
}
QAudioDeviceInfo getDevice() const { return _audioDeviceInfo; }
bool isDefault() const { return _isDefault; }
QAudio::Mode getMode() const { return _mode; }
HifiAudioDeviceInfo& operator=(const HifiAudioDeviceInfo& other);
bool operator==(const HifiAudioDeviceInfo& rhs) const;
bool operator!=(const HifiAudioDeviceInfo& rhs) const;
private:
QAudioDeviceInfo _audioDeviceInfo;
bool _isDefault { false };
QAudio::Mode _mode { QAudio::AudioInput };
public:
static const QString DEFAULT_DEVICE_NAME;
};
#endif

View file

@ -48,7 +48,8 @@ Q_DECLARE_METATYPE(JSONCallbackParameters)
const QString ACCOUNTS_GROUP = "accounts"; const QString ACCOUNTS_GROUP = "accounts";
const int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; const int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND;
const int PULL_SETTINGS_RETRY_INTERVAL = 1 * MSECS_PER_SECOND; const int PULL_SETTINGS_RETRY_INTERVAL = 2 * MSECS_PER_SECOND;
const int MAX_PULL_RETRIES = 10;
JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver,
const QString& jsonCallbackMethod, const QString& jsonCallbackMethod,
@ -73,9 +74,10 @@ QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply* requestReply)
} }
} }
AccountManager::AccountManager(UserAgentGetter userAgentGetter) : AccountManager::AccountManager(bool accountSettingsEnabled, UserAgentGetter userAgentGetter) :
_userAgentGetter(userAgentGetter), _userAgentGetter(userAgentGetter),
_authURL() _authURL(),
_accountSettingsEnabled(accountSettingsEnabled)
{ {
qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken"); qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken");
qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken"); qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken");
@ -92,9 +94,14 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) :
connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey); connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey);
connect(this, &AccountManager::loginComplete, this, &AccountManager::requestAccountSettings); connect(this, &AccountManager::loginComplete, this, &AccountManager::requestAccountSettings);
_pullSettingsRetryTimer = new QTimer(this);
_pullSettingsRetryTimer->setSingleShot(true);
_pullSettingsRetryTimer->setInterval(PULL_SETTINGS_RETRY_INTERVAL);
connect(_pullSettingsRetryTimer, &QTimer::timeout, this, &AccountManager::requestAccountSettings);
_postSettingsTimer = new QTimer(this); _postSettingsTimer = new QTimer(this);
_postSettingsTimer->setInterval(POST_SETTINGS_INTERVAL); _postSettingsTimer->setInterval(POST_SETTINGS_INTERVAL);
connect(this, SIGNAL(loginComplete(QUrl)), _postSettingsTimer, SLOT(start())); connect(this, SIGNAL(accountSettingsLoaded()), _postSettingsTimer, SLOT(start()));
connect(this, &AccountManager::logoutComplete, _postSettingsTimer, &QTimer::stop); connect(this, &AccountManager::logoutComplete, _postSettingsTimer, &QTimer::stop);
connect(_postSettingsTimer, &QTimer::timeout, this, &AccountManager::postAccountSettings); connect(_postSettingsTimer, &QTimer::timeout, this, &AccountManager::postAccountSettings);
connect(qApp, &QCoreApplication::aboutToQuit, this, &AccountManager::postAccountSettings); connect(qApp, &QCoreApplication::aboutToQuit, this, &AccountManager::postAccountSettings);
@ -104,6 +111,7 @@ const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
void AccountManager::logout() { void AccountManager::logout() {
postAccountSettings(); postAccountSettings();
_numPullRetries = 0;
// a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file // a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file
_accountInfo = DataServerAccountInfo(); _accountInfo = DataServerAccountInfo();
@ -796,6 +804,10 @@ void AccountManager::requestProfileError(QNetworkReply::NetworkError error) {
} }
void AccountManager::requestAccountSettings() { void AccountManager::requestAccountSettings() {
if (!_accountSettingsEnabled) {
return;
}
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QUrl lockerURL = _authURL; QUrl lockerURL = _authURL;
@ -826,20 +838,33 @@ void AccountManager::requestAccountSettingsFinished() {
emit accountSettingsLoaded(); emit accountSettingsLoaded();
} else { } else {
qCDebug(networking) << "Error in response for account settings: no data object"; qCDebug(networking) << "Error in response for account settings: no data object";
QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); if (!_pullSettingsRetryTimer->isActive() && _numPullRetries < MAX_PULL_RETRIES) {
++_numPullRetries;
_pullSettingsRetryTimer->start();
}
} }
} else { } else {
qCDebug(networking) << "Error in response for account settings" << lockerReply->errorString(); qCDebug(networking) << "Error in response for account settings" << lockerReply->errorString();
QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); if (!_pullSettingsRetryTimer->isActive() && _numPullRetries < MAX_PULL_RETRIES) {
++_numPullRetries;
_pullSettingsRetryTimer->start();
}
} }
} }
void AccountManager::requestAccountSettingsError(QNetworkReply::NetworkError error) { void AccountManager::requestAccountSettingsError(QNetworkReply::NetworkError error) {
qCWarning(networking) << "Account settings request encountered an error" << error; qCWarning(networking) << "Account settings request encountered an error" << error;
QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); if (!_pullSettingsRetryTimer->isActive() && _numPullRetries < MAX_PULL_RETRIES) {
++_numPullRetries;
_pullSettingsRetryTimer->start();
}
} }
void AccountManager::postAccountSettings() { void AccountManager::postAccountSettings() {
if (!_accountSettingsEnabled) {
return;
}
if (_settings.lastChangeTimestamp() <= _lastSuccessfulSyncTimestamp && _lastSuccessfulSyncTimestamp != 0) { if (_settings.lastChangeTimestamp() <= _lastSuccessfulSyncTimestamp && _lastSuccessfulSyncTimestamp != 0) {
// Nothing changed, skipping settings post // Nothing changed, skipping settings post
return; return;

View file

@ -60,7 +60,7 @@ const auto DEFAULT_USER_AGENT_GETTER = []() -> QString { return HIGH_FIDELITY_US
class AccountManager : public QObject, public Dependency { class AccountManager : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
public: public:
AccountManager(UserAgentGetter userAgentGetter = DEFAULT_USER_AGENT_GETTER); AccountManager(bool accountSettingsEnabled = false, UserAgentGetter userAgentGetter = DEFAULT_USER_AGENT_GETTER);
QNetworkRequest createRequest(QString path, AccountManagerAuth::Type authType); QNetworkRequest createRequest(QString path, AccountManagerAuth::Type authType);
Q_INVOKABLE void sendRequest(const QString& path, Q_INVOKABLE void sendRequest(const QString& path,
@ -182,9 +182,12 @@ private:
bool _limitedCommerce { false }; bool _limitedCommerce { false };
QString _configFileURL; QString _configFileURL;
bool _accountSettingsEnabled { false };
AccountSettings _settings; AccountSettings _settings;
quint64 _currentSyncTimestamp { 0 }; quint64 _currentSyncTimestamp { 0 };
quint64 _lastSuccessfulSyncTimestamp { 0 }; quint64 _lastSuccessfulSyncTimestamp { 0 };
int _numPullRetries { 0 };
QTimer* _pullSettingsRetryTimer { nullptr };
QTimer* _postSettingsTimer { nullptr }; QTimer* _postSettingsTimer { nullptr };
}; };

View file

@ -269,7 +269,7 @@ bool Connection::processReceivedSequenceNumber(SequenceNumber sequenceNumber, in
bool wasDuplicate = false; bool wasDuplicate = false;
if (sequenceNumber > _lastReceivedSequenceNumber) { if (sequenceNumber > _lastReceivedSequenceNumber) {
// Update largest recieved sequence number // Update largest received sequence number
_lastReceivedSequenceNumber = sequenceNumber; _lastReceivedSequenceNumber = sequenceNumber;
} else { } else {
// Otherwise, it could be a resend, try and remove it from the loss list // Otherwise, it could be a resend, try and remove it from the loss list
@ -312,9 +312,7 @@ void Connection::processControl(ControlPacketPointer controlPacket) {
// We're already in a state where we've received a handshake ack, so we are likely in a state // We're already in a state where we've received a handshake ack, so we are likely in a state
// where the other end expired our connection. Let's reset. // where the other end expired our connection. Let's reset.
#ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Got HandshakeRequest from" << _destination << "while active, stopping SendQueue";
qCDebug(networking) << "Got HandshakeRequest from" << _destination << ", stopping SendQueue";
#endif
_hasReceivedHandshakeACK = false; _hasReceivedHandshakeACK = false;
stopSendQueue(); stopSendQueue();
} }
@ -333,7 +331,7 @@ void Connection::processACK(ControlPacketPointer controlPacket) {
// validate that this isn't a BS ACK // validate that this isn't a BS ACK
if (ack > getSendQueue().getCurrentSequenceNumber()) { if (ack > getSendQueue().getCurrentSequenceNumber()) {
// in UDT they specifically break the connection here - do we want to do anything? // in UDT they specifically break the connection here - do we want to do anything?
Q_ASSERT_X(false, "Connection::processACK", "ACK recieved higher than largest sent sequence number"); Q_ASSERT_X(false, "Connection::processACK", "ACK received higher than largest sent sequence number");
return; return;
} }

View file

@ -73,6 +73,7 @@ public:
void setMaxBandwidth(int maxBandwidth); void setMaxBandwidth(int maxBandwidth);
void sendHandshakeRequest(); void sendHandshakeRequest();
bool hasReceivedHandshake() const { return _hasReceivedHandshake; }
void recordSentUnreliablePackets(int wireSize, int payloadSize); void recordSentUnreliablePackets(int wireSize, int payloadSize);
void recordReceivedUnreliablePackets(int wireSize, int payloadSize); void recordReceivedUnreliablePackets(int wireSize, int payloadSize);

View file

@ -548,12 +548,14 @@ void Socket::handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAdd
Lock connectionsLock(_connectionsHashMutex); Lock connectionsLock(_connectionsHashMutex);
const auto connectionIter = _connectionsHash.find(previousAddress); const auto connectionIter = _connectionsHash.find(previousAddress);
if (connectionIter != _connectionsHash.end()) { // Don't move classes that are unused so far.
if (connectionIter != _connectionsHash.end() && connectionIter->second->hasReceivedHandshake()) {
auto connection = move(connectionIter->second); auto connection = move(connectionIter->second);
_connectionsHash.erase(connectionIter); _connectionsHash.erase(connectionIter);
connection->setDestinationAddress(currentAddress); connection->setDestinationAddress(currentAddress);
_connectionsHash[currentAddress] = move(connection); _connectionsHash[currentAddress] = move(connection);
connectionsLock.unlock(); connectionsLock.unlock();
qCDebug(networking) << "Moved Connection class from" << previousAddress << "to" << currentAddress;
Lock sequenceNumbersLock(_unreliableSequenceNumbersMutex); Lock sequenceNumbersLock(_unreliableSequenceNumbersMutex);
const auto sequenceNumbersIter = _unreliableSequenceNumbers.find(previousAddress); const auto sequenceNumbersIter = _unreliableSequenceNumbers.find(previousAddress);

View file

@ -75,7 +75,8 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
if (motionState) { if (motionState) {
removeOwnershipData(motionState); removeOwnershipData(motionState);
_entitiesToRemoveFromPhysics.insert(entity); _entitiesToRemoveFromPhysics.insert(entity);
} else if (entity->isDead() && entity->getElement()) { }
if (entity->isDead() && entity->getElement()) {
_deadEntities.insert(entity); _deadEntities.insert(entity);
} }
} }

View file

@ -103,6 +103,10 @@ float Deck::position() const {
return Frame::frameTimeToSeconds(currentPosition); return Frame::frameTimeToSeconds(currentPosition);
} }
void Deck::setVolume(float volume) {
_volume = std::min(std::max(volume, 0.0f), 1.0f);
}
static const Frame::Time MIN_FRAME_WAIT_INTERVAL = Frame::secondsToFrameTime(0.001f); static const Frame::Time MIN_FRAME_WAIT_INTERVAL = Frame::secondsToFrameTime(0.001f);
static const Frame::Time MAX_FRAME_PROCESSING_TIME = Frame::secondsToFrameTime(0.004f); static const Frame::Time MAX_FRAME_PROCESSING_TIME = Frame::secondsToFrameTime(0.004f);

View file

@ -57,6 +57,9 @@ public:
float position() const; float position() const;
void seek(float position); void seek(float position);
float getVolume() const { return _volume; }
void setVolume(float volume);
signals: signals:
void playbackStateChanged(); void playbackStateChanged();
void looped(); void looped();
@ -76,6 +79,7 @@ private:
bool _pause { true }; bool _pause { true };
bool _loop { false }; bool _loop { false };
float _length { 0 }; float _length { 0 };
float _volume { 1.0f };
}; };
} }

View file

@ -117,7 +117,7 @@ void RecordingScriptingInterface::startPlaying() {
} }
void RecordingScriptingInterface::setPlayerVolume(float volume) { void RecordingScriptingInterface::setPlayerVolume(float volume) {
// FIXME _player->setVolume(std::min(std::max(volume, 0.0f), 1.0f));
} }
void RecordingScriptingInterface::setPlayerAudioOffset(float audioOffset) { void RecordingScriptingInterface::setPlayerAudioOffset(float audioOffset) {

View file

@ -95,8 +95,9 @@ public slots:
/**jsdoc /**jsdoc
* Sets the playback audio volume.
* @function Recording.setPlayerVolume * @function Recording.setPlayerVolume
* @param {number} volume * @param {number} volume - The playback audio volume, range <code>0.0</code> &ndash; <code>1.0</code>.
*/ */
void setPlayerVolume(float volume); void setPlayerVolume(float volume);

View file

@ -356,7 +356,7 @@ void OffscreenQmlSurface::onRootCreated() {
getSurfaceContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); getSurfaceContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
// Connect with the audio client and listen for audio device changes // Connect with the audio client and listen for audio device changes
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const QAudioDeviceInfo& device) { connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const HifiAudioDeviceInfo& device) {
if (mode == QAudio::Mode::AudioOutput) { if (mode == QAudio::Mode::AudioOutput) {
QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, Q_ARG(QString, device.deviceName())); QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, Q_ARG(QString, device.deviceName()));
} }

View file

@ -100,7 +100,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); }); DependencyManager::set<AccountManager>(false, [&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); });
DependencyManager::set<AddressManager>(); DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, listenPort); DependencyManager::set<NodeList>(NodeType::Agent, listenPort);

View file

@ -138,7 +138,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) :
DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<StatTracker>(); DependencyManager::set<StatTracker>();
DependencyManager::set<AccountManager>([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set<AccountManager>(false, [&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); });
DependencyManager::set<AddressManager>(); DependencyManager::set<AddressManager>();
DependencyManager::set<NodeList>(NodeType::Agent, _listenPort); DependencyManager::set<NodeList>(NodeType::Agent, _listenPort);