diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-12-16 16:00:41 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-01-20 15:28:26 +0000 |
commit | 58e74015c5239f269a1f0a59eabe43e92c47acd5 (patch) | |
tree | 0324430d8d0e4cabdcab2b86095637dbd06d9ba5 /src/plugins | |
parent | 57888ffdaf4ebf0538954aa47f101ce0af1887de (diff) |
Move Windows audio code over into Qt Multimedia
Change-Id: Ib4f652b49a2d0805a5a44e9f2114b24ab366cdb5
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp | 469 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h | 109 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.cpp | 732 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.h | 177 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiooutput.cpp | 676 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiooutput.h | 168 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioplugin.cpp | 77 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioplugin.h | 66 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioutils.cpp | 117 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioutils.h | 73 | ||||
-rw-r--r-- | src/plugins/windowsaudio/windows.pri | 25 | ||||
-rw-r--r-- | src/plugins/windowsaudio/windowsaudio.json | 3 |
12 files changed, 0 insertions, 2692 deletions
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp deleted file mode 100644 index 72d142da9..000000000 --- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// INTERNAL USE ONLY: Do NOT use for any other purpose. -// - - -#include <QtCore/qt_windows.h> -#include <QtCore/QDataStream> -#include <QtCore/QIODevice> -#include <mmsystem.h> -#include "qwindowsaudiodeviceinfo.h" -#include "qwindowsaudioutils.h" - -#if defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR) -struct IBaseFilter; // Needed for strmif.h from stock MinGW. -struct _DDPIXELFORMAT; -typedef struct _DDPIXELFORMAT* LPDDPIXELFORMAT; -#endif - -#include <strmif.h> -#if !defined(Q_CC_MINGW) || defined(__MINGW64_VERSION_MAJOR) -# include <uuids.h> -#else - -extern GUID CLSID_AudioInputDeviceCategory; -extern GUID CLSID_AudioRendererCategory; -extern GUID IID_ICreateDevEnum; -extern GUID CLSID_SystemDeviceEnum; - -#ifndef __ICreateDevEnum_INTERFACE_DEFINED__ -#define __ICreateDevEnum_INTERFACE_DEFINED__ - -DECLARE_INTERFACE_(ICreateDevEnum, IUnknown) -{ - STDMETHOD(CreateClassEnumerator)(REFCLSID clsidDeviceClass, - IEnumMoniker **ppEnumMoniker, - DWORD dwFlags) PURE; -}; - -#endif // __ICreateDevEnum_INTERFACE_DEFINED__ - -#ifndef __IErrorLog_INTERFACE_DEFINED__ -#define __IErrorLog_INTERFACE_DEFINED__ - -DECLARE_INTERFACE_(IErrorLog, IUnknown) -{ - STDMETHOD(AddError)(THIS_ LPCOLESTR, EXCEPINFO *) PURE; -}; - -#endif /* __IErrorLog_INTERFACE_DEFINED__ */ - -#ifndef __IPropertyBag_INTERFACE_DEFINED__ -#define __IPropertyBag_INTERFACE_DEFINED__ - -const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}}; - -DECLARE_INTERFACE_(IPropertyBag, IUnknown) -{ - STDMETHOD(Read)(THIS_ LPCOLESTR, VARIANT *, IErrorLog *) PURE; - STDMETHOD(Write)(THIS_ LPCOLESTR, VARIANT *) PURE; -}; - -#endif /* __IPropertyBag_INTERFACE_DEFINED__ */ - -#endif // defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR) - -QT_BEGIN_NAMESPACE - -// For mingw toolchain mmsystem.h only defines half the defines, so add if needed. -#ifndef WAVE_FORMAT_44M08 -#define WAVE_FORMAT_44M08 0x00000100 -#define WAVE_FORMAT_44S08 0x00000200 -#define WAVE_FORMAT_44M16 0x00000400 -#define WAVE_FORMAT_44S16 0x00000800 -#define WAVE_FORMAT_48M08 0x00001000 -#define WAVE_FORMAT_48S08 0x00002000 -#define WAVE_FORMAT_48M16 0x00004000 -#define WAVE_FORMAT_48S16 0x00008000 -#define WAVE_FORMAT_96M08 0x00010000 -#define WAVE_FORMAT_96S08 0x00020000 -#define WAVE_FORMAT_96M16 0x00040000 -#define WAVE_FORMAT_96S16 0x00080000 -#endif - - -QWindowsAudioDeviceInfo::QWindowsAudioDeviceInfo(QByteArray dev, QAudio::Mode mode) -{ - QDataStream ds(&dev, QIODevice::ReadOnly); - ds >> devId >> device; - this->mode = mode; - - updateLists(); -} - -QWindowsAudioDeviceInfo::~QWindowsAudioDeviceInfo() -{ - close(); -} - -bool QWindowsAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const -{ - return testSettings(format); -} - -QAudioFormat QWindowsAudioDeviceInfo::preferredFormat() const -{ - QAudioFormat nearest; - if (mode == QAudio::AudioOutput) { - nearest.setSampleRate(44100); - nearest.setChannelCount(2); - nearest.setByteOrder(QAudioFormat::LittleEndian); - nearest.setSampleType(QAudioFormat::SignedInt); - nearest.setSampleSize(16); - nearest.setCodec(QLatin1String("audio/pcm")); - } else { - nearest.setSampleRate(11025); - nearest.setChannelCount(1); - nearest.setByteOrder(QAudioFormat::LittleEndian); - nearest.setSampleType(QAudioFormat::SignedInt); - nearest.setSampleSize(8); - nearest.setCodec(QLatin1String("audio/pcm")); - } - return nearest; -} - -QString QWindowsAudioDeviceInfo::deviceName() const -{ - return device; -} - -QStringList QWindowsAudioDeviceInfo::supportedCodecs() -{ - return QStringList() << QStringLiteral("audio/pcm"); -} - -QList<int> QWindowsAudioDeviceInfo::supportedSampleRates() -{ - updateLists(); - return sampleRatez; -} - -QList<int> QWindowsAudioDeviceInfo::supportedChannelCounts() -{ - updateLists(); - return channelz; -} - -QList<int> QWindowsAudioDeviceInfo::supportedSampleSizes() -{ - updateLists(); - return sizez; -} - -QList<QAudioFormat::Endian> QWindowsAudioDeviceInfo::supportedByteOrders() -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian; -} - -QList<QAudioFormat::SampleType> QWindowsAudioDeviceInfo::supportedSampleTypes() -{ - updateLists(); - return typez; -} - - -bool QWindowsAudioDeviceInfo::open() -{ - return true; -} - -void QWindowsAudioDeviceInfo::close() -{ -} - -bool QWindowsAudioDeviceInfo::testSettings(const QAudioFormat& format) const -{ - WAVEFORMATEXTENSIBLE wfx; - if (qt_convertFormat(format, &wfx)) { - // query only, do not open device - if (mode == QAudio::AudioOutput) { - return (waveOutOpen(NULL, UINT_PTR(devId), &wfx.Format, 0, 0, - WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR); - } else { // AudioInput - return (waveInOpen(NULL, UINT_PTR(devId), &wfx.Format, 0, 0, - WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR); - } - } - - return false; -} - -void QWindowsAudioDeviceInfo::updateLists() -{ - if (!sizez.isEmpty()) - return; - - DWORD fmt = 0; - - if(mode == QAudio::AudioOutput) { - WAVEOUTCAPS woc; - if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) - fmt = woc.dwFormats; - } else { - WAVEINCAPS woc; - if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) - fmt = woc.dwFormats; - } - - sizez.clear(); - sampleRatez.clear(); - channelz.clear(); - typez.clear(); - - if (fmt) { - // Check sample size - if ((fmt & WAVE_FORMAT_1M08) - || (fmt & WAVE_FORMAT_1S08) - || (fmt & WAVE_FORMAT_2M08) - || (fmt & WAVE_FORMAT_2S08) - || (fmt & WAVE_FORMAT_4M08) - || (fmt & WAVE_FORMAT_4S08) - || (fmt & WAVE_FORMAT_48M08) - || (fmt & WAVE_FORMAT_48S08) - || (fmt & WAVE_FORMAT_96M08) - || (fmt & WAVE_FORMAT_96S08)) { - sizez.append(8); - } - if ((fmt & WAVE_FORMAT_1M16) - || (fmt & WAVE_FORMAT_1S16) - || (fmt & WAVE_FORMAT_2M16) - || (fmt & WAVE_FORMAT_2S16) - || (fmt & WAVE_FORMAT_4M16) - || (fmt & WAVE_FORMAT_4S16) - || (fmt & WAVE_FORMAT_48M16) - || (fmt & WAVE_FORMAT_48S16) - || (fmt & WAVE_FORMAT_96M16) - || (fmt & WAVE_FORMAT_96S16)) { - sizez.append(16); - } - - // Check sample rate - if ((fmt & WAVE_FORMAT_1M08) - || (fmt & WAVE_FORMAT_1S08) - || (fmt & WAVE_FORMAT_1M16) - || (fmt & WAVE_FORMAT_1S16)) { - sampleRatez.append(11025); - } - if ((fmt & WAVE_FORMAT_2M08) - || (fmt & WAVE_FORMAT_2S08) - || (fmt & WAVE_FORMAT_2M16) - || (fmt & WAVE_FORMAT_2S16)) { - sampleRatez.append(22050); - } - if ((fmt & WAVE_FORMAT_4M08) - || (fmt & WAVE_FORMAT_4S08) - || (fmt & WAVE_FORMAT_4M16) - || (fmt & WAVE_FORMAT_4S16)) { - sampleRatez.append(44100); - } - if ((fmt & WAVE_FORMAT_48M08) - || (fmt & WAVE_FORMAT_48S08) - || (fmt & WAVE_FORMAT_48M16) - || (fmt & WAVE_FORMAT_48S16)) { - sampleRatez.append(48000); - } - if ((fmt & WAVE_FORMAT_96M08) - || (fmt & WAVE_FORMAT_96S08) - || (fmt & WAVE_FORMAT_96M16) - || (fmt & WAVE_FORMAT_96S16)) { - sampleRatez.append(96000); - } - - // Check channel count - if (fmt & WAVE_FORMAT_1M08 - || fmt & WAVE_FORMAT_1M16 - || fmt & WAVE_FORMAT_2M08 - || fmt & WAVE_FORMAT_2M16 - || fmt & WAVE_FORMAT_4M08 - || fmt & WAVE_FORMAT_4M16 - || fmt & WAVE_FORMAT_48M08 - || fmt & WAVE_FORMAT_48M16 - || fmt & WAVE_FORMAT_96M08 - || fmt & WAVE_FORMAT_96M16) { - channelz.append(1); - } - if (fmt & WAVE_FORMAT_1S08 - || fmt & WAVE_FORMAT_1S16 - || fmt & WAVE_FORMAT_2S08 - || fmt & WAVE_FORMAT_2S16 - || fmt & WAVE_FORMAT_4S08 - || fmt & WAVE_FORMAT_4S16 - || fmt & WAVE_FORMAT_48S08 - || fmt & WAVE_FORMAT_48S16 - || fmt & WAVE_FORMAT_96S08 - || fmt & WAVE_FORMAT_96S16) { - channelz.append(2); - } - - typez.append(QAudioFormat::SignedInt); - typez.append(QAudioFormat::UnSignedInt); - - // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters. - // WaveOut and WaveInt might actually support more formats, the only way to know is to try - // opening the device with it. - QAudioFormat testFormat; - testFormat.setCodec(QStringLiteral("audio/pcm")); - testFormat.setByteOrder(QAudioFormat::LittleEndian); - testFormat.setSampleType(QAudioFormat::SignedInt); - testFormat.setChannelCount(channelz.first()); - testFormat.setSampleRate(sampleRatez.at(sampleRatez.size() / 2)); - testFormat.setSampleSize(sizez.last()); - const QAudioFormat defaultTestFormat(testFormat); - - // Check if float samples are supported - testFormat.setSampleType(QAudioFormat::Float); - testFormat.setSampleSize(32); - if (testSettings(testFormat)) - typez.append(QAudioFormat::Float); - - // Check channel counts > 2 - testFormat = defaultTestFormat; - for (int i = 3; i < 19; ++i) { // <mmreg.h> defines 18 different channels - testFormat.setChannelCount(i); - if (testSettings(testFormat)) - channelz.append(i); - } - - // Check more sample sizes - testFormat = defaultTestFormat; - const QList<int> testSampleSizes = QList<int>() << 24 << 32 << 48 << 64; - for (int s : testSampleSizes) { - testFormat.setSampleSize(s); - if (testSettings(testFormat)) - sizez.append(s); - } - - // Check more sample rates - testFormat = defaultTestFormat; - const QList<int> testSampleRates = QList<int>() << 8000 << 16000 << 32000 << 88200 << 192000; - for (int r : testSampleRates) { - testFormat.setSampleRate(r); - if (testSettings(testFormat)) - sampleRatez.append(r); - } - std::sort(sampleRatez.begin(), sampleRatez.end()); - } -} - -QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode) -{ - Q_UNUSED(mode); - - QList<QByteArray> devices; - //enumerate device fullnames through directshow api - auto hrCoInit = CoInitialize(nullptr); - ICreateDevEnum *pDevEnum = NULL; - IEnumMoniker *pEnum = NULL; - // Create the System device enumerator - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, - reinterpret_cast<void **>(&pDevEnum)); - - unsigned long iNumDevs = mode == QAudio::AudioOutput ? waveOutGetNumDevs() : waveInGetNumDevs(); - if (SUCCEEDED(hr)) { - // Create the enumerator for the audio input/output category - if (pDevEnum->CreateClassEnumerator( - mode == QAudio::AudioOutput ? CLSID_AudioRendererCategory : CLSID_AudioInputDeviceCategory, - &pEnum, 0) == S_OK) { - pEnum->Reset(); - // go through and find all audio devices - IMoniker *pMoniker = NULL; - while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag, - reinterpret_cast<void **>(&pPropBag)); - if (FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - // Find if it is a wave device - VARIANT var; - VariantInit(&var); - hr = pPropBag->Read(mode == QAudio::AudioOutput ? L"WaveOutID" : L"WaveInID", &var, 0); - if (SUCCEEDED(hr)) { - LONG waveID = var.lVal; - if (waveID >= 0 && waveID < LONG(iNumDevs)) { - VariantClear(&var); - // Find the description - hr = pPropBag->Read(L"FriendlyName", &var, 0); - if (SUCCEEDED(hr)) { - QByteArray device; - QDataStream ds(&device, QIODevice::WriteOnly); - ds << quint32(waveID) << QString::fromWCharArray(var.bstrVal); - devices.append(device); - } - } - } - - pPropBag->Release(); - pMoniker->Release(); - } - pEnum->Release(); - } - pDevEnum->Release(); - } - if (SUCCEEDED(hrCoInit)) - CoUninitialize(); - - return devices; -} - -QByteArray QWindowsAudioDeviceInfo::defaultDevice(QAudio::Mode mode) -{ - const QString &name = (mode == QAudio::AudioOutput) ? QStringLiteral("Default Output Device") - : QStringLiteral("Default Input Device"); - QByteArray defaultDevice; - QDataStream ds(&defaultDevice, QIODevice::WriteOnly); - ds << quint32(WAVE_MAPPER) // device ID for default device - << name; - - return defaultDevice; -} - -QT_END_NAMESPACE diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h deleted file mode 100644 index d84eb8acf..000000000 --- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - - -#ifndef QWINDOWSAUDIODEVICEINFO_H -#define QWINDOWSAUDIODEVICEINFO_H - -#include <QtCore/qbytearray.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qlist.h> -#include <QtCore/qdebug.h> - -#include <QtMultimedia/qaudiodeviceinfo.h> -#include <QtMultimedia/qaudiosystem.h> - - -QT_BEGIN_NAMESPACE - -const unsigned int MAX_SAMPLE_RATES = 5; -const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 }; - -class QWindowsAudioDeviceInfo : public QAbstractAudioDeviceInfo -{ - Q_OBJECT - -public: - QWindowsAudioDeviceInfo(QByteArray dev,QAudio::Mode mode); - ~QWindowsAudioDeviceInfo(); - - bool open(); - void close(); - - bool testSettings(const QAudioFormat& format) const; - void updateLists(); - QAudioFormat preferredFormat() const; - bool isFormatSupported(const QAudioFormat& format) const; - QString deviceName() const; - QStringList supportedCodecs(); - QList<int> supportedSampleRates(); - QList<int> supportedChannelCounts(); - QList<int> supportedSampleSizes(); - QList<QAudioFormat::Endian> supportedByteOrders(); - QList<QAudioFormat::SampleType> supportedSampleTypes(); - static QByteArray defaultDevice(QAudio::Mode mode); - static QList<QByteArray> availableDevices(QAudio::Mode); - -private: - QAudio::Mode mode; - QString device; - quint32 devId; - QList<int> sampleRatez; - QList<int> channelz; - QList<int> sizez; - QList<QAudioFormat::SampleType> typez; -}; - - - -QT_END_NAMESPACE - - -#endif // QWINDOWSAUDIODEVICEINFO_H diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.cpp b/src/plugins/windowsaudio/qwindowsaudioinput.cpp deleted file mode 100644 index addabbd32..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioinput.cpp +++ /dev/null @@ -1,732 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// INTERNAL USE ONLY: Do NOT use for any other purpose. -// - - -#include "qwindowsaudioinput.h" - -#include <QtCore/QDataStream> -#include <QtCore/qtimer.h> - -QT_BEGIN_NAMESPACE - -//#define DEBUG_AUDIO 1 - -QWindowsAudioInput::QWindowsAudioInput(const QByteArray &device) -{ - bytesAvailable = 0; - buffer_size = 0; - period_size = 0; - m_device = device; - totalTimeValue = 0; - intervalTime = 1000; - errorState = QAudio::NoError; - deviceState = QAudio::StoppedState; - audioSource = 0; - pullMode = true; - resuming = false; - finished = false; - waveBlockOffset = 0; - - mixerID = 0; - cachedVolume = -1.0f; - memset(&mixerLineControls, 0, sizeof(mixerLineControls)); -} - -QWindowsAudioInput::~QWindowsAudioInput() -{ - stop(); -} - -void QT_WIN_CALLBACK QWindowsAudioInput::waveInProc( HWAVEIN hWaveIn, UINT uMsg, - DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ) -{ - Q_UNUSED(dwParam1); - Q_UNUSED(dwParam2); - Q_UNUSED(hWaveIn); - - QWindowsAudioInput* qAudio; - qAudio = (QWindowsAudioInput*)(dwInstance); - if(!qAudio) - return; - - QMutexLocker locker(&qAudio->mutex); - - switch(uMsg) { - case WIM_OPEN: - break; - case WIM_DATA: - if(qAudio->waveFreeBlockCount > 0) - qAudio->waveFreeBlockCount--; - qAudio->feedback(); - break; - case WIM_CLOSE: - qAudio->finished = true; - break; - default: - return; - } -} - -WAVEHDR* QWindowsAudioInput::allocateBlocks(int size, int count) -{ - int i; - unsigned char* buffer; - WAVEHDR* blocks; - DWORD totalBufferSize = (size + sizeof(WAVEHDR))*count; - - if((buffer=(unsigned char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, - totalBufferSize)) == 0) { - qWarning("QAudioInput: Memory allocation error"); - return 0; - } - blocks = (WAVEHDR*)buffer; - buffer += sizeof(WAVEHDR)*count; - for(i = 0; i < count; i++) { - blocks[i].dwBufferLength = size; - blocks[i].lpData = (LPSTR)buffer; - blocks[i].dwBytesRecorded=0; - blocks[i].dwUser = 0L; - blocks[i].dwFlags = 0L; - blocks[i].dwLoops = 0L; - result = waveInPrepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR)); - if(result != MMSYSERR_NOERROR) { - qWarning("QAudioInput: Can't prepare block %d",i); - return 0; - } - buffer += size; - } - return blocks; -} - -void QWindowsAudioInput::freeBlocks(WAVEHDR* blockArray) -{ - WAVEHDR* blocks = blockArray; - - int count = buffer_size/period_size; - - for(int i = 0; i < count; i++) { - waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR)); - blocks++; - } - HeapFree(GetProcessHeap(), 0, blockArray); -} - -QAudio::Error QWindowsAudioInput::error() const -{ - return errorState; -} - -QAudio::State QWindowsAudioInput::state() const -{ - return deviceState; -} - -#ifndef DRVM_MAPPER_CONSOLEVOICECOM_GET - #ifndef DRVM_MAPPER - #define DRVM_MAPPER 0x2000 - #endif - #ifndef DRVM_MAPPER_STATUS - #define DRVM_MAPPER_STATUS (DRVM_MAPPER+0) - #endif - #define DRVM_USER 0x4000 - #define DRVM_MAPPER_RECONFIGURE (DRVM_MAPPER+1) - #define DRVM_MAPPER_PREFERRED_GET (DRVM_MAPPER+21) - #define DRVM_MAPPER_CONSOLEVOICECOM_GET (DRVM_MAPPER+23) -#endif - -void QWindowsAudioInput::setVolume(qreal volume) -{ - cachedVolume = volume; - for (DWORD i = 0; i < mixerLineControls.cControls; i++) { - - MIXERCONTROLDETAILS controlDetails; - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS); - controlDetails.dwControlID = mixerLineControls.pamxctrl[i].dwControlID; - controlDetails.cChannels = 1; - - if ((mixerLineControls.pamxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_FADER) || - (mixerLineControls.pamxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)) { - MIXERCONTROLDETAILS_UNSIGNED controlDetailsUnsigned; - controlDetailsUnsigned.dwValue = qBound(DWORD(0), DWORD(65535.0 * volume + 0.5), DWORD(65535)); - controlDetails.cMultipleItems = 0; - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); - controlDetails.paDetails = &controlDetailsUnsigned; - mixerSetControlDetails(mixerID, &controlDetails, MIXER_SETCONTROLDETAILSF_VALUE); - } - } -} - -qreal QWindowsAudioInput::volume() const -{ - for (DWORD i = 0; i < mixerLineControls.cControls; i++) { - if ((mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_FADER) && - (mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_VOLUME)) { - continue; - } - - MIXERCONTROLDETAILS controlDetails; - controlDetails.cbStruct = sizeof(controlDetails); - controlDetails.dwControlID = mixerLineControls.pamxctrl[i].dwControlID; - controlDetails.cChannels = 1; - controlDetails.cMultipleItems = 0; - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); - MIXERCONTROLDETAILS_UNSIGNED detailsUnsigned; - controlDetails.paDetails = &detailsUnsigned; - memset(controlDetails.paDetails, 0, controlDetails.cbDetails); - - MMRESULT result = mixerGetControlDetails(mixerID, &controlDetails, MIXER_GETCONTROLDETAILSF_VALUE); - if (result != MMSYSERR_NOERROR) - continue; - if (controlDetails.cbDetails < sizeof(MIXERCONTROLDETAILS_UNSIGNED)) - continue; - return detailsUnsigned.dwValue / 65535.0; - } - - return qFuzzyCompare(cachedVolume, qreal(-1.0f)) ? 1.0f : cachedVolume; -} - -void QWindowsAudioInput::setFormat(const QAudioFormat& fmt) -{ - if (deviceState == QAudio::StoppedState) - settings = fmt; -} - -QAudioFormat QWindowsAudioInput::format() const -{ - return settings; -} - -void QWindowsAudioInput::start(QIODevice* device) -{ - if(deviceState != QAudio::StoppedState) - close(); - - if(!pullMode && audioSource) - delete audioSource; - - pullMode = true; - audioSource = device; - - deviceState = QAudio::ActiveState; - - if(!open()) - return; - - emit stateChanged(deviceState); -} - -QIODevice* QWindowsAudioInput::start() -{ - if(deviceState != QAudio::StoppedState) - close(); - - if(!pullMode && audioSource) - delete audioSource; - - pullMode = false; - audioSource = new InputPrivate(this); - audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); - - deviceState = QAudio::IdleState; - - if(!open()) - return 0; - - emit stateChanged(deviceState); - - return audioSource; -} - -void QWindowsAudioInput::stop() -{ - if(deviceState == QAudio::StoppedState) - return; - - close(); - emit stateChanged(deviceState); -} - -bool QWindowsAudioInput::open() -{ -#ifdef DEBUG_AUDIO - QTime now(QTime::currentTime()); - qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; -#endif - header = 0; - - period_size = 0; - - if (!qt_convertFormat(settings, &wfx)) { - qWarning("QAudioInput: open error, invalid format."); - } else if (buffer_size == 0) { - buffer_size - = (settings.sampleRate() - * settings.channelCount() - * settings.sampleSize() - + 39) / 40; - period_size = buffer_size / 5; - } else { - period_size = buffer_size / 5; - } - - if (period_size == 0) { - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - return false; - } - - timeStamp.restart(); - elapsedTimeOffset = 0; - - QDataStream ds(&m_device, QIODevice::ReadOnly); - quint32 deviceId; - ds >> deviceId; - - if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx.Format, - (DWORD_PTR)&waveInProc, - (DWORD_PTR) this, - CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - qWarning("QAudioInput: failed to open audio device"); - return false; - } - waveBlocks = allocateBlocks(period_size, buffer_size/period_size); - waveBlockOffset = 0; - - if(waveBlocks == 0) { - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - qWarning("QAudioInput: failed to allocate blocks. open failed"); - return false; - } - - mutex.lock(); - waveFreeBlockCount = buffer_size/period_size; - mutex.unlock(); - - for(int i=0; i<buffer_size/period_size; i++) { - result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR)); - if(result != MMSYSERR_NOERROR) { - qWarning("QAudioInput: failed to setup block %d,err=%d",i,result); - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - return false; - } - } - result = waveInStart(hWaveIn); - if(result) { - qWarning("QAudioInput: failed to start audio input"); - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - return false; - } - timeStampOpened.restart(); - elapsedTimeOffset = 0; - totalTimeValue = 0; - errorState = QAudio::NoError; - initMixer(); - return true; -} - -void QWindowsAudioInput::close() -{ - if(deviceState == QAudio::StoppedState) - return; - - deviceState = QAudio::StoppedState; - waveInReset(hWaveIn); - - mutex.lock(); - for (int i=0; i<waveFreeBlockCount; i++) - waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); - freeBlocks(waveBlocks); - mutex.unlock(); - - waveInClose(hWaveIn); - closeMixer(); - - int count = 0; - while(!finished && count < 500) { - count++; - Sleep(10); - } -} - -void QWindowsAudioInput::initMixer() -{ - // Get the Mixer ID from the Sound Device ID - UINT mixerIntID = 0; - if (mixerGetID(reinterpret_cast<HMIXEROBJ>(hWaveIn), - &mixerIntID, MIXER_OBJECTF_HWAVEIN) != MMSYSERR_NOERROR) - return; - mixerID = reinterpret_cast<HMIXEROBJ>(quintptr(mixerIntID)); - - // Get the Destination (Recording) Line Information - MIXERLINE mixerLine; - mixerLine.cbStruct = sizeof(MIXERLINE); - mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; - if (mixerGetLineInfo(mixerID, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR) - return; - - // Set all the Destination (Recording) Line Controls - if (mixerLine.cControls > 0) { - mixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS); - mixerLineControls.dwLineID = mixerLine.dwLineID; - mixerLineControls.cControls = mixerLine.cControls; - mixerLineControls.cbmxctrl = sizeof(MIXERCONTROL); - mixerLineControls.pamxctrl = new MIXERCONTROL[mixerLineControls.cControls]; - if (mixerGetLineControls(mixerID, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL) != MMSYSERR_NOERROR) - closeMixer(); - else if (!qFuzzyCompare(cachedVolume, qreal(-1.0f))) - setVolume(cachedVolume); - } -} - -void QWindowsAudioInput::closeMixer() -{ - delete[] mixerLineControls.pamxctrl; - memset(&mixerLineControls, 0, sizeof(mixerLineControls)); -} - -int QWindowsAudioInput::bytesReady() const -{ - if(period_size == 0 || buffer_size == 0) - return 0; - - int buf = ((buffer_size/period_size)-waveFreeBlockCount)*period_size; - if(buf < 0) - buf = 0; - return buf; -} - -qint64 QWindowsAudioInput::read(char* data, qint64 len) -{ - bool done = false; - - char* p = data; - qint64 l = 0; - qint64 written = 0; - while(!done) { - // Read in some audio data - if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) { - if(pullMode) { - l = audioSource->write(waveBlocks[header].lpData + waveBlockOffset, - waveBlocks[header].dwBytesRecorded - waveBlockOffset); -#ifdef DEBUG_AUDIO - qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l; -#endif - if(l < 0) { - // error - qWarning("QAudioInput: IOError"); - errorState = QAudio::IOError; - - } else if(l == 0) { - // cant write to IODevice - qWarning("QAudioInput: IOError, can't write to QIODevice"); - errorState = QAudio::IOError; - - } else { - totalTimeValue += l; - errorState = QAudio::NoError; - if (deviceState != QAudio::ActiveState) { - deviceState = QAudio::ActiveState; - emit stateChanged(deviceState); - } - resuming = false; - } - } else { - l = qMin<qint64>(len, waveBlocks[header].dwBytesRecorded - waveBlockOffset); - // push mode - memcpy(p, waveBlocks[header].lpData + waveBlockOffset, l); - - len -= l; - -#ifdef DEBUG_AUDIO - qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l; -#endif - totalTimeValue += l; - errorState = QAudio::NoError; - if (deviceState != QAudio::ActiveState) { - deviceState = QAudio::ActiveState; - emit stateChanged(deviceState); - } - resuming = false; - } - } else { - //no data, not ready yet, next time - break; - } - - if (l < waveBlocks[header].dwBytesRecorded - waveBlockOffset) { - waveBlockOffset += l; - done = true; - } else { - waveBlockOffset = 0; - - waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); - - mutex.lock(); - waveFreeBlockCount++; - mutex.unlock(); - - waveBlocks[header].dwBytesRecorded=0; - waveBlocks[header].dwFlags = 0L; - result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); - if(result != MMSYSERR_NOERROR) { - result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); - qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result); - errorState = QAudio::IOError; - - mutex.lock(); - waveFreeBlockCount--; - mutex.unlock(); - - return 0; - } - result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR)); - if(result != MMSYSERR_NOERROR) { - qWarning("QAudioInput: failed to setup block %d,err=%d",header,result); - errorState = QAudio::IOError; - - mutex.lock(); - waveFreeBlockCount--; - mutex.unlock(); - - return 0; - } - header++; - if(header >= buffer_size/period_size) - header = 0; - p+=l; - - mutex.lock(); - if(!pullMode) { - if(len < period_size || waveFreeBlockCount == buffer_size/period_size) - done = true; - } else { - if(waveFreeBlockCount == buffer_size/period_size) - done = true; - } - mutex.unlock(); - } - - written+=l; - } -#ifdef DEBUG_AUDIO - qDebug()<<"read in len="<<written; -#endif - return written; -} - -void QWindowsAudioInput::resume() -{ - if(deviceState == QAudio::SuspendedState) { - deviceState = QAudio::ActiveState; - for(int i=0; i<buffer_size/period_size; i++) { - result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR)); - if(result != MMSYSERR_NOERROR) { - qWarning("QAudioInput: failed to setup block %d,err=%d",i,result); - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - return; - } - } - - mutex.lock(); - waveFreeBlockCount = buffer_size/period_size; - mutex.unlock(); - - header = 0; - resuming = true; - waveBlockOffset = 0; - waveInStart(hWaveIn); - QTimer::singleShot(20,this,SLOT(feedback())); - emit stateChanged(deviceState); - } -} - -void QWindowsAudioInput::setBufferSize(int value) -{ - buffer_size = value; -} - -int QWindowsAudioInput::bufferSize() const -{ - return buffer_size; -} - -int QWindowsAudioInput::periodSize() const -{ - return period_size; -} - -void QWindowsAudioInput::setNotifyInterval(int ms) -{ - intervalTime = qMax(0, ms); -} - -int QWindowsAudioInput::notifyInterval() const -{ - return intervalTime; -} - -qint64 QWindowsAudioInput::processedUSecs() const -{ - if (deviceState == QAudio::StoppedState) - return 0; - qint64 result = qint64(1000000) * totalTimeValue / - (settings.channelCount()*(settings.sampleSize()/8)) / - settings.sampleRate(); - - return result; -} - -void QWindowsAudioInput::suspend() -{ - if(deviceState == QAudio::ActiveState) { - waveInReset(hWaveIn); - deviceState = QAudio::SuspendedState; - emit stateChanged(deviceState); - } -} - -void QWindowsAudioInput::feedback() -{ -#ifdef DEBUG_AUDIO - QTime now(QTime::currentTime()); - qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this; -#endif - if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) - QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection); -} - -bool QWindowsAudioInput::deviceReady() -{ - bytesAvailable = bytesReady(); -#ifdef DEBUG_AUDIO - QTime now(QTime::currentTime()); - qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT"; -#endif - if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) - return true; - - if(pullMode) { - // reads some audio data and writes it to QIODevice - read(0, buffer_size); - } else { - // emits readyRead() so user will call read() on QIODevice to get some audio data - InputPrivate* a = qobject_cast<InputPrivate*>(audioSource); - a->trigger(); - } - - if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { - emit notify(); - elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; - timeStamp.restart(); - } - return true; -} - -qint64 QWindowsAudioInput::elapsedUSecs() const -{ - if (deviceState == QAudio::StoppedState) - return 0; - - return timeStampOpened.elapsed() * qint64(1000); -} - -void QWindowsAudioInput::reset() -{ - stop(); - if (period_size > 0) - waveFreeBlockCount = buffer_size / period_size; -} - -InputPrivate::InputPrivate(QWindowsAudioInput* audio) -{ - audioDevice = qobject_cast<QWindowsAudioInput*>(audio); -} - -InputPrivate::~InputPrivate() {} - -qint64 InputPrivate::readData( char* data, qint64 len) -{ - // push mode, user read() called - if(audioDevice->deviceState != QAudio::ActiveState && - audioDevice->deviceState != QAudio::IdleState) - return 0; - // Read in some audio data - return audioDevice->read(data,len); -} - -qint64 InputPrivate::writeData(const char* data, qint64 len) -{ - Q_UNUSED(data); - Q_UNUSED(len); - - emit readyRead(); - return 0; -} - -void InputPrivate::trigger() -{ - emit readyRead(); -} - -QT_END_NAMESPACE - -#include "moc_qwindowsaudioinput.cpp" diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.h b/src/plugins/windowsaudio/qwindowsaudioinput.h deleted file mode 100644 index 817176731..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioinput.h +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QWINDOWSAUDIOINPUT_H -#define QWINDOWSAUDIOINPUT_H - -#include "qwindowsaudioutils.h" - -#include <QtCore/qfile.h> -#include <QtCore/qdebug.h> -#include <QtCore/qelapsedtimer.h> -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qmutex.h> - -#include <QtMultimedia/qaudio.h> -#include <QtMultimedia/qaudiodeviceinfo.h> -#include <QtMultimedia/qaudiosystem.h> - - -QT_BEGIN_NAMESPACE - - -// For compat with 4.6 -#if !defined(QT_WIN_CALLBACK) -# if defined(Q_CC_MINGW) -# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer)) -# else -# define QT_WIN_CALLBACK CALLBACK -# endif -#endif - -class QWindowsAudioInput : public QAbstractAudioInput -{ - Q_OBJECT -public: - QWindowsAudioInput(const QByteArray &device); - ~QWindowsAudioInput(); - - qint64 read(char* data, qint64 len); - - void setFormat(const QAudioFormat& fmt); - QAudioFormat format() const; - QIODevice* start(); - void start(QIODevice* device); - void stop(); - void reset(); - void suspend(); - void resume(); - int bytesReady() const; - int periodSize() const; - void setBufferSize(int value); - int bufferSize() const; - void setNotifyInterval(int milliSeconds); - int notifyInterval() const; - qint64 processedUSecs() const; - qint64 elapsedUSecs() const; - QAudio::Error error() const; - QAudio::State state() const; - void setVolume(qreal volume); - qreal volume() const; - - QIODevice* audioSource; - QAudioFormat settings; - QAudio::Error errorState; - QAudio::State deviceState; - -private: - qint32 buffer_size; - qint32 period_size; - qint32 header; - QByteArray m_device; - int bytesAvailable; - int intervalTime; - QElapsedTimer timeStamp; - qint64 elapsedTimeOffset; - QElapsedTimer timeStampOpened; - qint64 totalTimeValue; - bool pullMode; - bool resuming; - WAVEFORMATEXTENSIBLE wfx; - HWAVEIN hWaveIn; - MMRESULT result; - WAVEHDR* waveBlocks; - volatile bool finished; - volatile int waveFreeBlockCount; - int waveBlockOffset; - - QMutex mutex; - static void QT_WIN_CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg, - DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); - - WAVEHDR* allocateBlocks(int size, int count); - void freeBlocks(WAVEHDR* blockArray); - bool open(); - void close(); - - void initMixer(); - void closeMixer(); - HMIXEROBJ mixerID; - MIXERLINECONTROLS mixerLineControls; - qreal cachedVolume; - -private slots: - void feedback(); - bool deviceReady(); - -signals: - void processMore(); -}; - -class InputPrivate : public QIODevice -{ - Q_OBJECT -public: - InputPrivate(QWindowsAudioInput* audio); - ~InputPrivate(); - - qint64 readData( char* data, qint64 len); - qint64 writeData(const char* data, qint64 len); - - void trigger(); -private: - QWindowsAudioInput *audioDevice; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp b/src/plugins/windowsaudio/qwindowsaudiooutput.cpp deleted file mode 100644 index e0635307e..000000000 --- a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp +++ /dev/null @@ -1,676 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// INTERNAL USE ONLY: Do NOT use for any other purpose. -// - -#include "qwindowsaudiooutput.h" -#include "qwindowsaudiodeviceinfo.h" -#include "qwindowsaudioutils.h" -#include <QtEndian> -#include <QtCore/QDataStream> -#include <QtCore/qtimer.h> -#include <private/qaudiohelpers_p.h> - -//#define DEBUG_AUDIO 1 - -QT_BEGIN_NAMESPACE - -QWindowsAudioOutput::QWindowsAudioOutput(const QByteArray &device) -{ - bytesAvailable = 0; - buffer_size = 0; - period_size = 0; - m_device = device; - totalTimeValue = 0; - intervalTime = 1000; - audioBuffer = 0; - errorState = QAudio::NoError; - deviceState = QAudio::StoppedState; - audioSource = 0; - pullMode = true; - finished = false; - volumeCache = qreal(1.0); - blocks_count = 5; -} - -QWindowsAudioOutput::~QWindowsAudioOutput() -{ - mutex.lock(); - finished = true; - mutex.unlock(); - - close(); -} - -void CALLBACK QWindowsAudioOutput::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, - DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ) -{ - Q_UNUSED(dwParam1); - Q_UNUSED(dwParam2); - Q_UNUSED(hWaveOut); - - QWindowsAudioOutput* qAudio; - qAudio = (QWindowsAudioOutput*)(dwInstance); - if(!qAudio) - return; - - QMutexLocker locker(&qAudio->mutex); - - switch(uMsg) { - case WOM_OPEN: - qAudio->feedback(); - break; - case WOM_CLOSE: - return; - case WOM_DONE: - if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) { - return; - } - qAudio->waveFreeBlockCount++; - if (qAudio->waveFreeBlockCount >= qAudio->blocks_count) - qAudio->waveFreeBlockCount = qAudio->blocks_count; - - qAudio->feedback(); - break; - default: - return; - } -} - -WAVEHDR* QWindowsAudioOutput::allocateBlocks(int size, int count) -{ - int i; - unsigned char* buffer; - WAVEHDR* blocks; - DWORD totalBufferSize = (size + sizeof(WAVEHDR))*count; - - if((buffer=(unsigned char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, - totalBufferSize)) == 0) { - qWarning("QAudioOutput: Memory allocation error"); - return 0; - } - blocks = (WAVEHDR*)buffer; - buffer += sizeof(WAVEHDR)*count; - for(i = 0; i < count; i++) { - blocks[i].dwBufferLength = size; - blocks[i].lpData = (LPSTR)buffer; - buffer += size; - } - return blocks; -} - -void QWindowsAudioOutput::freeBlocks(WAVEHDR* blockArray) -{ - WAVEHDR* blocks = blockArray; - for (int i = 0; i < blocks_count; ++i) { - waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR)); - blocks++; - } - HeapFree(GetProcessHeap(), 0, blockArray); -} - -QAudioFormat QWindowsAudioOutput::format() const -{ - return settings; -} - -void QWindowsAudioOutput::setFormat(const QAudioFormat& fmt) -{ - if (deviceState == QAudio::StoppedState) - settings = fmt; -} - -void QWindowsAudioOutput::start(QIODevice* device) -{ - if(deviceState != QAudio::StoppedState) - close(); - - if(!pullMode && audioSource) - delete audioSource; - - pullMode = true; - audioSource = device; - - deviceState = QAudio::ActiveState; - - if(!open()) - return; - - emit stateChanged(deviceState); -} - -QIODevice* QWindowsAudioOutput::start() -{ - if(deviceState != QAudio::StoppedState) - close(); - - if(!pullMode && audioSource) - delete audioSource; - - pullMode = false; - audioSource = new OutputPrivate(this); - audioSource->open(QIODevice::WriteOnly|QIODevice::Unbuffered); - - deviceState = QAudio::IdleState; - - if(!open()) - return 0; - - emit stateChanged(deviceState); - - return audioSource; -} - -void QWindowsAudioOutput::stop() -{ - if(deviceState == QAudio::StoppedState) - return; - close(); - if(!pullMode && audioSource) { - delete audioSource; - audioSource = 0; - } - emit stateChanged(deviceState); -} - -bool QWindowsAudioOutput::open() -{ -#ifdef DEBUG_AUDIO - QTime now(QTime::currentTime()); - qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; -#endif - - period_size = 0; - - if (!qt_convertFormat(settings, &wfx)) { - qWarning("QAudioOutput: open error, invalid format."); - } else if (buffer_size == 0) { - // Default buffer size, 200ms, default period size is 40ms - buffer_size - = (settings.sampleRate() - * settings.channelCount() - * settings.sampleSize() - + 39) / 40; - period_size = buffer_size / 5; - } else { - period_size = buffer_size / 5; - } - - // Make even size of wave block to prevent crackling - // due to waveOutWrite() does not like odd buffer length - period_size &= ~1; - - if (period_size == 0) { - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - return false; - } - - const int periods = buffer_size / period_size; - bool ok = false; - static int wave_buffers = qEnvironmentVariableIntValue("QT_WAVE_BUFFERS", &ok); - if (wave_buffers < periods) { - if (ok) - qWarning("Number of WAVE buffers (QT_WAVE_BUFFERS=%d) cannot be less than %d.", wave_buffers, periods); - wave_buffers = periods; - } - - blocks_count = wave_buffers; - waveBlocks = allocateBlocks(period_size, blocks_count); - - mutex.lock(); - waveFreeBlockCount = blocks_count; - mutex.unlock(); - - waveCurrentBlock = 0; - - if(audioBuffer == 0) - audioBuffer = new char[blocks_count * period_size]; - - timeStamp.restart(); - elapsedTimeOffset = 0; - - QDataStream ds(&m_device, QIODevice::ReadOnly); - quint32 deviceId; - ds >> deviceId; - - if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx.Format, - (DWORD_PTR)&waveOutProc, - (DWORD_PTR) this, - CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - qWarning("QAudioOutput: open error"); - return false; - } - - totalTimeValue = 0; - timeStampOpened.restart(); - elapsedTimeOffset = 0; - - errorState = QAudio::NoError; - if(pullMode) { - deviceState = QAudio::ActiveState; - QTimer::singleShot(10, this, SLOT(feedback())); - } else - deviceState = QAudio::IdleState; - - return true; -} - -void QWindowsAudioOutput::pauseAndSleep() -{ - waveOutPause(hWaveOut); - int bitrate = settings.sampleRate() * settings.channelCount() * settings.sampleSize() / 8; - // Time of written data. - int delay = (buffer_size - bytesFree()) * 1000 / bitrate; - Sleep(delay + 10); -} - -void QWindowsAudioOutput::close() -{ - if(deviceState == QAudio::StoppedState) - return; - - // Pause playback before reset to avoid uneeded crackling at the end. - pauseAndSleep(); - deviceState = QAudio::StoppedState; - errorState = QAudio::NoError; - waveOutReset(hWaveOut); - - freeBlocks(waveBlocks); - waveOutClose(hWaveOut); - delete [] audioBuffer; - audioBuffer = 0; - buffer_size = 0; -} - -int QWindowsAudioOutput::bytesFree() const -{ - int buf; - buf = waveFreeBlockCount*period_size; - - return buf; -} - -int QWindowsAudioOutput::periodSize() const -{ - return period_size; -} - -void QWindowsAudioOutput::setBufferSize(int value) -{ - if(deviceState == QAudio::StoppedState) - buffer_size = value; -} - -int QWindowsAudioOutput::bufferSize() const -{ - return buffer_size; -} - -void QWindowsAudioOutput::setNotifyInterval(int ms) -{ - intervalTime = qMax(0, ms); -} - -int QWindowsAudioOutput::notifyInterval() const -{ - return intervalTime; -} - -qint64 QWindowsAudioOutput::processedUSecs() const -{ - if (deviceState == QAudio::StoppedState) - return 0; - qint64 result = qint64(1000000) * totalTimeValue / - (settings.channelCount()*(settings.sampleSize()/8)) / - settings.sampleRate(); - - return result; -} - -qint64 QWindowsAudioOutput::write( const char *data, qint64 len ) -{ - // Write out some audio data - if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) - return 0; - - char* p = (char*)data; - int l = (int)len; - - QByteArray reverse; - if (settings.byteOrder() == QAudioFormat::BigEndian) { - - switch (settings.sampleSize()) { - case 8: - // No need to convert - break; - - case 16: - reverse.resize(l); - for (qint64 i = 0; i < (l >> 1); i++) - *((qint16*)reverse.data() + i) = qFromBigEndian(*((qint16*)data + i)); - p = reverse.data(); - break; - - case 32: - reverse.resize(l); - for (qint64 i = 0; i < (l >> 2); i++) - *((qint32*)reverse.data() + i) = qFromBigEndian(*((qint32*)data + i)); - p = reverse.data(); - break; - } - } - - WAVEHDR* current; - int remain; - current = &waveBlocks[waveCurrentBlock]; - while(l > 0) { - mutex.lock(); - if(waveFreeBlockCount==0) { - mutex.unlock(); - break; - } - mutex.unlock(); - - if(current->dwFlags & WHDR_PREPARED) - waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); - - if(l < period_size) - remain = l; - else - remain = period_size; - - if (volumeCache < qreal(1.0)) - QAudioHelperInternal::qMultiplySamples(volumeCache, settings, p, current->lpData, remain); - else - memcpy(current->lpData, p, remain); - - l -= remain; - p += remain; - current->dwBufferLength = remain; - waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); - waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); - - mutex.lock(); - waveFreeBlockCount--; -#ifdef DEBUG_AUDIO - qDebug("write out l=%d, waveFreeBlockCount=%d", - current->dwBufferLength,waveFreeBlockCount); -#endif - mutex.unlock(); - - totalTimeValue += current->dwBufferLength; - waveCurrentBlock++; - waveCurrentBlock %= blocks_count; - current = &waveBlocks[waveCurrentBlock]; - current->dwUser = 0; - errorState = QAudio::NoError; - if (deviceState != QAudio::ActiveState) { - deviceState = QAudio::ActiveState; - emit stateChanged(deviceState); - } - } - return (len-l); -} - -void QWindowsAudioOutput::resume() -{ - if(deviceState == QAudio::SuspendedState) { - deviceState = pullMode ? QAudio::ActiveState : QAudio::IdleState; - errorState = QAudio::NoError; - waveOutRestart(hWaveOut); - QTimer::singleShot(10, this, SLOT(feedback())); - emit stateChanged(deviceState); - } -} - -void QWindowsAudioOutput::suspend() -{ - if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) { - pauseAndSleep(); - deviceState = QAudio::SuspendedState; - errorState = QAudio::NoError; - emit stateChanged(deviceState); - } -} - -void QWindowsAudioOutput::feedback() -{ -#ifdef DEBUG_AUDIO - QTime now(QTime::currentTime()); - qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback()"; -#endif - bytesAvailable = bytesFree(); - - if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) { - if(bytesAvailable >= period_size) - QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection); - } -} - -bool QWindowsAudioOutput::deviceReady() -{ - if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState) - return false; - - if(pullMode) { - int chunks = bytesAvailable/period_size; -#ifdef DEBUG_AUDIO - qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes"; - qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<chunks*period_size; -#endif - bool startup = false; - if(totalTimeValue == 0) - startup = true; - - bool full=false; - - mutex.lock(); - if (waveFreeBlockCount==0) full = true; - mutex.unlock(); - - if (full) { -#ifdef DEBUG_AUDIO - qDebug() << "Skipping data as unable to write"; -#endif - if ((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { - emit notify(); - elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; - timeStamp.restart(); - } - return true; - } - - if(startup) - waveOutPause(hWaveOut); - int input = period_size*chunks; - int l = audioSource->read(audioBuffer,input); - if(l > 0) { - int out= write(audioBuffer,l); - if(out > 0) { - if (deviceState != QAudio::ActiveState) { - deviceState = QAudio::ActiveState; - emit stateChanged(deviceState); - } - } - if ( out < l) { - // Didn't write all data - audioSource->seek(audioSource->pos()-(l-out)); - } - if (startup) - waveOutRestart(hWaveOut); - } else if(l == 0) { - bytesAvailable = bytesFree(); - - int check = 0; - - mutex.lock(); - check = waveFreeBlockCount; - mutex.unlock(); - - if (check == blocks_count) { - if (deviceState != QAudio::IdleState) { - errorState = QAudio::UnderrunError; - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); - } - } - - } else if(l < 0) { - bytesAvailable = bytesFree(); - if (errorState != QAudio::IOError) - errorState = QAudio::IOError; - } - } else { - int buffered; - - mutex.lock(); - buffered = waveFreeBlockCount; - mutex.unlock(); - - if (buffered >= blocks_count && deviceState == QAudio::ActiveState) { - if (deviceState != QAudio::IdleState) { - errorState = QAudio::UnderrunError; - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); - } - } - } - if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) - return true; - - if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { - emit notify(); - elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; - timeStamp.restart(); - } - - return true; -} - -qint64 QWindowsAudioOutput::elapsedUSecs() const -{ - if (deviceState == QAudio::StoppedState) - return 0; - - return timeStampOpened.elapsed() * qint64(1000); -} - -QAudio::Error QWindowsAudioOutput::error() const -{ - return errorState; -} - -QAudio::State QWindowsAudioOutput::state() const -{ - return deviceState; -} - -void QWindowsAudioOutput::setVolume(qreal v) -{ - if (qFuzzyCompare(volumeCache, v)) - return; - - volumeCache = qBound(qreal(0), v, qreal(1)); -} - -qreal QWindowsAudioOutput::volume() const -{ - return volumeCache; -} - -void QWindowsAudioOutput::reset() -{ - stop(); -} - -OutputPrivate::OutputPrivate(QWindowsAudioOutput* audio) -{ - audioDevice = qobject_cast<QWindowsAudioOutput*>(audio); -} - -OutputPrivate::~OutputPrivate() {} - -qint64 OutputPrivate::readData( char* data, qint64 len) -{ - Q_UNUSED(data); - Q_UNUSED(len); - - return 0; -} - -qint64 OutputPrivate::writeData(const char* data, qint64 len) -{ - int retry = 0; - qint64 written = 0; - - if((audioDevice->deviceState == QAudio::ActiveState) - ||(audioDevice->deviceState == QAudio::IdleState)) { - qint64 l = len; - while(written < l) { - int chunk = audioDevice->write(data+written,(l-written)); - if(chunk <= 0) - retry++; - else - written+=chunk; - - if(retry > 10) - return written; - } - audioDevice->deviceState = QAudio::ActiveState; - } - return written; -} - -QT_END_NAMESPACE - -#include "moc_qwindowsaudiooutput.cpp" diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.h b/src/plugins/windowsaudio/qwindowsaudiooutput.h deleted file mode 100644 index e81121810..000000000 --- a/src/plugins/windowsaudio/qwindowsaudiooutput.h +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QWINDOWSAUDIOOUTPUT_H -#define QWINDOWSAUDIOOUTPUT_H - -#include "qwindowsaudioutils.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qelapsedtimer.h> -#include <QtCore/qiodevice.h> -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qmutex.h> - -#include <QtMultimedia/qaudio.h> -#include <QtMultimedia/qaudiodeviceinfo.h> -#include <QtMultimedia/qaudiosystem.h> - -// For compat with 4.6 -#if !defined(QT_WIN_CALLBACK) -# if defined(Q_CC_MINGW) -# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer)) -# else -# define QT_WIN_CALLBACK CALLBACK -# endif -#endif - -QT_BEGIN_NAMESPACE - -class QWindowsAudioOutput : public QAbstractAudioOutput -{ - Q_OBJECT -public: - QWindowsAudioOutput(const QByteArray &device); - ~QWindowsAudioOutput(); - - qint64 write( const char *data, qint64 len ); - - void setFormat(const QAudioFormat& fmt); - QAudioFormat format() const; - QIODevice* start(); - void start(QIODevice* device); - void stop(); - void reset(); - void suspend(); - void resume(); - int bytesFree() const; - int periodSize() const; - void setBufferSize(int value); - int bufferSize() const; - void setNotifyInterval(int milliSeconds); - int notifyInterval() const; - qint64 processedUSecs() const; - qint64 elapsedUSecs() const; - QAudio::Error error() const; - QAudio::State state() const; - void setVolume(qreal); - qreal volume() const; - - QIODevice* audioSource; - QAudioFormat settings; - QAudio::Error errorState; - QAudio::State deviceState; - -private slots: - void feedback(); - bool deviceReady(); - -private: - void pauseAndSleep(); - QByteArray m_device; - int bytesAvailable; - QElapsedTimer timeStamp; - qint64 elapsedTimeOffset; - QElapsedTimer timeStampOpened; - qint32 buffer_size; - qint32 period_size; - qint32 blocks_count; - qint64 totalTimeValue; - bool pullMode; - int intervalTime; - qreal volumeCache; - static void QT_WIN_CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, - DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); - - QMutex mutex; - - WAVEHDR* allocateBlocks(int size, int count); - void freeBlocks(WAVEHDR* blockArray); - bool open(); - void close(); - - WAVEFORMATEXTENSIBLE wfx; - HWAVEOUT hWaveOut; - WAVEHDR* waveBlocks; - volatile bool finished; - volatile int waveFreeBlockCount; - int waveCurrentBlock; - char* audioBuffer; -}; - -class OutputPrivate : public QIODevice -{ - Q_OBJECT -public: - OutputPrivate(QWindowsAudioOutput* audio); - ~OutputPrivate(); - - qint64 readData( char* data, qint64 len); - qint64 writeData(const char* data, qint64 len); - -private: - QWindowsAudioOutput *audioDevice; -}; - -QT_END_NAMESPACE - - -#endif // QWINDOWSAUDIOOUTPUT_H diff --git a/src/plugins/windowsaudio/qwindowsaudioplugin.cpp b/src/plugins/windowsaudio/qwindowsaudioplugin.cpp deleted file mode 100644 index 8f532fa70..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioplugin.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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 "qwindowsaudioplugin.h" -#include "qwindowsaudiodeviceinfo.h" -#include "qwindowsaudioinput.h" -#include "qwindowsaudiooutput.h" - -QT_BEGIN_NAMESPACE - -QWindowsAudioPlugin::QWindowsAudioPlugin(QObject *parent) - : QAudioSystemPlugin(parent) -{ -} - -QByteArray QWindowsAudioPlugin::defaultDevice(QAudio::Mode mode) const -{ - return QWindowsAudioDeviceInfo::defaultDevice(mode); -} - -QList<QByteArray> QWindowsAudioPlugin::availableDevices(QAudio::Mode mode) const -{ - return QWindowsAudioDeviceInfo::availableDevices(mode); -} - -QAbstractAudioInput *QWindowsAudioPlugin::createInput(const QByteArray &device) -{ - return new QWindowsAudioInput(device); -} - -QAbstractAudioOutput *QWindowsAudioPlugin::createOutput(const QByteArray &device) -{ - return new QWindowsAudioOutput(device); -} - -QAbstractAudioDeviceInfo *QWindowsAudioPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode) -{ - return new QWindowsAudioDeviceInfo(device, mode); -} - -QT_END_NAMESPACE diff --git a/src/plugins/windowsaudio/qwindowsaudioplugin.h b/src/plugins/windowsaudio/qwindowsaudioplugin.h deleted file mode 100644 index 5b36d1727..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioplugin.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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 QWINDOWSAUDIOPLUGIN_H -#define QWINDOWSAUDIOPLUGIN_H - -#include <QtMultimedia/qaudiosystemplugin.h> - -QT_BEGIN_NAMESPACE - -class QWindowsAudioPlugin : public QAudioSystemPlugin -{ - Q_OBJECT - - Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "windowsaudio.json") - -public: - QWindowsAudioPlugin(QObject *parent = 0); - ~QWindowsAudioPlugin() {} - - 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; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSAUDIOPLUGIN_H diff --git a/src/plugins/windowsaudio/qwindowsaudioutils.cpp b/src/plugins/windowsaudio/qwindowsaudioutils.cpp deleted file mode 100644 index 4eaa80b41..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioutils.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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 "qwindowsaudioutils.h" - -#ifndef SPEAKER_FRONT_LEFT - #define SPEAKER_FRONT_LEFT 0x00000001 - #define SPEAKER_FRONT_RIGHT 0x00000002 - #define SPEAKER_FRONT_CENTER 0x00000004 - #define SPEAKER_LOW_FREQUENCY 0x00000008 - #define SPEAKER_BACK_LEFT 0x00000010 - #define SPEAKER_BACK_RIGHT 0x00000020 - #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040 - #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080 - #define SPEAKER_BACK_CENTER 0x00000100 - #define SPEAKER_SIDE_LEFT 0x00000200 - #define SPEAKER_SIDE_RIGHT 0x00000400 - #define SPEAKER_TOP_CENTER 0x00000800 - #define SPEAKER_TOP_FRONT_LEFT 0x00001000 - #define SPEAKER_TOP_FRONT_CENTER 0x00002000 - #define SPEAKER_TOP_FRONT_RIGHT 0x00004000 - #define SPEAKER_TOP_BACK_LEFT 0x00008000 - #define SPEAKER_TOP_BACK_CENTER 0x00010000 - #define SPEAKER_TOP_BACK_RIGHT 0x00020000 - #define SPEAKER_RESERVED 0x7FFC0000 - #define SPEAKER_ALL 0x80000000 -#endif - -#ifndef WAVE_FORMAT_EXTENSIBLE - #define WAVE_FORMAT_EXTENSIBLE 0xFFFE -#endif - -#ifndef WAVE_FORMAT_IEEE_FLOAT - #define WAVE_FORMAT_IEEE_FLOAT 0x0003 -#endif - -static const GUID _KSDATAFORMAT_SUBTYPE_PCM = { - 0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - -static const GUID _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { - 0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - -QT_BEGIN_NAMESPACE - -bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx) -{ - if (!wfx - || !format.isValid() - || format.codec() != QStringLiteral("audio/pcm") - || format.sampleRate() <= 0 - || format.channelCount() <= 0 - || format.sampleSize() <= 0 - || format.byteOrder() != QAudioFormat::LittleEndian) { - return false; - } - - wfx->Format.nSamplesPerSec = format.sampleRate(); - wfx->Format.wBitsPerSample = wfx->Samples.wValidBitsPerSample = format.sampleSize(); - wfx->Format.nChannels = format.channelCount(); - wfx->Format.nBlockAlign = (wfx->Format.wBitsPerSample / 8) * wfx->Format.nChannels; - wfx->Format.nAvgBytesPerSec = wfx->Format.nBlockAlign * wfx->Format.nSamplesPerSec; - wfx->Format.cbSize = 0; - - if (format.sampleType() == QAudioFormat::Float) { - wfx->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; - wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - } else { - wfx->Format.wFormatTag = WAVE_FORMAT_PCM; - wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; - } - - if (format.channelCount() > 2) { - wfx->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - wfx->Format.cbSize = 22; - wfx->dwChannelMask = 0xFFFFFFFF >> (32 - format.channelCount()); - } - - return true; -} - -QT_END_NAMESPACE diff --git a/src/plugins/windowsaudio/qwindowsaudioutils.h b/src/plugins/windowsaudio/qwindowsaudioutils.h deleted file mode 100644 index b8567d85c..000000000 --- a/src/plugins/windowsaudio/qwindowsaudioutils.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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 QWINDOWSAUDIOUTILS_H -#define QWINDOWSAUDIOUTILS_H - -#include <qaudioformat.h> -#include <QtCore/qt_windows.h> -#include <mmsystem.h> - -#ifndef _WAVEFORMATEXTENSIBLE_ - - #define _WAVEFORMATEXTENSIBLE_ - typedef struct - { - WAVEFORMATEX Format; // Base WAVEFORMATEX data - union - { - WORD wValidBitsPerSample; // Valid bits in each sample container - WORD wSamplesPerBlock; // Samples per block of audio data; valid - // if wBitsPerSample=0 (but rarely used). - WORD wReserved; // Zero if neither case above applies. - } Samples; - DWORD dwChannelMask; // Positions of the audio channels - GUID SubFormat; // Format identifier GUID - } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE; - typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE; - -#endif - -QT_BEGIN_NAMESPACE - -bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx); - -QT_END_NAMESPACE - -#endif // QWINDOWSAUDIOUTILS_H diff --git a/src/plugins/windowsaudio/windows.pri b/src/plugins/windowsaudio/windows.pri deleted file mode 100644 index 6d5fe9495..000000000 --- a/src/plugins/windowsaudio/windows.pri +++ /dev/null @@ -1,25 +0,0 @@ -TARGET = qtaudio_windows -QT += multimedia-private - -LIBS += -lstrmiids -lole32 -loleaut32 -lwinmm - -HEADERS += \ - qwindowsaudioplugin.h \ - qwindowsaudiodeviceinfo.h \ - qwindowsaudioinput.h \ - qwindowsaudiooutput.h \ - qwindowsaudioutils.h - -SOURCES += \ - qwindowsaudioplugin.cpp \ - qwindowsaudiodeviceinfo.cpp \ - qwindowsaudioinput.cpp \ - qwindowsaudiooutput.cpp \ - qwindowsaudioutils.cpp - -OTHER_FILES += \ - windowsaudio.json - -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = QWindowsAudioPlugin -load(qt_plugin) diff --git a/src/plugins/windowsaudio/windowsaudio.json b/src/plugins/windowsaudio/windowsaudio.json deleted file mode 100644 index a31d52107..000000000 --- a/src/plugins/windowsaudio/windowsaudio.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": ["default"] -} |