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
qpipewire_audiodevice.cpp
Go to the documentation of this file.
1
// Copyright (C) 2025 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
#
include
"qpipewire_audiodevice_p.h"
5
6
#
include
<
QtCore
/
qdebug
.
h
>
7
#
include
<
QtMultimedia
/
private
/
qaudioformat_p
.
h
>
8
9
QT_BEGIN_NAMESPACE
10
11
namespace
QtPipeWire
{
12
13
namespace
{
14
15
QAudioFormat::SampleFormat toSampleFormat(spa_audio_format fmt)
16
{
17
switch
(fmt) {
18
case
SPA_AUDIO_FORMAT_S16:
19
return
QAudioFormat::Int16;
20
case
SPA_AUDIO_FORMAT_S32:
21
return
QAudioFormat::Int32;
22
case
SPA_AUDIO_FORMAT_U8:
23
return
QAudioFormat::UInt8;
24
case
SPA_AUDIO_FORMAT_F32:
25
return
QAudioFormat::Float;
26
default
:
27
return
QAudioFormat::Unknown;
28
}
29
}
30
31
QByteArray inferDeviceId(
const
PwPropertyDict &properties)
32
{
33
auto
nodeName = getNodeName(properties);
34
Q_ASSERT(nodeName);
35
if
(nodeName)
36
return
QByteArray{ *nodeName };
37
return
{};
38
}
39
40
template
<
typename
Lhs,
typename
Rhs>
41
bool
channelPositionsEqual(
const
Lhs &lhs,
const
Rhs &rhs)
42
{
43
return
std
::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
44
}
45
46
}
// namespace
47
48
QPipewireAudioDevicePrivate
::
QPipewireAudioDevicePrivate
(
const
PwPropertyDict
&
nodeProperties
,
49
const
PwPropertyDict
&
deviceProperties
,
50
const
SpaObjectAudioFormat
&
formats
,
51
QAudioDevice
::
Mode
mode
,
bool
isDefault
)
52
:
QAudioDevicePrivate
{
53
inferDeviceId
(
nodeProperties
),
54
mode
,
55
QString
::
fromUtf8
(
getNodeDescription
(
nodeProperties
).
value_or
(
""
)),
56
}
57
{
58
static
const
QList
allSampleFormats
= {
59
QAudioFormat
::
SampleFormat
::
UInt8
,
60
QAudioFormat
::
SampleFormat
::
Int16
,
61
QAudioFormat
::
SampleFormat
::
Int32
,
62
QAudioFormat
::
SampleFormat
::
Float
,
63
};
64
65
supportedSampleFormats
=
allSampleFormats
;
66
this
->
isDefault
=
isDefault
;
67
68
if
(
auto
path
=
getDeviceSysfsPath
(
deviceProperties
))
69
m_sysfsPath
.
assign
(*
path
);
70
71
if
(
auto
nodeName
=
getNodeName
(
nodeProperties
))
72
m_nodeName
.
assign
(*
nodeName
);
73
74
minimumSampleRate
=
QtMultimediaPrivate
::
allSupportedSampleRates
.
front
();
75
maximumSampleRate
=
QtMultimediaPrivate
::
allSupportedSampleRates
.
back
();
76
77
std
::
visit
([&](
const
auto
&
arg
) {
78
setPreferredSamplingRate
(
arg
);
79
},
formats
.
rates
);
80
81
std
::
visit
([&](
const
auto
&
arg
) {
82
setPreferredSampleFormats
(
arg
);
83
},
formats
.
sampleTypes
);
84
85
minimumChannelCount
= 1;
86
maximumChannelCount
=
formats
.
channelCount
;
87
88
m_channelPositions
=
formats
.
channelPositions
;
89
if
(
m_channelPositions
) {
90
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositionsMono
)) {
91
channelConfiguration
=
QAudioFormat
::
ChannelConfigMono
;
92
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositionsStereo
)) {
93
channelConfiguration
=
QAudioFormat
::
ChannelConfigStereo
;
94
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions2Dot1
)) {
95
channelConfiguration
=
QAudioFormat
::
ChannelConfig2Dot1
;
96
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions3Dot0
)) {
97
channelConfiguration
=
QAudioFormat
::
ChannelConfig3Dot0
;
98
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions3Dot1
)) {
99
channelConfiguration
=
QAudioFormat
::
ChannelConfig3Dot1
;
100
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions5Dot0
)) {
101
channelConfiguration
=
QAudioFormat
::
ChannelConfigSurround5Dot0
;
102
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions5Dot1
)) {
103
channelConfiguration
=
QAudioFormat
::
ChannelConfigSurround5Dot1
;
104
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions7Dot0
)) {
105
channelConfiguration
=
QAudioFormat
::
ChannelConfigSurround7Dot0
;
106
}
else
if
(
channelPositionsEqual
(*
m_channelPositions
,
channelPositions7Dot1
)) {
107
channelConfiguration
=
QAudioFormat
::
ChannelConfigSurround7Dot1
;
108
}
else
{
109
// now we need to guess
110
channelConfiguration
=
111
QAudioFormat
::
defaultChannelConfigForChannelCount
(
formats
.
channelCount
);
112
}
113
}
else
{
114
// we again need to guess
115
channelConfiguration
=
116
QAudioFormat
::
defaultChannelConfigForChannelCount
(
formats
.
channelCount
);
117
}
118
119
preferredFormat
.
setChannelCount
(
formats
.
channelCount
);
120
preferredFormat
.
setChannelConfig
(
channelConfiguration
);
121
}
122
123
QPipewireAudioDevicePrivate
::~
QPipewireAudioDevicePrivate
() =
default
;
124
125
void
QPipewireAudioDevicePrivate
::
setPreferredSamplingRate
(
int
arg
)
126
{
127
preferredFormat
.
setSampleRate
(
arg
);
128
}
129
130
void
QPipewireAudioDevicePrivate
::
setPreferredSamplingRate
(
QSpan
<
const
int
>
arg
)
131
{
132
constexpr
int
defaultPipewireSamplingRate
= 48000;
133
134
preferredFormat
.
setSampleRate
(
135
QtMultimediaPrivate
::
findClosestSamplingRate
(
defaultPipewireSamplingRate
,
arg
));
136
}
137
138
void
QPipewireAudioDevicePrivate
::
setPreferredSamplingRate
(
const
SpaRange
<
int
> &
arg
)
139
{
140
preferredFormat
.
setSampleRate
(
arg
.
defaultValue
);
141
}
142
143
void
QPipewireAudioDevicePrivate
::
setPreferredSampleFormats
(
spa_audio_format
arg
)
144
{
145
QAudioFormat
::
SampleFormat
fmt
=
toSampleFormat
(
arg
);
146
if
(
fmt
==
QAudioFormat
::
Unknown
) {
147
qWarning
() <<
"No sample format supported found for device"
<<
nodeName
();
148
return
;
149
}
150
151
preferredFormat
.
setSampleFormat
(
fmt
);
152
}
153
154
void
QPipewireAudioDevicePrivate
::
setPreferredSampleFormats
(
spa_audio_iec958_codec
codec
)
155
{
156
Q_ASSERT
(
codec
==
SPA_AUDIO_IEC958_CODEC_PCM
);
157
158
// technically iec958 would be 20 or 24 bit PCM, but pipewire will do software mixing, so float
159
// is our preferred option here
160
preferredFormat
.
setSampleFormat
(
QAudioFormat
::
Float
);
161
}
162
163
void
QPipewireAudioDevicePrivate
::
setPreferredSampleFormats
(
const
SpaEnum
<
spa_audio_format
> &
fmt
)
164
{
165
for
(
spa_audio_format
f
:
fmt
.
values
()) {
166
auto
qtFormat
=
toSampleFormat
(
f
);
167
if
(
qtFormat
!=
QAudioFormat
::
Unknown
)
168
supportedSampleFormats
.
push_back
(
qtFormat
);
169
}
170
171
QAudioFormat
::
SampleFormat
sampleFormat
=
toSampleFormat
(
fmt
.
defaultValue
());
172
if
(
sampleFormat
!=
QAudioFormat
::
Unknown
) {
173
preferredFormat
.
setSampleFormat
(
sampleFormat
);
174
}
else
{
175
if
(!
supportedSampleFormats
.
empty
())
176
preferredFormat
.
setSampleFormat
(
supportedSampleFormats
.
front
());
177
else
178
qWarning
() <<
"No sample format supported found for device"
<<
nodeName
();
179
}
180
}
181
182
}
// namespace QtPipeWire
183
184
QT_END_NAMESPACE
QPlatformGraphicsBufferHelper
\inmodule QtGui
QtPipeWire
Definition
qpipewire_async_support.cpp:10
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
qtmultimedia
src
multimedia
pipewire
qpipewire_audiodevice.cpp
Generated on
for Qt by
1.14.0