Commit graph

5508 commits

Author SHA1 Message Date
Wim Taymans
ffdc95655e filter-graph: pass softVolume unmodified if not used
If the filter-graph can apply volume, it will set the softVolume to 1.0
so that the rest of the audioconvert will not apply softVolume anymore.

If it however not applies softVolume, it should pass the given
softVolume and softMute unmodified to be applied elsewhere.

The problem is that the filter-graph completely removed the softVolume
and softMute properties and in case the filter-graph was in use, this
resulted in the channelVolumes being applied in software. This then
could result in double volumes, once in hardware and another time in
software, causing sudden volume loss.

Fixes #5344
2026-07-08 14:27:46 +02:00
zuozhiwei
776117164f bluez5: destroy update_delay_event on transport_start failure
transport_start() creates update_delay_event before ensuring SCO I/O.
When spa_bt_transport_ensure_sco_io() fails, the fail path only cleans
up codec_data and leaks the event source on the loop.

Destroy update_delay_event in fail, matching do_remove_source().
2026-07-07 14:33:31 +02:00
Mike Lothian
062f19b214 spa: alsa: acp-device: stop 100% CPU spin when a poll fd hangs up
handle_acp_poll() copies the poll revents into ACP and clears them, but
never actually looks at them. When one of the polled fds reports
POLLERR/POLLHUP - which happens when the ALSA card goes away, e.g. the
audio function of a USB dock being unplugged - the source is never
removed, and because that condition is level-triggered the loop just
keeps redispatching the handler.

The result is wireplumber pegged at 100% CPU, spinning on the card's
control fd:

    read(24, ..., 72) = -1 ENODEV (No such device)

with fd 24 pointing at a now-deleted /dev/snd/controlC<n>. It stays like
that until the card comes back or the service is restarted.

Accumulate the returned mask and, if anything reports SPA_IO_ERR or
SPA_IO_HUP, drop the poll sources so we stop hammering a dead descriptor.
The udev monitor still drives the real device removal and setup_sources()
re-arms the poll if the card reappears - the same teardown alsa-pcm.c
already does for its own control sources.

Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
2026-07-07 14:33:06 +02:00
刘佳和
3e7a1cdb8c bluez5: Fix JSON parser iterator usage in bcast_source config
Fix incorrect JSON iterator usage when parsing retransmissions and
max_transport_latency fields in BIS configuration.

The code incorrectly used it[2] iterator instead of it[1] when parsing
BIS object fields, causing undefined behavior and configuration values
being ignored.

Signed-off-by: liujiahe <liujiahe@uniontech.com>
2026-07-07 14:32:58 +02:00
Carlos Rafael Giani
8a91b5303f spa: Fix SPA_LOAD_ONCE and SPA_STORE_ONCE atomic macros
These expected pointer to variables instead of variables directly, which
is inconsistent with how the other atomic macros behave. Furthermore,
SPA_STORE_ONCE was plain broken, since the underlying operation expects
an additional argument that was not included.
2026-07-07 14:31:29 +02:00
Wim Taymans
0c3db348f0 audioconvert: small cleanups
Move the sync code to before it is used.

We don't need to clear the graph setup state anymore in force mode, we
did that before we did the sync.
2026-07-07 14:28:09 +02:00
Torkel Niklasson
deb79b74c6 audioconvert: sync filter-graphs out of data loop before forced rebuild
A forced setup_filter_graphs() deactivates and re-instantiates every graph,
which frees and recreates the underlying plugin handles (node_cleanup sets
node->hndl[i] = NULL before re-instantiating). This was done on a graph that
was still referenced by the RT data-loop snapshot (filter_graph[]), so the
RT thread could run a graph whose handles were NULL mid-rebuild, leading to a
NULL handle dereference in the filter-graph process path.

Mirror the safe ordering already used by load_filter_graph()/clean_filter_handles():
before reconfiguring, mark the graphs not-setup and sync_filter_graph() so the
data loop drops them from filter_graph[] under the loop lock. They are
republished by the sync that follows setup. The cheap snapshot swap is done
under the lock; the heavy re-instantiation stays off the RT path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-07 14:28:03 +02:00
刘佳和
bff0a410dd Please replace the comma operator with the correct semicolon when setting aec.name and aec.latency. This will help avoid syntax errors and improve readability.
Signed-off-by: liujiahe <liujiahe@uniontech.com>
2026-06-25 14:23:03 +02:00
Julian Bouzas
b62a4b6b4c alsa: acp: emit route param updates when card properties change
When jack state changes cause port properties to be updated, mark EnumRoute and
Route params as changed and call emit_info() so that the device re-emits the
route parameters with the updated port properties.
2026-06-15 13:04:14 +02:00
Wim Taymans
590c17cc1c acp: avoid segfault when removing a card
Fixes #5255
2026-06-15 13:03:53 +02:00
Barnabás Pőcze
5e17161d0f treewide: avoid unitialized spa_dict::flags
In multiple cases the `flags` member of `spa_dict` is left unitialized,
so try to avoid that. For example in `fill_node_info_proplist()` it is
accessed in `spa_dict_lookup_item()`.

This also modifies `collect_props()` to not depend on a partially initialized
`dict` parameter.
2026-06-15 13:00:48 +02:00
Barnabás Pőcze
4e54a731bf spa: param: spa_{param_dict,tag}_info_parse(): update size as well
In both functions the loop can break early, meaning that the true number
of valid items is `n`, and that should be reflected in the updated `*dict`.
2026-06-15 12:57:26 +02:00
Wim Taymans
71b38a6dc4 alsa: avoid rounding down period_size
Only try to round down the period_size to the lowest power of 2 when we
are resampling and scaling the period_size to match.

In all other cases, we should honour the requested quantum duration.

Fixes #5302
2026-06-15 12:55:19 +02:00
Wim Taymans
b09c8d79c5 filter-graph: sync_volume initializes the control ports
Setting the volume control ports with a volume param also initializes
the controls. This ensures the controls are not restored to their
default value when the graph is activated.

Fixes #5192
2026-05-20 11:39:54 +02:00
Wim Taymans
3563728e03 audioconvert: add dither noise even on empty input
When we are asked to add noise bits, don't call the clear function.

Make the passthrough and clear-on-empty flags available with a new flag
field to make it more extensible.

Fixes #5260
2026-05-18 17:38:46 +02:00
Wim Taymans
aae60d8db3 filter-graph: relax LADSPA plugin loading
Make a new library.filter-path for the filter-graph that will filter and
restrict the dlopen filenames (used for the LADSPA plugin only).

By default this is false and so filter-chain can load from absolute
paths without extra checks.

Enable the extra checks for the pulse LADSPA modules and the
audioconvert filter graphs because these allow loading LADSPA plugins
into other processes.

Fixes #5222
2026-05-18 17:31:51 +02:00
Wim Taymans
768895bdd5 alsa: fix warning about sign 2026-05-11 09:39:33 +02:00
Barnabás Pőcze
c6b5767c8a spa: alsa: pcm: spa_alsa_clear(): clear pointers
Use `spa_clear_ptr()` to ensure that all freed pointers are cleared.
2026-05-11 09:38:33 +02:00
Barnabás Pőcze
bf57911b83 spa: alsa: pcm: log_write(): return early if log level is disabled
If the "debug" log level is not enabled for the "spa.alsa" log topic,
then there is no point in going into the loop and splitting the data
into lines, so skip that.
2026-05-11 09:36:29 +02:00
Barnabás Pőcze
320fe9a6a0 spa: alsa: pcm: log_write(): don't use strcspn()
Do not use `strcspn()` because it assumes a null terminated string,
but the `fopencookie()` write callback receives a (ptr, length) pair.

So use `memchr()` instead to find the `\n`.
2026-05-11 09:36:20 +02:00
Barnabás Pőcze
892d2cb54e spa: alsa: pcm: log_write(): fix return value
The `fopencookie()` write callback should return the number of consumed
bytes, but it currently only ever returns 0, which signals an error
condition according to the documentation.

Fix that by not overwriting `size`.

Fixes: 73073eb33f ("alsa: redirect alsa output to log file")
2026-05-11 09:36:13 +02:00
Barnabás Pőcze
5ea19f5fca treewide: mark fopencookie() vtable const
`fopencookie()` takes the vtable by value, so it can be marked `const`, so do that.
2026-05-11 09:36:00 +02:00
Martin Geier
6affbf9cf2 audioconvert: update rate also for nodes with disabled resampler
When the graph rate changes it is possible that the follower node can
renegotiate to the new suggested audioconvert rate without requiring
resampling and so the extra check for the disabled resampler is not
required.

Fixes #4933
2026-05-08 15:53:17 +02:00
Wim Taymans
3730528419 bluez5: fix wrong use of F_GETFL and F_SETFL
The pattern is to F_GETFL the flags, then clear the NONBLOCK flag and
then F_SETFL the new flags.
2026-05-08 14:53:01 +02:00
Barnabás Pőcze
e5b741732d treewide: make more file descriptors cloexec
Avoid file descriptor leakage into child processes by marking them `O_CLOEXEC`.
2026-05-08 14:53:01 +02:00
Wim Taymans
2bfdc36954 filter-graph: guard against overflow of graph input/output 2026-05-08 14:52:54 +02:00
Wim Taymans
e8bf06ea56 security: add missing O_CLOEXEC flag to V4L2 device open
File and Resource Handling: Medium

The V4L2 device file descriptor was opened without the O_CLOEXEC flag.
If a child process is subsequently spawned (e.g., via fork+exec), the
video device fd would be inherited, potentially allowing the child
process unauthorized access to the camera device.

Fixed by adding O_CLOEXEC to the open() flags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-08 13:53:17 +02:00
Wim Taymans
4d7c448150 security: add missing O_CLOEXEC/SOCK_CLOEXEC flags
File and Resource Handling: Medium

Several file and socket operations were missing the close-on-exec flag,
which causes file descriptors to leak to child processes created via
fork+exec. This could allow child processes unintended access to
privileged resources.

- node-driver.c: SOCK_DGRAM socket for SIOCETHTOOL ioctl leaked to
  child processes
- pw-container.c: Unix domain listen socket leaked to spawned
  container processes
- compress-offload-api.c: ALSA compress-offload device fd leaked to
  child processes

Added O_CLOEXEC to open() calls and SOCK_CLOEXEC to socket() calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-08 13:52:53 +02:00
Wim Taymans
0b11792194 filter-graph: error when there are no valid nodes
The nodes might have failed to load or there was an empty array or the
array did not contain objects.
2026-05-08 13:28:28 +02:00
Wim Taymans
4a303edb9e spa: limit the number of buffer blocks
Unbounded values might overflow the stack.
2026-05-08 12:17:50 +02:00
Wim Taymans
3a503ea4b6 filter-graph: remove the pipe filter
It's a terrible idea, doesn't work so well (locks up the data-loop when
read is blocked) and a security mightmare. If you really need to pipe
samples through some program, do that somewhere else, like from the
command line with pw-cat and pw-record.
2026-05-08 12:03:37 +02:00
Wim Taymans
82dbfd558f acp: partially revert f76327e076
The Line Out mute seems to break things.

See #5246
2026-04-28 12:11:53 +02:00
Wim Taymans
8bf7ae5e74 audiomixer: rate limit the "out of buffers" debug
See #5249
2026-04-28 12:11:42 +02:00
zuozhiwei
e01ff7e67e audioconvert: fix tmp_datas[1] when scratch ports grow 2026-04-21 17:17:31 +02:00
Masum Reza
cf8a0b012f alsa: acp: don’t override user-selected port on availability changes
ACP was re-selecting the “best” port on every port availability event,
even when a port was already explicitly selected by the user. This
differs from PulseAudio’s behavior, where port switching decisions are
left to higher-level policy.

This caused issues on devices where Line Out (speakers) and Headphones
share the same analog interface: when headphones are plugged in, ACP
would immediately switch away from the user-selected Line Out, or end up
in a state where no sound is produced despite selecting speakers explicitly from
clients like pwvucontrol.

Fix this by only re-evaluating and switching ports when:
  - no active port is currently selected, or
  - the active port has become unavailable

This preserves manual user choices and prevents ACP from fighting client
port selections during route activation.

Additionally, adjust ALSA mixer paths to better separate Line Out and
Headphones behavior:
  - Disable Line Out controls in the headphones path
  - Add explicit Line Out and Auto-Mute Mode handling in the lineout path

Together, these changes align PipeWire’s behavior more closely with
PulseAudio and fix cases where selecting speakers while headphones are
plugged results in no audio output.

Signed-off-by: John Titor <masumrezarock100@gmail.com>
2026-04-21 17:15:05 +02:00
Pauli Virtanen
04af44d5c3 bluez5: more MT7925 quirks
The MT7925 chipset has several alternative USB ids recognized by kernel,
list them all.

(cherry picked from commit cee1bdfb5a)
2026-04-19 19:15:23 +03:00
Pauli Virtanen
bb6199214d bluez5: add quirk for LC3-24kHz for HFP
MT7925 fails to setup a SCO connection that results to working LC3-24kHz
audio. Other controllers (Intel etc) appear to work OK.

Add quirk for disabling this codec, and disable it for this Mediatek
controller.

(cherry picked from commit 84e6845aa6)
2026-04-19 19:15:23 +03:00
Pauli Virtanen
b2028a03f0 bluez5: fix disabling HFP codecs via bluez5.codecs
backend-native should not advertise disabled HFP codecs as available.

(cherry picked from commit 6e8e234e61)
2026-04-19 19:15:23 +03:00
Martin Geier
c148028f5a bluez5: iso-io: don't use streams without tx_latency enabled for fill level calculation
When there is a stream without tx_latency enabled, the fill_count ends
with MIN_FILL value. This causes one buffer of silence to be written to
every stream before the actual data in each iteration.
Consequently, more data is written than consumed in each iteration.
After several iterations, spa_bt_send fails, triggering a
group_latency_check failure in few next iterations and leading to
dropped data.

Skip streams without tx_latency enabled in fill level calculations
to prevent these audio glitches.

(cherry picked from commit 42415eadd9)
2026-04-19 19:15:23 +03:00
Alexander Sarmanow
78888a78c3 bluez5: bap: add support for manual BIS config
(cherry picked from commit 54a4515b09)
2026-04-19 19:15:23 +03:00
ValdikSS
5918e6f05d bluez5: aac: Use VBR encoding with Mode 5 by default
(cherry picked from commit ee1b429441)
2026-04-19 19:15:23 +03:00
ValdikSS
cb1d19e433 bluez5: aac: use higher band limit for CBR mode
FDK-AAC encoder uses band pass filter, which is automatically
applied at all bitrates.
For CBR encoding mode, its values are as follows (for stereo):

* 0-12 kb/s:   5   kHz
* 12-20 kb/s:  6.4 kHz
* 20-28 kb/s:  9.6 kHz
* 40-56 kb/s:  13  kHz
* 56-72 kb/s:  16  kHz
* 72-576 kb/s: 17  kHz

VBR uses the following table (stereo):

* Mode 1: 13   kHz
* Mode 2: 13   kHz
* Mode 3: 15.7 kHz
* Mode 4: 16.5 kHz
* Mode 5: 19.3 kHz

17 kHz for CBR is a limiting value for high bitrate.

Assume >110 kbit/s as a "high bitrate" CBR and increase the
band pass cutout up to 19.3 kHz (as in mode 5 VBR).

Link: d8e6b1a3aa/libAACenc/src/bandwidth.cpp (L114-L160)
(cherry picked from commit a35b6b0c4b)
2026-04-19 19:15:23 +03:00
ValdikSS
cc71d011e0 bluez5: aac: use maximum possible peak bitrate according to MTU
Android 11 and newer, in both CBR and VBR modes,
* Sets bitrate (AACENC_BITRATE) to the max_bitrate value of A2DP
* Sets peak bitrate (AACENC_PEAK_BITRATE) according to the maximum data
   which could fit into single audio packet based on MTU

AACENC_BITRATE is used only in CBR mode. For VBR mode, the only limiting
factor is AACENC_PEAK_BITRATE.

Do the same in Pipewire.

Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/work_items/1482#note_2949680
Link: https://cs.android.com/android/platform/superproject/+/android16-qpr2-release:packages/modules/Bluetooth/system/stack/a2dp/a2dp_aac_encoder.cc;drc=37d7b4549f7b8740df1a290f04c20c591a2d3391;l=269
(cherry picked from commit 49d5f4f236)
2026-04-19 19:15:23 +03:00
Wim Taymans
e0697f52c3 alsa-seq: add : between client and port name
The separator is important for applications to find the client name and
group ports.

Fixes #5229
2026-04-16 10:19:05 +02:00
zuozhiwei
b0f719edd4 alsa: fix inverted port validity check in port_reuse_buffer
The CHECK_PORT condition in impl_node_port_reuse_buffer was inverted with a negation operator, causing the function to reject valid output ports and accept invalid ones.

Fixes the logic so that valid ports proceed to buffer recycling and invalid ports are properly rejected.
2026-04-16 10:18:58 +02:00
Wim Taymans
db0fa4b419 filter-graph: allow negative Gain in mixer
To allow for polarity changes.

Fixes #5228
2026-04-16 10:18:47 +02:00
Wim Taymans
d9b6153123 alsa-seq: remove port from mix_list on destroy
When the port is destroyed we need to remove it from the mix_list or
else the process function will keep trying to use the invalid memory.

This is because the port logic does not want to call any functions on
the port (like clearing the IO or Format) after it emitted the destroy
signal and we need to clean up ourselves.

Fixes #5221
2026-04-16 10:18:30 +02:00
Wim Taymans
8be0d7534b dlopen: support search path ending in /
When the search path is /usr/lib/, /usr/lib/foo.so fails to load because
there is no / after the search path. Fix this by requiring that either
the search path end with / or the following char is a /.
2026-04-16 10:18:03 +02:00
Wim Taymans
d6adf944df filter-graph: return current control value correctly
The control values are only set in the port control_data after the
filter has been activated and the instances are created.

Property enumerations might happen before that and then we can either
return the current_value (when set in a control section or later with a
param property) or the default value.
2026-04-08 17:55:33 +02:00
Wim Taymans
821b62dac5 dlopen: improve prefix check some more
If we pass a path /usr/libevil/mycode.so, it might have a prefix of
/usr/lib but we should still reject it. Do thi by checking that after
the prefix match, we start a new directory.
2026-04-08 16:22:04 +02:00