Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsaudiodevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4//
5// W A R N I N G
6// -------------
7//
8// This file is not part of the Qt API. It exists for the convenience
9// of other Qt classes. This header file may change from version to
10// version without notice, or even be removed.
11//
12// INTERNAL USE ONLY: Do NOT use for any other purpose.
13//
14
17
18#include <QtCore/qt_windows.h>
19#include <QtCore/QDataStream>
20#include <QtCore/QIODevice>
21
22#include <audioclient.h>
23#include <mmsystem.h>
24
25#include <initguid.h>
26#include <wtypes.h>
27#include <propkeydef.h>
28#include <mmdeviceapi.h>
29
31
32QWindowsAudioDeviceInfo::QWindowsAudioDeviceInfo(QByteArray dev, ComPtr<IMMDevice> immDev, int waveID, const QString &description, QAudioDevice::Mode mode)
34 m_devId(waveID),
35 m_immDev(std::move(immDev))
36{
37 Q_ASSERT(m_immDev);
38
39 this->description = description;
40
41 ComPtr<IAudioClient> audioClient;
42 HRESULT hr = m_immDev->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr,
43 (void **)audioClient.GetAddressOf());
44 if (SUCCEEDED(hr)) {
45 WAVEFORMATEX *pwfx = nullptr;
46 hr = audioClient->GetMixFormat(&pwfx);
47 if (SUCCEEDED(hr))
49 }
50
51 if (!preferredFormat.isValid()) {
55 }
56
57 DWORD fmt = 0;
58
60 WAVEOUTCAPS woc;
61 if (waveOutGetDevCaps(m_devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
62 fmt = woc.dwFormats;
63 } else {
64 WAVEINCAPS woc;
65 if (waveInGetDevCaps(m_devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
66 fmt = woc.dwFormats;
67 }
68
69 if (!fmt)
70 return;
71
72 // Check sample size
73 if ((fmt & WAVE_FORMAT_1M08)
74 || (fmt & WAVE_FORMAT_1S08)
75 || (fmt & WAVE_FORMAT_2M08)
76 || (fmt & WAVE_FORMAT_2S08)
77 || (fmt & WAVE_FORMAT_4M08)
78 || (fmt & WAVE_FORMAT_4S08)
79 || (fmt & WAVE_FORMAT_48M08)
80 || (fmt & WAVE_FORMAT_48S08)
81 || (fmt & WAVE_FORMAT_96M08)
82 || (fmt & WAVE_FORMAT_96S08)) {
84 }
85 if ((fmt & WAVE_FORMAT_1M16)
86 || (fmt & WAVE_FORMAT_1S16)
87 || (fmt & WAVE_FORMAT_2M16)
88 || (fmt & WAVE_FORMAT_2S16)
89 || (fmt & WAVE_FORMAT_4M16)
90 || (fmt & WAVE_FORMAT_4S16)
91 || (fmt & WAVE_FORMAT_48M16)
92 || (fmt & WAVE_FORMAT_48S16)
93 || (fmt & WAVE_FORMAT_96M16)
94 || (fmt & WAVE_FORMAT_96S16)) {
96 }
97
98 minimumSampleRate = std::numeric_limits<int>::max();
100 // Check sample rate
101 if ((fmt & WAVE_FORMAT_1M08)
102 || (fmt & WAVE_FORMAT_1S08)
103 || (fmt & WAVE_FORMAT_1M16)
104 || (fmt & WAVE_FORMAT_1S16)) {
107 }
108 if ((fmt & WAVE_FORMAT_2M08)
109 || (fmt & WAVE_FORMAT_2S08)
110 || (fmt & WAVE_FORMAT_2M16)
111 || (fmt & WAVE_FORMAT_2S16)) {
114 }
115 if ((fmt & WAVE_FORMAT_4M08)
116 || (fmt & WAVE_FORMAT_4S08)
117 || (fmt & WAVE_FORMAT_4M16)
118 || (fmt & WAVE_FORMAT_4S16)) {
121 }
122 if ((fmt & WAVE_FORMAT_48M08)
123 || (fmt & WAVE_FORMAT_48S08)
124 || (fmt & WAVE_FORMAT_48M16)
125 || (fmt & WAVE_FORMAT_48S16)) {
128 }
129 if ((fmt & WAVE_FORMAT_96M08)
130 || (fmt & WAVE_FORMAT_96S08)
131 || (fmt & WAVE_FORMAT_96M16)
132 || (fmt & WAVE_FORMAT_96S16)) {
135 }
136 if (minimumSampleRate == std::numeric_limits<int>::max())
138
139 minimumChannelCount = std::numeric_limits<int>::max();
141 // Check channel count
142 if (fmt & WAVE_FORMAT_1M08
143 || fmt & WAVE_FORMAT_1M16
144 || fmt & WAVE_FORMAT_2M08
145 || fmt & WAVE_FORMAT_2M16
146 || fmt & WAVE_FORMAT_4M08
147 || fmt & WAVE_FORMAT_4M16
148 || fmt & WAVE_FORMAT_48M08
149 || fmt & WAVE_FORMAT_48M16
150 || fmt & WAVE_FORMAT_96M08
151 || fmt & WAVE_FORMAT_96M16) {
154 }
155 if (fmt & WAVE_FORMAT_1S08
156 || fmt & WAVE_FORMAT_1S16
157 || fmt & WAVE_FORMAT_2S08
158 || fmt & WAVE_FORMAT_2S16
159 || fmt & WAVE_FORMAT_4S08
160 || fmt & WAVE_FORMAT_4S16
161 || fmt & WAVE_FORMAT_48S08
162 || fmt & WAVE_FORMAT_48S16
163 || fmt & WAVE_FORMAT_96S08
164 || fmt & WAVE_FORMAT_96S16) {
167 }
168
169 if (minimumChannelCount == std::numeric_limits<int>::max())
171
172 // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters.
173 // WaveOut and WaveInt might actually support more formats, the only way to know is to try
174 // opening the device with it.
175 QAudioFormat testFormat;
177 testFormat.setSampleRate(maximumSampleRate);
178 const QAudioFormat defaultTestFormat(testFormat);
179
180 // Check if float samples are supported
181 testFormat.setSampleFormat(QAudioFormat::Float);
182 if (testSettings(testFormat))
184
185 // Check channel counts > 2
186 testFormat = defaultTestFormat;
187 for (int i = 18; i > 2; --i) { // <mmreg.h> defines 18 different channels
188 testFormat.setChannelCount(i);
189 if (testSettings(testFormat)) {
191 break;
192 }
193 }
194
196
197 ComPtr<IPropertyStore> props;
198 hr = m_immDev->OpenPropertyStore(STGM_READ, props.GetAddressOf());
199 if (SUCCEEDED(hr)) {
200 PROPVARIANT var;
201 PropVariantInit(&var);
202 hr = props->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &var);
203 if (SUCCEEDED(hr) && var.uintVal != 0)
205 }
206}
207
211
213{
214 WAVEFORMATEXTENSIBLE wfx;
216 // query only, do not open device
217 if (mode == QAudioDevice::Output) {
218 return (waveOutOpen(NULL, UINT_PTR(m_devId), &wfx.Format, 0, 0,
219 WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
220 } else { // AudioInput
221 return (waveInOpen(NULL, UINT_PTR(m_devId), &wfx.Format, 0, 0,
222 WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
223 }
224 }
225
226 return false;
227}
228
QAudioFormat::ChannelConfig channelConfiguration
QAudioFormat preferredFormat
QList< QAudioFormat::SampleFormat > supportedSampleFormats
Mode
Describes the mode of this device.
The QAudioFormat class stores audio stream parameter information.
constexpr void setSampleRate(int sampleRate) noexcept
Sets the sample rate to samplerate in Hertz.
static Q_MULTIMEDIA_EXPORT ChannelConfig defaultChannelConfigForChannelCount(int channelCount)
Returns a default channel configuration for channelCount.
constexpr bool isValid() const noexcept
Returns true if all of the parameters are valid.
constexpr void setSampleFormat(SampleFormat f) noexcept
Sets the sample format to format.
constexpr void setChannelCount(int channelCount) noexcept
Sets the channel count to channels.
\inmodule QtCore
Definition qbytearray.h:57
void append(parameter_type t)
Definition qlist.h:458
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool testSettings(const QAudioFormat &format) const
QWindowsAudioDeviceInfo(QByteArray dev, ComPtr< IMMDevice > immdev, int waveID, const QString &description, QAudioDevice::Mode mode)
Combined button and popup list for selecting options.
QAudioFormat waveFormatExToFormat(const WAVEFORMATEX &in)
bool formatToWaveFormatExtensible(const QAudioFormat &format, WAVEFORMATEXTENSIBLE &wfx)
QAudioFormat::ChannelConfig maskToChannelConfig(UINT32 mask, int count)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum mode
GLenum GLuint GLsizei const GLenum * props
GLint GLsizei GLsizei GLenum format
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QVideoFrameFormat::PixelFormat fmt
long HRESULT