source: trunk/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtMultimedia module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists for the convenience
47// of other Qt classes. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include <QtCore/qstringlist.h>
54#include <QtCore/qlist.h>
55#include <QtCore/qbytearray.h>
56#include <QtCore/qdatastream.h>
57#include <QtCore/qdebug.h>
58#include <private/qcore_mac_p.h>
59
60#include <QtMultimedia/qaudiodeviceinfo.h>
61#include "qaudio_mac_p.h"
62#include "qaudiodeviceinfo_mac_p.h"
63
64
65
66QT_BEGIN_NAMESPACE
67
68
69QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray const& handle, QAudio::Mode)
70{
71 QDataStream ds(handle);
72 quint32 did, tm;
73
74 ds >> did >> tm >> name;
75 deviceId = AudioDeviceID(did);
76 mode = QAudio::Mode(tm);
77}
78
79bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
80{
81 QAudioDeviceInfoInternal *self = const_cast<QAudioDeviceInfoInternal*>(this);
82
83 return format.isValid()
84 && format.codec() == QString::fromLatin1("audio/pcm")
85 && self->frequencyList().contains(format.frequency())
86 && self->channelsList().contains(format.channels())
87 && self->sampleSizeList().contains(format.sampleSize());
88}
89
90QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
91{
92 QAudioFormat rc;
93
94 UInt32 propSize = 0;
95
96 if (AudioDeviceGetPropertyInfo(deviceId,
97 0,
98 mode == QAudio::AudioInput,
99 kAudioDevicePropertyStreams,
100 &propSize,
101 0) == noErr) {
102
103 const int sc = propSize / sizeof(AudioStreamID);
104
105 if (sc > 0) {
106 AudioStreamID* streams = new AudioStreamID[sc];
107
108 if (AudioDeviceGetProperty(deviceId,
109 0,
110 mode == QAudio::AudioInput,
111 kAudioDevicePropertyStreams,
112 &propSize,
113 streams) == noErr) {
114
115 for (int i = 0; i < sc; ++i) {
116 if (AudioStreamGetPropertyInfo(streams[i],
117 0,
118 kAudioStreamPropertyPhysicalFormat,
119 &propSize,
120 0) == noErr) {
121
122 AudioStreamBasicDescription sf;
123
124 if (AudioStreamGetProperty(streams[i],
125 0,
126 kAudioStreamPropertyPhysicalFormat,
127 &propSize,
128 &sf) == noErr) {
129 rc = toQAudioFormat(sf);
130 break;
131 }
132 }
133 }
134 }
135
136 delete streams;
137 }
138 }
139
140 return rc;
141}
142
143QAudioFormat QAudioDeviceInfoInternal::nearestFormat(const QAudioFormat& format) const
144{
145 QAudioFormat rc(format);
146 QAudioFormat target = preferredFormat();
147
148 if (!format.codec().isEmpty() && format.codec() != QString::fromLatin1("audio/pcm"))
149 return QAudioFormat();
150
151 rc.setCodec(QString::fromLatin1("audio/pcm"));
152
153 if (rc.frequency() != target.frequency())
154 rc.setFrequency(target.frequency());
155 if (rc.channels() != target.channels())
156 rc.setChannels(target.channels());
157 if (rc.sampleSize() != target.sampleSize())
158 rc.setSampleSize(target.sampleSize());
159 if (rc.byteOrder() != target.byteOrder())
160 rc.setByteOrder(target.byteOrder());
161 if (rc.sampleType() != target.sampleType())
162 rc.setSampleType(target.sampleType());
163
164 return rc;
165}
166
167QString QAudioDeviceInfoInternal::deviceName() const
168{
169 return name;
170}
171
172QStringList QAudioDeviceInfoInternal::codecList()
173{
174 return QStringList() << QString::fromLatin1("audio/pcm");
175}
176
177QList<int> QAudioDeviceInfoInternal::frequencyList()
178{
179 QSet<int> rc;
180
181 // Add some common frequencies
182 rc << 8000 << 11025 << 22050 << 44100;
183
184 //
185 UInt32 propSize = 0;
186
187 if (AudioDeviceGetPropertyInfo(deviceId,
188 0,
189 mode == QAudio::AudioInput,
190 kAudioDevicePropertyAvailableNominalSampleRates,
191 &propSize,
192 0) == noErr) {
193
194 const int pc = propSize / sizeof(AudioValueRange);
195
196 if (pc > 0) {
197 AudioValueRange* vr = new AudioValueRange[pc];
198
199 if (AudioDeviceGetProperty(deviceId,
200 0,
201 mode == QAudio::AudioInput,
202 kAudioDevicePropertyAvailableNominalSampleRates,
203 &propSize,
204 vr) == noErr) {
205
206 for (int i = 0; i < pc; ++i)
207 rc << vr[i].mMaximum;
208 }
209
210 delete vr;
211 }
212 }
213
214 return rc.toList();
215}
216
217QList<int> QAudioDeviceInfoInternal::channelsList()
218{
219 QList<int> rc;
220
221 // Can mix down to 1 channel
222 rc << 1;
223
224 UInt32 propSize = 0;
225 int channels = 0;
226
227 if (AudioDeviceGetPropertyInfo(deviceId,
228 0,
229 mode == QAudio::AudioInput,
230 kAudioDevicePropertyStreamConfiguration,
231 &propSize,
232 0) == noErr) {
233
234 AudioBufferList* audioBufferList = static_cast<AudioBufferList*>(qMalloc(propSize));
235
236 if (audioBufferList != 0) {
237 if (AudioDeviceGetProperty(deviceId,
238 0,
239 mode == QAudio::AudioInput,
240 kAudioDevicePropertyStreamConfiguration,
241 &propSize,
242 audioBufferList) == noErr) {
243
244 for (int i = 0; i < int(audioBufferList->mNumberBuffers); ++i) {
245 channels += audioBufferList->mBuffers[i].mNumberChannels;
246 rc << channels;
247 }
248 }
249
250 qFree(audioBufferList);
251 }
252 }
253
254 return rc;
255}
256
257QList<int> QAudioDeviceInfoInternal::sampleSizeList()
258{
259 return QList<int>() << 8 << 16 << 24 << 32 << 64;
260}
261
262QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::byteOrderList()
263{
264 return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
265}
266
267QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::sampleTypeList()
268{
269 return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
270}
271
272static QByteArray get_device_info(AudioDeviceID audioDevice, QAudio::Mode mode)
273{
274 UInt32 size;
275 QByteArray device;
276 QDataStream ds(&device, QIODevice::WriteOnly);
277 AudioStreamBasicDescription sf;
278 CFStringRef name;
279 Boolean isInput = mode == QAudio::AudioInput;
280
281 // Id
282 ds << quint32(audioDevice);
283
284 // Mode
285 size = sizeof(AudioStreamBasicDescription);
286 if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioDevicePropertyStreamFormat,
287 &size, &sf) != noErr) {
288 return QByteArray();
289 }
290 ds << quint32(mode);
291
292 // Name
293 size = sizeof(CFStringRef);
294 if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioObjectPropertyName,
295 &size, &name) != noErr) {
296 qWarning() << "QAudioDeviceInfo: Unable to find device name";
297 }
298 ds << QCFString::toQString(name);
299
300 CFRelease(name);
301
302 return device;
303}
304
305QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
306{
307 AudioDeviceID audioDevice;
308 UInt32 size = sizeof(audioDevice);
309
310 if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size,
311 &audioDevice) != noErr) {
312 qWarning() << "QAudioDeviceInfo: Unable to find default input device";
313 return QByteArray();
314 }
315
316 return get_device_info(audioDevice, QAudio::AudioInput);
317}
318
319QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
320{
321 AudioDeviceID audioDevice;
322 UInt32 size = sizeof(audioDevice);
323
324 if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size,
325 &audioDevice) != noErr) {
326 qWarning() << "QAudioDeviceInfo: Unable to find default output device";
327 return QByteArray();
328 }
329
330 return get_device_info(audioDevice, QAudio::AudioOutput);
331}
332
333QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
334{
335 QList<QByteArray> devices;
336
337 UInt32 propSize = 0;
338
339 if (AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propSize, 0) == noErr) {
340
341 const int dc = propSize / sizeof(AudioDeviceID);
342
343 if (dc > 0) {
344 AudioDeviceID* audioDevices = new AudioDeviceID[dc];
345
346 if (AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propSize, audioDevices) == noErr) {
347 for (int i = 0; i < dc; ++i) {
348 QByteArray info = get_device_info(audioDevices[i], mode);
349 if (!info.isNull())
350 devices << info;
351 }
352 }
353
354 delete audioDevices;
355 }
356 }
357
358 return devices;
359}
360
361
362QT_END_NAMESPACE
363
Note: See TracBrowser for help on using the repository browser.