From b53968fd6465bce1e16cddf8b8009d3d9fea8cd1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 30 Mar 2016 23:12:53 -0700 Subject: [PATCH] Add automatic switching the Oculus headphones and mic when activating the plugin --- libraries/plugins/src/plugins/DisplayPlugin.h | 3 + plugins/oculus/CMakeLists.txt | 5 +- plugins/oculus/src/OculusBaseDisplayPlugin.h | 1 + plugins/oculus/src/OculusDisplayPlugin.cpp | 105 ++++++++++++++++++ plugins/oculus/src/OculusDisplayPlugin.h | 11 +- 5 files changed, 118 insertions(+), 7 deletions(-) diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 77d984f924..b855e08ff1 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -74,6 +74,9 @@ public: /// whether the HMD is being worn virtual bool isDisplayVisible() const { return false; } + virtual QString getPreferredAudioInDevice() const { return QString(); } + virtual QString getPreferredAudioOutDevice() const { return QString(); } + // Rendering support /** diff --git a/plugins/oculus/CMakeLists.txt b/plugins/oculus/CMakeLists.txt index e5cbffda21..a91690ecdd 100644 --- a/plugins/oculus/CMakeLists.txt +++ b/plugins/oculus/CMakeLists.txt @@ -12,8 +12,8 @@ if (WIN32) add_definitions(-DGLEW_STATIC) set(TARGET_NAME oculus) - setup_hifi_plugin() - link_hifi_libraries(shared gl gpu controllers ui plugins display-plugins input-plugins) + setup_hifi_plugin(Multimedia) + link_hifi_libraries(shared gl gpu controllers ui plugins display-plugins input-plugins audio-client networking) include_hifi_library_headers(octree) @@ -21,5 +21,6 @@ if (WIN32) find_package(LibOVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) + target_link_libraries(${TARGET_NAME} Winmm.lib) endif() \ No newline at end of file diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 2259a4ca89..71f876a82a 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -21,6 +21,7 @@ public: // Stereo specific methods virtual void resetSensors() override final; virtual void beginFrameRender(uint32_t frameIndex) override; + float getTargetFrameRate() override { return _hmdDesc.DisplayRefreshRate; } protected: diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 8078e8d6ec..9e52bb80d3 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -6,7 +6,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "OculusDisplayPlugin.h" + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + #include +#include #include "OculusHelpers.h" const QString OculusDisplayPlugin::NAME("Oculus Rift"); @@ -18,9 +33,38 @@ bool OculusDisplayPlugin::internalActivate() { if (result && _session) { ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode); } + + auto audioClient = DependencyManager::get(); + QString riftAudioIn = getPreferredAudioInDevice(); + if (riftAudioIn != QString()) { + _savedAudioIn = audioClient->getDeviceName(QAudio::Mode::AudioInput); + QMetaObject::invokeMethod(audioClient.data(), "switchInputToAudioDevice", Q_ARG(const QString&, riftAudioIn)); + } else { + _savedAudioIn.clear(); + } + + QString riftAudioOut = getPreferredAudioOutDevice(); + if (riftAudioOut != QString()) { + _savedAudioOut = audioClient->getDeviceName(QAudio::Mode::AudioOutput); + QMetaObject::invokeMethod(audioClient.data(), "switchOutputToAudioDevice", Q_ARG(const QString&, riftAudioOut)); + } else { + _savedAudioOut.clear(); + } + return result; } +void OculusDisplayPlugin::internalDeactivate() { + auto audioClient = DependencyManager::get(); + if (_savedAudioIn != QString()) { + QMetaObject::invokeMethod(audioClient.data(), "switchInputToAudioDevice", Q_ARG(const QString&, _savedAudioIn)); + } + if (_savedAudioOut != QString()) { + QMetaObject::invokeMethod(audioClient.data(), "switchOutputToAudioDevice", Q_ARG(const QString&, _savedAudioOut)); + } + Parent::internalDeactivate(); +} + void OculusDisplayPlugin::cycleDebugOutput() { if (_session) { currentDebugMode = static_cast((currentDebugMode + 1) % ovrPerfHud_Count); @@ -86,3 +130,64 @@ void OculusDisplayPlugin::hmdPresent() { } } } + +bool OculusDisplayPlugin::isHmdMounted() const { + ovrSessionStatus status; + return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) && + (ovrFalse != status.HmdMounted)); +} + +static QString audioDeviceFriendlyName(LPCWSTR device) { + QString deviceName; + + HRESULT hr = S_OK; + CoInitialize(NULL); + IMMDeviceEnumerator* pMMDeviceEnumerator = NULL; + CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator); + IMMDevice* pEndpoint; + hr = pMMDeviceEnumerator->GetDevice(device, &pEndpoint); + if (hr == E_NOTFOUND) { + printf("Audio Error: device not found\n"); + deviceName = QString("NONE"); + } else { + IPropertyStore* pPropertyStore; + pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore); + pEndpoint->Release(); + pEndpoint = NULL; + PROPVARIANT pv; + PropVariantInit(&pv); + hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); + pPropertyStore->Release(); + pPropertyStore = NULL; + deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal); + if (!IsWindows8OrGreater()) { + // Windows 7 provides only the 31 first characters of the device name. + const DWORD QT_WIN7_MAX_AUDIO_DEVICENAME_LEN = 31; + deviceName = deviceName.left(QT_WIN7_MAX_AUDIO_DEVICENAME_LEN); + } + qDebug() << " device:" << deviceName; + PropVariantClear(&pv); + } + pMMDeviceEnumerator->Release(); + pMMDeviceEnumerator = NULL; + CoUninitialize(); + return deviceName; +} + + +QString OculusDisplayPlugin::getPreferredAudioInDevice() const { + WCHAR buffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]; + if (!OVR_SUCCESS(ovr_GetAudioDeviceInGuidStr(buffer))) { + return QString(); + } + return audioDeviceFriendlyName(buffer); +} + +QString OculusDisplayPlugin::getPreferredAudioOutDevice() const { + WCHAR buffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]; + if (!OVR_SUCCESS(ovr_GetAudioDeviceOutGuidStr(buffer))) { + return QString(); + } + return audioDeviceFriendlyName(buffer); +} + diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index e7d7791e7f..a5dd70c68d 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -12,20 +12,19 @@ struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; -const float TARGET_RATE_Oculus = 75.0f; - class OculusDisplayPlugin : public OculusBaseDisplayPlugin { using Parent = OculusBaseDisplayPlugin; public: const QString& getName() const override { return NAME; } - float getTargetFrameRate() override { return TARGET_RATE_Oculus; } + QString getPreferredAudioInDevice() const override; + QString getPreferredAudioOutDevice() const override; protected: bool internalActivate() override; + void internalDeactivate() override; void hmdPresent() override; - // FIXME update with Oculus API call once it's available in the SDK - bool isHmdMounted() const override { return true; } + bool isHmdMounted() const override; void customizeContext() override; void uncustomizeContext() override; void cycleDebugOutput() override; @@ -34,6 +33,8 @@ private: static const QString NAME; bool _enablePreview { false }; bool _monoPreview { true }; + QString _savedAudioIn; + QString _savedAudioOut; SwapFboPtr _sceneFbo; };