summaryrefslogtreecommitdiffstats
path: root/src/plugins/wasapi
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/wasapi')
-rw-r--r--src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp167
-rw-r--r--src/plugins/wasapi/qwasapiaudiodeviceinfo.h85
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.cpp555
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.h121
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.cpp568
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.h122
-rw-r--r--src/plugins/wasapi/qwasapiplugin.cpp85
-rw-r--r--src/plugins/wasapi/qwasapiplugin.h76
-rw-r--r--src/plugins/wasapi/qwasapiutils.cpp344
-rw-r--r--src/plugins/wasapi/qwasapiutils.h147
-rw-r--r--src/plugins/wasapi/wasapi.json3
-rw-r--r--src/plugins/wasapi/wasapi.pro30
12 files changed, 0 insertions, 2303 deletions
diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
deleted file mode 100644
index 53345dec8..000000000
--- a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
+++ /dev/null
@@ -1,167 +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 "qwasapiaudiodeviceinfo.h"
-#include "qwasapiutils.h"
-
-#include <Audioclient.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcMmDeviceInfo, "qt.multimedia.deviceinfo")
-
-QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode)
- : m_deviceName(QString::fromLocal8Bit(dev))
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__ << dev << mode;
- m_interface = QWasapiUtils::createOrGetInterface(dev, mode);
-
- QAudioFormat referenceFormat = m_interface->m_mixFormat;
-
- const int rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
- for (int rate : rates) {
- QAudioFormat f = referenceFormat;
- f.setSampleRate(rate);
- if (isFormatSupported(f))
- m_sampleRates.append(rate);
- }
-
- for (int i = 1; i <= 18; ++i) {
- QAudioFormat f = referenceFormat;
- f.setChannelCount(i);
- if (isFormatSupported(f))
- m_channelCounts.append(i);
- }
-
- const int sizes[] = {8, 12, 16, 20, 24, 32, 64};
- for (int s : sizes) {
- QAudioFormat f = referenceFormat;
- f.setSampleSize(s);
- if (isFormatSupported(f))
- m_sampleSizes.append(s);
- }
-
- referenceFormat.setSampleType(QAudioFormat::SignedInt);
- if (isFormatSupported(referenceFormat))
- m_sampleTypes.append(QAudioFormat::SignedInt);
-
- referenceFormat.setSampleType(QAudioFormat::Float);
- if (isFormatSupported(referenceFormat))
- m_sampleTypes.append(QAudioFormat::Float);
-}
-
-QWasapiAudioDeviceInfo::~QWasapiAudioDeviceInfo()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
-}
-
-bool QWasapiAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__ << format;
-
- WAVEFORMATEX nfmt;
- if (!QWasapiUtils::convertToNativeFormat(format, &nfmt))
- return false;
-
- WAVEFORMATEX closest;
- WAVEFORMATEX *pClosest = &closest;
- HRESULT hr;
- hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nfmt, &pClosest);
-
- if (hr == S_OK) // S_FALSE is inside SUCCEEDED()
- return true;
-
- if (lcMmDeviceInfo().isDebugEnabled()) {
- QAudioFormat f;
- QWasapiUtils::convertFromNativeFormat(pClosest, &f);
- qCDebug(lcMmDeviceInfo) << __FUNCTION__ << hr << "Closest match is:" << f;
- }
-
- return false;
-}
-
-QAudioFormat QWasapiAudioDeviceInfo::preferredFormat() const
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_interface->m_mixFormat;
-}
-
-QString QWasapiAudioDeviceInfo::deviceName() const
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_deviceName;
-}
-
-QStringList QWasapiAudioDeviceInfo::supportedCodecs()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return QStringList() << QStringLiteral("audio/pcm");
-}
-
-QList<int> QWasapiAudioDeviceInfo::supportedSampleRates()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_sampleRates;
-}
-
-QList<int> QWasapiAudioDeviceInfo::supportedChannelCounts()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_channelCounts;
-}
-
-QList<int> QWasapiAudioDeviceInfo::supportedSampleSizes()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_sampleSizes;
-}
-
-QList<QAudioFormat::Endian> QWasapiAudioDeviceInfo::supportedByteOrders()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return QList<QAudioFormat::Endian>() << m_interface->m_mixFormat.byteOrder();
-}
-
-QList<QAudioFormat::SampleType> QWasapiAudioDeviceInfo::supportedSampleTypes()
-{
- qCDebug(lcMmDeviceInfo) << __FUNCTION__;
- return m_sampleTypes;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.h b/src/plugins/wasapi/qwasapiaudiodeviceinfo.h
deleted file mode 100644
index 878d0273a..000000000
--- a/src/plugins/wasapi/qwasapiaudiodeviceinfo.h
+++ /dev/null
@@ -1,85 +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$
-**
-****************************************************************************/
-
-#ifndef QWASAPIAUDIODEVICEINFO_H
-#define QWASAPIAUDIODEVICEINFO_H
-
-#include <QtCore/QList>
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QStringList>
-#include <QtMultimedia/QAbstractAudioDeviceInfo>
-#include <QtMultimedia/QAudio>
-#include <QtMultimedia/QAudioFormat>
-
-#include <wrl.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcMmDeviceInfo)
-
-class AudioInterface;
-class QWasapiAudioDeviceInfo : public QAbstractAudioDeviceInfo
-{
- Q_OBJECT
-public:
- explicit QWasapiAudioDeviceInfo(QByteArray dev,QAudio::Mode mode);
- ~QWasapiAudioDeviceInfo();
-
- QAudioFormat preferredFormat() const override;
- bool isFormatSupported(const QAudioFormat& format) const override;
- QString deviceName() const override;
- QStringList supportedCodecs() override;
- QList<int> supportedSampleRates() override;
- QList<int> supportedChannelCounts() override;
- QList<int> supportedSampleSizes() override;
- QList<QAudioFormat::Endian> supportedByteOrders() override;
- QList<QAudioFormat::SampleType> supportedSampleTypes() override;
-
-private:
- Microsoft::WRL::ComPtr<AudioInterface> m_interface;
- QString m_deviceName;
- QList<int> m_sampleRates;
- QList<int> m_channelCounts;
- QList<int> m_sampleSizes;
- QList<QAudioFormat::SampleType> m_sampleTypes;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWASAPIAUDIODEVICEINFO_H
diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp
deleted file mode 100644
index 561584e83..000000000
--- a/src/plugins/wasapi/qwasapiaudioinput.cpp
+++ /dev/null
@@ -1,555 +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 "qwasapiaudioinput.h"
-#include "qwasapiutils.h"
-
-#include <QtCore/QMutexLocker>
-#include <QtCore/QThread>
-#include <QtCore/qfunctions_winrt.h>
-
-#include <Audioclient.h>
-
-using namespace Microsoft::WRL;
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcMmAudioInput, "qt.multimedia.audioinput")
-
-class WasapiInputDevicePrivate : public QIODevice
-{
- Q_OBJECT
-public:
- WasapiInputDevicePrivate(QWasapiAudioInput* input);
- ~WasapiInputDevicePrivate();
-
- qint64 readData(char* data, qint64 len);
- qint64 writeData(const char* data, qint64 len);
-
-private:
- QWasapiAudioInput *m_input;
-};
-
-WasapiInputDevicePrivate::WasapiInputDevicePrivate(QWasapiAudioInput* input)
- : m_input(input)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
-}
-
-WasapiInputDevicePrivate::~WasapiInputDevicePrivate()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
-}
-
-qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
-
- const quint32 channelCount = m_input->m_currentFormat.channelCount();
- const quint32 sampleBytes = m_input->m_currentFormat.sampleSize() / 8;
-
- const quint32 requestedFrames = len / channelCount / sampleBytes;
- quint32 availableFrames = 0;
- HRESULT hr = m_input->m_capture->GetNextPacketSize(&availableFrames);
-
- quint32 readFrames = qMin(requestedFrames, availableFrames);
- const qint64 readBytes = readFrames * channelCount * sampleBytes;
-
- BYTE* buffer;
- DWORD flags;
-
- QMutexLocker locker(&m_input->m_mutex);
-
- quint64 devicePosition;
- hr = m_input->m_capture->GetBuffer(&buffer, &readFrames, &flags, &devicePosition, NULL);
- if (hr != S_OK) {
- m_input->m_currentError = QAudio::FatalError;
- emit m_input->errorChanged(m_input->m_currentError);
- hr = m_input->m_capture->ReleaseBuffer(readFrames);
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer.";
- return 0;
- }
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) {
- // In case this flag is set, user is supposed to ignore the content
- // of the buffer and manually write silence
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: "
- << "Ignoring buffer and writing silence.";
- memset(data, 0, readBytes);
- } else {
- memcpy(data, buffer, readBytes);
- }
-
- hr = m_input->m_capture->ReleaseBuffer(readFrames);
- if (hr != S_OK)
- qFatal("Could not release buffer");
-
- if (m_input->m_interval && m_input->m_openTime.elapsed() - m_input->m_openTimeOffset > m_input->m_interval) {
- emit m_input->notify();
- m_input->m_openTimeOffset = m_input->m_openTime.elapsed();
- }
-
- m_input->m_bytesProcessed += readBytes;
-
- if (m_input->m_currentState != QAudio::ActiveState) {
- m_input->m_currentState = QAudio::ActiveState;
- emit m_input->stateChanged(m_input->m_currentState);
- }
- return readBytes;
-}
-
-qint64 WasapiInputDevicePrivate::writeData(const char* data, qint64 len)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- Q_UNUSED(data)
- Q_UNUSED(len)
- return 0;
-}
-
-QWasapiAudioInput::QWasapiAudioInput(const QByteArray &device)
- : m_deviceName(device)
- , m_volumeCache(qreal(1.))
- , m_currentState(QAudio::StoppedState)
- , m_currentError(QAudio::NoError)
- , m_bufferFrames(0)
- , m_bufferBytes(4096)
- , m_eventThread(0)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << device;
- Q_UNUSED(device)
-}
-
-QWasapiAudioInput::~QWasapiAudioInput()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- stop();
-}
-
-void QWasapiAudioInput::setVolume(qreal vol)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << vol;
- m_volumeCache = vol;
- if (m_volumeControl) {
- quint32 channelCount;
- HRESULT hr = m_volumeControl->GetChannelCount(&channelCount);
- for (quint32 i = 0; i < channelCount; ++i) {
- hr = m_volumeControl->SetChannelVolume(i, vol);
- RETURN_VOID_IF_FAILED("Could not set audio volume.");
- }
- }
-}
-
-qreal QWasapiAudioInput::volume() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- return m_volumeCache;
-}
-
-void QWasapiAudioInput::process()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- DWORD waitRet;
-
- m_processing = true;
- do {
- waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
- if (waitRet != WAIT_OBJECT_0) {
- qFatal("Returned while waiting for event.");
- return;
- }
-
- QMutexLocker locker(&m_mutex);
-
- if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
- break;
- QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
- } while (m_processing);
-}
-
-void QWasapiAudioInput::processBuffer()
-{
- if (!m_pullMode) {
- emit m_eventDevice->readyRead();
- ResetEvent(m_event);
- return;
- }
-
- QMutexLocker locker(&m_mutex);
- const quint32 channelCount = m_currentFormat.channelCount();
- const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
- BYTE* buffer;
- HRESULT hr;
-
- quint32 packetFrames;
- hr = m_capture->GetNextPacketSize(&packetFrames);
-
- while (packetFrames != 0 && m_currentState == QAudio::ActiveState) {
- DWORD flags;
- quint64 devicePosition;
- hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL);
- if (hr != S_OK) {
- m_currentError = QAudio::FatalError;
- emit errorChanged(m_currentError);
- // Also Error Buffers need to be released
- hr = m_capture->ReleaseBuffer(packetFrames);
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer.";
- return;
- }
- const quint32 writeBytes = packetFrames * channelCount * sampleBytes;
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) {
- // In case this flag is set, user is supposed to ignore the content
- // of the buffer and manually write silence
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: "
- << "Ignoring buffer and writing silence.";
- buffer = new BYTE[writeBytes];
- memset(buffer, 0, writeBytes);
- }
-
- const qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes);
-
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT))
- delete [] buffer;
-
- if (written < static_cast<qint64>(writeBytes)) {
- if (m_currentError != QAudio::UnderrunError) {
- m_currentError = QAudio::UnderrunError;
- emit errorChanged(m_currentError);
- }
- }
- hr = m_capture->ReleaseBuffer(packetFrames);
- if (hr != S_OK)
- qFatal("Could not release buffer");
-
- m_bytesProcessed += writeBytes;
-
- hr = m_capture->GetNextPacketSize(&packetFrames);
- }
- ResetEvent(m_event);
-
- if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
- emit notify();
- m_openTimeOffset = m_openTime.elapsed();
- }
- m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
-}
-
-bool QWasapiAudioInput::initStart(bool pull)
-{
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- stop();
-
- QMutexLocker locker(&m_mutex);
-
- m_interface = QWasapiUtils::createOrGetInterface(m_deviceName, QAudio::AudioInput);
- Q_ASSERT(m_interface);
-
- m_pullMode = pull;
- WAVEFORMATEX nFmt;
- WAVEFORMATEX closest;
- WAVEFORMATEX *pClose = &closest;
-
- if (!m_currentFormat.isValid() || !QWasapiUtils::convertToNativeFormat(m_currentFormat, &nFmt)) {
- m_currentError = QAudio::OpenError;
- emit errorChanged(m_currentError);
- return false;
- }
-
- HRESULT hr;
-
- hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nFmt, &pClose);
- if (hr != S_OK) {
- m_currentError = QAudio::OpenError;
- emit errorChanged(m_currentError);
- return false;
- }
-
- REFERENCE_TIME t = ((10000.0 * 10000 / nFmt.nSamplesPerSec * 1024) + 0.5);
- if (m_bufferBytes)
- t = m_currentFormat.durationForBytes(m_bufferBytes) * 10;
-
- const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
- hr = m_interface->m_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, t, 0, &nFmt, NULL);
- EMIT_RETURN_FALSE_IF_FAILED("Could not initialize audio client.", QAudio::OpenError)
-
- hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_capture));
- EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError)
-
- hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl));
- if (FAILED(hr))
- qCDebug(lcMmAudioInput) << "Could not acquire volume control.";
-
- hr = m_interface->m_client->GetBufferSize(&m_bufferFrames);
- EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError)
-
- m_event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
- m_eventThread = new QWasapiProcessThread(this, false);
- m_eventThread->m_event = m_event;
- hr = m_interface->m_client->SetEventHandle(m_event);
- EMIT_RETURN_FALSE_IF_FAILED("Could not set event handle.", QAudio::OpenError)
-
- if (!m_pullMode) {
- m_eventDevice = new WasapiInputDevicePrivate(this);
- m_eventDevice->open(QIODevice::ReadOnly|QIODevice::Unbuffered);
- }
-
- hr = m_interface->m_client->Start();
- EMIT_RETURN_FALSE_IF_FAILED("Could not start audio render client.", QAudio::OpenError)
-
- m_openTime.restart();
- m_openTimeOffset = 0;
- m_bytesProcessed = 0;
-
- return true;
-}
-
-QAudio::Error QWasapiAudioInput::error() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << m_currentError;
- return m_currentError;
-}
-
-QAudio::State QWasapiAudioInput::state() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- return m_currentState;
-}
-
-void QWasapiAudioInput::start(QIODevice* device)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << device;
- if (!initStart(true)) {
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "failed";
- return;
- }
- m_eventDevice = device;
-
- m_mutex.lock();
- m_currentState = QAudio::ActiveState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- m_eventThread->start();
-}
-
-QIODevice *QWasapiAudioInput::start()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (!initStart(false)) {
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "failed";
- return nullptr;
- }
-
- m_mutex.lock();
- m_currentState = QAudio::IdleState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- m_eventThread->start();
- return m_eventDevice;
-}
-
-void QWasapiAudioInput::stop()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return;
-
- m_mutex.lock();
- m_currentState = QAudio::StoppedState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
-
- if (m_currentError != QAudio::NoError) {
- m_mutex.lock();
- m_currentError = QAudio::NoError;
- m_mutex.unlock();
- emit errorChanged(m_currentError);
- }
-
- HRESULT hr = m_interface->m_client->Stop();
- hr = m_interface->m_client->Reset();
-
- if (m_eventThread) {
- SetEvent(m_eventThread->m_event);
- while (m_eventThread->isRunning())
- QThread::yieldCurrentThread();
- m_eventThread->deleteLater();
- m_eventThread = 0;
- }
-}
-
-void QWasapiAudioInput::setFormat(const QAudioFormat& fmt)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << fmt;
- if (m_currentState != QAudio::StoppedState)
- return;
- m_currentFormat = fmt;
-}
-
-QAudioFormat QWasapiAudioInput::format() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- return m_currentFormat;
-}
-
-int QWasapiAudioInput::bytesReady() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState != QAudio::IdleState && m_currentState != QAudio::ActiveState)
- return 0;
-
- const quint32 channelCount = m_currentFormat.channelCount();
- const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
-
- quint32 packetFrames;
- HRESULT hr = m_capture->GetNextPacketSize(&packetFrames);
-
- if (FAILED(hr))
- return 0;
- const quint32 writeBytes = packetFrames * channelCount * sampleBytes;
-
- return writeBytes;
-}
-
-void QWasapiAudioInput::resume()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState != QAudio::SuspendedState)
- return;
-
- HRESULT hr = m_interface->m_client->Start();
- EMIT_RETURN_VOID_IF_FAILED("Could not start audio render client.", QAudio::FatalError)
-
- m_mutex.lock();
- m_currentError = QAudio::NoError;
- m_currentState = QAudio::ActiveState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- m_eventThread->start();
-}
-
-void QWasapiAudioInput::setBufferSize(int value)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << value;
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- return;
- m_bufferBytes = value;
-}
-
-int QWasapiAudioInput::bufferSize() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- return m_bufferFrames * m_currentFormat.channelCount()* m_currentFormat.sampleSize() / 8;
-
- return m_bufferBytes;
-}
-
-int QWasapiAudioInput::periodSize() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- REFERENCE_TIME defaultDevicePeriod;
- REFERENCE_TIME minimumPeriod;
- HRESULT hr = m_interface->m_client->GetDevicePeriod(&defaultDevicePeriod, &minimumPeriod);
- if (FAILED(hr))
- return 0;
- const int res = m_currentFormat.bytesForDuration(minimumPeriod / 10);
- return res;
-}
-
-void QWasapiAudioInput::setNotifyInterval(int ms)
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__ << ms;
- m_interval = qMax(0, ms);
-}
-
-int QWasapiAudioInput::notifyInterval() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- return m_interval;
-}
-
-qint64 QWasapiAudioInput::processedUSecs() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return 0;
- qint64 res = qint64(1000000) * m_bytesProcessed /
- (m_currentFormat.channelCount() * (m_currentFormat.sampleSize() / 8)) /
- m_currentFormat.sampleRate();
-
- return res;
-}
-
-void QWasapiAudioInput::suspend()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState != QAudio::ActiveState)
- return;
-
- m_mutex.lock();
- m_currentState = QAudio::SuspendedState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
-
- HRESULT hr = m_interface->m_client->Stop();
- EMIT_RETURN_VOID_IF_FAILED("Could not suspend audio render client.", QAudio::FatalError);
-
- if (m_eventThread) {
- SetEvent(m_eventThread->m_event);
- while (m_eventThread->isRunning())
- QThread::yieldCurrentThread();
- }
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "Thread has stopped";
-}
-
-qint64 QWasapiAudioInput::elapsedUSecs() const
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return 0;
- return m_openTime.elapsed() * qint64(1000);
-}
-
-void QWasapiAudioInput::reset()
-{
- qCDebug(lcMmAudioInput) << __FUNCTION__;
- stop();
-}
-
-QT_END_NAMESPACE
-
-#include "qwasapiaudioinput.moc"
diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h
deleted file mode 100644
index 6e9775490..000000000
--- a/src/plugins/wasapi/qwasapiaudioinput.h
+++ /dev/null
@@ -1,121 +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$
-**
-****************************************************************************/
-
-#ifndef QAUDIOINPUTWASAPI_H
-#define QAUDIOINPUTWASAPI_H
-
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QMutex>
-#include <QtCore/QElapsedTimer>
-#include <QtMultimedia/QAbstractAudioInput>
-#include <QtMultimedia/QAudio>
-
-#include <wrl.h>
-
-struct IAudioCaptureClient;
-struct IAudioStreamVolume;
-
-QT_BEGIN_NAMESPACE
-
-class AudioInterface;
-class WasapiInputDevicePrivate;
-class QWasapiProcessThread;
-
-Q_DECLARE_LOGGING_CATEGORY(lcMmAudioInput)
-
-class QWasapiAudioInput : public QAbstractAudioInput
-{
- Q_OBJECT
-public:
- explicit QWasapiAudioInput(const QByteArray &device);
- ~QWasapiAudioInput();
-
- void start(QIODevice* device) override;
- QIODevice* start() override;
- void stop() override;
- void reset() override;
- void suspend() override;
- void resume() override;
- int bytesReady() const override;
- int periodSize() const override;
- void setBufferSize(int value) override;
- int bufferSize() const override;
- void setNotifyInterval(int milliSeconds) override;
- int notifyInterval() const override;
- qint64 processedUSecs() const override;
- qint64 elapsedUSecs() const override;
- QAudio::Error error() const override;
- QAudio::State state() const override;
- void setFormat(const QAudioFormat& fmt) override;
- QAudioFormat format() const override;
- void setVolume(qreal) override;
- qreal volume() const override;
-
- void process();
-public slots:
- void processBuffer();
-private:
- bool initStart(bool pull);
- friend class WasapiInputDevicePrivate;
- friend class WasapiInputPrivate;
- QByteArray m_deviceName;
- Microsoft::WRL::ComPtr<AudioInterface> m_interface;
- Microsoft::WRL::ComPtr<IAudioCaptureClient> m_capture;
- Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl;
- qreal m_volumeCache;
- QMutex m_mutex;
- QAudio::State m_currentState;
- QAudio::Error m_currentError;
- QAudioFormat m_currentFormat;
- qint64 m_bytesProcessed;
- QElapsedTimer m_openTime;
- int m_openTimeOffset;
- int m_interval;
- bool m_pullMode;
- quint32 m_bufferFrames;
- quint32 m_bufferBytes;
- HANDLE m_event;
- QWasapiProcessThread *m_eventThread;
- QAtomicInt m_processing;
- QIODevice *m_eventDevice;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp
deleted file mode 100644
index 79548011c..000000000
--- a/src/plugins/wasapi/qwasapiaudiooutput.cpp
+++ /dev/null
@@ -1,568 +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 "qwasapiaudiooutput.h"
-#include "qwasapiutils.h"
-#include <QtCore/qfunctions_winrt.h>
-#include <QtCore/QMutexLocker>
-#include <QtCore/QThread>
-#include <QtCore/QTimer>
-
-#include <Audioclient.h>
-#include <functional>
-
-using namespace Microsoft::WRL;
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcMmAudioOutput, "qt.multimedia.audiooutput")
-
-class WasapiOutputDevicePrivate : public QIODevice
-{
- Q_OBJECT
-public:
- WasapiOutputDevicePrivate(QWasapiAudioOutput* output);
- ~WasapiOutputDevicePrivate();
-
- qint64 readData(char* data, qint64 len);
- qint64 writeData(const char* data, qint64 len);
-
-private:
- QWasapiAudioOutput *m_output;
- QTimer m_timer;
-};
-
-WasapiOutputDevicePrivate::WasapiOutputDevicePrivate(QWasapiAudioOutput* output)
- : m_output(output)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
-
- m_timer.setSingleShot(true);
- connect(&m_timer, &QTimer::timeout, [=](){
- if (m_output->m_currentState == QAudio::ActiveState) {
- m_output->m_currentState = QAudio::IdleState;
- emit m_output->stateChanged(m_output->m_currentState);
- m_output->m_currentError = QAudio::UnderrunError;
- emit m_output->errorChanged(m_output->m_currentError);
- }
- });
-}
-
-WasapiOutputDevicePrivate::~WasapiOutputDevicePrivate()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
-}
-
-qint64 WasapiOutputDevicePrivate::readData(char* data, qint64 len)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- Q_UNUSED(data)
- Q_UNUSED(len)
-
- return 0;
-}
-
-qint64 WasapiOutputDevicePrivate::writeData(const char* data, qint64 len)
-{
- if (m_output->state() != QAudio::ActiveState && m_output->state() != QAudio::IdleState)
- return 0;
-
- QMutexLocker locker(&m_output->m_mutex);
- m_timer.stop();
-
- const quint32 channelCount = m_output->m_currentFormat.channelCount();
- const quint32 sampleBytes = m_output->m_currentFormat.sampleSize() / 8;
- const quint32 freeBytes = static_cast<quint32>(m_output->bytesFree());
- const quint32 bytesToWrite = qMin(freeBytes, static_cast<quint32>(len));
- const quint32 framesToWrite = bytesToWrite / (channelCount * sampleBytes);
-
- BYTE *buffer;
- HRESULT hr;
- hr = m_output->m_renderer->GetBuffer(framesToWrite, &buffer);
- if (hr != S_OK) {
- m_output->m_currentError = QAudio::UnderrunError;
- QMetaObject::invokeMethod(m_output, "errorChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::Error, QAudio::UnderrunError));
- // Also Error Buffers need to be released
- hr = m_output->m_renderer->ReleaseBuffer(framesToWrite, 0);
- return 0;
- }
-
- memcpy_s(buffer, bytesToWrite, data, bytesToWrite);
-
- hr = m_output->m_renderer->ReleaseBuffer(framesToWrite, 0);
- if (hr != S_OK)
- qFatal("Could not release buffer");
-
- if (m_output->m_interval && m_output->m_openTime.elapsed() - m_output->m_openTimeOffset > m_output->m_interval) {
- QMetaObject::invokeMethod(m_output, "notify", Qt::QueuedConnection);
- m_output->m_openTimeOffset = m_output->m_openTime.elapsed();
- }
-
- m_output->m_bytesProcessed += bytesToWrite;
-
- if (m_output->m_currentState != QAudio::ActiveState) {
- m_output->m_currentState = QAudio::ActiveState;
- emit m_output->stateChanged(m_output->m_currentState);
- }
- if (m_output->m_currentError != QAudio::NoError) {
- m_output->m_currentError = QAudio::NoError;
- emit m_output->errorChanged(m_output->m_currentError);
- }
-
- quint32 paddingFrames;
- hr = m_output->m_interface->m_client->GetCurrentPadding(&paddingFrames);
- const quint32 paddingBytes = paddingFrames * m_output->m_currentFormat.channelCount() * m_output->m_currentFormat.sampleSize() / 8;
-
- m_timer.setInterval(m_output->m_currentFormat.durationForBytes(paddingBytes) / 1000);
- m_timer.start();
- return bytesToWrite;
-}
-
-QWasapiAudioOutput::QWasapiAudioOutput(const QByteArray &device)
- : m_deviceName(device)
- , m_volumeCache(qreal(1.))
- , m_currentState(QAudio::StoppedState)
- , m_currentError(QAudio::NoError)
- , m_interval(1000)
- , m_pullMode(true)
- , m_bufferFrames(0)
- , m_bufferBytes(4096)
- , m_eventThread(0)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << device;
-}
-
-QWasapiAudioOutput::~QWasapiAudioOutput()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- stop();
-}
-
-void QWasapiAudioOutput::setVolume(qreal vol)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << vol;
- m_volumeCache = vol;
- if (m_volumeControl) {
- quint32 channelCount;
- HRESULT hr = m_volumeControl->GetChannelCount(&channelCount);
- for (quint32 i = 0; i < channelCount; ++i) {
- hr = m_volumeControl->SetChannelVolume(i, vol);
- RETURN_VOID_IF_FAILED("Could not set audio volume.");
- }
- }
-}
-
-qreal QWasapiAudioOutput::volume() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- return m_volumeCache;
-}
-
-void QWasapiAudioOutput::process()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- DWORD waitRet;
-
- m_processing = true;
- do {
- waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
- if (waitRet != WAIT_OBJECT_0) {
- qFatal("Returned while waiting for event.");
- return;
- }
-
- QMutexLocker locker(&m_mutex);
-
- if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
- break;
- QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
- } while (m_processing);
-}
-
-void QWasapiAudioOutput::processBuffer()
-{
- QMutexLocker locker(&m_mutex);
-
- const quint32 channelCount = m_currentFormat.channelCount();
- const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
- BYTE* buffer;
- HRESULT hr;
-
- quint32 paddingFrames;
- hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
-
- const quint32 availableFrames = m_bufferFrames - paddingFrames;
- hr = m_renderer->GetBuffer(availableFrames, &buffer);
- if (hr != S_OK) {
- m_currentError = QAudio::UnderrunError;
- emit errorChanged(m_currentError);
- // Also Error Buffers need to be released
- hr = m_renderer->ReleaseBuffer(availableFrames, 0);
- ResetEvent(m_event);
- return;
- }
-
- const quint32 readBytes = availableFrames * channelCount * sampleBytes;
- const qint64 read = m_eventDevice->read((char*)buffer, readBytes);
- if (read < static_cast<qint64>(readBytes)) {
- // Fill the rest of the buffer with zero to avoid audio glitches
- if (m_currentError != QAudio::UnderrunError) {
- m_currentError = QAudio::UnderrunError;
- emit errorChanged(m_currentError);
- }
- if (m_currentState != QAudio::IdleState) {
- m_currentState = QAudio::IdleState;
- emit stateChanged(m_currentState);
- }
- }
-
- hr = m_renderer->ReleaseBuffer(availableFrames, 0);
- if (hr != S_OK)
- qFatal("Could not release buffer");
- ResetEvent(m_event);
-
- if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
- emit notify();
- m_openTimeOffset = m_openTime.elapsed();
- }
-
- m_bytesProcessed += read;
- m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
-}
-
-bool QWasapiAudioOutput::initStart(bool pull)
-{
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- stop();
-
- QMutexLocker locker(&m_mutex);
-
- m_interface = QWasapiUtils::createOrGetInterface(m_deviceName, QAudio::AudioOutput);
- Q_ASSERT(m_interface);
-
- m_pullMode = pull;
- WAVEFORMATEX nFmt;
- WAVEFORMATEX closest;
- WAVEFORMATEX *pClose = &closest;
-
- if (!m_currentFormat.isValid() || !QWasapiUtils::convertToNativeFormat(m_currentFormat, &nFmt)) {
- m_currentError = QAudio::OpenError;
- emit errorChanged(m_currentError);
- return false;
- }
-
- HRESULT hr;
-
- hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nFmt, &pClose);
- if (hr != S_OK) {
- m_currentError = QAudio::OpenError;
- emit errorChanged(m_currentError);
- return false;
- }
-
- REFERENCE_TIME t = ((10000.0 * 10000 / nFmt.nSamplesPerSec * 1024) + 0.5);
- if (m_bufferBytes)
- t = m_currentFormat.durationForBytes(m_bufferBytes) * 100;
-
- DWORD flags = pull ? AUDCLNT_STREAMFLAGS_EVENTCALLBACK : 0;
- hr = m_interface->m_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, t, 0, &nFmt, NULL);
- EMIT_RETURN_FALSE_IF_FAILED("Could not initialize audio client.", QAudio::OpenError)
-
- hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_renderer));
- EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError)
-
- hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl));
- if (FAILED(hr))
- qCDebug(lcMmAudioOutput) << "Could not acquire volume control.";
-
- hr = m_interface->m_client->GetBufferSize(&m_bufferFrames);
- EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError)
-
- if (m_pullMode) {
- m_eventThread = new QWasapiProcessThread(this);
- m_event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
- m_eventThread->m_event = m_event;
-
- hr = m_interface->m_client->SetEventHandle(m_event);
- EMIT_RETURN_FALSE_IF_FAILED("Could not set event handle.", QAudio::OpenError)
- } else {
- m_eventDevice = new WasapiOutputDevicePrivate(this);
- m_eventDevice->open(QIODevice::WriteOnly|QIODevice::Unbuffered);
- }
- // Send some initial data, do not exit on failure, latest in process
- // those an error will be caught
- BYTE *pdata = nullptr;
- hr = m_renderer->GetBuffer(m_bufferFrames, &pdata);
- hr = m_renderer->ReleaseBuffer(m_bufferFrames, AUDCLNT_BUFFERFLAGS_SILENT);
-
- hr = m_interface->m_client->Start();
- EMIT_RETURN_FALSE_IF_FAILED("Could not start audio render client.", QAudio::OpenError)
-
- m_openTime.restart();
- m_openTimeOffset = 0;
- m_bytesProcessed = 0;
- return true;
-}
-
-QAudio::Error QWasapiAudioOutput::error() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << m_currentError;
- return m_currentError;
-}
-
-QAudio::State QWasapiAudioOutput::state() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- return m_currentState;
-}
-
-void QWasapiAudioOutput::start(QIODevice *device)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << device;
- if (!initStart(true)) {
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << "failed";
- return;
- }
- m_eventDevice = device;
-
- m_mutex.lock();
- m_currentState = QAudio::ActiveState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- m_eventThread->start();
-}
-
-QIODevice *QWasapiAudioOutput::start()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
-
- if (!initStart(false)) {
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << "failed";
- return nullptr;
- }
-
- m_mutex.lock();
- m_currentState = QAudio::IdleState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
-
- return m_eventDevice;
-}
-
-void QWasapiAudioOutput::stop()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return;
-
- if (!m_pullMode) {
- HRESULT hr;
- hr = m_interface->m_client->Stop();
- hr = m_interface->m_client->Reset();
- }
-
- m_mutex.lock();
- m_currentState = QAudio::StoppedState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- if (m_currentError != QAudio::NoError) {
- m_mutex.lock();
- m_currentError = QAudio::NoError;
- m_mutex.unlock();
- emit errorChanged(m_currentError);
- }
-
- HRESULT hr = m_interface->m_client->Stop();
- if (m_currentState == QAudio::StoppedState) {
- hr = m_interface->m_client->Reset();
- }
-
- if (m_eventThread) {
- SetEvent(m_eventThread->m_event);
- while (m_eventThread->isRunning())
- QThread::yieldCurrentThread();
- m_eventThread->deleteLater();
- m_eventThread = 0;
- }
-}
-
-int QWasapiAudioOutput::bytesFree() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
- return 0;
-
- quint32 paddingFrames;
- HRESULT hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
- if (FAILED(hr)) {
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << "Could not query padding frames.";
- return bufferSize();
- }
-
- const quint32 availableFrames = m_bufferFrames - paddingFrames;
- const quint32 res = availableFrames * m_currentFormat.channelCount() * m_currentFormat.sampleSize() / 8;
- return res;
-}
-
-int QWasapiAudioOutput::periodSize() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- REFERENCE_TIME defaultDevicePeriod;
- HRESULT hr = m_interface->m_client->GetDevicePeriod(&defaultDevicePeriod, NULL);
- if (FAILED(hr))
- return 0;
- const QAudioFormat f = m_currentFormat.isValid() ? m_currentFormat : m_interface->m_mixFormat;
- const int res = m_currentFormat.bytesForDuration(defaultDevicePeriod / 10);
- return res;
-}
-
-void QWasapiAudioOutput::setBufferSize(int value)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << value;
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- return;
- m_bufferBytes = value;
-}
-
-int QWasapiAudioOutput::bufferSize() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState)
- return m_bufferFrames * m_currentFormat.channelCount()* m_currentFormat.sampleSize() / 8;
-
- return m_bufferBytes;
-}
-
-void QWasapiAudioOutput::setNotifyInterval(int ms)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << ms;
- m_interval = qMax(0, ms);
-}
-
-int QWasapiAudioOutput::notifyInterval() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- return m_interval;
-}
-
-qint64 QWasapiAudioOutput::processedUSecs() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return 0;
- qint64 res = qint64(1000000) * m_bytesProcessed /
- (m_currentFormat.channelCount() * (m_currentFormat.sampleSize() / 8)) /
- m_currentFormat.sampleRate();
-
- return res;
-}
-
-void QWasapiAudioOutput::resume()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
-
- if (m_currentState != QAudio::SuspendedState)
- return;
-
- HRESULT hr = m_interface->m_client->Start();
- EMIT_RETURN_VOID_IF_FAILED("Could not start audio render client.", QAudio::FatalError)
-
- m_mutex.lock();
- m_currentError = QAudio::NoError;
- m_currentState = m_pullMode ? QAudio::ActiveState : QAudio::IdleState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
- if (m_eventThread)
- m_eventThread->start();
-}
-
-void QWasapiAudioOutput::setFormat(const QAudioFormat& fmt)
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << fmt;
- if (m_currentState != QAudio::StoppedState)
- return;
- m_currentFormat = fmt;
-}
-
-QAudioFormat QWasapiAudioOutput::format() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- return m_currentFormat;
-}
-
-void QWasapiAudioOutput::suspend()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
-
- if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
- return;
-
- m_mutex.lock();
- m_currentState = QAudio::SuspendedState;
- m_mutex.unlock();
- emit stateChanged(m_currentState);
-
- HRESULT hr = m_interface->m_client->Stop();
- EMIT_RETURN_VOID_IF_FAILED("Could not suspend audio render client.", QAudio::FatalError);
- if (m_eventThread) {
- SetEvent(m_eventThread->m_event);
- while (m_eventThread->isRunning())
- QThread::yieldCurrentThread();
- qCDebug(lcMmAudioOutput) << __FUNCTION__ << "Thread has stopped";
- }
-}
-
-qint64 QWasapiAudioOutput::elapsedUSecs() const
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- if (m_currentState == QAudio::StoppedState)
- return 0;
- return m_openTime.elapsed() * qint64(1000);
-}
-
-void QWasapiAudioOutput::reset()
-{
- qCDebug(lcMmAudioOutput) << __FUNCTION__;
- stop();
-}
-
-QT_END_NAMESPACE
-
-#include "qwasapiaudiooutput.moc"
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h
deleted file mode 100644
index e5d5bc5b1..000000000
--- a/src/plugins/wasapi/qwasapiaudiooutput.h
+++ /dev/null
@@ -1,122 +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$
-**
-****************************************************************************/
-
-#ifndef QAUDIOOUTPUTWASAPI_H
-#define QAUDIOOUTPUTWASAPI_H
-
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QMutex>
-#include <QtCore/QElapsedTimer>
-#include <QtMultimedia/QAbstractAudioOutput>
-#include <QtMultimedia/QAudio>
-
-#include <QReadWriteLock>
-#include <wrl.h>
-
-struct IAudioRenderClient;
-struct IAudioStreamVolume;
-
-QT_BEGIN_NAMESPACE
-
-class AudioInterface;
-class WasapiOutputDevicePrivate;
-class QWasapiProcessThread;
-
-Q_DECLARE_LOGGING_CATEGORY(lcMmAudioOutput)
-
-class QWasapiAudioOutput : public QAbstractAudioOutput
-{
- Q_OBJECT
-public:
- explicit QWasapiAudioOutput(const QByteArray &device);
- ~QWasapiAudioOutput();
-
- void start(QIODevice* device) override;
- QIODevice* start() override;
- void stop() override;
- void reset() override;
- void suspend() override;
- void resume() override;
- int bytesFree() const override;
- int periodSize() const override;
- void setBufferSize(int value) override;
- int bufferSize() const override;
- void setNotifyInterval(int milliSeconds) override;
- int notifyInterval() const override;
- qint64 processedUSecs() const override;
- qint64 elapsedUSecs() const override;
- QAudio::Error error() const override;
- QAudio::State state() const override;
- void setFormat(const QAudioFormat& fmt) override;
- QAudioFormat format() const override;
- void setVolume(qreal) override;
- qreal volume() const override;
-
- void process();
-public slots:
- void processBuffer();
-private:
- bool initStart(bool pull);
- friend class WasapiOutputDevicePrivate;
- friend class WasapiOutputPrivate;
- QByteArray m_deviceName;
- Microsoft::WRL::ComPtr<AudioInterface> m_interface;
- Microsoft::WRL::ComPtr<IAudioRenderClient> m_renderer;
- Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl;
- qreal m_volumeCache;
- QMutex m_mutex;
- QAudio::State m_currentState;
- QAudio::Error m_currentError;
- QAudioFormat m_currentFormat;
- qint64 m_bytesProcessed;
- QElapsedTimer m_openTime;
- int m_openTimeOffset;
- int m_interval;
- bool m_pullMode;
- quint32 m_bufferFrames;
- quint32 m_bufferBytes;
- HANDLE m_event;
- QWasapiProcessThread *m_eventThread;
- QAtomicInt m_processing;
- QIODevice *m_eventDevice;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/wasapi/qwasapiplugin.cpp b/src/plugins/wasapi/qwasapiplugin.cpp
deleted file mode 100644
index 9325dc400..000000000
--- a/src/plugins/wasapi/qwasapiplugin.cpp
+++ /dev/null
@@ -1,85 +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 "qwasapiplugin.h"
-#include "qwasapiaudiodeviceinfo.h"
-#include "qwasapiaudioinput.h"
-#include "qwasapiaudiooutput.h"
-#include "qwasapiutils.h"
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcMmPlugin, "qt.multimedia.plugin")
-
-QWasapiPlugin::QWasapiPlugin(QObject *parent)
- : QAudioSystemPlugin(parent)
-{
- qCDebug(lcMmPlugin) << __FUNCTION__;
-}
-
-QByteArray QWasapiPlugin::defaultDevice(QAudio::Mode mode) const
-{
- return QWasapiUtils::defaultDevice(mode);
-}
-
-QList<QByteArray> QWasapiPlugin::availableDevices(QAudio::Mode mode) const
-{
- qCDebug(lcMmPlugin) << __FUNCTION__ << mode;
- return QWasapiUtils::availableDevices(mode);
-}
-
-QAbstractAudioInput *QWasapiPlugin::createInput(const QByteArray &device)
-{
- qCDebug(lcMmPlugin) << __FUNCTION__ << device;
- return new QWasapiAudioInput(device);
-}
-
-QAbstractAudioOutput *QWasapiPlugin::createOutput(const QByteArray &device)
-{
- qCDebug(lcMmPlugin) << __FUNCTION__ << device;
- return new QWasapiAudioOutput(device);
-}
-
-QAbstractAudioDeviceInfo *QWasapiPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode)
-{
- qCDebug(lcMmPlugin) << __FUNCTION__ << device << mode;
- return new QWasapiAudioDeviceInfo(device, mode);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/wasapi/qwasapiplugin.h b/src/plugins/wasapi/qwasapiplugin.h
deleted file mode 100644
index 7b20676f6..000000000
--- a/src/plugins/wasapi/qwasapiplugin.h
+++ /dev/null
@@ -1,76 +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$
-**
-****************************************************************************/
-
-#ifndef QWASAPIPLUGIN_H
-#define QWASAPIPLUGIN_H
-
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QList>
-#include <QtMultimedia/qaudiosystemplugin.h>
-#include <QtMultimedia/private/qaudiosystempluginext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcMmPlugin)
-
-class QWasapiPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
-{
- Q_OBJECT
-
- Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "wasapi.json")
- Q_INTERFACES(QAudioSystemPluginExtension)
-
-public:
- explicit QWasapiPlugin(QObject *parent = 0);
- ~QWasapiPlugin() {}
-
- QByteArray defaultDevice(QAudio::Mode mode) const override;
- QList<QByteArray> availableDevices(QAudio::Mode mode) const override;
- QAbstractAudioInput *createInput(const QByteArray &device) override;
- QAbstractAudioOutput *createOutput(const QByteArray &device) override;
- QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode) override;
-
-private:
- QList<QByteArray> m_deviceNames;
- QList<QByteArray> m_deviceIds;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWASAPIPLUGIN_H
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
diff --git a/src/plugins/wasapi/qwasapiutils.h b/src/plugins/wasapi/qwasapiutils.h
deleted file mode 100644
index 7cfdd3cda..000000000
--- a/src/plugins/wasapi/qwasapiutils.h
+++ /dev/null
@@ -1,147 +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$
-**
-****************************************************************************/
-
-#ifndef QWASAPIUTILS_H
-#define QWASAPIUTILS_H
-#include "qwasapiaudiodeviceinfo.h"
-#include "qwasapiaudioinput.h"
-#include "qwasapiaudiooutput.h"
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QThread>
-#include <QtMultimedia/QAudio>
-#include <QtMultimedia/QAudioFormat>
-
-#include <wrl.h>
-#include <Audioclient.h>
-#include <mmdeviceapi.h>
-
-struct IAudioClient;
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcMmAudioInterface)
-Q_DECLARE_LOGGING_CATEGORY(lcMmUtils)
-
-#define EMIT_RETURN_FALSE_IF_FAILED(msg, err) \
- if (FAILED(hr)) { \
- m_currentError = err; \
- emit errorChanged(m_currentError); \
- } \
- RETURN_FALSE_IF_FAILED(msg)
-
-#define EMIT_RETURN_VOID_IF_FAILED(msg, err) \
- if (FAILED(hr)) { \
- m_currentError = err; \
- emit errorChanged(m_currentError); \
- } \
- RETURN_VOID_IF_FAILED(msg)
-
-class AudioInterface : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags
- <Microsoft::WRL::Delegate>, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler>
-{
-public:
- enum State {
- Initialized = 0,
- Activating,
- Activated,
- Error
- } ;
-
- explicit AudioInterface();
-
- ~AudioInterface();
-
- virtual HRESULT STDMETHODCALLTYPE ActivateCompleted(IActivateAudioInterfaceAsyncOperation *op);
-
- inline State state() const { return m_currentState; }
- void setState(State s) { m_currentState = s; }
-
- Microsoft::WRL::ComPtr<IAudioClient> m_client;
- QWasapiAudioDeviceInfo *m_parent;
- State m_currentState;
- QAudioFormat m_mixFormat;
-};
-
-class QWasapiProcessThread : public QThread
-{
-public:
- explicit QWasapiProcessThread(QObject *item, bool output = true) : QThread(),
- m_endpoint(item),
- m_output(output)
- {
- qCDebug(lcMmUtils) << __FUNCTION__ << item;
- }
-
- ~QWasapiProcessThread()
- {
- qCDebug(lcMmUtils) << __FUNCTION__;
- CloseHandle(m_event);
- }
-
- void run()
- {
- qCDebug(lcMmUtils) << __FUNCTION__ << m_endpoint;
- if (m_output) {
- QWasapiAudioOutput *output = static_cast<QWasapiAudioOutput *>(m_endpoint);
- output->process();
- } else {
- QWasapiAudioInput *input = static_cast<QWasapiAudioInput *>(m_endpoint);
- input->process();
- }
- }
-
- HANDLE m_event;
-private:
- QObject *m_endpoint;
- bool m_output;
-};
-
-namespace QWasapiUtils
-{
- bool convertToNativeFormat(const QAudioFormat &qt, WAVEFORMATEX *native);
- bool convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFormat *qt);
-
- QByteArray defaultDevice(QAudio::Mode mode);
- QList<QByteArray> availableDevices(QAudio::Mode mode);
- Microsoft::WRL::ComPtr<AudioInterface> createOrGetInterface(const QByteArray &dev, QAudio::Mode mode);
-}
-
-QT_END_NAMESPACE
-
-#endif // QWASAPIUTILS_H
diff --git a/src/plugins/wasapi/wasapi.json b/src/plugins/wasapi/wasapi.json
deleted file mode 100644
index 8d6876490..000000000
--- a/src/plugins/wasapi/wasapi.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": ["wasapi"]
-}
diff --git a/src/plugins/wasapi/wasapi.pro b/src/plugins/wasapi/wasapi.pro
deleted file mode 100644
index 11dfd8abe..000000000
--- a/src/plugins/wasapi/wasapi.pro
+++ /dev/null
@@ -1,30 +0,0 @@
-TARGET = qtaudio_wasapi
-QT += core-private multimedia-private
-
-HEADERS += \
- qwasapiplugin.h \
- qwasapiaudiodeviceinfo.h \
- qwasapiaudioinput.h \
- qwasapiaudiooutput.h \
- qwasapiutils.h
-
-SOURCES += \
- qwasapiplugin.cpp \
- qwasapiaudiodeviceinfo.cpp \
- qwasapiaudioinput.cpp \
- qwasapiaudiooutput.cpp \
- qwasapiutils.cpp
-
-OTHER_FILES += \
- wasapi.json
-
-LIBS += Mmdevapi.lib
-
-win32-* {
- DEFINES += CLASSIC_APP_BUILD
- LIBS += runtimeobject.lib
-}
-
-PLUGIN_TYPE = audio
-PLUGIN_CLASS_NAME = QWasapiPlugin
-load(qt_plugin)