Patch by David Nowotny
In make_matrix (channelmix-ops.c), the matrix-filling loop at the done:
label allows the index i (and j in the inner loop) to grow beyond MAX_CHANNELS
when dst_paired/src_paired has sparse bits set. In that case the continue
fires for most values of i < CHANNEL_BITS, so i advances much faster than ic,
and matrix[i][j] reads off the end of the stack-allocated array.
Add bounds guards to both loop conditions so i and j cannot exceed
MAX_CHANNELS.
Fixes#5176
When the driver changes, the clock position can also change and there
would be a discont in the rtp_timestamp.
This is not usually a problem except in RAOP mode where the base rtp
timestamp is negotiated and anything that deviates too much is to be
discarded.
If we are not using direct_timestamp for the sender, make sure we always
keep the rtp_time aligned to avoid this problem.
See #5167
Going from PLAYING to PAUSED will have basesrc calling unlock and
setting flushing to false. Going back to PLAYING may then fail in
wait_negotiated, as unlock_stop will be called after change_state.
Fix by remove the flushing check, since already in that "state".
The jack_activate loop was only queuing NOTIFY_TYPE_PORTREGISTRATION
for the activating client's own ports. Ports belonging to other clients
— including all WirePlumber-managed ports and MIDI ports — were silently
skipped due to the o->port.port->client != c condition.
This caused two observable bugs for clients using libjackserver (e.g.
jackdbus):
- JackPortRegistrationCallback was not fired for any pre-existing
foreign ports at activate time, leaving the patchbay empty unless
the session manager happened to start after the client.
- JACK MIDI ports were never announced via callback, even though they
are correctly returned by jack_get_ports().
The graph_order_callback fallback (used by jackdbus for initial port
enumeration) is also ineffective here because pipewire-jack only fires
it on connection events, not on activate.
Fix by iterating all non-removed foreign ports in the object list and
queuing registration callbacks for those whose node is active, matching
the semantics already implemented in node_info() for ports of nodes
that transition to running state after activate.
The change is libjackserver.so only. libjack.so behaviour is left
unmodifed, as carla is showing ports of each client twice.
The thread id is very useful for debugging, add it to the every log
message so that it does not have to be inferred from the content itself.
This is already done in the systemd journal logger, so implement
it here as well.
Before:
[I][00:13:11.120303] pw.context | [ pipewire.c: 585 pw_init()] version 1.7.0
After:
[I][365073][00:13:11.120303] pw.context | [ pipewire.c: 585 pw_init()] version 1.7.0
Using `spa_strbuf` simplifies a code a great deal by removing the manual
tracking of buffer sizes, and it also removes the need for the separate
strings for the timestamp, topic, etc.
Cancellation handlers use setjmp/longjmp, for which the C99
specification has the following note:
> 17.3.2.1 (3)
> All accessible objects have values, and all other components of the
> abstract machine) have state, as of the time the longjmp function was
> called, except that the values of objects of automatic storage
> duration that are local to the function containing the invocation of
> the corresponding setjmp macro that do not have volatile-qualified
> type and have been changed between the setjmp invocation and longjmp
> call are indeterminate.
While everything works fine with GCC, with Clang we see that the
cancellation handler doesn't seem to have an effect (loop-test fails
when it notices that its spa_source's priv and mask have not been
cleaned up).
The underlying cause is that the compiler can assume data.ep_count is
only used in loop_iterate_cancel(), and so can be cached in a register.
When we access that field in the cancellation handler, it was never
actually written to the memory on the stack, so the read in
cancellation_handler() does not see the current value.
We fix this by marking all fields on the stack that we expect to be
modified in loop_iterate_cancel() as volatile, forcing the memory to be
updated and correctly available to the cancellation handler.
This fixes a missing definition error in thread.c:
../src/pipewire/thread.c:129:30: error: use of undeclared identifier 'SCHED_RESET_ON_FORK'
129 | SPA_FLAG_UPDATE(new_policy, SCHED_RESET_ON_FORK, reset_on_fork);
pipewire-jack defines TYPE_ID_VIDEO=1 between audio and MIDI, shifting
TYPE_ID_MIDI to 2. This caused jack_port_type_id() to return 2 for MIDI
ports, breaking compatibility with jack1/jack2 which return 1.
The jack_port_type_id() return value is part of the public JACK API and
consumers such as jackdbus rely on the conventional values established
by jack1/jack2: 0 for audio, 1 for MIDI.
Map internal TYPE_ID_* values to their jack1/jack2 compatible equivalents
before returning. All MIDI variants (MIDI, OSC, UMP) map to 1. Video has
no jack1/jack2 equivalent so maps to 3, beyond the conventional range.
The jack_activate loop was only queuing NOTIFY_TYPE_PORTREGISTRATION
for the activating client's own ports. Ports belonging to other clients
— including all WirePlumber-managed ports and MIDI ports — were silently
skipped due to the o->port.port->client != c condition.
This caused two observable bugs for clients using libjackserver (e.g.
jackdbus):
- JackPortRegistrationCallback was not fired for any pre-existing
foreign ports at activate time, leaving the patchbay empty unless
the session manager happened to start after the client.
- JACK MIDI ports were never announced via callback, even though they
are correctly returned by jack_get_ports().
The graph_order_callback fallback (used by jackdbus for initial port
enumeration) is also ineffective here because pipewire-jack only fires
it on connection events, not on activate.
Fix by iterating all non-removed foreign ports in the object list and
queuing registration callbacks for those whose node is active, matching
the semantics already implemented in node_info() for ports of nodes
that transition to running state after activate.
As stated in https://pubs.opengroup.org/onlinepubs/9799919799//basedefs/netinet_in.h.html,
> The <netinet/in.h> header shall define the sockaddr_in structure [...]
This fixes the following build error:
In file included from ../src/modules/module-protocol-native.c:44:
../src/modules/network-utils.h:96:35: error: incomplete definition of type 'struct sockaddr_in'
96 | if (inet_ntop(sa->ss_family, &in->sin_addr, ip, len) == NULL)
| ~~^
NULL tags are never handled and so tags just keeps configured on the
ports. It's also hard to know the direction from the NULL data.
Instead, send an empty Tag with the direction to clear everything.
Always do a control change to the instances when they are created. This
is to make sure the internal state is synced to the control values.
The sofa filter and biquads need this to correctly configure themselves
after a suspend.
Fixes#5152
Now that the loop_leave function will assert when the unlock fails we
need to be extra careful with the cancellable loop. If it cancels inside
the poll or one of the before/after callbacks we need to make sure that
we lock the loop correctly again or we will create an assert later on.
Do this by pushing the cleanup earlier and then record all the things we
managed to do before we get canceled. If we ever get canceled and the
lock was unlocked but not locked again, fix this up.
Fix fixes issues when using the JACK API causing assertions when the
data loop is stopped/cancelled.
Don't close an -1 fd in clear_data.
If we let the client allocate buffer, set our fd and data to invalid
values. If the client decides to renegotiate before we get the buffer
data we might otherwise try to clear the mem_id (default 0) or
close the fd (also default 0).
Fixes#5162