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
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)
| ~~^
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
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.
Add a port.passive = follow mode and the node.passive equivalents
out-follow, in-follow, follow.
This makes it possible to control how a port influences the state of
the peer and how the peer influences the state of the node independently.
In passive mode, the port will not make the peer runnable and will also
not become runnable when the peer activates.
In the follow mode, the port will not make the peer runnable but it will
become runnable when the peer is active.
This makes it possible to do new things like (f for follow):
Source -> (f)loopback1-in|loopback1-out(f) -> Sink
It will not make the source and sink run but when one of them start, all
will become runnable.
Or you can now better do the leak node hack that was previously used:
Source -> (f)pw-record
That will only start running when the source is activated by something
else.
With port.passive = true|false|follow there is a potential 4th case
which would activate the peer but not be activated by the peer, which is
not something that makes sense.
Sink/Source pairs should not have the same link-group otherwise the
session manager will not be able to autoconnect them with a loopback or
some other internally linked stream.
We used to skip the runnable state from driver nodes because we assume
that they will be activated from other nodes. We however need to make
this more general to all suspendable nodes.
This makes pw-play -> loopback1-sink loopback1-out -> loopback2-sink
loopback-out -> sink also work correctly because the loopback2-sink does
not activate loopback1-out then.
Fix path comparison in is_socket_unix() and don't unset LISTEN_FDS since
the function that uses it is called more than once and it was not unset
when sd_listen_fds() was used.
Fixes#5140
Instead of writing packets sequentially and losing sync on any
frame gap, compute the write position from the VBAN header's
n_frames field. Out-of-order packets land at the correct
ringbuffer offset, matching how module-rtp handles this.
Only advance the writeindex when a packet extends the frontier
so that late arrivals fill gaps without moving the pointer
backwards.
Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/5145
The sender makes an input stream for each connected client. This makes
it easier to do the per client conversion using the adapter and send
different channels to clients.
The receiver uses linear regression to map ringbuffer indexes to server
timestamps and server timestamps to client timestamps. It can then
schedule playback against its own clock.
The sync-groups are only to group nodes with the same driver but don't
make them runnable.
This avoid making v4l2 runnable (without a link) when running ardour
because ardour uses the transport, which activates the sync group.
Move the runnable state calculation out of the collect_nodes function.
They are really two different steps that doin't overlap much.
The runnable state of a node is very easy to calculate. A node is
runnable if it is linked to another node without a passive port. When we
find two runnable nodes, make them runnable, which makes all nodes
linked to them runnable, stopping at passive ports.
We don't have to check the active state of the nodes or links to group
them together. This ensures we don't swap nodes around too much when the
node or link state changes.
There is no reason to delay preparing the link (by the scheduler) when
both nodes are active, we can do that right from the start.
This makes things a bit more symetrical because deactivating a node does
not unprepare a link.
This however changes things a bit because you can no longer delay link
prepare until you activate the node. I don't know if this is actually in
use and it would probably be to delay format negotiation. The right way
do delay format negotiation is to wait until an EnumFormat is set but
that is something to improve later.