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
55static 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
74static 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
89AudioDevicesBase::AudioDevicesBase(QWidget *parent)
90 : QMainWindow(parent)
91{
92 setupUi(this);
93}
94
95AudioDevicesBase::~AudioDevicesBase() {}
96
97
98AudioTest::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
118void 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
147void 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
159void 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
217void 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
265void AudioTest::sampleRateChanged(int idx)
266{
267 // sample rate has changed
268 m_settings.setSampleRate(sampleRateBox->itemText(index: idx).toInt());
269}
270
271void AudioTest::channelChanged(int idx)
272{
273 m_settings.setChannelCount(channelsBox->itemText(index: idx).toInt());
274}
275
276void AudioTest::codecChanged(int idx)
277{
278 m_settings.setCodec(codecsBox->itemText(index: idx));
279}
280
281void AudioTest::sampleSizeChanged(int idx)
282{
283 m_settings.setSampleSize(sampleSizesBox->itemText(index: idx).toInt());
284}
285
286void 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
300void 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

source code of qtmultimedia/examples/multimedia/audiodevices/audiodevices.cpp