summaryrefslogtreecommitdiff
path: root/src/plugins/wasapi/qwasapiutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/wasapi/qwasapiutils.cpp')
-rw-r--r--src/plugins/wasapi/qwasapiutils.cpp344
1 files changed, 0 insertions, 344 deletions
diff --git a/src/plugins/wasapi/qwasapiutils.cpp b/src/plugins/wasapi/qwasapiutils.cpp
deleted file mode 100644
index 497e5fa6e..000000000
--- a/src/plugins/wasapi/qwasapiutils.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwasapiutils.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/private/qeventdispatcher_winrt_p.h>
-
-// For Desktop Win32 support
-#ifdef CLASSIC_APP_BUILD
-#define Q_OS_WINRT
-#endif
-#include <QtCore/qfunctions_winrt.h>
-
-#include <QtMultimedia/QAudioDeviceInfo>
-#include <Audioclient.h>
-#include <windows.devices.enumeration.h>
-#include <windows.foundation.collections.h>
-#include <windows.media.devices.h>
-
-#include <functional>
-
-using namespace ABI::Windows::Devices::Enumeration;
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::Foundation::Collections;
-using namespace ABI::Windows::Media::Devices;
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-#define RETURN_EMPTY_LIST_IF_FAILED(msg) RETURN_IF_FAILED(msg, return QList<QByteArray>())
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcMmAudioInterface, "qt.multimedia.audiointerface")
-Q_LOGGING_CATEGORY(lcMmUtils, "qt.multimedia.utils")
-
-#ifdef CLASSIC_APP_BUILD
-// Opening bracket has to be in the same line as MSVC2013 and 2015 complain on
-// different lines otherwise
-#pragma warning (suppress: 4273)
-HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT()> &delegate, bool waitForRun) {
- Q_UNUSED(waitForRun)
- return delegate();
-}
-#endif
-
-namespace QWasapiUtils {
-struct DeviceMapping {
- QList<QByteArray> outputDeviceNames;
- QList<QString> outputDeviceIds;
- QList<QByteArray> inputDeviceNames;
- QList<QString> inputDeviceIds;
-};
-Q_GLOBAL_STATIC(DeviceMapping, gMapping)
-}
-
-struct CoInitializer
-{
- CoInitializer()
- {
- CoInitializeEx(NULL, COINIT_MULTITHREADED);
- }
-
- ~CoInitializer()
- {
- CoUninitialize();
- }
-};
-
-static void CoInitIfNeeded()
-{
- static CoInitializer initializer;
-}
-
-AudioInterface::AudioInterface()
-{
- qCDebug(lcMmAudioInterface) << __FUNCTION__;
- m_currentState = Initialized;
-}
-
-AudioInterface::~AudioInterface()
-{
- qCDebug(lcMmAudioInterface) << __FUNCTION__;
-}
-
-HRESULT AudioInterface::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *op)
-{
- qCDebug(lcMmAudioInterface) << __FUNCTION__;
-
- IUnknown *aInterface;
- HRESULT hr;
- HRESULT hrActivate;
- hr = op->GetActivateResult(&hrActivate, &aInterface);
- if (FAILED(hr) || FAILED(hrActivate)) {
- qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not query activate results.";
- m_currentState = Error;
- return hr;
- }
-
- hr = aInterface->QueryInterface(IID_PPV_ARGS(&m_client));
- if (FAILED(hr)) {
- qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not access AudioClient interface.";
- m_currentState = Error;
- return hr;
- }
-
- WAVEFORMATEX *format;
- hr = m_client->GetMixFormat(&format);
- if (FAILED(hr)) {
- qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not get mix format.";
- m_currentState = Error;
- return hr;
- }
-
- QWasapiUtils::convertFromNativeFormat(format, &m_mixFormat);
-
- m_currentState = Activated;
- return S_OK;
-}
-
-bool QWasapiUtils::convertToNativeFormat(const QAudioFormat &qt, WAVEFORMATEX *native)
-{
- if (!native
- || !qt.isValid()
- || qt.codec() != QStringLiteral("audio/pcm")
- || qt.sampleRate() <= 0
- || qt.channelCount() <= 0
- || qt.sampleSize() <= 0
- || qt.byteOrder() != QAudioFormat::LittleEndian) {
- return false;
- }
-
- native->nSamplesPerSec = qt.sampleRate();
- native->wBitsPerSample = qt.sampleSize();
- native->nChannels = qt.channelCount();
- native->nBlockAlign = (native->wBitsPerSample * native->nChannels) / 8;
- native->nAvgBytesPerSec = native->nBlockAlign * native->nSamplesPerSec;
- native->cbSize = 0;
-
- if (qt.sampleType() == QAudioFormat::Float)
- native->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
- else
- native->wFormatTag = WAVE_FORMAT_PCM;
-
- return true;
-}
-
-bool QWasapiUtils::convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFormat *qt)
-{
- if (!native || !qt)
- return false;
-
- qt->setByteOrder(QAudioFormat::LittleEndian);
- qt->setChannelCount(native->nChannels);
- qt->setCodec(QStringLiteral("audio/pcm"));
- qt->setSampleRate(native->nSamplesPerSec);
- qt->setSampleSize(native->wBitsPerSample);
- qt->setSampleType(native->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ? QAudioFormat::Float : QAudioFormat::SignedInt);
-
- return true;
-}
-
-QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
-{
- qCDebug(lcMmUtils) << __FUNCTION__ << mode;
-
- CoInitIfNeeded();
- QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
- QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds;
- if (deviceNames.isEmpty() || deviceIds.isEmpty()) // Initialize
- availableDevices(mode);
- if (deviceNames.isEmpty() || deviceIds.isEmpty()) // No audio devices at all
- return QByteArray();
-
- ComPtr<IMediaDeviceStatics> mediaDeviceStatics;
- HRESULT hr;
-
- hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mediaDeviceStatics);
- Q_ASSERT_SUCCEEDED(hr);
-
- HString defaultAudioDevice;
- quint32 dADSize = 0;
-
- if (mode == QAudio::AudioOutput)
- hr = mediaDeviceStatics->GetDefaultAudioRenderId(AudioDeviceRole_Default, defaultAudioDevice.GetAddressOf());
- else
- hr = mediaDeviceStatics->GetDefaultAudioCaptureId(AudioDeviceRole_Default, defaultAudioDevice.GetAddressOf());
-
- const wchar_t *dadWStr = defaultAudioDevice.GetRawBuffer(&dADSize);
- const QString defaultAudioDeviceId = QString::fromWCharArray(dadWStr, dADSize);
- Q_ASSERT(deviceIds.indexOf(defaultAudioDeviceId) != -1);
-
- return deviceNames.at(deviceIds.indexOf(defaultAudioDeviceId));
-}
-
-QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
-{
- qCDebug(lcMmUtils) << __FUNCTION__ << mode;
-
- CoInitIfNeeded();
- ComPtr<IDeviceInformationStatics> statics;
- HRESULT hr;
-
- hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(),
- &statics);
- Q_ASSERT_SUCCEEDED(hr);
-
- DeviceClass dc = mode == QAudio::AudioInput ? DeviceClass_AudioCapture : DeviceClass_AudioRender;
-
- QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
- QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds;
-
- // We need to refresh due to plugable devices (ie USB)
- deviceNames.clear();
- deviceIds.clear();
-
- ComPtr<IAsyncOperation<ABI::Windows::Devices::Enumeration::DeviceInformationCollection *>> op;
- hr = statics->FindAllAsyncDeviceClass(dc, &op );
- RETURN_EMPTY_LIST_IF_FAILED("Could not query audio devices.");
-
- ComPtr<IVectorView<DeviceInformation *>> resultVector;
- hr = QWinRTFunctions::await(op, resultVector.GetAddressOf());
- RETURN_EMPTY_LIST_IF_FAILED("Could not receive audio device list.");
-
- quint32 deviceCount;
- hr = resultVector->get_Size(&deviceCount);
- RETURN_EMPTY_LIST_IF_FAILED("Could not access audio device count.");
- qCDebug(lcMmUtils) << "Found " << deviceCount << " audio devices for" << mode;
-
- for (quint32 i = 0; i < deviceCount; ++i) {
- ComPtr<IDeviceInformation> item;
- hr = resultVector->GetAt(i, &item);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not access audio device item.");
- continue;
- }
-
- HString hString;
- quint32 size;
-
- hr = item->get_Name(hString.GetAddressOf());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not access audio device name.");
- continue;
- }
- const wchar_t *nameWStr = hString.GetRawBuffer(&size);
- const QString deviceName = QString::fromWCharArray(nameWStr, size);
-
- hr = item->get_Id(hString.GetAddressOf());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not access audio device id.");
- continue;
- }
- const wchar_t *idWStr = hString.GetRawBuffer(&size);
- const QString deviceId = QString::fromWCharArray(idWStr, size);
-
- boolean enabled;
- hr = item->get_IsEnabled(&enabled);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not access audio device enabled.");
- continue;
- }
-
- qCDebug(lcMmUtils) << "Audio Device:" << deviceName << " ID:" << deviceId
- << " Enabled:" << enabled;
-
- deviceNames.append(deviceName.toLocal8Bit());
- deviceIds.append(deviceId);
- }
- return deviceNames;
-}
-
-Microsoft::WRL::ComPtr<AudioInterface> QWasapiUtils::createOrGetInterface(const QByteArray &dev, QAudio::Mode mode)
-{
- qCDebug(lcMmUtils) << __FUNCTION__ << dev << mode;
- Q_ASSERT((mode == QAudio::AudioInput ? gMapping->inputDeviceNames.indexOf(dev) : gMapping->outputDeviceNames.indexOf(dev)) != -1);
- CoInitIfNeeded();
-
- Microsoft::WRL::ComPtr<AudioInterface> result;
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([dev, mode, &result]() {
- HRESULT hr;
- QString id = mode == QAudio::AudioInput ? gMapping->inputDeviceIds.at(gMapping->inputDeviceNames.indexOf(dev)) :
- gMapping->outputDeviceIds.at(gMapping->outputDeviceNames.indexOf(dev));
-
- result = Make<AudioInterface>();
-
- ComPtr<IActivateAudioInterfaceAsyncOperation> op;
-
- // We cannot use QWinRTFunctions::await here as that will return
- // E_NO_INTERFACE. Instead we leave the lambda and wait for the
- // status to get out of Activating
- result->setState(AudioInterface::Activating);
- hr = ActivateAudioInterfaceAsync(reinterpret_cast<LPCWSTR>(id.utf16()), __uuidof(IAudioClient), NULL, result.Get(), op.GetAddressOf());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not invoke audio interface activation.");
- result->setState(AudioInterface::Error);
- }
- return hr;
- });
- qCDebug(lcMmUtils) << "Activation stated:" << hr;
- while (result->state() == AudioInterface::Activating) {
- QThread::yieldCurrentThread();
- }
- qCDebug(lcMmUtils) << "Activation done:" << hr;
- return result;
-}
-
-QT_END_NAMESPACE