When the driver starts, save all previous node timestamps, not just the
previous signal time.
For async nodes, uses the previous timestamps in the profiler messages
so that we get stats with 1 cycle of delay instead of bogus values
because the node is still processing.
Fixes pw-top for async nodes.
Collect the request scheduling flags and when there is a lazy driver,
set the lazy scheduling flag in its clock. This means that the driver
can expect RequestProcess commands to start the scheduling.
Pass the lazy scheduling clock flag to the node.
Make sure lazy scheduling driver have a higher priority than their
request drivers.
Client-side bugs calling methods on destroyed proxies like
pw_proxy_ref(p);
pw_proxy_destroy(p);
...
wait for server to ack the remove
...
pw_core_destroy(p->core, p); /* p already removed & destroyed */
should not send messages with the stale proxy id to server.
Set id to SPA_ID_INVALID when removing a proxy from the id map, so that
such client bugs only result to ENOENT.
In our current world, it is possible to have a negative delay. This
means that the stream should be delayed to sync with other streams.
The pulse-server sets negative delay and the Latency message can hold
those negative values so make sure we handle them in the helper
functions as well.
Do the delay calculations in pw_stream and JACK with signed values to
correctly handle negative values. Clamp JACK latency range to 0 because
negative latency is not supported in JACK.
We should also probably make sure we never end up with negative
latency, mostly in ALSA when we set a Latency offset, but that is
another detail.
So that a config override can disable the execution of the command by
setting the property to false in the pulse.properties config override.
Expose some conf.c method for this purpose.
Make the xrun reporting as info. This can generate a lot of logging if
the error is persistent and the errors are also reported in pw-top etc.
Fixes#4361
Flush with drain calls the drained callback for each cycle until paused
or resumed. Setting the stream to active again, clears the drained state
and makes things resume.
Flush without drain does not set the state to PAUSED but simply clears
the queued data. This is mostly useful when pausing or stopping.
At no point should the flush operation result in a PAUSED state change.
Convert the RequestProcess event to a command and send this to the
driver node. This ensures that any future properties on the Event will be
passed to the Command as well, such as timestamps etc.
Save the complete RequestProcess command when we need to send it later
when the node is RUNNING so that we preserver the properties.
Make a function to emit an event from a stream. Use this function
internally to emit the RequestProcess.
Make the RequestProcess event construction a little more efficient.
Don't queue an async state change completion for exported nodes. The
server sends a ping to check for completion and we want this ping reply
to happen after the state completion.
Consider the case where we have a follower and a driver, the follower is
sent the Start/Ping commands and replies to the ping but is still
processing the state change async. The server can then Start the driver,
which will then try to schedule the (still starting) follower and fail.
We could add the ping to the work queue as well but that creates
complications because modules (clients) and server share the same work
queues right now and block each other completions.
We could also make a method to process the work queue immediately but
that would be dangerous as well because it could contain a BUSY item
from some module that would block things.
Don't wait for the completion of the Pause command of the node but send
it to the stream immediately. Delaying it might make it come after the
set_param calls are done and confuse the stream.
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