1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
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 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "audiodevices.h" |
52 | |
53 | // Utility functions for converting QAudioFormat fields into text |
54 | |
55 | static QString toString(QAudioFormat::SampleType sampleType) |
56 | { |
57 | QString result("Unknown" ); |
58 | switch (sampleType) { |
59 | case QAudioFormat::SignedInt: |
60 | result = "SignedInt" ; |
61 | break; |
62 | case QAudioFormat::UnSignedInt: |
63 | result = "UnSignedInt" ; |
64 | break; |
65 | case QAudioFormat::Float: |
66 | result = "Float" ; |
67 | break; |
68 | case QAudioFormat::Unknown: |
69 | result = "Unknown" ; |
70 | } |
71 | return result; |
72 | } |
73 | |
74 | static QString toString(QAudioFormat::Endian endian) |
75 | { |
76 | QString result("Unknown" ); |
77 | switch (endian) { |
78 | case QAudioFormat::LittleEndian: |
79 | result = "LittleEndian" ; |
80 | break; |
81 | case QAudioFormat::BigEndian: |
82 | result = "BigEndian" ; |
83 | break; |
84 | } |
85 | return result; |
86 | } |
87 | |
88 | |
89 | AudioDevicesBase::AudioDevicesBase(QWidget *parent) |
90 | : QMainWindow(parent) |
91 | { |
92 | setupUi(this); |
93 | } |
94 | |
95 | AudioDevicesBase::~AudioDevicesBase() {} |
96 | |
97 | |
98 | AudioTest::AudioTest(QWidget *parent) |
99 | : AudioDevicesBase(parent) |
100 | { |
101 | connect(sender: testButton, signal: &QPushButton::clicked, receiver: this, slot: &AudioTest::test); |
102 | connect(sender: modeBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::modeChanged); |
103 | connect(sender: deviceBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::deviceChanged); |
104 | connect(sender: sampleRateBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::sampleRateChanged); |
105 | connect(sender: channelsBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::channelChanged); |
106 | connect(sender: codecsBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::codecChanged); |
107 | connect(sender: sampleSizesBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::sampleSizeChanged); |
108 | connect(sender: sampleTypesBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::sampleTypeChanged); |
109 | connect(sender: endianBox, signal: QOverload<int>::of(ptr: &QComboBox::activated), receiver: this, slot: &AudioTest::endianChanged); |
110 | connect(sender: populateTableButton, signal: &QPushButton::clicked, receiver: this, slot: &AudioTest::populateTable); |
111 | |
112 | modeBox->setCurrentIndex(0); |
113 | modeChanged(idx: 0); |
114 | deviceBox->setCurrentIndex(0); |
115 | deviceChanged(idx: 0); |
116 | } |
117 | |
118 | void AudioTest::test() |
119 | { |
120 | // tries to set all the settings picked. |
121 | testResult->clear(); |
122 | |
123 | if (!m_deviceInfo.isNull()) { |
124 | if (m_deviceInfo.isFormatSupported(format: m_settings)) { |
125 | testResult->setText(tr(s: "Success" )); |
126 | nearestSampleRate->setText("" ); |
127 | nearestChannel->setText("" ); |
128 | nearestCodec->setText("" ); |
129 | nearestSampleSize->setText("" ); |
130 | nearestSampleType->setText("" ); |
131 | nearestEndian->setText("" ); |
132 | } else { |
133 | QAudioFormat nearest = m_deviceInfo.nearestFormat(format: m_settings); |
134 | testResult->setText(tr(s: "Failed" )); |
135 | nearestSampleRate->setText(QString("%1" ).arg(a: nearest.sampleRate())); |
136 | nearestChannel->setText(QString("%1" ).arg(a: nearest.channelCount())); |
137 | nearestCodec->setText(nearest.codec()); |
138 | nearestSampleSize->setText(QString("%1" ).arg(a: nearest.sampleSize())); |
139 | nearestSampleType->setText(toString(sampleType: nearest.sampleType())); |
140 | nearestEndian->setText(toString(endian: nearest.byteOrder())); |
141 | } |
142 | } |
143 | else |
144 | testResult->setText(tr(s: "No Device" )); |
145 | } |
146 | |
147 | void AudioTest::modeChanged(int idx) |
148 | { |
149 | testResult->clear(); |
150 | deviceBox->clear(); |
151 | const QAudio::Mode mode = idx == 0 ? QAudio::AudioInput : QAudio::AudioOutput; |
152 | for (auto &deviceInfo: QAudioDeviceInfo::availableDevices(mode)) |
153 | deviceBox->addItem(atext: deviceInfo.deviceName(), auserData: QVariant::fromValue(value: deviceInfo)); |
154 | |
155 | deviceBox->setCurrentIndex(0); |
156 | deviceChanged(idx: 0); |
157 | } |
158 | |
159 | void AudioTest::deviceChanged(int idx) |
160 | { |
161 | testResult->clear(); |
162 | |
163 | if (deviceBox->count() == 0) |
164 | return; |
165 | |
166 | // device has changed |
167 | m_deviceInfo = deviceBox->itemData(index: idx).value<QAudioDeviceInfo>(); |
168 | |
169 | sampleRateBox->clear(); |
170 | QList<int> sampleRatez = m_deviceInfo.supportedSampleRates(); |
171 | for (int i = 0; i < sampleRatez.size(); ++i) |
172 | sampleRateBox->addItem(atext: QString("%1" ).arg(a: sampleRatez.at(i))); |
173 | if (sampleRatez.size()) |
174 | m_settings.setSampleRate(sampleRatez.at(i: 0)); |
175 | |
176 | channelsBox->clear(); |
177 | QList<int> chz = m_deviceInfo.supportedChannelCounts(); |
178 | for (int i = 0; i < chz.size(); ++i) |
179 | channelsBox->addItem(atext: QString("%1" ).arg(a: chz.at(i))); |
180 | if (chz.size()) |
181 | m_settings.setChannelCount(chz.at(i: 0)); |
182 | |
183 | codecsBox->clear(); |
184 | QStringList codecs = m_deviceInfo.supportedCodecs(); |
185 | for (int i = 0; i < codecs.size(); ++i) |
186 | codecsBox->addItem(atext: QString("%1" ).arg(a: codecs.at(i))); |
187 | if (codecs.size()) |
188 | m_settings.setCodec(codecs.at(i: 0)); |
189 | // Add false to create failed condition! |
190 | codecsBox->addItem(atext: "audio/test" ); |
191 | |
192 | sampleSizesBox->clear(); |
193 | QList<int> sampleSizez = m_deviceInfo.supportedSampleSizes(); |
194 | for (int i = 0; i < sampleSizez.size(); ++i) |
195 | sampleSizesBox->addItem(atext: QString("%1" ).arg(a: sampleSizez.at(i))); |
196 | if (sampleSizez.size()) |
197 | m_settings.setSampleSize(sampleSizez.at(i: 0)); |
198 | |
199 | sampleTypesBox->clear(); |
200 | QList<QAudioFormat::SampleType> sampleTypez = m_deviceInfo.supportedSampleTypes(); |
201 | |
202 | for (int i = 0; i < sampleTypez.size(); ++i) |
203 | sampleTypesBox->addItem(atext: toString(sampleType: sampleTypez.at(i))); |
204 | if (sampleTypez.size()) |
205 | m_settings.setSampleType(sampleTypez.at(i: 0)); |
206 | |
207 | endianBox->clear(); |
208 | QList<QAudioFormat::Endian> endianz = m_deviceInfo.supportedByteOrders(); |
209 | for (int i = 0; i < endianz.size(); ++i) |
210 | endianBox->addItem(atext: toString(endian: endianz.at(i))); |
211 | if (endianz.size()) |
212 | m_settings.setByteOrder(endianz.at(i: 0)); |
213 | |
214 | allFormatsTable->clearContents(); |
215 | } |
216 | |
217 | void AudioTest::populateTable() |
218 | { |
219 | int row = 0; |
220 | |
221 | QAudioFormat format; |
222 | for (auto codec: m_deviceInfo.supportedCodecs()) { |
223 | format.setCodec(codec); |
224 | for (auto sampleRate: m_deviceInfo.supportedSampleRates()) { |
225 | format.setSampleRate(sampleRate); |
226 | for (auto channels: m_deviceInfo.supportedChannelCounts()) { |
227 | format.setChannelCount(channels); |
228 | for (auto sampleType: m_deviceInfo.supportedSampleTypes()) { |
229 | format.setSampleType(sampleType); |
230 | for (auto sampleSize: m_deviceInfo.supportedSampleSizes()) { |
231 | format.setSampleSize(sampleSize); |
232 | for (auto endian: m_deviceInfo.supportedByteOrders()) { |
233 | format.setByteOrder(endian); |
234 | if (m_deviceInfo.isFormatSupported(format)) { |
235 | allFormatsTable->setRowCount(row + 1); |
236 | |
237 | QTableWidgetItem *codecItem = new QTableWidgetItem(format.codec()); |
238 | allFormatsTable->setItem(row, column: 0, item: codecItem); |
239 | |
240 | QTableWidgetItem *sampleRateItem = new QTableWidgetItem(QString("%1" ).arg(a: format.sampleRate())); |
241 | allFormatsTable->setItem(row, column: 1, item: sampleRateItem); |
242 | |
243 | QTableWidgetItem *channelsItem = new QTableWidgetItem(QString("%1" ).arg(a: format.channelCount())); |
244 | allFormatsTable->setItem(row, column: 2, item: channelsItem); |
245 | |
246 | QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(sampleType: format.sampleType())); |
247 | allFormatsTable->setItem(row, column: 3, item: sampleTypeItem); |
248 | |
249 | QTableWidgetItem *sampleSizeItem = new QTableWidgetItem(QString("%1" ).arg(a: format.sampleSize())); |
250 | allFormatsTable->setItem(row, column: 4, item: sampleSizeItem); |
251 | |
252 | QTableWidgetItem *byteOrderItem = new QTableWidgetItem(toString(endian: format.byteOrder())); |
253 | allFormatsTable->setItem(row, column: 5, item: byteOrderItem); |
254 | |
255 | ++row; |
256 | } |
257 | } |
258 | } |
259 | } |
260 | } |
261 | } |
262 | } |
263 | } |
264 | |
265 | void AudioTest::sampleRateChanged(int idx) |
266 | { |
267 | // sample rate has changed |
268 | m_settings.setSampleRate(sampleRateBox->itemText(index: idx).toInt()); |
269 | } |
270 | |
271 | void AudioTest::channelChanged(int idx) |
272 | { |
273 | m_settings.setChannelCount(channelsBox->itemText(index: idx).toInt()); |
274 | } |
275 | |
276 | void AudioTest::codecChanged(int idx) |
277 | { |
278 | m_settings.setCodec(codecsBox->itemText(index: idx)); |
279 | } |
280 | |
281 | void AudioTest::sampleSizeChanged(int idx) |
282 | { |
283 | m_settings.setSampleSize(sampleSizesBox->itemText(index: idx).toInt()); |
284 | } |
285 | |
286 | void AudioTest::sampleTypeChanged(int idx) |
287 | { |
288 | switch (sampleTypesBox->itemText(index: idx).toInt()) { |
289 | case QAudioFormat::SignedInt: |
290 | m_settings.setSampleType(QAudioFormat::SignedInt); |
291 | break; |
292 | case QAudioFormat::UnSignedInt: |
293 | m_settings.setSampleType(QAudioFormat::UnSignedInt); |
294 | break; |
295 | case QAudioFormat::Float: |
296 | m_settings.setSampleType(QAudioFormat::Float); |
297 | } |
298 | } |
299 | |
300 | void AudioTest::endianChanged(int idx) |
301 | { |
302 | switch (endianBox->itemText(index: idx).toInt()) { |
303 | case QAudioFormat::LittleEndian: |
304 | m_settings.setByteOrder(QAudioFormat::LittleEndian); |
305 | break; |
306 | case QAudioFormat::BigEndian: |
307 | m_settings.setByteOrder(QAudioFormat::BigEndian); |
308 | } |
309 | } |
310 | |