Commit graph

1233 commits

Author SHA1 Message Date
Rui Matos
ec11859a48 spa: Add predefined properties for clock identifiers 2025-10-28 07:18:59 +00:00
Wim Taymans
94d0d8bc09 spa: add spa_json_init_relax
spa_json_init assumes that we start in an object and always requires a
key/value pair. If the last part is a key, it returns and error and does
not want to return the key value.

This causes problems when parsing AUX0,AUX1,AUX2 or any relaxed array
withand odd number of elements.

Make a new spa_json_init_relax that takes the type of the container
we're assuming we're in and set the state of the parser to array when we
are parsing a relaxed array.

Fixes #4944
2025-10-27 13:32:03 +01:00
Pauli Virtanen
c6d0b364ab spa: param: add size checks for spa_audio_info* structs
In the API that take struct size for spa_audio_info*, also check the
struct size.
2025-10-26 18:23:17 +02:00
Pauli Virtanen
8a23b13798 spa: param: pass correct struct size to spa_format_audio_raw_ext_parse/build 2025-10-26 17:44:03 +02:00
Pauli Virtanen
93495d3a75 spa: param: infer raw audio channels from position if unset
The behavior before b8eeb2db45 was that spa_audio_info_raw_update()
always sets audio.channels when audio.position is updated.  The new
behavior does not set audio.channels when parsing audio.position.

This breaks things e.g. when combine-sink and loopback nodes are created
with only audio.position specified.

Restore the previous behavior.
2025-10-26 15:47:48 +02:00
Wim Taymans
aa0272f6f3 treewide: remove some obsolete channel checks
The spa_audio_info can not be parsed with too many channels so there
is always enough space for the positions.
2025-10-24 10:31:45 +02:00
Wim Taymans
78219471ff spa: remove some obsolete functions
The spa_audio_info array now always holds enough positions for all
channels and we don't need to wrap around.
2025-10-24 09:35:59 +02:00
Wim Taymans
6d74eee874 spa: bump channels to 128 again
Remove the SPA_AUDIO_MAX_POSITION define and use the
SPA_AUDIO_MAX_CHANNELS again.

Make a compile time define to override the default max channels of 64.

Make sure we compile the SPA library with the default 64 channels. If
you use the SPA library on a spa_audio_info you will get 64 channel
support, like before. If you want more channels, you will need to make
a padded structure or redefine the MAX_CHANNELS before you use the
spa_audio_info structures. You can use the padded structure with the
new functions that take the structure size.

With the extra checks in the parsing code, we avoid making a
valid spa_audio_info with too many channels that don't fit in the
structure. This means that code that receives a spa_audio_info can
assume there is enough padding for all the channels.
2025-10-24 08:53:21 +02:00
Wim Taymans
b8eeb2db45 spa: make it possible to extend the spa_audio_info struct
Add functions that take the size of the spa_audio_info struct in various
functions. We can use this to determine how many channels and channel
positions we can store.

Error out if we try to use more channels than we can fit positions. This
is probably the safest thing to do because most code will blindly try to
get the positions without checking the channel count.

Make sure we also propagate errors to the callers.
2025-10-23 17:59:51 +02:00
Wim Taymans
c5533b3c32 spa: add all channel positions to the params
Pass all the positions of all channels to the format param, even when
there are more channels then positions.
2025-10-22 13:26:52 +02:00
Wim Taymans
11f1298f53 spa: make a function to make a channel short name
Make a function that can generate and parse a short name for
the positions that are not in the type list, like the AUX channels.
2025-10-22 13:04:53 +02:00
Wim Taymans
6465a63bf6 spa: parse the audio.position completetly
Parse the audio.position spec completely so that we have the right
number of channels but only store the first max_position channels.

Also rename some field to make it clear that this is about the max
number of channel positions.
2025-10-22 12:47:00 +02:00
Wim Taymans
ae50bb5dc0 audio: don't limit channels to max positions
We can have more channels than we have positions.
2025-10-22 09:39:15 +02:00
Wim Taymans
99bbac9cbf spa: increase SPA_AUDIO_MAX_CHANNELS to 128
This should now not change the ABI because the position array size is
now controlled with the SPA_AUDIO_MAX_POSITION constant.
2025-10-21 17:01:31 +02:00
Wim Taymans
f19b075306 spa: add SPA_AUDIO_MAX_POSITION
Add a new SPA_AUDIO_MAX_POSITION constant with the maximum number of
channel positions that can be kept in the various audio_info structures.

Repurpose the SPA_AUDIO_MAX_CHANNELS as a suggestion for applications
for the max allowed number of channels in the system. Make it possible
to make this a compile time constant.
2025-10-21 16:08:24 +02:00
Wim Taymans
dbc5c81e4a spa: avoid using SPA_AUDIO_MAX_CHANNELS
Use SPA_N_ELEMENTS instead of the array we try to handle.
2025-10-21 16:05:33 +02:00
Wim Taymans
818d1435ce treewide: access the position information using helpers
Make sure we don't access out of bounds and that we use the helpers
wherever we can to access the position information.
2025-10-21 13:06:25 +02:00
Wim Taymans
8bbca3b8f3 spa: add spa_audio_parse_position_n
Add a function that accepts the size of the position array when reading
the audio positions. This makes it possible to decouple the position
array size from SPA_AUDIO_MAX_CHANNELS.

Also use SPA_N_ELEMENTS to pass the number of array elements to
functions instead of a fixed constant. This makes it easier to change
the array size later to a different constant without having to patch up
all the places where the size is used.
2025-10-21 09:59:13 +02:00
Wim Taymans
eb096bfb62 spa: provide information about channels > SPA_AUDIO_MAX_CHANNELS
Define some rules for how the position information works for channels >
SPA_AUDIO_MAX_CHANNELS. We basically wrap around and incrementing the
AUX channel counters. Make a function to implement this.
2025-10-21 09:40:08 +02:00
Wim Taymans
ede13a8cb5 spa: don't add more channels than we have positions 2025-10-20 18:31:35 +02:00
Wim Taymans
c94aff8cae Revert "audio: bump max channels to 128"
This reverts commit c91f75ae2e.

This change causes a subtle ABI change and also breaks the Rust
bindings.
2025-10-20 09:17:26 +02:00
Wim Taymans
aede3d049c buffer: update comment, we have flags now 2025-10-06 10:31:52 +02:00
Carlos Rafael Giani
83ee3021e9 spa: Remove channel field from spa_audio_info_mpegh structure
A fixed channel count makes no sense with an entity based 3D audio format
like MPEG-H, because MPEG-H decoders do not simply decode; they
"spatialize" the entities, meaning that said entities are decoded and
rendered accordingto the needs of the target playback system and its
channel count.
2025-10-02 12:12:53 +02:00
Wim Taymans
c91f75ae2e audio: bump max channels to 128 2025-10-01 09:21:36 +02:00
Wim Taymans
00d983a40d meta: add metadata features
Add a new features property to the metadata param. This should be
of type CHOICE_FEATURES_Int and should contain the extra features
supported by this metadata.

Make a special features metadata type that is a combination of the
metadata type in the upper 16 bits and the features for that type in the
lower 16 bits. Make a function to search if a type has certain feature
bits.

On the server, when negotiating buffers and metadata, check the result
of the features after filtering and if they are not 0, place them as
0 sized extra feature metadata on the buffer.

Add some metadata features for the sync_timeline, one that specifies
that the RELEASE flag is supported. With this in place, a producer can
see if a consumer supports the UNSCHEDULED_RELEASE flag.

See #4885
2025-09-19 14:05:04 +02:00
Wim Taymans
a859c7a651 builder: add support for FEATURE choice
This is the same as the Flags choice but the property (if any) has the
DROP flag set.

This means that when filtering, the property is dropped when one side
is missing the property. Otherwise, the flags are AND-ed together with a
negotiation failure when the result if 0.

This can be used to make sure both sides present compatible feature bits.
The result of the filter is then:

  1. no property (one side didn't present bits). This is likely because
     the other side is old and doesn't know about the feature bits yet.
     Code can take a backwards compatibility codepath.
  2. a negotiation failure, both sides presented bits but the AND is 0,
     they don't have compatible features.
  3. a property with bits (features) that are compatible.

This is different from normal flags in that the flags are not dropped
when the other size is missing the property.
2025-09-19 13:40:52 +02:00
Wim Taymans
83b59d6ebe pod: add SPA_POD_PROP_FLAG_DROP
The property will be dropped from the filtered result when one of the
pods to filter does not have the property.

This can be used as a feature mask. If side A provides a flags property
and B doesn't, the property will be removed from the result. Without the
flag, property A would be added and it would not be possible to see if
filtering happened (when B had compatible flags) or not.
2025-09-16 11:00:04 +02:00
Wim Taymans
f89428d9f8 tools: print async node state in pw-top
Pass the node async state in the profiler and use this in pw-top to draw
the node with = instead of a + in the tree when it's async.
2025-09-15 12:29:57 +02:00
Wim Taymans
9df770eb16 spa: support props flags building and parsing
Add an option to make a property with specific flags. Do this by
changing the parser and builder to see the invalid property as an escape
sequence followed by the property key and the flags.
2025-09-12 16:54:04 +02:00
Wim Taymans
41e6e875e5 spa: clean up the filter code
Use SPA_FLAG_IS_SET() and use the same if/else pattern.
2025-09-12 16:33:48 +02:00
Wim Taymans
818ef4e138 spa: flags just have 1 value 2025-09-12 16:17:26 +02:00
Wim Taymans
2be4c2ba51 meta: add SPA_META_SYNC_TIMELINE_UNSCHEDULED_RELEASE
This flag is set by the producer and should be cleared by the consumer
when it promises to signal the release point.

When a consumer dequeues a buffer with the flag set, it should assume
the client is not going to signal the release point and so it should
reuse the buffer right away. This can only happen when the client
didn't dequeue the buffer at all (killed, timeout, error, ...) or when
it dequeued and queued the buffer without clearing the flag.

See #4885
2025-09-10 13:43:51 +02:00
Wim Taymans
f10dec9dae spa: fix typo in raw-types for LLFE
Spotted by Nikolai

Fixes #4881
2025-09-05 15:44:22 +02:00
Wim Taymans
e2ac91b860 ump: make sure we set the group correctly 2025-08-29 16:59:38 +02:00
Wim Taymans
335d891ee9 spa: avoid warnings when compiling cpp
I don't think those qualifiers are needed when doing the atomic
operations.

../spa/include/spa/pod/body.h:250:9: note: in expansion of macro ‘SPA_POD_BODY_LOAD_FIELD_ONCE’
  250 |         SPA_POD_BODY_LOAD_FIELD_ONCE(&b, body, value);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
../spa/include/spa/pod/body.h: In function ‘int spa_pod_body_get_rectangle(const spa_pod*, const void*, spa_rectangle*)’:
../spa/include/spa/pod/body.h:110:81: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers]
  110 | #define SPA_POD_BODY_LOAD_FIELD_ONCE(a, b, field) ((a)->field = SPA_LOAD_ONCE(&((volatile __typeof__(a))(b))->field))
      |                                                                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
../spa/include/spa/utils/atomic.h:22:58: note: in definition of macro ‘SPA_LOAD_ONCE’
   22 | #define SPA_LOAD_ONCE(s)                __atomic_load_n((s), __ATOMIC_RELAXED)
      |                                                          ^
2025-08-26 14:54:23 +02:00
Dimitris Papaioannou
f60638a3aa spa: Make spa_pod_parser_pop return int again
This fixes an API break that couldn't let the Rust bindings build.

See e317edcfb9 (caedda3d4b09299412c1c1ea2f100ac54cfc7b6d_128_190)
2025-08-20 08:04:21 +00:00
Wim Taymans
e35a8554f8 control: improve UMP to Midi conversiom
Improve the spa_ump_to_midi function so that it can consume multiple UMP
messages and produce multiple midi messages.

Some UMP messages (like program changes) need to be translated into up
to 3 midi messages. Do this byt adding a state to the function and by
making it consume the input bytes, just like the spa_ump_from_midi
function.

Adapt code to this new world. This is a little API break..
2025-08-19 18:33:59 +02:00
Demi Marie Obenour
bac3d31283 pod: fix some data races in body code
The body code didn't use atomic loads, so it had undefined behavior if
the body was concurrently modified.  Use atomic loads to fix this.
Since the memory order is __ATOMIC_RELAXED this has no runtime overhead.
Also add barriers around a strncpy call and cast to volatile before
checking for a NUL terminator, though NUL-terminated strings in shared
memory are unuseable.  There are some places where bytewise atomic
memcpy(), which doesn't currently exist, is needed.  Instead, try to
fake it by using two barriers around memcpy().
2025-08-05 10:49:33 -04:00
Wim Taymans
0b647a9009 pod: fuse can_collect, SKIP and COLLECT
Make one COLLECT function that always reads all the varargs (SKIP)
and then tries to collect the pod+body with type checks
(can_collect + COLLECT). This makes things nicer because we can do
everything in one go and we only do one type check.
2025-08-01 16:23:37 +02:00
Wim Taymans
bef0706238 Revert "pod: remove checks from spa_pod_body_get_*()"
This partially reverts commit f7ae61cb1e.

We do want to do the checks in spa_pod_body_get_*() for extra safety.
The reason they were removed is because then we do the checks twice in
the parser. It should however be possible to fuse the can_collect and
COLLECT and SKIP calls together in the future.
2025-08-01 10:46:45 +02:00
Wim Taymans
00dbe9cb2a pod: add missing parser varargs formats 2025-07-31 14:13:41 +02:00
Wim Taymans
ede1924ded pod: add more functions for easy pod+body parsing
Add functions to parse an object and struct from pod+body.
2025-07-31 11:21:28 +02:00
Wim Taymans
45ed70d480 control: mark the input as const, we don't change it 2025-07-31 10:54:09 +02:00
Wim Taymans
abcf70538d pod: add barrier around memcpy
We need to be sure that the compiler does not perform invented loads
after we checked the pod size. Otherwise we could have found that the
size was ok, only to be overwritten by an invalid size.

One way of avoiding this is to surround the memcpy with a barrier.

See #4822
2025-07-30 18:10:09 +02:00
Wim Taymans
77494086c1 pod: add support for vararg building and parsing of pod+body 2025-07-30 15:14:49 +02:00
Wim Taymans
f7ae61cb1e pod: remove checks from spa_pod_body_get_*()
The pattern is _is_foo() and then _get_foo(). This allows us to reuse
some of the get code in the parser without doing checks twice.
2025-07-30 12:56:39 +02:00
Wim Taymans
2c11f65701 pod: avoid child size check
This will give us 0 children later and is not a problem for this
function.
2025-07-30 11:02:00 +02:00
Wim Taymans
0cab2fcb75 pod: don't unpack array values in get_values
This is only for choice, everything else stays the pod.
2025-07-29 17:01:47 +02:00
Wim Taymans
e317edcfb9 pod: rework the parser
Make a new body.h file with some functions to deal with pod and their
body. Make the iter.h functions use mostly this.

Rework the parser so that it only uses body.h functions. With the separation
of pod+body, we can read and verify the pod once and then use the
verified copy to handle the rest of the body safely.

We do this because iter.h only works in pods in memory that doesn't change
because it is vulnerable to modifications of the data after verifying it.

The new parser is not vulnerable to this and will not cause invalid
memory access when used on shared memory. There is however no need for
atomic operations to read the headers, whever is read is either valid
and useable of invalid and rejected.

See #4822
2025-07-29 15:15:02 +02:00
Wim Taymans
87333537d2 pod: also check 0 terminted strings in copy_string
Use get_string() to get a pointer to the string in the pod so that we
also check if it has a 0 terminator.

Fix the test case now that is_string returns true even for non
zero-terminated strings.
2025-07-25 17:33:46 +02:00