Commit graph

625 commits

Author SHA1 Message Date
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
Wim Taymans 74de723ecc impl-node: improve node activation
Only activate the nodes when it was not-triggered, do this check with an
atomic compare-and-swap so that we only activate a node once.

We might be able to use this later to make sure that we resume the
untriggered peer nodes when we remove a node from the graph.
2024-04-04 22:01:44 +02:00
Wim Taymans 7a9dfc188a jack: improve midi buffer handling
nframes in the midi buffer should be set to the current cycle
buffer_size and it should restrict the timestamps that can be set on the
midi events.

Keep the last max_frames around in a globals so that we can use it to
set the midi buffer to the default size.

Return NULL when we do jack_port_get_buffer() with larger nframes than
the current cycle buffer_size, just like JACK. Otherwise this could
result in a crash when we try to mix more than the available buffer
space.

Check and reset the midi buffer better. Check if the MAGIC is still ok.
jack_midi_reset_buffer() should restore the MAGIC and other values.
2024-03-12 16:41:59 +01:00
Wim Taymans ca4f9d4989 jack: set the output buffer size correctly
The output buffer size is always the current cycle buffer_size.
The size that is give by the JACK API is only used to restrict the
number of mixdown samples or midi offsets.

Fixes #3892
2024-03-12 15:53:02 +01:00
Wim Taymans 1e92ecea53 jack: fix multiple midi input ports
On the midi input ports, do the same trick as on the output ports:
first convert the midi to JACK and then copy the whole buffer to the
port specific storage.

This makes it possible to have a different midi buffer per port and
allow multiple threads to get the buffer concurrently.

Fixes #3901
2024-03-08 16:31:00 +01:00
Wim Taymans 06f63f489a node: add node.sync-group and node.sync
node.sync-group can contain a list of strings. When a node in the graph
sets node.sync = true, it will be scheduled with all of the other nodes with
common node.sync-group strings. By default all nodes are placed in
group.sync.0 except the freewheel and dummy driver.

Use this to ensure that all nodes are grouped under the same driver
(that is not the freewheel and dummy driver) as soon as the transport is
started so that the transport is visible to all nodes from the same
sync-groups. We also don't deactive the sync-group anymore for the node,
even if the transport is stopped, to avoid driver changes and transport
jumps.

When the node that activated the sync/transport is destroyed, things are
restored to their original state. Note that this is different from JACK
where starting the transport outlives the application and always needs
to be explicitly stopped again. We can't really do this (by default) because
it leaves the graph in an unnatural state with all devices in sync.

The reason for the node.sync-group is that it is possible to still have N
different subgraphs with a separate transports by manually specifying
the node.sync-group.

It's also slightly different from the node.group, that is always active.
The sync-group is something you only want to enable in specific cases
because it groups drivers together and enables adaptive resampling etc.

It's also possible to place this option in the jack.conf file to
automatically sync all devices and apps as soon as a jack app is started.

Fixes #3850
2024-02-29 18:04:05 +01:00
Wim Taymans d063ab7322 node: use new node.transport property to start/stop transport
Instead of modifying the driver activation to start/stop the transport,
use a property on the node and let the server handle the change.
2024-02-29 17:45:28 +01:00
Wim Taymans 94d19f2673 jack: when leaving freewheel, set property to empty string
Setting it to NULL will remove it from the properties and will not
send the updated property to the server, keeping things freewheeling
forever.
2024-02-28 18:53:52 +01:00
Wim Taymans 66792c1e77 jack: handle freewheel property a little better
Don't just overwite the node.group property when changing the freewheel
thate but append the frewheel group and remove it again to preserve
the original node.group.
2024-02-28 16:39:03 +01:00
Wim Taymans 1b407d1c6d jack: FORCE_RATE should just contain the rate 2024-02-26 17:04:21 +01:00