Commit graph

634 commits

Author SHA1 Message Date
Barnabás Pőcze
fc91f93af3 pipewire-jack: examples: video-dsp-play: add missing includes
`strerror()` needs `string.h`, and `lrintf()` needs `math.h`.
2025-02-02 14:25:08 +01:00
Wim Taymans
1a737a9fed jack: use a new JackPortIsMIDI2 flag
The JACK2 maintainer would prefer to use a new port flag to mark the
MIDI2 capability of the port and keep the port type as MIDI. Add the
proposed flags to the API.

If we register a MIDI port with the MIDI2 flag, promote it to UMP.
Expose v1 MIDI ports with the MIDI DSP property again.

If we see an UMP port, set the MIDI2 flag on the port.

This is functionaly equivalent to what we have. Old jack midi ports will
now however not have the UMP DSP format but the old MIDI format so that
we can, in the JACK API, make a distinction between MIDI1 and MIDI2 ports.
2025-01-27 13:05:21 +01:00
Wim Taymans
9e2a494d05 jack: add a UMP source example 2025-01-23 15:53:17 +01:00
Barnabás Pőcze
591c40eed4 pipewire-jack: fix property list underallocation
`(n_items) + 1 * sizeof(*items)` is not the correct size to allocate
for `n_items + 1` count of objects each with size `sizeof(*items)`,
the `+ 1` should be inside the parentheses.

Fixes #4481
Fixes: 4baa94fce2 ("thread: make it possible to set a custom create function")
2025-01-05 21:03:50 +00:00
Wim Taymans
188d920733 pass the right types to the methods
This currently works because we accept void* for these functions but it
will fail when we will use the real types.
2024-11-20 10:17:37 +01:00
Wim Taymans
da86026b7a latency: handle negative latency correctly
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.
2024-10-23 10:47:58 +02:00
Wim Taymans
27961630a6 jack: actually clear the mix io
When we are asked to clear the mix io areas, actually do it, otherwise
the process thread might still be accessing the old memory and crash.

Also check that we have set io on the port before we decrement the
counter with active io or else we have a negative value and cause
problems later. This can happen when we susupend and set io to NULL but
there was never any io set on the port.

Fixes #4337
2024-10-06 12:36:18 +02:00
Wim Taymans
d8f0cc7817 jack: take the right locks when modifying globals. 2024-09-26 16:42:20 +02:00
Wim Taymans
f759bb68f5 jack: free ports and cached objects
Free the client ports when closing.

Move the per client cached objects to the global cache.

Free the per-client cached mix and ports.

Add a destructor that frees the cached global objects.
2024-09-26 16:24:00 +02:00
Wim Taymans
c7c5b61dac jack: use the CPU max_alignment
Instead of aligning the buffers to 16 bytes, use the CPU max_align
value (32 on intel).

Move the mix function from a static global variable to a per client
member because this could change per client.
2024-09-25 15:16:25 +02:00
Wim Taymans
ed0556e34c jack: Improve transport BBT handling
The bar can start from 0 in JACK.

Add bar_start_tick and ticks_per_beat to the io_segment_bar so that we
can losslesly store the complete jack BBT values.

See #4314
2024-09-24 18:43:33 +02:00
Wim Taymans
b5cccdb382 json: add and use spa_json_str_object_find()
Parse a string as a json object and copy the value with key as a string.
2024-09-16 13:12:05 +02:00
Wim Taymans
ce390d5b22 spa: add spa_json_object_next
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.
2024-09-16 09:50:36 +02:00
Wim Taymans
cd81b5f39a spa: add spa_json_begin_array/object and relaxed versions
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.
2024-09-16 09:50:33 +02:00
Wim Taymans
ef40bb1d48 jack: emit buffer_size during jack_activate()
JACK emits the bufsize callback from the processing thread while
jack_activate() is called. Do the same with a blocking invoke.

The GStreamer plugin relies on this and when it reives the bufsize
callback later, it will error out.

Fixes #4260
2024-09-09 12:56:22 +02:00
Wim Taymans
36617fc833 jack: improve debug
Log current and target sample_rate and buffer_size
2024-09-09 12:30:42 +02:00
Nedko Arnaudov
6f88b8bf68 jack: Implement jack_get_client_pid() 2024-08-29 14:23:01 +02:00
Nedko Arnaudov
fc25adc825 jack: make jackctl_server_close() succeed (still dummy) 2024-08-29 14:22:58 +02:00
Nedko Arnaudov
b2508b1d2b jack: make jackctl_server_stop() succeed (still dummy) 2024-08-29 14:22:55 +02:00
Nedko Arnaudov
80679c45be jack: Fix crash when pw_context_connect() fails in jack_client_open() 2024-08-29 14:22:52 +02:00
Nedko Arnaudov
3539bc4bed jack: add jackserver.pc 2024-08-29 14:22:49 +02:00
Nedko Arnaudov
d85c6212b3 jack: set current pipewire version in jack.pc file
jack[server] version has 3 for major
and pipewire's "1000*major + 100*minor + micro" as minor version
2024-08-29 14:22:46 +02:00
Wim Taymans
b710cd03d3 jack: use pipewire version for minor/micro/proto
Use the pipewire header version for the minor/micro/proto in the
jack version. That way the jack version will increment and we can
easily see what pipewire version it was compied with.
2024-08-28 15:50:40 +02:00
Wim Taymans
b13705d6de jack: ignore port_set_mix INVALID for destroyed ports 2024-08-22 13:22:12 +02:00
Wim Taymans
4bd421e25e jack: improve error reporting
Add the function and some params to the error message.
2024-08-22 13:21:33 +02:00
Wim Taymans
cc2c86a55b impl-node: always INACTIVATE a node when stopping
Set the node state INACTIVE on the client and server side in all cases
when stopping to ensure nothing tries to schedule the node anymore.
2024-08-08 15:15:39 +02:00
Wim Taymans
648ba982d4 jack: Add UMP to MIDI conversions
Add 2 new port format extensions, one for OSC and another for UMP.

Make sure we convert the events from UMP/OSC/MIDI to jack events
depending on the port type.

Try to produce UMP by default.
2024-07-29 18:15:58 +02:00
Wim Taymans
842e620c1a jack: jack_get_time() returns microseconds
As found by David García Goñi

Fixes #4128
2024-07-19 10:04:44 +02:00
Wim Taymans
398060bc7b jack: don't check timestamps in mixdown
jack_port_get_buffer() can be called with 0 frames, This is to restrict
the available space in the returned midi buffer after mixdown. While we
mixdown, we should not check timestamps so that all midi events are
added to the mixdown buffer.

Fixes qsynth.
2024-07-18 16:49:11 +02:00
Wim Taymans
4baa94fce2 thread: make it possible to set a custom create function
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
2024-07-09 17:04:35 +02:00
Wim Taymans
1ae4374ccf Fix compilation with -Werror=float-conversion
Better make the conversions explicit so that we don't get any surprises.

Fixes #4065
2024-06-18 12:17:56 +02:00
Wim Taymans
33f1a713cd impl-node: set active_driver_id
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.
2024-06-18 09:47:33 +02:00
Wim Taymans
a07f73ce82 impl-node: add more backwards compat
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.
2024-06-17 12:07:09 +02:00
Wim Taymans
b7af52e3fb impl-node: partially revert target rework
We can't let a client decrement the required state because if it crashes
or fails to decrement, the graph becomes unschedulable.
2024-06-13 17:40:55 +02:00
Wim Taymans
1d0d67da1c jack: queue free of old mem in node_set_io as well
Avoid freeing the old io Position area before the data loop has managed
to get a pointer to it. Queue a free operation that will be executed
from the main loop after the data loop has the io area.

Fixes a crash when stressing jack clients to switch between drivers.
2024-06-12 09:54:12 +02:00
Wim Taymans
b0ce5d0dd8 jack: don't call free_link from the data thread
We are not allowed to call free_link from the data thread because it
does free() and some pw_mem calls which should only be called from the
main thread.

To solve this, pause the core, queue a free_link operation on the data
thread, which will be scheduled after the previous remove_link operation
completes, free the link and then resume the core. Blocking and resuming
the core is necessary because we can't block for completion of the
invoke calls (the jack method is not allowed to block) and we must
ensure that nothing can happen with the memory (like reuse the mem_id)
before we have cleaned it up.

Fixes a crash in jack with create/destroy link stress.
2024-06-11 17:17:32 +02:00
Wim Taymans
74e340507a JACK: remove useless io_data member 2024-06-10 10:26:06 +02:00
Wim Taymans
b144aa24fa JACK: check the io of the right cycle
The port->io always points to a 2 item ptrarray of buffers so check
if there is actually a buffer for the current cycle instead.

Avoids a crash.
2024-06-10 10:26:06 +02:00
Wim Taymans
46f71b1cd2 Rework how targets are managed
Manage them like we do on the client and reuse logic. Make a node
function to safely add and remove a target.

Activate the targets from the process loop when we can be sure that we
can resume them. This avoids incrementing the pending state when we are
not going to be able to resume the nodes (like when the cycle is ongoing
and we have already been scheduled) and avoids glitches and xruns.

When a node is added to the poll loop, it can activate its own targets.
This is mostly for driver so that they have something to schedule and
can then activate the other targets.

Try to resume the target when it is removed and we are supposed to be
scheduled.

Also add targets to the target_list when the node is remote to make sure
the profiler can see the targets as well.

Keep the node in the INACTIVE state as long as the eventfd of the node
is not added to the loop. Skip nodes in the INACTIVE state from going to
the NOT_TRIGGERED status, which avoids scheduling the node.

Make sure we remove any local targets we have in a node when we export
it, we will receive new targets from the server.

This should eliminate any glitches when adding and removing nodes from
the graph.

See #4026, #2468
2024-06-05 15:37:15 +02:00
Wim Taymans
05abc4e41f jack: rename a function
Add/remove_link is more what this function does.
2024-06-04 17:15:54 +02:00
Wim Taymans
fa154955af jack: update the eventfd from the data loop
Also update the variables we use from the data loop.
2024-06-04 17:14:02 +02:00
Wim Taymans
ffb0eff708 impl-node: resume peer targets when unlinking
Atomically change the node status from TRIGGERED to AWAKE. Only trigger
the peer nodes when the node was previously in the AWAKE state.

When we remove a node from the graph or when we destroy a link, we need
to manually resume the peers. We can do this now by atomically setting
the node to FINISHED and checking if it was previously != FINISHED.

This ensures that removing nodes/links never leaves some nodes (and also
the driver) untriggered and cause a xruns.

Fixes #4026
2024-05-27 16:58:39 +02:00
Diego Viola
7410755c03 Fix typos
found them with codespell.

Signed-off-by: Diego Viola <diego.viola@gmail.com>
2024-05-22 09:19:34 +02:00
Wim Taymans
cdc150a2c3 jack: copy events to right offset
The larger events need to be copied into the target buffer at the same
offset as the source buffer or else we overwrite the header and make
a corrupt buffer.
2024-05-10 12:15:36 +02:00
Wim Taymans
fac0d47c23 impl-port: swap io areas instead of doing cycle math
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.
2024-05-08 10:45:53 +02:00
Wim Taymans
afd9960dc3 jack: pass client to get_mix_buffer instead of port
The port can be null when we try to get a buffer from a port that is not
ours. Just use the client to get to the current cycle.
2024-04-30 15:48:10 +02:00
Barnabás Pőcze
6a26e6dd3f treewide: fix some format string issues
Use the proper specifier, and cast to a known type where the type
is not guaranteed by any standard.

See #3975
2024-04-25 07:24:10 +00:00
Wim Taymans
20b52d2082 keys: add and use some loop keys 2024-04-23 11:49:12 +02:00
Wim Taymans
68916e062b impl-node: implement async scheduling
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
2024-04-18 10:31:29 +02:00
Wim Taymans
34c8322986 impl-node: count missed wakeups as xruns 2024-04-08 17:02:20 +02:00