When node.async is set, make the node async.
Advertize SPA_IO_AsyncBuffers on mixer ports when supported. Set a new
port flag when AsyncBuffer is supported on the port.
When making a link and if one of the nodes is async and the linked ports
support AsyncBuffer, make the link async and set this as a property on
the link. For async nodes we will use SPA_IO_AsyncBuffers on the mixer
ports.
Nodes that are async will not increment the peer required counters. This
ensures that the peer can start immediately before the async node is
ready.
On an async link, writers will write to the (cycle+1 & 1) async buffers
entry and readers will read from (cycle & 1). This makes the readers read
from the previously filled area.
We need to have two very controlled areas with specific rules for who
reads and who writes where because the two nodes will run concurrently
and no special synchronization is possible otherwise.
These async nodes can be paused and blocked without blocking or xrunning
the rest of graph. If the node didn't produce anything when the next
cycle starts, the graph will run with silence.
See #3509
Change the flag from MAPPABLE to UNMAPPABLE to ease compatibility.
Older servers with newer client will not set the flag and so memory is
mappable for the client.
Newer server will set the flag but the client will ignore it and act
like before.
This flags means that the fd can be mmaped without special handling. It
is the equivalent of the SPA_DATA_FLAG_MAPPABLE. Refuse to map memory
that is not mappable.
Make sure we make all allocated MemFd memory MAPPABLE by default. We can
then remove the stream and filter special handling for MemFd types and
just check the more generic MAPPABLE flag.
Make one exception when a client uploads MemFd buffer memory. We must
manually set the MAPPABLE flag for MemFd to make things backwards
compatible.
clear_port() clears all struct mix and removes the port, and can occur
before port io is set to NULL. In this case the port memmaps are not
freed, and are leaked until client pool closes.
Fix by freeing the old io memmap when setting io to NULL, also when the
port was already cleared, so that the memmap lifecycle is the same as
that of the IO.
Avoid leaking buffers when freeing mix, in case the port was not cleared
properly.
These leaks don't seem to be occurring currently, but better be sure.
The remote end may destroy the port via client_node_port_update(),
before corresponding pw_impl_port_mix are released.
clear_port() removes all struct mix, but this prevents the
pw_impl_port_mix from being removed from io_map, which causes stale mix
ids be left in io_map, so we end up continuously allocating new io
areas.
Make lifecycle of io_map entries match port_init_mix/release_mix
exactly, separately from the lifecycle of the port and struct mix.
When freeing struct mix in port_release_mix(), make sure it corresponds
to the mix being released.
First check if all of the new buffers are ok before attemping to replace
our exising ones with the new ones. Else we might end up copying some
of the new buffers and cleaning them up twice later.
struct mix contain pointers to themselves (see do_port_use_buffers) and
cannot be copied by value, so they should not be stored in pw_array.
Store them in pw_map instead.
Remove the context_driver events and replace them with realtime node
events. The problem is that the realtime node events are emitted from
the node data thread, which can be different for each node and
aggregating them into context_driver events is not a good idea.
It's also nice for the stream drained event, which no longer needs to go
through the context_driver events.
Remove some includes of private.h
Add some methods to get the mempool of client and context so that we can
remove direct access.
Move some things around.
Use methods to get pw_loop variables.
See #3243
Use the port_set_mix_info to add and remove mix info information to the
client.
Previously it was impossible to clean up mix_info.
With this change we can also simplify the jack peer port detection.
Because the mix info is always sent before the link appears we can
simply look up the info when the link appears.
There is already an id in the port_mix structure that can be used to
index the mix structures in map if needed, the mix_id is the port_id of
the mixer and should not be confused.
Bump the client-node version because we use the writefd differently now.
Support driver nodes using the old version somewhat. The stats will be
wrong but then again, we don't have any flatpak driver nodes that could
use an older version.
Don't make an extra eventfd for activating the remote-node, we can
use the server side eventfd and send them to the remote side using
the transport.
The remote node already adds the eventfd to the data-loop so avoids
doing the same on the server.
This makes driver nodes trigger all remote nodes directly instead of
going through an intermediate eventfd. For resuming nodes, we already
used the node eventfd directly so this only a small optimization
for the initial cycle start.
Pass the ready status to the client-node using the state array.
Don't just SPA_STATUS_HAVE_DATA on the server side but use the value
from the client.
This avoids some potential extra work when a driver sink pulls in data
with the NEED_DATA ready callback but then the server performs the
actions (tee) as if it were SPA_STATUS_HAVE_DATA.
First set some of the port flags and data, especially the owner_data
before calling pw_impl_port_set_mix(), which will use the owner_data
to send the mix_info.
See #2847
We don't always need to send buffers to a remote port, when the port
is an output port, all the mix ports use the same buffers. This means
that when we add another link to a port, we don't get the mix_info
anymore and then we don't know the peer_id and we don't complete the
link and we don't call the connection_callback.
Instead, send the mix_info right before sending the Buffer Io area. We
always do this for all mix io and after we have sent the buffers so this
is a better place.
Fixes#2841
For now, put a limit on the amount of items we can send and receive
over the native protocol. A more complex way of allocating and freeing
can be implemented later when we really need to raise the limits.
Fixes#2070
Make sure we mark the port invalid when we can't allocate an id
for it. Also check that the id does not exceed the max amount of
areas we have allocated and release resources correctly.