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
If a file descriptor is expected to be closed by the associated `pw_memblock`,
and closing fails, then that usually signals a more serious issue in the memory
accounting. So add a log message when that happens.
Calling "iterate()" on a loop that has not been entered by the
calling thread is invalid. So try to diagnose misbehaving applications
on a "best effort" basis by checking `impl::enter_count`.
This is not a foolproof check, and can also technically cause data
races while reading the variable.
See #5148
Previously when parameters were enumarated, it was checked if at least one
param was known for `id`. If not, `-ENOENT` was returned to signal that
this param id is not supported.
This is not necessarily true, since a param id might be supported, but it
might have zero params at the moment, in which case an unexpected error
would be returned.
Fix that by using `pw_param_info_find()` with the underlying impl object
to check if the param id is actually supported.
If the param enumeration fails, do not set `spa_param_info::user` to 1
indicating that the result is cached. Doing so can lead to the first
(uncached) call failing, while the rest will succeed (with 0 params).
HFP codecs don't have a direction dependent "target" profile, and this
function was returning false if A2DP is disabled.
Don't check target profile for HFP, leave checks to backend.
Fixes HFP-only configurations, which were missing profiles.