Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmacosaudiodatautils_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 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#ifndef QMACOSAUDIODATAUTILS_P_H
5#define QMACOSAUDIODATAUTILS_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <CoreAudio/AudioHardware.h>
19
20#include <QtMultimedia/qaudiodevice.h>
21#include <QtMultimedia/private/qcoreaudioutils_p.h>
22#include <QtCore/qdebug.h>
23#include <QtCore/qspan.h>
24#include <QtCore/private/qcore_mac_p.h>
25
26#include <optional>
27#include <vector>
28
30
31namespace QCoreAudioUtils
32{
33
34// coreaudio string helpers
38
42
44 const QByteArray &id,
46
47[[nodiscard]] std::optional<AudioDeviceID> findAudioDeviceId(const QAudioDevice &device);
48
49template<typename... Args>
50void printUnableToReadWarning(AudioObjectID objectID, const AudioObjectPropertyAddress &address, Args &&...args)
51{
52 using namespace QCoreAudioUtils;
53 auto warn = qWarning();
54 warn << "Unable to read property" << QCoreAudioUtils::audioPropertySelectorToString(address.mSelector)
55 << "for object" << objectID << ", scope" << QCoreAudioUtils::audioPropertyScopeToString(address.mScope) << ";";
56 (warn << ... << args);
57 warn << "\n If the warning is unexpected use test_audio_config to get comprehensive audio info and report a bug";
58}
59
60
62 AudioObjectPropertySelector selector,
63 QAudioDevice::Mode mode,
64 AudioObjectPropertyElement element = kAudioObjectPropertyElementMain);
65
67 AudioObjectID objectID,
68 const AudioObjectPropertyAddress &address,
69 QSpan<std::byte> destination,
70 bool warnIfMissing = true);
71
72template<typename T>
73std::optional<std::vector<T>> getAudioPropertyList(AudioObjectID objectID,
74 const AudioObjectPropertyAddress &address,
75 bool warnIfMissing = true)
76{
77 static_assert(std::is_trivial_v<T>, "A trivial type is expected");
78
79 UInt32 size = 0;
80 const auto res = AudioObjectGetPropertyDataSize(objectID, &address, 0, nullptr, &size);
81
82 if (res != noErr) {
83 if (warnIfMissing)
84 printUnableToReadWarning(objectID, address,
85 "AudioObjectGetPropertyDataSize failed, Err:", res);
86 } else {
87 std::vector<T> data(size / sizeof(T));
88 if (getAudioPropertyRaw(objectID, address, as_writable_bytes(QSpan{data})))
89 return data;
90 }
91
92 return {};
93}
94
95template<typename T>
96std::optional<T> getAudioProperty(AudioObjectID objectID, const AudioObjectPropertyAddress &address,
97 bool warnIfMissing = false)
98{
99 if constexpr(std::is_same_v<T, QCFString>) {
100 const std::optional<CFStringRef> string = getAudioProperty<CFStringRef>(
101 objectID, address, warnIfMissing);
102 if (string)
103 return QCFString{*string};
104
105 return {};
106 } else {
107 static_assert(std::is_trivial_v<T>, "A trivial type is expected");
108
109 T object{};
110 if (getAudioPropertyRaw(objectID, address, as_writable_bytes(QSpan(&object, 1)), warnIfMissing))
111 return object;
112
113 return {};
114 }
115}
116
117template<typename T>
119getAudioPropertyWithFlexibleArrayMember(AudioObjectID objectID, const AudioObjectPropertyAddress &address,
120 bool warnIfMissing = false)
121{
122 static_assert(std::is_trivial_v<T>, "A trivial type is expected");
123
124 UInt32 size = 0;
125 const auto res = AudioObjectGetPropertyDataSize(objectID, &address, 0, nullptr, &size);
126 if (res != noErr) {
127 if (warnIfMissing)
128 printUnableToReadWarning(objectID, address,
129 "AudioObjectGetPropertyDataSize failed, Err:", res);
130 return nullptr;
131 }
132 if (size < sizeof(T)) {
133 printUnableToReadWarning(objectID, address, "Data size is too small:", size, "VS",
134 sizeof(T), "bytes");
135 return nullptr;
136 }
137
138 using QCoreAudioUtils::QFreeDeleter;
139 std::unique_ptr<std::byte, QFreeDeleter> region {
140 reinterpret_cast<std::byte*>(::malloc(size))
141 };
142
143 if (getAudioPropertyRaw(objectID, address,
144 QSpan(region.get(), size), warnIfMissing))
145 return std::unique_ptr<T, QFreeDeleter>{
146 reinterpret_cast<T*>(region.release())
147 };
148
149 return {};
150}
151
152} // namespace QCoreAudioUtils
153
154
155
156QT_END_NAMESPACE
157
158#endif // QMACOSAUDIODATAUTILS_P_H
QDarwinAudioSink SinkType
void stop(ShutdownPolicy policy)
bool start(AudioCallback cb)
bool start(QIODevice *device)
void updateStreamIdle(bool arg) override
QDarwinAudioSource SourceType
bool start(AudioCallback &&)
void stop(ShutdownPolicy)
void updateStreamIdle(bool idle) override
QLatin1String backendName() const override
QList< QAudioDevice > findAudioOutputs() const override
QPlatformAudioSource * createAudioSource(const QAudioDevice &, const QAudioFormat &, QObject *parent) override
QPlatformAudioSink * createAudioSink(const QAudioDevice &, const QAudioFormat &, QObject *parent) override
QList< QAudioDevice > findAudioInputs() const override
std::unique_ptr< T, QCoreAudioUtils::QFreeDeleter > getAudioPropertyWithFlexibleArrayMember(AudioObjectID objectID, const AudioObjectPropertyAddress &address, bool warnIfMissing=false)
std::optional< T > getAudioProperty(AudioObjectID objectID, const AudioObjectPropertyAddress &address, bool warnIfMissing=false)
QStringView audioPropertySelectorToString(AudioObjectPropertySelector selector)
QStringView audioPropertyElementToString(AudioObjectPropertyElement element)
void printUnableToReadWarning(AudioObjectID objectID, const AudioObjectPropertyAddress &address, Args &&...args)
AudioObjectPropertyAddress makePropertyAddress(AudioObjectPropertySelector selector, QAudioDevice::Mode mode, AudioObjectPropertyElement element=kAudioObjectPropertyElementMain)
QByteArray readPersistentDeviceId(AudioDeviceID, QAudioDevice::Mode)
std::optional< std::vector< T > > getAudioPropertyList(AudioObjectID objectID, const AudioObjectPropertyAddress &address, bool warnIfMissing=true)
bool getAudioPropertyRaw(AudioObjectID objectID, const AudioObjectPropertyAddress &address, QSpan< std::byte > destination, bool warnIfMissing=true)
std::optional< AudioDeviceID > findAudioDeviceId(const QByteArray &id, QAudioDevice::Mode)
QStringView audioPropertyScopeToString(AudioObjectPropertyScope scope)