1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qwasapiaudiodeviceinfo.h"
41 #include "qwasapiutils.h"
42
43 #include <Audioclient.h>
44
45 QT_BEGIN_NAMESPACE
46
47 Q_LOGGING_CATEGORY(lcMmDeviceInfo, "qt.multimedia.deviceinfo")
48
QWasapiAudioDeviceInfo(QByteArray dev,QAudio::Mode mode)49 QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode)
50 : m_deviceName(QString::fromLocal8Bit(dev))
51 {
52 qCDebug(lcMmDeviceInfo) << __FUNCTION__ << dev << mode;
53 m_interface = QWasapiUtils::createOrGetInterface(dev, mode);
54
55 QAudioFormat referenceFormat = m_interface->m_mixFormat;
56
57 const int rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
58 for (int rate : rates) {
59 QAudioFormat f = referenceFormat;
60 f.setSampleRate(rate);
61 if (isFormatSupported(f))
62 m_sampleRates.append(rate);
63 }
64
65 for (int i = 1; i <= 18; ++i) {
66 QAudioFormat f = referenceFormat;
67 f.setChannelCount(i);
68 if (isFormatSupported(f))
69 m_channelCounts.append(i);
70 }
71
72 const int sizes[] = {8, 12, 16, 20, 24, 32, 64};
73 for (int s : sizes) {
74 QAudioFormat f = referenceFormat;
75 f.setSampleSize(s);
76 if (isFormatSupported(f))
77 m_sampleSizes.append(s);
78 }
79
80 referenceFormat.setSampleType(QAudioFormat::SignedInt);
81 if (isFormatSupported(referenceFormat))
82 m_sampleTypes.append(QAudioFormat::SignedInt);
83
84 referenceFormat.setSampleType(QAudioFormat::Float);
85 if (isFormatSupported(referenceFormat))
86 m_sampleTypes.append(QAudioFormat::Float);
87 }
88
~QWasapiAudioDeviceInfo()89 QWasapiAudioDeviceInfo::~QWasapiAudioDeviceInfo()
90 {
91 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
92 }
93
isFormatSupported(const QAudioFormat & format) const94 bool QWasapiAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
95 {
96 qCDebug(lcMmDeviceInfo) << __FUNCTION__ << format;
97
98 WAVEFORMATEX nfmt;
99 if (!QWasapiUtils::convertToNativeFormat(format, &nfmt))
100 return false;
101
102 WAVEFORMATEX closest;
103 WAVEFORMATEX *pClosest = &closest;
104 HRESULT hr;
105 hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nfmt, &pClosest);
106
107 if (hr == S_OK) // S_FALSE is inside SUCCEEDED()
108 return true;
109
110 if (lcMmDeviceInfo().isDebugEnabled()) {
111 QAudioFormat f;
112 QWasapiUtils::convertFromNativeFormat(pClosest, &f);
113 qCDebug(lcMmDeviceInfo) << __FUNCTION__ << hr << "Closest match is:" << f;
114 }
115
116 return false;
117 }
118
preferredFormat() const119 QAudioFormat QWasapiAudioDeviceInfo::preferredFormat() const
120 {
121 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
122 return m_interface->m_mixFormat;
123 }
124
deviceName() const125 QString QWasapiAudioDeviceInfo::deviceName() const
126 {
127 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
128 return m_deviceName;
129 }
130
supportedCodecs()131 QStringList QWasapiAudioDeviceInfo::supportedCodecs()
132 {
133 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
134 return QStringList() << QStringLiteral("audio/pcm");
135 }
136
supportedSampleRates()137 QList<int> QWasapiAudioDeviceInfo::supportedSampleRates()
138 {
139 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
140 return m_sampleRates;
141 }
142
supportedChannelCounts()143 QList<int> QWasapiAudioDeviceInfo::supportedChannelCounts()
144 {
145 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
146 return m_channelCounts;
147 }
148
supportedSampleSizes()149 QList<int> QWasapiAudioDeviceInfo::supportedSampleSizes()
150 {
151 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
152 return m_sampleSizes;
153 }
154
supportedByteOrders()155 QList<QAudioFormat::Endian> QWasapiAudioDeviceInfo::supportedByteOrders()
156 {
157 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
158 return QList<QAudioFormat::Endian>() << m_interface->m_mixFormat.byteOrder();
159 }
160
supportedSampleTypes()161 QList<QAudioFormat::SampleType> QWasapiAudioDeviceInfo::supportedSampleTypes()
162 {
163 qCDebug(lcMmDeviceInfo) << __FUNCTION__;
164 return m_sampleTypes;
165 }
166
167 QT_END_NAMESPACE
168