Add a new followerClock block in the profiler info. This is only set
when the follower could be a driver and it contains the clock info used
for following the driver, mostly the rate difference and delay.
Dump this info in pw-profiler -J
Make sure we always set the info in the clock, especially also when we
are following.
Use the new UMP alsa sequencer API to make it produce UMP packets.
Set the alsa sequencer to MIDI2.0, which will make it convert all
messages to MIDI-2.0 UMP automatically. We can copy this straight into
the control buffers.
This also solves some problems with large sysex messages that are now
nicely split into chunks with UMP.
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
The alsa sequencer rate matching was not actually working correctly.
It would compare the previous queue time with the current time and
compare that to the quantum. This would include uncorrected errors from
jitter and would result in the timeouts being scaled in the wrong
direction forever.
Instead, calculate an ideal queue time and compare our current queue
time against that. We then use the correction to scale the timeout or
the next queue time prediction.
Also use the predicted time as the base time for the event timestamps.
this results in less jitter.
Fixes#3657
Drivers should only read the target_ values in the timeout, update the
timeout with the new duration and then update the position.
For the position we simply need to add the previous duration to the
position and then set the new duration + rate.
Otherwise, everything else should read the duration/rate and not use
the target_ values.
When reading the timerfd gives an error, we should return right away
because the timeout did not happen.
If we change the timerfd timeout before reading it, we can get -EAGAIN.
Don't log an error in that case but wait for the new timeout.
port_enum_params should use right param id for SPA_PARAM_Format.
Fix typoed , instead of ; at end of line. Pop frame before putting
state.offset, in case there would be padding added (apparently usually
no).
Pass MIDI events as they are.
JACK requires NoteOn 0-velocity midi events to be patched to NoteOff
events for compatibility with LV2 plugins. Let's do this patchup in
the JACK layer then and add an option to disable it.
It's best to pass the midi messages unmodified and then patch them up
wherever they need patching up.
We need to first mark the removed port as invalid, and then look for the
last valid port in the port array otherwise last_port becomes 0 and
midi dataflow stops.
Fixes#1601
The calculation of the elapsed time is actually not a good idea because
it becomes larger and larger and a tiny change in the rate could result
in a large difference that would make things fail quickly.
Until that is fixed, this patch will need to do..
Fixes a number of warnings that look like this:
In file included from ../spa/include/spa/utils/result.h:37,
from ../spa/plugins/alsa/alsa-seq.c:35:
In function ‘set_timers’,
inlined from ‘do_reassign_follower’ at ../spa/plugins/alsa/alsa-seq.c:909:2:
../spa/include/spa/utils/defs.h:191:39: warning: ‘now.tv_sec’ may be used uninitialized [-Wmaybe-uninitialized]
191 | #define SPA_TIMESPEC_TO_NSEC(ts) ((ts)->tv_sec * SPA_NSEC_PER_SEC + (ts)->tv_nsec)
| ~~~~^~~~~~~~
../spa/plugins/alsa/alsa-seq.c:840:28: note: in expansion of macro ‘SPA_TIMESPEC_TO_NSEC’
840 | state->next_time = SPA_TIMESPEC_TO_NSEC(&now);
| ^~~~~~~~~~~~~~~~~~~~
../spa/plugins/alsa/alsa-seq.c: In function ‘do_reassign_follower’:
../spa/plugins/alsa/alsa-seq.c:836:25: note: ‘now’ declared here
836 | struct timespec now;
| ^~~
The reason for these warnings is that spa_system_clock_gettime() may
fail if a version check fails, but the code in question didn't check for
the possible fail. If it failed, then execution would continue, and the
arguments that were passed to the macro will be used uninitialized.
Fix this by checking whether function succeeded.
Allocate up to the first 16 ports, use the last 2 ports and free the
first 14 ports.
This ensure our ports are not among the first ports so that port 128
and following are for normal apps, what is usually expected when
PipeWire is not running.
Fixes#951
Pass the right value for the rate, we need to pass the graph rate.
Don't reduce bandwidth, it is not needed.
Fixes timings for reading the alsa-sequencer.
The announce messages are not put in a queue so we don't need
to allocate one (and a timer). Without the timer, we avoid wakeups
and consume less power.
See #225
We can produce data whenever the io area status != HAVE_DATA. We
don't need to look for NEED_DATA.
Also recycling buffer happens whenever the status != HAVE_DATA.