Add macro SPA_CMP to do 3-way comparisons safely, and use it to avoid
signed integer overflows.
Fix also float/double comparisons (previously 0.1 == 0.8 since cast to
return type int).
Fix Id/Bool comparisons so they can return negative value.
Kernel-provided MTU does not work for USB controllers and the correct
packet size to send can be known currently only from RX. So we are
waiting for RX to get it.
The known problem is USB-specific, we shouldn't need the workaround for
other transport types.
Don't wait for POLLIN for non-USB controllers on connect, but ready
things on POLLOUT as usual.
For non-USB controllers, pick some sensible packet sizes to use
initially, before we switch to same size as for RX.
The default kernel pool size on the input is 200 cells. A cell is
about 28 bytes long so the maximum message that can be received in one
go is about 5600 bytes. This causes problems when using amidi to upload
larger sysex messages because they simply can't be received by the
sequencer.
It if however possible to increase this limit with the set_client_pool()
function. Increase the pool size to at least the quantum_limit * 2.
This ensures we can receive and send at least 2 quantums of raw data,
which should be a fairly long sysex message.
Make a min and max value for the pool size. There is an upper limit of
2000 in the kernel but make this configurable and clamp the final
pool size to the min/max.
Make the MAX_EVENT_SIZE 256, because this is how the sequencer seems to
splits the input data as well and it results in less wasted space in the
output buffer.
See #4005
snd_midi_event_encode() will reset the encoder when it returns an
encoded event. It is possible that the function returns with an encoded
event when the internal buffer is full, in that case we need to push the
event and continue encoding without reseting the encoder.
0 is not a snd_midi_event_encode() error, so don't handle it like
one.
The messages, mostly sysex, can be split over multiple control message.
This happens when we read large messages from the sequencer, the
snd_seq_event_input function returns split messages that we transfer to
control messages directly.
When we send those messages out, however, the encoder wants the complete
message before it will return a valid event that we can send out. Keep
on calling the encoder with the control events until we get a complete
message that we can send out.
Fixes#4005
Add a count to each invoke item that is updated with an increasing
loop atomic counter. Flush items from the queues based on their count
so that items are flushed in the order they were added even if they
were added to different queues.
Instead of doing (cycle+1) & 1 for output ports, simply swap the io
areas depending on the port direction (0 = input, 1 = output) and
just to cycle&1 for all ports.
Libcamera formats are generally little-endian, matching DMA DRM
fourccs, while PW ones are big-endian. Thus we have to invert the
order.
Only RGB and BGR where tested, as these are the formats currently
supported by the software ISP. This fixes inverted red and blue in
Snapshot on the Librem5 and Pinephone (OG).
See also gstlibcamera-utils.cpp in libcamera.
C++20 introduced designated initializers similar to the ones found
in C99, however, in C++ designated initializers cannot be mixed
with non-designated initializers. GCC rejects mixed initializers
with an error.
This fixes an issue introduced in 771f71f622
where the quantum is forced and may break applications the specify their
own quantum.
Signed-off-by: Lukas Rusak <lorusak@gmail.com>
Because we now have a dedicated queue per thread, we can simply add our
invoke item to the queue and then flush all the queues when we are
running in the thread of the loop.
This simplifies some things and removes potential out-of-order messages
that got queued while flushing.
Keep a thread local queue. This makes it possible for multiple threads
to write to the ringbuffer.
There is a lock to protect the list of queues. It can only be contended
when new queues are created in the threads but this can be done at
thread startup.
Fixes#3983
Make an internal queue object that implements the invoke queue.
Because we can not do invokes concurrently from different threads, this
is required to make per-thread invoke queues later.
Debug and trace log messages are often written based on the stderr
logging, where code location is always visible.
journalctl does not show the code location without extra tricks,
which makes user-submitted debug logs from journal more cryptic.
Make journal log more similar to stderr logs by prepending the code
location and log level in the log message when the log topic
level is >= DEBUG.
Change the GenericFd data type to SyncObj. It's probably better to
explicitly state the data type than to make something generic. Otherwise
we would need to transfer the specific fd type somewhere else and there
is no room for that in the buffer and the the metadata is not a good idea
either because it can be modified and corrupted at runtime.
Add the SyncTimeline metadata. This contains 2 points on two timelines
(SyncObj datas in the buffer). The buffer can be accessed when the
acquire_point is signaled on the timeline and when the buffer
can be released, the release_point on the timeline should be signaled.
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.
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
This is to iterate params that are common to all ports, such as
EnumFormat or the supported IO areas. Mostly interesting for mixer and
splitter nodes so that we don't have to create a new port just to query
things.
spa_loop_invoke from data loop to main loop is not OK, as Wireplumber
currently runs its main loop with "pw_loop_enter(); pw_loop_iterate();
pw_loop_leave();" which causes the loop to be entered only when it is
processing an event.
In this case, part of the time the loop impl->thread==0, and calling
spa_loop_invoke() at such time causes the callback to be run from the
current thread, ie. in this case data loop which must not happen here.
Fix this by using eventfd instead, which is safe as the callback always
runs from the main loop.
Eventfd is also slightly more natural here, as multiple events will
group to the same mainloop cycle.