Partially revert 86af9de739
The PortParam does not give enough information to derive the direction
of the converter. If the converter is configured in convert/convert
there is just no way to know when to output a quantum or not.
Fix this by doing a quick probe of the follower and then pass the
direction to the converter.
See !2227
When the follower doesn't produce enough data for this many attempts,
bail and cause an xrun to avoid an infinite loop.
The limit of 8 cause real-life problems and should be larger. It should
probably depend on the expected size per cycle (node.latency) and the
current quantum but we don't always have this information.
See #4334
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.
First try to pass the format of the converter directly into the
follower. This allows us to avoid conversion when it can be avoided.
Iterate all follower formats (not just the first one) to find something
that intersects with the converter formats.
We don't need to use the raw audio format parsing functions, we can use
the more generic audio ones. This avoids some extra parsing for the
media type and subtype and will support compressed audio formats
as well when the converter handles this.
Move the check for the follower==target to the negotiate functions.
Refer to the target when doing operations. The converter reference
is just some internal element that may or may not be active at the
moment. If we have multiple converter elements, the current active
one will be in target.
The IO_Buffers is used in the data thread to check if the port should be
scheduled or not. Make sure it is only set after we set buffers on the
port and cleared before the buffers are cleared.
Make sure we sync the port->io with the data thread.
See #4094
We can remove most of the special async handling in adapter, filter and
stream because this is now handled in the core.
Add a node.data-loop property to assign the node to a named data-loop.
Assign the non-rt stream and filter to the main loop. This means that
the node fd will be added to the main-loop and will be woken up directly
without having to wake up the RT thread and invoke the process callback
in the main-loop first. Because non-RT implies async, we can do all of
this like we do our rt processing because the output will only be used
in the next cycle.
Update the started and ready state after we suspend/pause the node so
that we don't complain if scheduling happens between setting the fields
and actually stopping the follower.
Also only complain when the scheduling happens when the node is not
ready. It is possible that the node is scheduled before we manage to set
the started field.
Move the driver and warned bits after the int field in the struct so
that they are placed in separate memory.
Otherwise, a write from the data thread might race with a write from the
main thread and leave the bits in the wrong state.
Don't blindly clear the format when EnumFormat changes. This will
just stop the node without renegotiating.
We should probably find a new best format, check if it changed and
then Stop/configure/Resume the follower with the new format.
This fixes a stall when a node is running and you change the allowed
codecs.
When we are operating in passthrough, let the Start command pass through
to the follower in all cases. Only do the negotiate/buffers when not in
passthrough.
This fixes a case where the buffers are cleared on the alsa node and it
Pauses but then never resumes in a Start because the node is already
started. The real problem is probably somewhere else (in PipeWire) but
for now this will improve things in passthrough.
Don't just forward the tag and latency events to the follower but let
the audioconvert aggregate and emit the updated tag/latency event
that is then configured on the follower.
When using the DSP mode of the audioconvert, this results in an
accumulated latency/tag from all the DSP ports instead of just
the last DSP port param update.
Put properties with media. prefix in tags in pw-cat.
The tag param has a list of arbitrary key/value pairs. Like the Latency
param, it travels up and downstream. Mixers will append the info
dictionaries or do some more fancy merging.
The purpose is to transport arbirary metadata, out-of-band, through the
graph and it's used for stream metadata and other stream properties.
Add a _fast callback function that skips the version and method check.
We can use this in places where performance is critical when we do the
check out of the critical loops.
Make all system methods _fast calls. We expect them to exist and have
the right version. If we add new versions we can make them slow.
Use a new boolean to check if the follower is allowed to emit a ready
event. This can be done right after negotiating.
Set the started field to true after we finish setting the state of the
converter and follower. This fields is used to block calling into the
process function before we complete the setup.
This avoid a crash in always-process nodes when the node is scheduled
before the audioconverter completes setup.
When the node receives a set_param Props, it calls the follower
set_param implementation. If that one calls set_param again on the
adapter, discards the original set_param.
This makes it possible for the follower to intercept the Props param and
set a modified version on the converter. This can be used to intercept
volume changes.
Ensure that we clear the rate matching when we are not using the
converter. This will make the follower use the quantum instead of the
dummy unused rate matching area.
Exit when we can't make an internal converter because then things really
are not going to work. Remove some of the pointless NULL checks.
Make a real debug context with a log function and move it to a new file.
This way we don't need to redefine a macro.
Make a new context for debugging to a log file. Make new functions to
debug to a log file.
Move the stringbuffer to string utils.
Integrate file/line/func and topics into the debug log.
We can remove some more things from the pipewire log_object function and
also add support for topics.