Follow the state of the node and update the stream state accordingly.
The most important part is that Start is async and so it's better to
wait for completion from the node before emiting the STREAMING state.
When we emit the RequestProcess event from an exported node, don't
send the RequestProcess command to ourselves but let the server
decide where to send it to.
This gets the next key and value from an object. This function is better
because it will skip key/value pairs that don't fit in the array to hold
the key.
The previous code patter would stop parsing the object as soon as a key
larger than the available space was found.
Add spa_json_begin_array/object to replace
spa_json_init+spa_json_begin_array/object
This function is better because it does not waste a useless spa_json
structure as an iterator. The relaxed versions also error out when the
container is mismatched because parsing a mismatched container is not
going to give any results anyway.
Keep the original sequence number of the port_set_param(Format) and
port_use_buffer() calls around. When they produce an error, we will
get an error with the same sequence number.
When the sync completes, check if we got an error for the pending
operation and return that as the result.
We then also mark the link in error. We don't mark the port in error
because that is not really the case.
This should make the link error when negotiation of format or buffers
fails instead of silently continuing.
Place the async state of the node in its activation.
Don't increment the pending state of the driver when an async node is
found because the async nodes will not trigger the driver when they
complete.
See !2104
`pw_link_info::error` was previously not cleared when a link was destroyed,
leading to a memory leak if an error message had been set. For example,
if format negotiation fails, and as a result the link is destroyed.
Don't schedule nodes that didn't receive us as the driver node yet
because they will not be able to signal us when they complete and leave
us xrun.
Also only count the nodes that we will actually schedule and expect a
signal from, set this in the pending activation counter. This can be
less when some nodes are still starting or receiving the driver
activation record.
This eleminates some errors when adding and removing nodes.
See #4182
Check if the node is FINISHED instead of checking the refcounts. It's
possible that the refcounts are 0 but the node was not scheduled or
finished yet.
If the node is not FINISHED but TRIGGERED, we can run the recover
without reporting an error.
Any other state is an error and we need to log this and recover.
See #4182
Use ATOMIC_LOAD to get status.
Debug the pending state after decrementing so we debug the value we
are actually going to test.
Add node id to debug lines to better track things.
Don't just overwrite the state with FINISHED but only do this when the
state was AWAKE.
The server might already have started a new cycle and placed
NOT_TRIGGERED as the state. Or, it might have changed the state to
INACTIVE. In all cases, we should not overwrite the state unless it was
AWAKE and we should only trigger peers when we were AWAKE.
This fixes some spurious xruns and glitches.
See #4182
When the queue is full, before this patch we used to go into usleep in
the hope that the other thread will run and empty the queue and that we
can retry after the usleep.
This however does not always work because the other thread might be waiting
for the thread that does the invoke call and we lock forever.
Therefore we should always try to make progress in some way. Instead of
waiting, allocate an (or use the previously allocated) overflow queue and
write to that one. We can chain multiple overflow queues together as many
as we need (but we might want to bound that as well).
The loop.retry-timeout property is now deprecated.
See #4114
Commit d04a28daef moved the configuration
of the IO_Position after we removed the node from the old driver but
forgot to move the code that updates the pending_state.
See #4094
Add OSC and UMP control types and make sure the mixer converts to the
selected format.
Mostly useful for legacy filters that use the old MIDI format, placing
the Midi control type in the format will make the mixer convert to it.
Make sure we clear IO_Buffers on the port and mixer before we clear the
buffers or the format. The IO_Buffer is used to check if the port should
be processed or not and its update is synchronized with the data-thread.
Set IO_Buffers on the mixer and node only after we have configured the
buffers on the node.
See #4094
We simply cannot schedule async nodes properly if we don't have the
async link. This change was done to make sure that driver sources don't
end up with async buffers and cause a unneccesary 1 cycle delay in
async clients. But we can fix this in a better way, like this:
Increment the cycle counter after we copy the output port buffers. This
ensures the async clients immediately pick up the new buffers (or the
output buffers from the previous cycle).
Also remove some old compatibility code that is no longer useful.
Fixes#4138
See #4133
A remote node is prepared when the Start command sync reply has been
received.
If we however quickly switch from active to inactive, the
pending reply is cancelled but the remote node will have set the
FINISHED status and will be ready to be scheduled.
Make it so that we always set the INACTIVE status when the node is
canceled and unprepared, even if we didn't get the reply and the node
was not prepared.
Fixes#4122
Make a new flag that is set when the process function is called because
of a recover from a graph xrun.
Use this flag in the freewheel driver to detect a recover and to avoid
scheduling a new timeout. We should schedule a new timeout only when the
process function was called after completion.
This fixes export in ardour some more when the initial driver timeout
didn't complete (when, for example, some nodes were still starting up).
Make a property to pass a custom function pointer to create threads
instead of pthread_create.
Use this in jack instead of bypassing the thread utils create function,
which gives the wrong thread rt priority with rtkit.
Fixes#4099
Don't wait for the client to set the INACTIVE state, do it on the
server. We already decremented the target required so we don't want to
schedule the node anymore.
Fixes some xruns when removing nodes in a stress test.
Make it so that a driver node can never be scheduled async. It could
possibly make sense when the driver node is not currently driving the
graph but when it drives the graph it always needs to be sync. This
also simplifies the target activation because we can simply check the
async state and ignore if the node is driving or not.
Also make sure that we never make an async link with a driver output port.
This does not make sense because the driver node will always be
triggered sync first and before the async node so we can simply make
a sync link.
This fixes the modified (only generate 1 buffer) video-src -> video-play
case where the buffer never arrives in video-play because of the
useless async link.
Fixes#4092
Keep track of the sync nodes we added to a driver and bring in the other
nodes from the same sync group, group or link groups. This makes it
possible to have disjoint sync groups each with their own driver.
When checking for the nodes to collect with a driver, don't just skip
checking the other nodes when the driver is not in the sync group.
Instead collect all nodes that have the same group and link group as
the driver first and then check the sync groups.
Fixes export in ardour8
Fixes#4083
When the node activation.required was incremented because it was a
driver, only decrement it in that case, regardless of the current driver
state of the node.
This fixes the case of KODI where the required field gets out of sync
and things become unschedulable.
Fixes#4087
A driver can't be async, we always need to be able to trigger it
to start it so increment the required field.
Fixes an issue with asunc drivers such as the video-src example or gnome
screen sharing.
Can be used to group ports together. Mostly because they are all from
the same stream and split into multiple ports by audioconvert/adapter.
Also useful for the alsa sequence to group client ports together.
Also interesting when pw-filter would be able to handle streams in the
future to find out what ports belong to what streams.
It's not used anymore because it does work so well.
The problem is that while it transparently proxies param enums on
ports to peers, it fails to emit events when those peer
params change in a way that would make the enum result change as well.
This makes it quite hard to use this correctly.
This is the driver id that the client has received and is using right
now. We don't use this yet but it could be used in the future to check
if a client has the most up to date info.
Make sure newer clients can work with an older server:
- Add client and server versions in the activation
- On older server, clients needs to trigger peers without CAS of status
- On older server, jack transport is started with command.
- Use client version to know when to set the INACTIVE/FINISHED
state on the server instead.
- Async clients need to trigger peers on old server.
Also handle the relation between a node and the driver with pw_node_peer,
like we do with the links.
Because these are refcounted, we only make one peer for a node that is
linked to another node that is also the driver (pw-play -> sink) and we
save some fds as well as some admin stuff and overhead for the refcounts.
This in return then results in less problems getting all the refcounts
right when adding/removing nodes.
Set the new IO Position after we removed the node from the old driver
and before the new driver is going to schedule the node. This makes
a little more sense.
This reverts commit cfeb937443.
Let's remove this for now, the node.rules and device.rules are mostly
used for this. We can add this later when there is a need for it.