We need to deactivate the graph when the format was cleared on both the
input and output. This means we got suspended and we need to clear. We
can safely do this now because we take the right locks.
SF_FORMAT_WAVEX is not supported to SF_ENDIAN_CPU. Due to that, unable
to record in .wav file (for > 2 channels). Add case for SF_FORMAT_WAVEX
to get assign SF_ENDIAN_FILE.
Fixes#5233
1. The period calls were added to handle timeouts.
2. Handle the case where lock must be unlocked after 60s if the
controller owning the locked does not release it.
Takes an input file, processes it with audioconvert and writes to an
output file. Can be used to test all audioconvert features such as
resample, channelmix, filter-graph, format conversion, dither, etc.
Boilerplate written by Claude.
The object, node, client, factory, module, and link IDs are all uint32_t values but were being formatted with %d.
This would produce incorrect negative values if an ID ever exceeded INT_MAX
When a node is inactive but linked to a driver, the only reason it is
not being scheduled is because it is inactive.
We already set up the links and negotiate the format and buffers to
prepare going to RUNNING. This patch now also make the node go to IDLE,
which makes the adapter negotiate a forma and buffers with the internal
node.
This makes things more symetrical, when linking a node, it becomes IDLE,
when activating it becomes RUNNABLE, when inactive it goes back to IDLE.
The switch to RUNNING will also be faster when things are already set up
in the IDLE state.
The main advantage is that it allows us to implement the startup of
corked streams in pulseaudio better. Before this patch we had to set the
stream to active to make it go through the Format and buffer negotiation
and then quickly set it back to inactive, hopefully without skipping a
cycle. After this patch, the corked stream goes all the way to IDLE,
where it then waits to become active.
See #4991
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 /.
When pw_init() was not called and the init_count is 0, the plugin path
was not set and loading plugins will fail/segfault.
Avoid this and return en error early instead with a message that
pw_init() should be called first.
See !2784
COLS could be very small and the statusbar array might overflow with
strcpy and strcat. Also initializing the variable array seems to cause
problems on older compilers.
Instead use a fixed array that is big enough to hold all possible
values we write into it.
Add a standalone tool that creates virtual AVB talker/listener endpoints
visible in the PipeWire graph (e.g. Helvum). Uses the loopback transport
so no AVB hardware or network access is needed.
The sink node consumes audio silently, the source produces silence.
Supports --milan flag for Milan v1.2 mode and --name for custom node
name prefix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add stream_setup_socket and stream_send ops to avb_transport_ops so the
stream data plane can use the same pluggable transport backend as the
control plane. Move the raw AF_PACKET socket setup from stream.c into
avdecc.c as raw_stream_setup_socket(), and add a raw_stream_send()
wrapper around sendmsg().
Add a stream list (spa_list) to struct server so streams can be iterated
after creation, and add stream_activate_virtual() for lightweight
activation without MRP/MAAP network operations.
Implement loopback stream ops: eventfd-based dummy sockets and no-op
send that discards audio data. This enables virtual AVB nodes that work
without network hardware or privileges.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a test suite for the AVB (Audio Video Bridging) protocol stack that
runs entirely in software, requiring no hardware, root privileges, or
running PipeWire daemon.
The loopback transport (avb-transport-loopback.h) replaces raw AF_PACKET
sockets with in-memory packet capture, using a synthetic MAC address and
eventfd for protocol handlers that need a valid fd.
Test utilities (test-avb-utils.h) provide helpers for creating test
servers, injecting packets, advancing time, and building ADP packets.
Tests cover:
- ADP entity available/departing/discover/timeout
- MRP attribute lifecycle (create, begin, join)
- Milan v1.2 mode server creation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce struct avb_transport_ops vtable with setup/send_packet/
make_socket/destroy callbacks. The existing raw AF_PACKET socket code
becomes the default "raw" transport. avdecc_server_new() defaults to
avb_transport_raw if no transport is set, and avdecc_server_free()
delegates cleanup through the transport ops.
This enables alternative transports (e.g. loopback for testing) without
modifying protocol handler code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix two bugs in handle_cmd_lock_entity_milan_v12():
1. When server_find_descriptor() returns NULL, reply_status() was called
with the AEM packet pointer instead of the full ethernet frame,
corrupting the response ethernet header.
2. When refreshing an existing lock, the expire timeout was extended by
raw seconds (60) instead of nanoseconds (60 * SPA_NSEC_PER_SEC),
causing the lock to expire almost immediately after re-lock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handle_acquire_entity_avb_legacy() and handle_lock_entity_avb_legacy()
incorrectly treated the full ethernet frame pointer as the AEM packet
pointer, causing p->payload to read descriptor_type and descriptor_id
from the wrong offset. Fix by properly skipping the ethernet header,
matching the pattern used by all other AEM command handlers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In handle_connect_tx_command() and handle_disconnect_tx_command(),
AVB_PACKET_ACMP_SET_MESSAGE_TYPE() is called after the goto done
target. When find_stream() fails and jumps to done, the response
is sent with the original command message type (e.g., CONNECT_TX_COMMAND)
instead of the correct response type (CONNECT_TX_RESPONSE).
Move the SET_MESSAGE_TYPE call before find_stream() so error responses
are always sent with the correct response message type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AVB_MRP_SEND_NEW was defined as 0, making it indistinguishable from
"no pending send" in the MSRP and MVRP event handlers which check
`if (!pending_send)`. This meant that when an attribute was first
declared (applicant state VN or AN), the NEW message was silently
dropped instead of being transmitted on the network.
Fix by shifting all AVB_MRP_SEND_* values to start at 1, so that 0
unambiguously means "no send pending". Update the MSRP and MVRP
encoders to subtract 1 when encoding to the IEEE 802.1Q wire format
(which uses 0-based event values).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The msrp_notify() and mvrp_notify() functions call dispatch table
notify callbacks without checking for NULL. In MSRP, the
TALKER_FAILED attribute type has a NULL notify callback, which would
crash if a talker-failed attribute received a registrar state change
notification (e.g. RX_NEW triggering NOTIFY_NEW).
Add NULL checks before calling the dispatch notify callbacks, matching
the defensive pattern used in the encode path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
server_add_descriptor() allocates the descriptor and its data in a
single calloc (d->ptr = SPA_PTROFF(d, sizeof(struct descriptor))),
so d->ptr points inside the same allocation as d. Calling free(d->ptr)
frees an interior pointer, corrupting the heap. Only free(d) is needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When we add a Format property after we dereffed all the other params in
the builder, we might relocate the builder memory and invalidate all
previously dereffed params, causing corruption.
Instead, first add all the params to the builder and then deref the
params.
There is a special case when we have both a capture and playback
stream. The capture stream will receive all filter params and the
playback stream will just receive its Format param.
Fixes#5202
Make a function to parse the passive mode and use that in ports and
nodes. Improve the node passive mode parsing a little.
Also make Duplex nodes follow-suspend.
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.
Integer overflows can result in map_range_init() to return wrong offset
or size that can result in access to invalid or unmapped memory.
Check for the overflows and return an EOVERFLOW error.
Found by Claude Code.
We might overflow the path buffer when we strcat the provided filename
into it, which might crash or cause unexpected behaviour.
Instead use spa_scnprintf which avoids overflow and properly truncates
and null-terminates the string.
Found by Claude Code.
Check that the number of fds for the message does not exceed the number
of received fds with SCM_RIGHTS.
The check was simply doing an array bounds check. This could still lead
to out-of-sync fds or usage of uninitialized/invalid fds when the
message header claims more fds than there were passed with SCM_RIGHTS.
Found by Claude Code.
This reverts commit bb0efd777f.
It is unclear what the problem was before this commit. If there are any
pending operations, the suspend should simply cancel them.
See #5207
Using connect() on a UDP receiver creates a strict filter based on
the sender's _source_ port, not the sender's destination port. The
source port specifies at what sender port the packet exits the sender.
The destination port specifies at what receiver port the packet enters
the receiver. But, the RTP sink uses an ephemeral (= random) port as the
source port. Consequently, connect() at the receiver will cause a
comparison of that ephemeral port with the fixated one (which is actually
the number of the _destination_ port). This incorrect filtering causes
all packets to be dropped.
Use bind() to filter for the local destination port, and use recvmsg()
with manual IP comparison to filter for the sender's identity.
They are emited from the streaming thread and therefore can be emitted
concurrently with the events on the main thread. This can cause crashes
when the hook list is iterated.
Instead, make those events into callbacks that are more efficient,
and threadsafe.