Compare commits

...

1002 commits

Author SHA1 Message Date
Wim Taymans
9f3c553298 tools: add -t option to the help 2025-10-28 10:29:01 +01:00
Wim Taymans
a813830024 po: update Turkish translation 2025-10-28 08:48:18 +01:00
Wim Taymans
a837dcd40b audioadapter: renegotiate when driver changes
The renegotiated format can depend on the clock rate of the new
driver.

See #4933
2025-10-28 08:32:03 +01:00
Rui Matos
752de866ae spa: node-driver: Expose the clock id as param properties 2025-10-28 07:18:59 +00:00
Rui Matos
ec11859a48 spa: Add predefined properties for clock identifiers 2025-10-28 07:18:59 +00:00
Carlos Rafael Giani
1096d63468 module-rtp-source: implement IGMP recovery for multicast subscription loss
Add IGMP recovery mechanism that monitors RTP packet reception and
triggers multicast group refresh when no packets are received if
a deadline is reached. The deadline is configurable via a new stream
property "igmp.deadline.sec" (in seconds), with the default value
being 30 seconds (and a minimum of 5 seconds).

A timer checks regularly if the deadline was reached. That timer's
interval is set by the igmp.check.interval.sec property (in seconds),
with the default value being 5 seconds (and a minimum of 1 second).

When the deadline is reached, the mechanism performs IGMP leave/rejoin
operations to refresh multicast group membership. This ensures RTP
data continues to be received when network conditions cause IGMP
membership to expire or become stale due to router timeouts or
network issues.
2025-10-27 22:40:22 +01:00
Carlos Rafael Giani
955c9ae837 module-rtp: Get the current stream time in a reusable manner
That way, redundant pw_stream_get_nsec() and clock_gettime()
calls can be avoided.
2025-10-27 22:40:22 +01:00
Carlos Rafael Giani
3e0f4daf60 module-rtp-sap: implement IGMP recovery for multicast subscription loss
Add IGMP recovery mechanism that monitors SAP packet reception and
triggers multicast group refresh when no packets are received if
a deadline is reached. The deadline is set to half of the cleanup
interval, with a minimum of 1 second.

When the deadline is reached, the mechanism performs IGMP leave/rejoin
operations to refresh multicast group membership. This ensures SAP
announcements continue to be received when network conditions cause
IGMP membership to expire or become stale due to router timeouts or
network issues.
2025-10-27 22:40:22 +01:00
Carlos Rafael Giani
5d21e12658 module-rtp-source: Use make_socket() error value instead of errno
make_socket() already returns the negative errno.
2025-10-27 22:14:09 +01:00
Carlos Rafael Giani
f1ffd5e5e8 module-rtp-source: Read cleanup.sec property from stream properties
This allows for setting the cleanup.sec value in the create-stream
block in the module-rtp-sap configuration.
2025-10-27 22:14:09 +01:00
Carlos Rafael Giani
80e7302a05 module-rtp-sap: Add retry code for when start_sap() fails due to ENODEV 2025-10-27 22:14:09 +01:00
Carlos Rafael Giani
b57bd00be0 module-rtp-sap: Improve names for clearer code 2025-10-27 22:14:09 +01:00
Rui Matos
c1e737bbe4 module-rtp: Attempt to reconnect the ptp management socket
This should gracefully recover the cases where the other end of the
socket isn't ready yet when we start or terminates and gets restarted.
2025-10-27 18:08:00 +01:00
Jonas Holmberg
76a31a47c2 module-echo-cancel: Avoid discontinuity
Keep the samples in the ringbuffer that are needed the next cycle to
avoid discontinuity when the aec blocksize is not equal to or divisible
by quantum.
2025-10-27 14:39:29 +01:00
Wim Taymans
23c449af5d test: add test for an array with odd number of items
We have to use the relax version to get the expected container type
correct.
2025-10-27 14:20:25 +01: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
Wim Taymans
0276bb5b06 modules: ringbuffer avail is signed 2025-10-27 11:43:04 +01:00
Jonas Holmberg
614186a590 module-echo-cancel: Sync capture and sink buffers
Call process() when capture and sink ringbuffers contain data from the
same graph cycle and only process the latest block from them to avoid
adding latency that can accumulate if one of the streams gets more than
one buffer before the other gets its first buffer when starting up.
2025-10-27 08:43:08 +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
3d08c0557f properties: fix assign + conditional expression 2025-10-26 14:12:19 +00:00
Pauli Virtanen
68dc45cc62 audioconvert: simplify volume ramp generation
Don't use floating point accumulators, interpolate from sample position.
2025-10-26 14:12:19 +00:00
Pauli Virtanen
b0e308e0dc spa: examples: fix getopt usage + typos in adapter-control 2025-10-26 14:12:19 +00:00
Pauli Virtanen
fe2c62b9b1 meson.build: set project cc flags also for native builds
Use the build flags also for all native build targets.
Avoids spurious warnings in spa-json-dump
2025-10-26 14:12:19 +00:00
Pauli Virtanen
3febf09b85 alsa: fix typoed braces in condition + assign 2025-10-26 14:12:19 +00: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
Pauli Virtanen
9f1a149876 ci: add file package, for coverity
Try to fix coverity by adding missing 'file' package to container
2025-10-25 12:42:45 +03:00
Wim Taymans
88c65932d8 acp: use global max channels if defined 2025-10-24 17:16:03 +02:00
Wim Taymans
c8d4de5e77 acp: bump max channels to 128 2025-10-24 17:00:42 +02:00
Wim Taymans
c4244a6cf3 string: use spa_strbuf instead of snprintf magic 2025-10-24 17:00:11 +02:00
Wim Taymans
f7c3d37969 fmt-ops: allocate shaper memory dynamically
It is based on the number of channels so allocate it dynamically.
2025-10-24 12:46:38 +02:00
Wim Taymans
d18670d7bb pw-cat: improve channel checks
Make sure we don't use too many channels.
2025-10-24 10:42:05 +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
be29ae4ef6 audioadapter: add some more debug info when parsing fails 2025-10-23 18:05:22 +02:00
Wim Taymans
5e1e3fca1e modules: handle format parsing errors 2025-10-23 18:01:35 +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
7177f8269d bluez: use function to get the channel position from a name 2025-10-22 12:54:30 +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
9e7cae13df alsa: use the amount of positions we will write 2025-10-21 09:43:59 +02:00
Wim Taymans
13b8c23767 Don't use SPA_AUDIO_MAX_CHANNELS directly
Make a MAX_CHANNELS define and use that one in code. This makes it
easier to change the constant later.
2025-10-21 09:43:06 +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
f453b1545d audio: don't use SPA_AUDIO_MAX_CHANNELS in some places
When we know the max size of the array, just use this instead of the
SPA_AUDIO_MAX_CHANNELS constant.
2025-10-20 18:31:17 +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
fb49759d1f module-echo-cancel: drop samples when source not ready
When we can't dequeue a buffer from the source stream, drop the samples
instead of leaving them queued in the ringbuffer.
2025-10-17 14:51:14 +02:00
Wim Taymans
f70b0892ea doc: swap the name and id of the device.product
Fixes #4935
2025-10-17 12:28:15 +02:00
Wim Taymans
3263e2497e 1.5.81 2025-10-16 10:07:11 +02:00
Pauli Virtanen
453ca31214 doc: update doxygen-awesome.css
Update doxygen-awesome.css to v2.4.1 (1f3620084ff7573) from upstream.

Link: https://github.com/jothepro/doxygen-awesome-css/
2025-10-15 20:39:14 +00:00
Pauli Virtanen
0b78a2d97c ci: bump Fedora version to Fedora 42
This brings newer Doxygen.
2025-10-15 20:39:14 +00:00
Pauli Virtanen
da2cecf074 alsa: acp: don't disable dB if negative max unless range is small
Disabling dB volumes for max_dB < 0 was added in Pulseaudio in 2021,
based on a device which had -128..-127.07 range. However, negative
max_dB is valid value for USB devices, and there are devices that have
it.

Eg. Microsoft LifeChat LX-3000 has

numid=6,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=151,step=0
  : values=150,150
  | dBminmax-min=-28.37dB,max=-0.06dB

and the dB range seems to be OK. Web search for "The decibel volume
range for element" also gives other hits with seemingly OK looking
ranges.

Don't disable dB volume unless both the max is negative and the range is
suspiciously small. This should still disable it for the device this
check was originally added for.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/447
Link: 10ac01a206
2025-10-15 21:37:06 +03:00
Wim Taymans
a75cea96fb modules: port modules to timer-queue
Instead of using timerfd, use the context timer-queue to schedule
timeouts. This saves fds and removes some redundant code.

Make the rtp-source timeout and standby code a bit better by using
atomic operations.
2025-10-15 16:57:24 +02:00
Wim Taymans
b220f85790 module-rtp-sap: reorganize generation of SDP
Move the code to recalculate the hash and version into make_sdp. Add a
boolean argument to the make_sdp function. Recalculate the hash and
version when we are making a new SDP and leave the old values if we
are making an SDP to compare against the current one.
2025-10-15 14:08:24 +02:00
Wim Taymans
c40e0d1d98 module-rtp: unset ptp_fd or else we might close it 2025-10-15 14:05:29 +02:00
Wim Taymans
f91aed5eeb impl-link: pass error codes in link error state
Pass the error code when setting the link in the error state.

Add some more debug.
2025-10-15 11:20:01 +02:00
Wim Taymans
9b507d3210 context: add support for rlimit.<resource> = <value>
Add support for rlimit.<resource> = <value> in the context.properties to
adjust the rlimits of the process. A value of -1 sets the max limit.

This can be used to increase the number of file descriptors in a
pipewire process when select() is not used, for example. Other resource
limits might be interesting as well maybe.

Fixes #4047
2025-10-15 09:26:36 +02:00
Wim Taymans
9f2d873760 examples: set exclusive and reliable flags
We need exclusive port use if we negotiated SyncTimeline because there
can only be one consumer of the syncobj.

We also need to enable reliable transport if synctimeline is supported
but the release flag isn't.

Add some more logging to the port when the exclusive and reliable states
changed.

Fixes #4885
2025-10-14 11:56:22 +02:00
Wim Taymans
20d2a331be impl-node: add a NODE_RELIABLE property
Add a PW_KEY_NODE_RELIABLE and PW_KEY_PORT_RELIABLE property. the port
property value is inherited from the parent when not explicitly set.

Setting the property on a port will activate a more reliable tee, that
actually only recycles buffers that were consumed. It will also activate
a mode in stream that gives out new buffers only when the previous one
was recycled and nothing else is queued. This is necessary to avoid
queuing in the stream when the other side is not consuming.

When a link is async but the output node is a driver of the input, we
can avoid async io. This also removes a potential out-of-order buffer
recycling when the node resumes at a different cycle.

See #4885
2025-10-14 11:55:25 +02:00
Pauli Virtanen
c89acd3e1c alsa: acp: fix volume rounding down causing mute
Some ALSA devices have minimum HW volume value that is muted.  ALSA
indicates it with SND_CTL_TLV_DB_GAIN_MUTE = -9999999 dB/100 volume dB.
When rounding down to HW volume, we may get this muted value.

When determining splitting of volumes to mixers and soft volume, we
don't want HW mixers to set volume to muted, unless the target volume is
actually muted.

Fix by adding element_ask_unmuted_dB_vol() that rounds up if the asked
rounding mode resulted to mute.

This fixes mic getting muted at low volume despite ALSA reporting the dB
values correctly.

Fixes #4890
2025-10-14 08:02:23 +00:00
Pauli Virtanen
91702975f7 bluez5: media-sink: cleanup ISO rate matching
Move accounting for pending ISO packet to the reference time.  Make sure
rate matching is reset on start, and reset matching on resync properly.

Allow resync on first cycle, ok since iso_io->now is valid immediately.
2025-10-14 07:59:55 +00:00
Pauli Virtanen
4e3a5d9e6f bluez5: iso-io: initialize stream->size, now when setting cb
Ensure size and now have valid values after exiting
spa_bt_iso_io_set_cb(), so data may be provided already on first cycle.
2025-10-14 07:59:55 +00:00
Pauli Virtanen
4ca1d70979 bluez5: media-sink: fix silence padding for ISO stream resync
Silence padding larger than ISO packet may be needed for resync when
quantum is large. We can't insert silence by adding data to encoding
buffer, as the encoding buffer may be then too small and it may also be
partially filled.

Fix by inserting silence from flush_data() just before buffers would be
consumed.

Fixes ISO stream alignment at playback start.
2025-10-14 07:59:55 +00:00
Pauli Virtanen
8bf8600e59 bluez5: if Acquire results to NoReply, try to clean up with Release
If BlueZ doesn't reply, it may consider the operation still active.
Try to Release the transport to get to a known state.

This can happen if device doesn't respond to operations in reasonable
time and BlueZ doesn't have its own timeout which is the case for BAP
currently (which is a bug there).
2025-10-11 20:52:59 +03:00
Barnabás Pőcze
126d61db1b ci: build_on_debian: set test timeout multiplier
Some tests - for example test-fmt-ops - are compute heavy. Since tests
in non-x86 builds are run inside qemu, they can be significantly slower,
exceeding the default 30 second timeout.

So set the timeout multiplier to 2 to allow for slower execution.
2025-10-10 16:06:16 +00:00
Pauli Virtanen
c65e70fce0 doc: document missing api.acp.* properties 2025-10-10 18:30:26 +03:00
Wim Taymans
4da25df986 filter-graph: accept String param values
We parse the string as a float and if that works, set the value.
2025-10-10 15:03:04 +02:00
Jonas Holmberg
16ce5a2ccf filter-graph: Accept params of type Long
Integer numbers in lua are sent over protocol-native as Longs so make
sure to handle them.
2025-10-10 10:53:03 +00:00
George Kiagiadakis
2aa725e4fe audioconvert: accept prop params that are encoded as Long in the pod 2025-10-10 13:48:10 +03:00
Arun Raghavan
154ab33607 spa: alsa: Add option to use ELD-detected channels 2025-10-10 09:34:43 +00:00
Arun Raghavan
91e2f184e2 spa: alsa: Read and expose channel count and position from ELD
The next step will be to propagate this to the correct node.
2025-10-10 09:34:43 +00:00
Wim Taymans
d268b6e104 examples: add some options to enable features 2025-10-10 10:41:53 +02:00
Wim Taymans
bd6081018f tests: fix warning 2025-10-09 09:29:32 +02:00
Wim Taymans
b7b9e7dc6e tests: fix compilation 2025-10-09 09:22:07 +02:00
Arun Raghavan
a4ec02f9d7 spa: tests: Add an offline AEC benchmark 2025-10-09 00:16:51 +00:00
Barnabás Pőcze
dcdb88d7b7 spa: libcamera: device: adapt to libcamera change
The interface of string typed controls has recently been changed in
libcamera[0], which affects `properties::Model`, so adapt to that change
in such a way that is compatible with both the new and old versions.

[0]: f84522d7cd
2025-10-08 13:23:11 +02:00
Wim Taymans
4fb0a0aeea example: add sync timeline example
Add an example producer and consumer using the SyncTimeline metadata.
The syncobj are just eventfd for the purpose of the example.

Also demonstrate the RELEASE feature when negotiated.

Add some switches to tweak the SyncTimeline and features support.

See #4885
2025-10-08 12:53:30 +02:00
Wim Taymans
7d781e696f profiler: avoid null dereference
Avoid shadowing some variables from the parent block.

The node of a target can be NULL when the target is running in another
instance. We already do some checks for this but make sure we never
deref the NULL pointer.

Fixes #4922
2025-10-06 14:38:38 +02:00
Barnabás Pőcze
e4480cf804 ci: enable ffmpeg in build_on_debian
The dependencies are already installed, but since the ffmpeg related
meson options are set to `disabled`, they were not used.
2025-10-06 12:10:23 +00:00
Barnabás Pőcze
e72962fb42 pw-cat: do not use deprecated FF_PROFILE_*
These macros were deprecated in 2023[0], and are absent in the latest
ffmpeg 8.0[1]. So use the new names.

[0]: 8238bc0b5e
[1]: 8224327698
2025-10-06 12:10:23 +00:00
Wim Taymans
e9aef9196f examples: add example MemFd sink
Add an example of a filter sink that requires MemFd memory on the
input port. Show that it gets automatically mapped and that it contains
MemFd memory.

Fixes #4918
2025-10-06 13:37:59 +02:00
Wim Taymans
5ccaf29793 stream: only mmap buffers when not already mapped
Don't just blindly mmap the buffer but only when the data pointer
is NULL. If it was mapped already by the peer or the adapter or the
buffer allocation, we don't want to mmap it again and override the buffer
data pointer.

Also mmap with the permissions on the data. There is not much point in
limiting the permissions for an input port (to read only). We could do
this but then we would not be allowed to modify the existing data
pointer. The problem is that when the stream mmaps the data as READ only
and set the data pointer, if it is then handed to the mixer, it would
assume it is mapped with the permissions and then segfault when it
tries to write to the memory. It's just better to only mmap when the
data is NULL.
2025-10-06 13:17:00 +02:00
Wim Taymans
e7bc261830 filter: don't lock the Buffers param
It should be possible to override the Buffers params in the filter.
2025-10-06 13:16:32 +02:00
Wim Taymans
984b2d296e context: only make active nodes runnable
Only try to make active nodes runnable. This can happen when the node is
destroyed.

Avoids a -EIO error when destroying nodes from pavucontrol.
2025-10-06 11:48:40 +02:00
Wim Taymans
b66d49702f examples: avoid mmap in the example
We don't need to do this ourselves, the MAP_BUFFERS port flag already
makes sure this is done for use.

We used to have to do this here to ensure the mixer could find the data
pointer and not error out. Now that the mixer can MMAP, this can go.

See #4918
2025-10-06 11:17:08 +02:00
Wim Taymans
af3ad7bf9f buffers: improve allocation
There are really 2 options for the buffer allocation:

1. allocate the buffers skeleton and meta/chunk/data in malloc memory.
   This is when the PW_BUFFERS_FLAG_SHARED is unset.
2. allocate buffers skeleton in alloc memory and the meta/chunk/data
   in shared memory when the PW_BUFFERS_FLAG_SHARED is set.

Optionally the data can be left unallocated in both cases when the
PW_BUFFERS_FLAG_NO_MEM is set. In this case we also need to pass the
SPA_BUFFER_ALLOC_FLAG_NO_DATA flag to allocator or else it will set the
data pointers to 0 sized memory in the skeleton.

If we use SHARED and we allocated memory, we can also set the MemFd and
mapoffset into our shared mem. We can do this even if the data_type is
MemPtr.

We can decide on the datatype to use earlier, based on the negotiated
flags. In the MemFd case, make sure the buffer data is page aligned in
that case to make things easier. Also force everything in SHARED mem
when the data is in SHARED mem. We also don't need to
PW_BUFFERS_FLAG_SHARED_MEM because we work with the negotiated flags
now to decide if SHARED mem is needed or not.

With this change, a node port could provide a MemFd data_type mask in
the Buffers param and this would negotiate shared mem with the mixer.
Previously, it would only ever allocate malloc memory.

See #4918
2025-10-06 10:58:19 +02:00
Wim Taymans
1a54b9e66f impl-port: handle errors from the mixer use_buffers
Also handle errors when we fail to set mixer buffers on the output port
of the mixer.
2025-10-06 10:38:08 +02:00
Wim Taymans
aede3d049c buffer: update comment, we have flags now 2025-10-06 10:31:52 +02:00
Gabriel Golfetti
df2f36ad8f Add support for mappable buffers in mixer-dsp 2025-10-04 10:04:50 +00:00
Wim Taymans
fe78e80614 tools: fix compilation after removal of field 2025-10-02 16:39:18 +02:00
Wim Taymans
0b0226322f examples: add DSP sink example
Add example of ALLOC_BUFFERS on the input port.

See #4918
2025-10-02 16:26:27 +02:00
Wim Taymans
4161fa3071 impl-port: also honour CAN_ALLOC flag between mixer/node
When we have a mixer node and we need to negotiate buffers between the
mixer and the node, take the CAN_ALLOC flag into account.

This is for input ports, which can have a mixer. If you make a filter
with a CAN_ALLOC input port, it will now not already contain buffer
data.

See #4918
2025-10-02 16:26:27 +02:00
Wim Taymans
1fdde582c0 buffers: add some more comments to the flags 2025-10-02 16:26:27 +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
Carlos Rafael Giani
52041e888c meson.build: Make libswscale a requirement only if videoconvert is enabled 2025-10-02 12:05:07 +02:00
zay-yar-lwin
0de80603e1 update Burmese Translation 2025-10-02 09:11:14 +00:00
Pauli Virtanen
6755f24a3d bluez5: reduce log level for unhandled RFCOMM commands
Don't log warnings about not passing on RFCOMM commands to modem if
there is no modem configured, as this is normal occurrence.
2025-10-02 01:33:23 +03:00
Pauli Virtanen
8277bf6b36 bluez5: improve error messages when connection drops
Log something less confusing when connection to remote device drops
unexpectedly.

Silence logging transport Release() error in cases where the transport
was simultaneously deleted.
2025-10-02 01:25:56 +03:00
Wim Taymans
4625f7ee3a mixer-dsp: only use passthrough when DYNAMIC_DATA
We can only change the data pointers on the output buffer when the data
had the DYNAMIC_DATA flag.
2025-10-01 11:13:42 +02:00
Wim Taymans
91ae1c13b7 impl-port: only use DYNAMIC_DATA when allowed
Allocate buffers with the DYNAMIC_DATA flag set only when the port
actually allows it.

See #4918
2025-10-01 11:11:36 +02:00
Wim Taymans
0915ed8be0 adapter: enhance converter flags with follower flags
We don't want to override the converter flags with the follower flags,
just enhance them with specific follower flags. Otherwise we lose the
DYNAMIC_DATA and other port flags from the converter.

See #4918
2025-10-01 11:03:53 +02:00
Wim Taymans
c91f75ae2e audio: bump max channels to 128 2025-10-01 09:21:36 +02:00
Wim Taymans
532140ca90 bluez5: Don't assume channels fit in uint8_t
There is no reason to believe the number of channels can fit in a
uint8_t. Limit the number of channels in some places where it can not
be avoided.
2025-10-01 09:13:42 +02:00
filmsi
74e6e6c29d Update Slovenian translation 2025-09-29 18:05:19 +02:00
Pauli Virtanen
2248807835 bluez5: sco-io: send keepalive TX data if sink is not feeding it
When using LC3-24kHz, remote device drops connection after a few seconds
if there is no sink playback.  Avoid this by sending silence, one TX
packet for each RX packet, if sink hasn't been feeding data within a
timeout.
2025-09-29 14:15:46 +00:00
Niklas Carlsson
3f9ae1ee10 filter-graph: allow 8 channels in max plugin
Mimic the same channel behavior as for other plugins that allows
for 8 channels, such as Mixer and Mult.
2025-09-29 14:11:27 +00:00
Wim Taymans
3cf182255f context: handle leaf nodes better
Find leaf nodes by looking at the number of max in/out ports and the
link group. This should give us nodes that only consume/produce data.

If a leaf node is linked to a driver with only passive links, it will
never be able to be scheduled unless we also make it runnable when the
driver is made runnable from another node.

This can happen when you do:

pw-record -P '{ node.passive=true }' test.wav

and then

pw-record test2.wav

Without this, the first pw-record would never be scheduled. With the
patch it will be scheduled when the second pw-record is started.

Fixes #4915
2025-09-29 14:38:19 +02:00
Wim Taymans
468a9ac954 pulse-server: add the peer ip to client properties
When clients connect with IP, add the peer IP address to properties. We
might use this later to make a better stream node.name than a copy of the
client application name.
2025-09-29 09:39:57 +02:00
Wim Taymans
fdc74df383 modules: use timer-queue in avahi-poll
Pass the pw_context to get to the shared queue and loop.
Patch up the users of avahi-poll.

Fixes #4913
2025-09-26 13:39:49 +02:00
Wim Taymans
678e571d80 timer-queue: delete next timer event when it got fired
When we fire the timer event, mark the next timeout as NULL because
nothing else is going to timeout anymore until we rearm the timer.

This has the effect that if we cancel and add the same timer from the
callback that we will reprogram the timer with the new timeout instead
of thinking the item as already programmed.
2025-09-26 13:02:53 +02:00
Wim Taymans
9be06c46b7 pulse-server: fix case statement 2025-09-26 11:43:52 +02:00
Wim Taymans
17cad8e7ef pulse-server: add a help message
Shows all available messages on /core because I keep forgetting.
2025-09-26 10:57:04 +02:00
Wim Taymans
5a894270e6 pulse-server: add a pipewire-pulse:list-modules message
It list all available module names, which you can then describe further.
Make a little module_info iterator function for this.
2025-09-26 10:55:10 +02:00
Wim Taymans
ecac86b0ca avahi: handle fd allocation errors
When we fail to allocate an io source or a timerfd, return NULL instead
of crashing later on.

See #4913
2025-09-26 10:52:40 +02:00
Wim Taymans
06214b6087 pulse-server: map some more errno to errors
Mostly EADDRINUSE to ERR_BUSY, which happens when loading TCP when
it's already loaded on the address.
2025-09-26 10:50:52 +02:00
Peter Ujfalusi
9c42c06af0 alsa: Use the minimum period size as headroom for SOF cards
Configure the headroom to be equal of the minimum allowed period size for
the configuration.

This is desirable when the ALSA driver's hw_ptr is 'jumpy' due to
underplaying hardware architecture, like SOF.
In case of SOF the DSP firmware will burst read at stream start to fill
it's host facing buffer and later settles to a constant pace. The minimal
period size is constrained by the driver to cover the initial burst and
settling time of the hw_ptr.

Guard this mode of working with a new boolean flag, which is only enabled
for SOF cards, kept it disabled for other cards to avoid any unforeseen
side effects.

Even if the use-period-size-min-as-headroom is set to true, the manual
headroom configuration will take precedence to allow experimentation.

Link: https://github.com/thesofproject/linux/issues/5284
Link: https://github.com/thesofproject/sof/issues/9695#issuecomment-2569033847
Link: https://github.com/thesofproject/sof/issues/10172
Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4489
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
2025-09-25 16:30:08 +03:00
Wim Taymans
19198d2982 pw-cat: fix DSD file reading
Now that the server asks for the right amount of samples for DSD, just
give it the right amount of samples without doing some weird scaling.

Make a method to calculate the size (stride) of one sample, which
depends on the interleave and channels of the stream.

See !2540
2025-09-25 13:56:51 +02:00
Wim Taymans
f8389cbdb7 alsa: improve force_rate handling
Replace force_rate with force_quantum. We use force_rate when we need
to play an IEC958 or a DSD format but it does not make sense to just
force the rate without also forcing the duration.

This is also what happens when doing IRQ based scheduling, we then force
both the duration and rate of the graph so we can reuse this logic.

Also when forcing a quantum, take into account the suggested duration
and rate of the graph and scale that with the currently configured rate
for the period size. This gives a quantum that will match the requested
rate better. This is important for the DSD, where rate are very high and
we want the period size to be something reasonable relative to the
selected graph rate.

For batch devices (and when using a timer) we also configure a period
size that is half the duration of the quantum, to make sure we get some
headroom. We however need to force the full duration as the quantum, so
keep track of this scaling and apply when calculating the duration.
2025-09-25 12:29:05 +02:00
Carlos Rafael Giani
65e49b38d1 module-rtp: Add process.latency.from.sess prop to set process latency 2025-09-24 22:54:06 +02:00
Carlos Rafael Giani
63df661eff module-rtp: Handle Latency and ProcessLatency in stream 2025-09-24 22:54:06 +02:00
Wim Taymans
f1e1f720bf adapter: fix Start of adapter
Commit cbbf37c3b8 changed the logic of the
Start command. Before this commit, when there was no converter, the
follower would always get the Start command. After the commit, the
follower would only get Start when previously Paused.

This however breaks when we set a format or buffers on the follower
without a converter because those actions might change the state of the
follower to Paused implicitly.

We should simply remove the started check here and always call Start on
the converter and follower, the implementations themselves will keep track
if anything needs to be done.

Fixes #4911
2025-09-24 12:36:13 +02:00
Pauli Virtanen
2e2f7c9f79 alsa: don't fail if 3 periods_min fails
Some drivers (emu10k1) appear to not necessarily support more than 2
periods.

Don't fail start if snd_pcm_hw_params_set_periods_min() fails, then we
just set nearest possible periods and buffer sizes.
2025-09-23 07:21:29 +00:00
lumingzh
f0a5f09420 update Chinese translation 2025-09-23 07:20:19 +00:00
Wim Taymans
3c921acb48 impl-port: rework port properties
Don't update info.props all the time, just once when we create the
properties, the dict will not change after that.

Move the port property check code to a new function. Keep track if we
auto generated path, name or alias and if we explicitly update it or
not.

Listen for node property changes and update the port properties if
necessary. Some of the port properties or feature depend on the node
properties so we want to keep those in sync.
2025-09-22 14:30:09 +02:00
Wim Taymans
ad33ff34f7 doc: fix some spelling, grammar and formatting mistakes 2025-09-22 11:24:23 +02:00
Wim Taymans
0267a5906e doc: add DSP filter tutorial
Add CLAUDE generated tutorial7 based on the audio-dsp-filter
example.
2025-09-22 11:01:52 +02:00
Wim Taymans
6bc451cf6d timer: fix compilation on arm 2025-09-19 16:16:25 +02:00
Wim Taymans
12464ed1bb impl-port: copy node.terminal and node.physical properties
Make 2 new node properties to make all ports of a node terminal or
physical.

Skip the monitor ports for this, though, they can never be terminal or
physical.

This is important for JACK clients that often enumerate physical
terminal ports in order to link to them and with this you can make JACK
clients link to virtual sinks and sources as well.
2025-09-19 15:58:56 +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
b57c6d3729 examples: count the params as we add them
Count the params as we add them to the param arrays and use that to
update the stream params instead of using hardcoded indexes and sizes.

This makes it easier to add params and it also revealed a miscounted
param.
2025-09-19 13:08:22 +02:00
Wim Taymans
83242a5c3c buffers: small cleanup of the buffer allocation
Calculate the min_buffers separately and then use that to ensure we have
enough buffers. This makes it easier to increase the min amount later.
2025-09-19 09:17:47 +02:00
Wim Taymans
1717ff336e impl-port: init some stuff earlier
Initialize the mix_hooks, port_map and latency earlier, before we call
pw_impl_port_set_mix() and update_info, that could potentially expect
this to be initialized.
2025-09-18 15:21:50 +02:00
Wim Taymans
c296c52cae stream: avoid work at the end of the cycle
Driver output streams will start the cycle with a _trigger() operation,
which will call the process function (if necessary) to dequeue/queue a
buffer before starting the graph cycle. At the end of the cycle, the
internal stream process function is called again to recycle any buffers
but we should not try to dequeue a new buffer (if there was any in the
queue) and say that we have data.

Do this by keeping track of when the internal process function was
called because of trigger or because of the end of the cycle. At the end
of the cycle, we can call the trigger_end() but we should not prepare a
new buffer on the output io.
2025-09-18 15:08:24 +02:00
Wim Taymans
06efc8ffb6 pulse-server: clear timer when stream is created
Make a function when the stream is created so that we can clear the
create_tag and the timer.
2025-09-18 14:22:00 +02:00
Wim Taymans
ca713c08ee pulse-server: use the new timer-queue for timeouts
Use the timer queue for scheduling stream and object data timeouts.

This avoids allocating timerfds for these timeouts and the timer queue
can handle many timeouts more efficiently.
2025-09-18 13:55:43 +02:00
Wim Taymans
38cb14d39d timer-queue: add a new timer queue helper
This allows you to schedule timeouts. It keeps a sorted list of
timeouts and uses just 1 timerfd to schedule the head of the timeout
list.
2025-09-18 13:52:51 +02:00
Wim Taymans
361a0de85a pulse-server: make timer function static and fix formatting 2025-09-17 19:18:27 +02:00
Arun Raghavan
cfde4c1b17 pulse: Handle timed out streams
If we don't get a link on a stream, we might never send a create stream
reply. The client handles this fine by timing out after 30s and dropping
the stream, but the server holds on to the pw_stream forever (or until
the client quits).

Let's add a timer to clean up such streams on the server.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4901
2025-09-17 11:48:27 -04:00
Wim Taymans
d5608c07c3 control: unit test for event sort
After some discussions with CLAUDE it made me this unit test, which
I think is ok and actually tests useful things.
2025-09-17 13:42:12 +02:00
Wim Taymans
707bd256b9 systemd: remove RestrictNamespaces from service file
Wireplumber loads the libcamera nodes into the pipewire server.
We need to remove the RestrictNamespaces option from the service file
to allow libcamera to load sandboxed IPA modules.
2025-09-17 10:21:10 +02:00
Wim Taymans
e6bcd7b611 doc: mention async link latency in latency doc 2025-09-16 14:09:08 +02:00
Wim Taymans
6305eada80 impl-port: add port.exclusive flag
Add a port.exclusive flag and inherit the value from the node.exclusive
flag if not otherwise specified.

Make it so that exclusive ports can only be linked once. This is
important for explicit sync where there can be only one producer and one
consumer in order to signal the timeline objects correctly.
2025-09-16 13:41:11 +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
03c5f493dc control: fix event compare function
We can only compare UMP when both types are 2 or 4, so it must be
different from 2 *and* 4 to be rejected.

Fixes #4899
2025-09-16 10:47:12 +02:00
Wim Taymans
af6571d0c7 test: fix assigment and compare error
Fixes #4898
2025-09-16 10:42:44 +02:00
Wim Taymans
336b2dbbc2 modules: remove output latency handling in raop sink
pw_stream now handles the other (output) latency for us, it will keep
the param and report it. If we are not interested in upstream latency we
don't have to parse and store it and we can just be concerned with the
latency we report on our input port (input latency).
2025-09-16 09:29:43 +02:00
Pauli Virtanen
9daf499fff ci: build pages only from master branch
The job on master branch builds pages for all versions at the same time.
It should not be run on branches.
2025-09-15 18:03:33 +00:00
Piotr Drąg
6686d5d1e6 Update Polish translation 2025-09-15 18:02:38 +00:00
Philippe Normand
96ac4ae10d pipewiresrc: Fix caps leak
pwsrc->possible_caps wasn't un-reffed before re-assignment.
2025-09-15 18:01:53 +00:00
Wim Taymans
4dccddd564 impl-link: add 1 quantum latency for async links
Update the scheduling doc with some information about how async
scheduling works. Also add something about the latency.

Async links add 1 quantum of latency so take that into account when
aggregating latencies.

Also a source directly linked to an async node does not add latency
(we evaluate the tee before incrementing the cycle so that it effectively
is executed in the previous cycle and consumed immediately by async
nodes). We can do this because the driver source always provides data
before the async node, and never concurrently.

Add a listener to the link for the node driver change as well because
that can now influence the latency for async nodes.
2025-09-15 17:42:03 +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
09cd7bf783 impl-node: only do unprepare once
There is not reason to do the unprepare logic twice and it might
actually interfere with the actions of the client.

See #4840
Fixes #4893
2025-09-15 10:22:16 +02:00
Wim Taymans
f81bb670c3 Revert "impl-node: improve the node unprepare function"
This reverts commit 2891e579a1.

This seems to cause regresssions with nodes xrun etc.

See #4893
2025-09-15 10:15:07 +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
862ac1f7c8 examples: use BGRA as the format
RGB is not supported by videoconvert.
2025-09-09 16:40:42 +02:00
Wim Taymans
2891e579a1 impl-node: improve the node unprepare function
do_node_unprepare runs in both the server and the client when a node is
stopped. On the server size, set the status to FINISHED and trigger any
targets. This ensures the node will not be scheduled in this cycle
anymore. We have to do this because we can't know if the node is still
alive or not.

When the client receives the stop message, it will unprepare and set the
status to INACTIVE. This ensures the driver will no longer trigger the
node. If the server didn't already trigger the targets, do this in the
remote node then.

This avoid a race where both the client and the server are setting the
status and if the INACTIVE state is set by the server, it might stall
processing of the client.

Fixes #4840
2025-09-09 15:14:36 +02:00
Wim Taymans
d6488c5351 stream: decouple the requested size from scheduling
The docs say that a requested size of 0 can be returned and it means
that there is no suggestion for the size.

Make this so by decoupling the requested size value and the triggering
of the process callback. If we have no rate_match and no quantum
(because the driver didn't set it) we still want to schedule with a 0
requested size.
2025-09-09 15:11:45 +02:00
Wim Taymans
1e5a938e43 adapter: disable rate_match for the video adapter
We don't actually implement this for the video adapter. We should
ideally check for the SPA_IO_RateMatch param to decide this..
2025-09-09 15:10:12 +02:00
Wim Taymans
144c3630ea examples: fix texture updates 2025-09-09 14:29:18 +02:00
Barnabás Pőcze
0b08468035 pipewire: mem: pw_memblock_map(): fix pointer when reusing mapping
Previously the pointer was determined as follows:

  mm->this.ptr = SPA_PTROFF(m->ptr, range.start, void);

however, when `pw_map_range` is calculated, `pw_map_range::start` is the offset
from the beginning of the first page, starting at `pw_map_range::offset`.

This works correctly if `memblock_map()` runs because that will map the file
with expected offset, so using `range.start` is correct.

However, when a mapping is reused (i.e. `memblock_find_mapping()`) finds something,
then `range.start` is not necessarily correct. Consider the following example:

  * page size is 10
  * one memblock with size 20 (2 pages)
  * the applications wants to mappings:
    * (offset=5,size=10)
    * (offset=15,size=5)

After the first request from the application, a `mapping` object is created
that covers the first two pages of the memblock: offset=0 and size=20. During
the second request, the calculated `pw_map_range` is as follows:

  { start = 5, offset = 10, size = 10 }

and the only previously created mapping is reused since (0 <= 5) and (10 <= 20). When
the pointer of the mapping is adjusted afterwards it will be incorrect since `m->ptr`
points to byte 0 on page 0 (instead of byte 0 on page 1 -- that is assumed). Thereforce
the two will unexpectedly overlap.

Fix that by using `offset - m->offset` when adjusting the mapping's pointer. Also move
the `range` variable into a smaller scope because it only makes sense there. And add
a test that check the above previously incorrect case.

Fixes: 2caf81c97c ("mem: improve memory handling")
Fixes #4884
2025-09-08 11:38:42 +00:00
Barnabás Pőcze
93774b1d14 pipewire: mem: log page size on creation 2025-09-08 11:38:42 +00:00
Barnabás Pőcze
9d01a26242 pipewire: mem: forward declare spa_hook
This type is used in function arguments, so forward declare it.
2025-09-08 11:38:42 +00:00
Barnabás Pőcze
91b764faac pipewire-v4l2: support choice sizes
Add support for `SPA_CHOICE_{None,Enum,Step,Range}`. They can all
be naturally mapped to `v4l2_frmsizeenum`.
2025-09-08 11:36:24 +00:00
Barnabás Pőcze
cec0ab322e meson.build: set PW_BUILDDIR in devenv
This is needed by `pw-v4l2`.
2025-09-08 11:36:24 +00:00
Pauli Virtanen
589bc4b6f4 bluez5: iso-io: sync to ISO RX clock, align stream RX in group
Align RX of streams in same ISO group:

- Ensure all streams in ISO group have same target latency also for BAP
  Client

- Determine rate matching to ISO group clock from RX times of all
  streams in the group

- Based on this, compute nominal packet RX times, and feed them to
  decode-buffer instead of the real RX time. This is enough for
  sub-sample level sync.

- Customise buffer overrun handling for ISO so that it drops data to
  arrive exactly at the target, for faster convergence at RX start

The ISO clock matching is done based on kernel-provided packet RX times,
so it has unknown offset from the actual ISO clock, probably a few ms.

Current kernels (6.17) do not provide anything better to use for the
clock matching, and doing it properly appears to be controller
vendor-defined (if possible at all).
2025-09-07 18:26:03 +00:00
Pauli Virtanen
94c354c290 bluez5: decode-buffer: sub-sample accurate fill level tracking
Take resampler delay into account when computing the buffer fill level,
including the fractional part.

If decode-buffer is now fed nominal packet reference times in
write_packet(), it converges the total buffer + resampler latency to the
target at sub-sample accuracy.

This is needed for aligning RX of ISO streams in the same group, so that
e.g. stereo pair alignment is achieved even though the streams have
separate resamplers. Resampler phases get aligned via independent rate
matching.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
e446e3aac5 bluez5: media-source: account for driver clock rate difference in rate match
The rate matching calculations are done in the system clock domain.  If
the driver ticks at a different rate, the correction factor needs to be
adjusted by the rate_diff.

setup_matching() also needs to be before spa_bt_decode_buffer_process():
as follower we should use rate matching value calculated on the
*previous* cycle, because this is what driver is doing when it adjusts
it tick rate.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
f48a72a504 bluez5: smaller max latency for BAP client capture
4 packets should be enough jitter buffer. This matters only for BAP
client, server is controlled by presentation delay.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
7e04f8fe44 bluez5: ensure capture target latency is uniform for an ISO group
All BAP client sources in the ISO group should use same target latency,
so that capture streams stay in sync.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
396d37594c bluez5: media-source: drop all errqueue data when ignoring 2025-09-07 18:26:03 +00:00
Pauli Virtanen
28393cb896 audioconvert: add log topic for resampler 2025-09-07 18:26:03 +00:00
Pauli Virtanen
bf783ab08f alsa: report extra latency for FireWire drivers
Based on testing, ALSA FireWire drivers introduce additional latency
determined by the buffer size.

Report that latency.

Pass device.bus to the node, so it can recognize firewire.
2025-09-07 18:23:31 +00:00
Pauli Virtanen
916896c1cc alsa: force IRQ scheduling for firewire in pro-audio profile
FireWire ALSA driver latency is determined by the buffer size and not the
period. Timer-based scheduling is then not really useful on these devices as
the latency is fixed.

In pro-audio profile, enable IRQ scheduling unconditionally for these
devices, so that controlling the latency works properly.

See #4785
2025-09-07 18:23:31 +00:00
Pauli Virtanen
64aaf8a832 alsa: set minimum period count before automatic period size
Some devices (FireWire) fail to produce audio if period count is < 3,
and also have small buffer size. When quantum is too large, we might
then get too few periods and broken sound.

Set minimum for the period count in ALSA, to determine the maximum
period size we can use. If smaller than what we were going to use, round
down to power-of-2.

See #4785
2025-09-07 18:23:31 +00:00
Barnabás Pőcze
7a98bcf735 spa: libcamera: source: fix typo in log message
';' -> ':'
2025-09-07 18:21:53 +00:00
Barnabás Pőcze
756df7b6ae spa: libcamera: source: remove buffer::ptr
With the removal of `SPA_DATA_MemPtr` support, this member is no longer used.

Fixes: b948ffdb25 ("spa: libcamera: source: remove `SPA_DATA_MemPtr` support")
2025-09-07 18:21:53 +00:00
Barnabás Pőcze
93941e5207 spa: libcamera: source: query frame buffer planes just once 2025-09-07 18:21:53 +00:00
Pauli Virtanen
47780884e1 bluez5: media-source: pass through node.rate and node.latency
Allow user to specify custom values for node.rate and note.latency.

Also restore the 512 default latency.
2025-09-07 18:04:28 +00:00
George Kiagiadakis
e9b78f1c31 bluez5: media-source: add option to control the target latency of the decode-buffer
On production systems, having a constant high latency is favored over
dynamically adjusting it in order to optimize for low latency,
because every time a dynamic adjustment happens, there's a glitch.

This adds an option to let the user specify the exact amount of latency
they want.
2025-09-07 18:04:28 +00:00
George Kiagiadakis
5af8340183 bluez5: media-source: don't set node.latency by default
The hardcoded latency of 512/<rate> is quite low on some ALSA devices.
Instead of forcing that latency onto the graph, just don't set it at all
unless it originates from the BAP presentation delay. That means that
the functionality remains the same for BAP but changes for A2DP to favor
the preferred quantum of the ALSA sink (or whatever is the driver).

Also, avoid setting an empty string ("") latency and rate in the cases
where it's not defined. This allows users to override those properties
through the wireplumber monitor rules if they need to.
2025-09-07 18:04:28 +00:00
Barnabás Pőcze
3b33f60d2f treewide: map SPA_PROP_exposure to V4L2_CID_EXPOSURE_ABSOLUTE
Currently the v4l2 and libcamera plugins map `SPA_PROP_exposure` in incompatible
ways. So change the v4l2 mapping to `V4L2_CID_EXPOSURE_ABSOLUTE` because at least
that is in units of time (a step closer to addressing #4697), and because that
is more relevant for UVC cameras.

Also change the pipewire-v4l2 translation layer.
2025-09-05 17:26:44 +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
0877eba761 tools: add Latency reporting to pw-link
Rework how the monitor mode works. Instead of having separate paths for
the list and monitor mode, reuse the list mode. We simply mark all
changes and then list the changes in a loop.

This makes it possible to accumulate some updates and print them
together.

Add a -t option to list the latency params on a port.
2025-09-03 14:42:23 +02:00
Pauli Virtanen
0f1e4f8706 doc: add more properties missing from docs 2025-09-03 09:34:54 +00:00
Pauli Virtanen
36871ff1ff doc: show tabs on top on doxygen >= 1.13 2025-09-03 09:34:54 +00:00
Pauli Virtanen
bde2aa34ef doc: improve property documentation
Add some more examples, and more xref links to index.
2025-09-03 09:34:54 +00:00
Pauli Virtanen
98b7a34102 doc: support alternative index name in @IDX@ 2025-09-03 09:34:54 +00:00
Wim Taymans
1bf5ca28d8 modules: nmake dynamic ports work in link-factory
Just making a port and adding it to a node does not make it a working
port..

Make a new node function to get a new free port, this will actually call
the implementation spa_node_add_port(), which will add the new port
which we can then pick up and use.

See #4876
2025-09-03 10:38:59 +02:00
Wim Taymans
9f88d6997f audiomixer: set change mask correctly 2025-09-03 10:01:38 +02:00
Wim Taymans
233b7f1d4a audiomixer: format is Id 2025-09-03 10:01:00 +02:00
Wim Taymans
0f6aae914f alsa: don't add MAX_LATENCY when using IRQ scheduling
The Max latency property only works for timer based scheduling so that
we don't select a quantum larger than we can handle in our buffer.

With IRQ based scheduling this does not make sense because we will
reconfigure the buffer completely when we change quantums and so the
currently selected buffer size does not limit the latency in any way.

Fixes #4877
2025-09-02 18:52:38 +02:00
Wim Taymans
9606b37776 alsa: use 3 periods in IRQ mode by default
3 seems to work better as a default for Firewire. It does not actually
add latency because we only keep 1 period filled with data at all times.
2025-09-02 17:29:26 +02:00
Wim Taymans
00bb4a936a filter: removed QUEUED flag and add DEQUEUED flag
Remove the QUEUED flags to check if a buffer is in some queue.

Add a new flag to check if a buffer was dequeued by the application.
Check if the application only queues buffers with the DEQUEUED flag set.
2025-09-02 16:46:03 +02:00
Wim Taymans
b6ce585da6 stream: remove QUEUED buffer flag
The flag was used to see if a buffer was in a queue or not but that
doesn't really matter much and with the DEQUEUED flag we can only move
buffers from dequeued to queued.
2025-09-02 16:37:53 +02:00
Jonas Ådahl
220bdf8a00 pipewire/stream: Don't queue back cleared buffers
When renegotiating stream parameters (e.g. size), the buffers
are cleared should no longer be queued back. Add a flag to detect this,
while logging a warning and erroring out when the user tries to queue
such a buffer.
2025-09-02 14:32:46 +00:00
Wim Taymans
0095d79ef8 alsa: use 2 (or 3 for batch) periods in IRQ mode
Some drivers (Firewire) have a latency depending on the ALSA buffer size
instead of the period size.

In IRQ mode, we can safely use 2 (or 3 for batch devices) periods
because we always need to reconfigure the hardware when we want to
change the period and so we don't need to keep some headroom like we do
for timer based scheduling.

See #4785
2025-09-02 14:13:19 +02:00
Wim Taymans
0d42f11b87 v4l2: delay pipewire init until first openat call
Initialization of PipeWire could happen too early and deadlock in some
cases. Instead, initialize pipewire right before we're going to actually
use it for the first time.

Fixes #4859
2025-09-01 13:33:38 +02:00
James Seo
d46a4686a8 stream: fix comment for requested field of pw_buffer
The requested field was added in 0.3.50, not 0.3.49.
2025-09-01 11:02:36 +00:00
Wim Taymans
370d190572 pulse: improve stream suspended state handling
Only send out SUSPENDED event when there is a change in the suspended
state. This avoids sending out unsuspend events when we simply uncork.

Implement the fail_on_suspend flag for capture and playback streams.
Instead of suspending those streams, we need to kill them.
2025-09-01 12:55:51 +02:00
Wim Taymans
0310bb5c5c audiommixer: only clear mix_ops when initialized
It's possible that the mix_ops was not initialized and then the free
pointer is NULL, so check this instead of segfaulting.
2025-09-01 12:39:08 +02:00
Robert Mader
4796b3fb95 systemd: Allow mincore syscal for Mesa/EGL
This is required in order to allow plugins to use GL as mincore
is used in Mesas `_eglPointerIsDereferenceable()`.

One example for a client wanting to do so is the in-development
libcamera GPUISP, see https://patchwork.libcamera.org/cover/24183/
2025-08-31 09:10:07 +00:00
Wim Taymans
8425307ca1 tools: fix compilation on alpine 2025-08-29 17:59:00 +02:00
Wim Taymans
9eb6cda245 tools: add pw-midi2play and pw-midi2record aliases
And update the documentation.
2025-08-29 17:43:13 +02:00
Wim Taymans
eda3290883 tools: add midi clip support
The SMF2 CLIP format is the official container for storing MIDI 2.0
messages.

Add support in mididump and pw-cat.
2025-08-29 17:34:34 +02:00
Wim Taymans
b192099353 tools: don't generate error when closing read midi file 2025-08-29 17:01:29 +02:00
Wim Taymans
4b177f4557 tools: add guards around header include 2025-08-29 17:00:41 +02:00
Wim Taymans
70ec3aec64 tools: debug utility messages better 2025-08-29 17:00:06 +02:00
Wim Taymans
e2ac91b860 ump: make sure we set the group correctly 2025-08-29 16:59:38 +02:00
Wim Taymans
ddc5c17163 tools: move midievent to separate file 2025-08-28 18:05:36 +02:00
Torkel Niklasson
1ce85ee2ae tools: add -n option to pw-cat
Add sample limit switch -n to pw-cat to stop the recording or playback
after a set number of samples received.

Change-Id: Iaa551db9849acd6acdb6897dbfaa92a21afa1312
2025-08-28 16:04:47 +00:00
Wim Taymans
6c110a3b18 raop: write ALAC end tag
Fixes #4853
2025-08-28 12:17:52 +02:00
Martin Geier
c99311e822 filter-graph: clear external field in unsetup_graph
Without this change the playback with different number of channels
fails with `input port %s[%d]:%s already used as input %d, use mixer`
on the first port.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>

Fixes #4866
2025-08-28 10:15:05 +02:00
Piotr Drąg
a0e27314c6 Update Polish translation 2025-08-27 18:01:47 +02:00
Wim Taymans
2385aa18e1 audioconvert: handle filter-graph setup better
Force filter graph reconfiguration in setup_convert.

When adding/removing filter-graphs, only perform setup when we were
already setup, otherwise we will do this in setup_convert later.

Don't do channelmix_init when we were not setup.

Deactivate the filter-graphs when we suspend.

Fixes #4866
2025-08-27 17:56:14 +02:00
Pauli Virtanen
984c44b044 bluez5: fix BIS source presentation delay
The value comes from QoS preset, not configurable otherwise right now.

Patch from @michael-kong754
2025-08-27 15:55:50 +00:00
alexdlm
b0b6b1fcc5 Map Razer BlackShark v3 ACP 2025-08-27 15:55:02 +00: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
Wim Taymans
e3cc44966b filter-graph: pass void * to connect_port
This makes it a bit more generic and allows us to connect other things
that float arrays.

Add a SPA_FGA_PORT_SEQUENCE as a new port type. The data to connect to
this port is a Sequence type with the size field set to the max/size of
the data.
2025-08-26 13:19:01 +02:00
Wim Taymans
7359491b97 tools: dump sndfile loginfo on error when verbose 2025-08-26 10:59:11 +02:00
Arun Raghavan
28ed09b155 tools: Fix -C handling for pw-dump
The short form needs to have a :: to signal an optional argument so
that something like -Calways can work.
2025-08-25 09:48:47 -04:00
Carlos Rafael Giani
caf72fd9bc module-rtp: Synchronize access to timer_running flag 2025-08-25 10:33:50 +00:00
Carlos Rafael Giani
37e597ff0a module-rtp: Replace "started" boolean with internal state enum
The started boolean is insufficient to fully cover the possible internal
states. For this reason, it needs to be replaced by an enum that covers
these states.

Also, due to potential access by both the dataloop and the mainloop,
access to that internal state needs to be synchronized.

Finally, a variable "internal_state" makes for code that is easier to
read, since it emphasizes that this is state that is fully internal
inside the stream (and is not visible to the rtp-sink and rtp-source
modules for example).
2025-08-25 10:33:50 +00:00
Carlos Rafael Giani
3476e77714 module-rtp: Replace state_changed callbacks
The state_changed callbacks fulfill multiple roles, which is both a problem
regarding separation of concerns and regarding code clarity. De facto,
these callbacks cover error reporting, opening connections, and closing
connection, all in one, depending on a state that is arguably an internal
stream detail. The code in these callbacks tie these internal states to
assumptions that opening/closing callbacks is directly tied to specific
state changes in a common way, which is not always true. For example,
stopping the stream may not _actually_ stop it if a background send timer
is still running.

The notion of a "state_changed" callback is also problematic because the
pw_streams that are used in rtp-sink and rtp-source also have a callback
for state changes, causing confusion.

Solve this by replacing state_changed with three new callbacks:

1. report_error : Used for reporting nonrecoverable errors to the caller.
   Note that currently, no one does such error reporting, but the feature
   does exist, so this callback is introduced to preserve said feature.
2. open_connection : Used for opening a connection. Its optional return
   value informs about success or failure.
3. close_connection : Used for opening a connection. Its optional return
   value informs about success or failure.

Importantly, these callbacks do not export any internal stream state. This
improves encapsulation, and also makes it possible to invoke these
callbacks in situations that may not neatly map to a state change. One
example could be to close the connection as part of a stream_start call
to close any connection(s) left over from a previous run. (Followup commits
will in fact introduce such measures.)
2025-08-25 10:33:50 +00:00
Carlos Rafael Giani
2f22c1d595 module-rtp: Stop any ongoing timer when starting stream 2025-08-25 10:33:50 +00:00
Robert Mader
5f3ae4376e gst: pool: Keep dmabufs mapped
Downstream elements accessing dmabufs from the CPU currently need to map
and unmap buffers on every frame.
While the kernel's page cache avoids most overhead, this still requires a
round-trip through the kernel and possibly non-negligible work in
`dma_buf_mmap()`. Keeping the buffers mapped avoids that without causing
additional syncronization work, as the later should only happen when
`DMA_BUF_IOCTL_SYNC` is triggered in `gst_dmabuf_mem_map()`.

A common scenario where this matters is clients using cameras. The
downstream elements in question may not be aware of dmabufs - e.g.
`videoconvert` - or fail to import the dmabuf and fall back to import
from memory - e.g. `glupload`.

Notes:
 - GstShmAllocator implicitly does this already.
 - We could also do this in the MemFd case, however I'm less convinced
   about the trade-offs.
2025-08-24 13:54:32 +02:00
Robert Mader
95497f8777 gst: pool: Remove last g_slice remnants
It has long been deprecated and just makes the code harder to read.
2025-08-24 13:48:33 +02:00
Arun Raghavan
d991be6a26 doc: Fix Device::Info id field type in protocol documentation 2025-08-22 21:57:57 -04:00
Arun Raghavan
2958692eca doc: Fix some trailing whitespace in protocol.dox 2025-08-22 21:57:15 -04:00
Barnabás Pőcze
882737b077 pipewire: module-link-factory: cancel async work in link's destroy event
When a link enters the "ERROR" state, it is scheduled for destruction in
`module-link-factory.c:link_state_changed()`, which queues `destroy_link()`
to be executed on the context's work queue.

However, if the link is destroyed by means of `pw_impl_link_destroy()`
directly after that, then `link_destroy()` unregisters the associated
`pw_global`'s event hook, resulting in `global_destroy()` not being called
when `pw_impl_link_destroy()` proceeds to call `pw_global_destroy()` some
time later. This causes the scheduled async work to not be cancelled. When
it runs later, it will trigger a use-after-free since the `link_data` object
is directly tied to the `pw_impl_link` object.

For example, if the link is destroyed when the client disconnects:

==259313==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ce753028af0 at pc 0x7f475354a565 bp 0x7ffd71501930 sp 0x7ffd71501920
READ of size 8 at 0x7ce753028af0 thread T0
    #0 0x7f475354a564 in destroy_link ../src/modules/module-link-factory.c:253
    #1 0x7f475575a234 in process_work_queue ../src/pipewire/work-queue.c:67
    #2 0x7b47504e7f24 in source_event_func ../spa/plugins/support/loop.c:1011
    [...]

0x7ce753028af0 is located 1136 bytes inside of 1208-byte region [0x7ce753028680,0x7ce753028b38)
freed by thread T0 here:
    #0 0x7f475631f79d in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:51
    #1 0x7f4755594a44 in pw_impl_link_destroy ../src/pipewire/impl-link.c:1742
    #2 0x7f475569dc11 in do_destroy_link ../src/pipewire/impl-port.c:1386
    #3 0x7f47556a428b in pw_impl_port_for_each_link ../src/pipewire/impl-port.c:1673
    #4 0x7f475569dc3e in pw_impl_port_unlink ../src/pipewire/impl-port.c:1392
    #5 0x7f47556a02d8 in pw_impl_port_destroy ../src/pipewire/impl-port.c:1453
    #6 0x7f4755634f79 in pw_impl_node_destroy ../src/pipewire/impl-node.c:2447
    #7 0x7b474f722ba8 in client_node_resource_destroy ../src/modules/module-client-node/client-node.c:1253
    #8 0x7f47556d7c6c in pw_resource_destroy ../src/pipewire/resource.c:325
    #9 0x7f475545f07d in destroy_resource ../src/pipewire/impl-client.c:627
    #10 0x7f47554550cd in pw_map_for_each ../src/pipewire/map.h:222
    #11 0x7f4755460aa4 in pw_impl_client_destroy ../src/pipewire/impl-client.c:681
    #12 0x7b474fb0658b in handle_client_error ../src/modules/module-protocol-native.c:471
    [...]

Fix this by cancelling the work queue item in `link_destroy()`, which should
always run, regardless of the ordering of events.

Fixes #4691
2025-08-20 23:21:26 +02:00
filmsi
07f36ab580 Updated Slovenian (sl.po) 2025-08-20 14:03:35 +00:00
Wim Taymans
b801527f88 jack: emit port_rename callbacks
When the port is renamed, we queue a PORT_RENAME callback with an arg1
as 1. Before emitting the event we check the registered state of the
port but we want to suppress the event if the port was *not* registered,
ie. when the registered state != 1 (arg1).
2025-08-20 11:39:30 +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
b7412169f5 tools: Use the same -M option as pw-cat to force midi 2025-08-20 10:00:07 +02:00
Wim Taymans
00bb29de0f tools: add -M option to pw-cat and friends
It forces conversion to or from UMP. By default, the events will be
converted to UMP before injecting them into the graph.
2025-08-19 18:34:00 +02: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
Wim Taymans
bf10458604 tools: handle both Midi and UMP when recording
The midifile can handle both UMP and Midi formats when saving so allow
this here.
2025-08-19 18:33:59 +02:00
Wim Taymans
15f3b1f450 tools: add -m options to mididump
The -m option forces conversion to MIDI 1.0 and will then dump the midi
1 events.
2025-08-19 18:33:59 +02:00
Wim Taymans
c0a7c01a35 midifile: fix seeking in midifile
When we perform a seek, we need to update the current position in the
file as well or we calculate wrong offsets.
2025-08-19 18:33:58 +02:00
Wim Taymans
f562394596 alsa-seq: improve debug
Make it easier to change the event debug. Also add some more context
to the event debug.
2025-08-19 18:33:58 +02:00
Jordi Mas
0aff6e0ef0 Update Catalan translation 2025-08-18 11:58:40 +00:00
Wim Taymans
5153dc3362 stream: emit RUNNING state from Start
cd68819feb added code to follow the state
change of the node because at the time it the Start code was async and
it was better to complete it before emitting the state.

9b80855821 however made the Start command
sync again and so we can safely emit the running state in the Start.

The effect is that the Running state change is emitted first and then
the node eventfd is added to the data loop that can then call the process
callback. Having the process callback happen before the RUNNING state
change is unexpected and racy.
2025-08-18 13:40:01 +02:00
Wim Taymans
3643c468e4 impl-port: keep auto-generated port.alias in sync
When the port.alias was auto-generated from the port.name, make sure we
update it when the port.name changes.

See #4851
2025-08-18 11:28:15 +02:00
Wim Taymans
1d437dfb8e global: allow property updated for registered globals
The idea of fd2db174c1 was to allow for
property updates after the global was registered but this check was not
removed to actually make this happen.

Fixes #4851
2025-08-18 11:25:50 +02:00
Robert Mader
e8ae244b2b gst: src: Promote 'set format' log to info
Follow various other elements like glupload and gtk4paintablesink and
print the negotiated caps at a higher priority than debug. A small
quality of life improvement to facilitate debugging.
2025-08-13 22:41:38 +02:00
Barnabás Pőcze
b82160c2e7 spa: libcamera: source: remove stale data from buffers
When clearing the buffers, remove the stale pointers and file descriptors
as accidental reuse of those is problematic and potentially difficult to
diagnose. Do this for every data plane.

Also clear the node's `buffer` structures to remove any references to
the provided `spa_buffer` objects and related metadata.
2025-08-13 17:57:30 +02:00
Barnabás Pőcze
bf327d3dfb spa: libcamera: source: simplify spa_libcamera_clear_buffers()
Remove the unused `impl` parameter and the unnecessary early return.
2025-08-13 17:56:48 +02:00
Barnabás Pőcze
b948ffdb25 spa: libcamera: source: remove SPA_DATA_MemPtr support
The current handling of `SPA_DATA_MemPtr` is not entirely correct because
its handling of multi-planar buffers is not appropriate: it leaks memory
mappings because it overwrites `buffer::ptr` for each plane.

Since this data type should not really be in use in normal deployments,
let's remove it for now.
2025-08-13 17:56:44 +02:00
Barnabás Pőcze
3e28f3e859 spa: libcamera: source: rework startup sequence
After e0e8bf083 ("spa: libcamera: source: create eventfd before starting camera"),
things are still not entirely correct. This change ensures that if starting
the camera fails, then the runtime state, most importantly the ring buffer
of completed requests is restored to its initial state.

Furthermore, it is also ensured that `impl::active` can never be observed
by the data thread while it is being changed, which is achieved by setting
it before/after adding/removing the event source.
2025-08-13 10:24:24 +02:00
Barnabás Pőcze
507688e6c9 spa: libcamera: source: add eventfd to loop while locked
While concurrent `spa_loop_add_source()` invocations work with the current
main epoll-based implementation, this is not guaranteed, so lock the loop.
Similarly to how it is done elsewhere and for removal already.
2025-08-13 10:24:16 +02:00
Barnabás Pőcze
1f60cd291f spa: libcamera: source: keep libcamera::FrameBufferAllocator
Instantiate it once and keep it instead of always dynamically
allocating it when the camera is acquired.
2025-08-13 10:24:05 +02:00
Barnabás Pőcze
c517e712ed spa: libcamera: source: clear buffers when format is changed
pipewire assumes that the buffers are removed from a port when its format is
changed even without an explicit call to `port_use_buffer()`.

So if the format is not just tested, clear the buffers, as well as the libcamera
requests and buffers because they are also recreated when a new format is set.
This matches the behaviour of the v4l2 plugin. Furthermore, this change also
removes the call to `spa_libcamera_use_buffers()` because that function does
nothing. And finally this change necessitates that the current format is always
reset (when not testing), not just before reaching `spa_libcamera_set_format()`.
2025-08-13 10:24:01 +02:00
Barnabás Pőcze
31176120f5 spa: libcamera: source: handle try-only format unset
Do nothing if `format == nullptr` and `SPA_NODE_PARAM_FLAG_TEST_ONLY` is present.
2025-08-13 10:23:57 +02:00
Barnabás Pőcze
a8a60832cd spa: libcamera: source: do not emit param change if try-only
If `SPA_NODE_PARAM_FLAG_TEST_ONLY`, then the format does not change
on the node, it is only tested. So do not emit the param change events.
2025-08-13 10:23:52 +02:00
Barnabás Pőcze
dac9e40be6 spa: libcamera: source: extract presence of SPA_NODE_PARAM_FLAG_TEST_ONLY
Use a boolean named `try_only` instead of checking `flags` each time.
2025-08-13 10:23:46 +02:00
Barnabás Pőcze
05a9e52caf spa: libcamera: source: remove format config shortcut
Remove the code that is supposed to compare the current and the to-be-set
format for returning early if they match. This is removed:

  * v4l2 also does not have it either;
  * it needs more consideration (there are not properly handled fields);
  * it would make later changes somewhat more complicated.
2025-08-13 10:23:42 +02:00
Barnabás Pőcze
25075bb3d7 spa: libcamera: source: set chunk flags on error
Set `SPA_CHUNK_FLAG_CORRUPTED` if the frame buffer metadata
signals anything other than success.
2025-08-13 10:23:36 +02:00
Barnabás Pőcze
019a5c130f spa: libcamera: source: process requests on data loop
Since `impl::requestComplete()` runs in an internal libcamera thread, extra care
would need to be taken to validate all accesses to common data structures. For
example, the function might call `spa_libcamera_buffer_recycle()`, which accesses
`impl::ctrls`, which would be unsafe because it could read or modified at the same
time on the data thread. So move the processing of requests to the data loop.
2025-08-13 10:23:32 +02:00
Barnabás Pőcze
22ddb88072 spa: libcamera: source: process all requests in the ring buffer
It is possible that multiple requests complete before the data loop can run
`libcamera_on_fd_events()`. However, previously only the earliest item was
processed from the ring buffer, meaning that in those cases request processing
could be lagging request completion by multiple requests.

Fix that by getting the number of available requests and processing them all.
2025-08-13 10:23:28 +02:00
Barnabás Pőcze
c01a2977a5 spa: libcamera: source: reset ring buffer when stopping
Presently, the ring buffer of completed requests is only cleared
when the buffers are removed from the port. This is not entirely
correct since pause/start commands do not clear the buffers but
they stop the camera. As a consequence, it is possible that some
completed requests stay in the ring buffer, causing them to be
mistakenly processed when the camera is started next.

So reset the ring buffer after the camera is stopped, the same time
as the queue of free buffers is cleared.
2025-08-13 10:23:22 +02:00
Barnabás Pőcze
72fd462090 spa: libcamera: source: move request completion data to impl
A `libcamera::Request` is directly tied to the camera, not any ports ("streams")
of it. So move the request completion ring buffer into the `impl` struct.

This is a prerequisite for supporting multiple libcamera streams (~ exposing
multiple ports on the node) in the future.
2025-08-13 10:23:17 +02:00
Barnabás Pőcze
099292d63d spa: libcamera: source: store the request pointer in ring buffer
The request will be needed later, so store that directly in the
completion ring buffer for easy access.

This is fine even though `impl::requestComplete()` calls `Request::reuse()`
because only the request cookie is used in `libcamera_on_fd_events()` and
that remains constant during the lifetime of a request object.
2025-08-13 10:23:13 +02:00
Barnabás Pőcze
68627c5563 spa: libcamera: source: remove impl::pendingRequests
The handling of `impl::pendingRequests` is a bit problematic because,
for example, during startup, if `spa_libcamera_buffer_recycle()` observes
that `impl::active == false`, then it will try to append to `impl::pendingRequests`,
which is being iterated in the main thread in `spa_libcamera_stream_on()`.
That is not allowed on an `std::deque`.

So instead remove it altogether, and simply queue all requests when starting.
After `libcamera::Camera::stop()` returns, every request is guaranteed not
to be used by libcamera, and they can be freely reused, so this is safe to do.

This also removes the need for calling `spa_libcamera_buffer_recycle()` when
the buffers are set/unset on a port since that function no longer changes
anything apart from updating `buffer::flags` but `spa_libcamera_alloc_buffers()`
is modified appropriately to take care of that. And in the case of
`spa_libcamera_clear_buffers()` clearing the flag is not required because the
next `spa_libcamera_alloc_buffers()` call will reset reset the flags.
2025-08-13 10:23:09 +02:00
Barnabás Pőcze
475665d615 spa: libcamera: source: persistent requests <-> buffer association
Currently only a single stream is used. This makes it easy to associate
each request with the appropriate frame buffer when it is created. In
turn, this makes reusing requests a bit simpler and a bit more efficient.

So do that: add buffers to requests when they are allocated in `allocBuffers()`.
2025-08-13 10:23:05 +02:00
Barnabás Pőcze
29b0c87d71 spa: libcamera: source: allocBuffers(): more error checking
First, check if the request pool is empty, and signal an error if it
is not. Second, ensure that the number of allocated buffers matches.
2025-08-13 10:23:01 +02:00
Barnabás Pőcze
348e703be0 spa: libcamera: source: allocBuffers(): restore on failure
Undo the allocation and clear the requests if a failure is encountered
in order to leave things in a known state.
2025-08-13 10:22:57 +02:00
Barnabás Pőcze
b9b7c0ab05 spa: libcamera: source: freeBuffers(): call when format is unset
At the moment the libcamera buffer allocation is completely tied to format
negotiation. `freeBuffers()` undoes `allocBuffers()`. And `allocBuffers()`
is called as part of `spa_libcamera_set_format()`. Therefore `freeBuffers()`
should be called independent of the state of the buffers on any port.

Otherwise unsetting the format while there are no buffers on the port will
cause the libcamera requests and buffers not to be released correctly. Similarly,
removing the buffers from a port would clear the libcamera requests and buffers,
making the node unusable without setting a new format.
2025-08-13 10:22:53 +02:00
Barnabás Pőcze
89545946fd spa: libcamera: source: freeBuffers(): split pending request removal
`freeBuffers()` should undo exactly what `allocBuffers()` does. However,
it currently also clears `impl::pendingRequests`, but that is filled
by `spa_libcamera_buffer_recycle()` during `spa_libcamera_alloc_buffers()`.

So remove the clearing of `impl::pendingRequests` from `freeBuffers()` and
move it directly into `spa_libcamera_clear_buffers()`.
2025-08-13 10:22:50 +02:00
Barnabás Pőcze
14e0a8f66f spa: libcamera: source: propagate error when setting format
If `spa_libcamera_set_format()` fails, propagate its return value
as is without rewriting it to `EINVAL`.
2025-08-13 10:22:46 +02:00
Barnabás Pőcze
47ee86938b spa: libcamera: source: port_set_format(): remove goto
Remove the `done` label by moving things into the `format != nullptr` branch.
2025-08-13 10:22:41 +02:00
Barnabás Pőcze
860e455440 spa: libcamera: source: support libcamera::formats::R8
Map `libcamera::formats::R8` to `SPA_VIDEO_FORMAT_GRAY8`.
2025-08-13 09:46:56 +02:00
Sertonix
3914d0cab3 module-jack: fix name of LIBJACK_PATH environment variable
Fixes 0629647cb5 module-jack: load libjack.so.0 with dlopen
2025-08-13 07:15:16 +00:00
Barnabás Pőcze
0fcabdbd0c ci: cross compile on debian 13 to multiple architectures
Debian supports many architectures, and it is relatively easy to work
with multiarch packages, and finally `meson env2mfile` supports
generating cross files with the `--debarch` option.

Previously only native builds were done in the CI, so use debian to
build pipewire for multiple architectures.

Some packages are unfortunately not multiarch compatible, so a separate
container is built for every architecture.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
9438df8d30 Revert "ci: Add an x86 build"
This reverts commit 2042a0483b.
A new approach is added in subsequent commits based on debian
for more architectures.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
fcb318b9c5 pwtest: is_debugger_attached(): rework test
Check if the "TracerPid" field in `/proc/self/status` is non-zero. This does
not need libcap, and does not depend on capabilities, and it also works under
qemu user emulation.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
0d0108e954 test: spa-utils: utils_snprintf_abort_neg_size: remove valgrind check
Death tests are always skipped by the framework when running on valgrind,
so there is no need for the check.
2025-08-13 07:14:33 +00:00
Frédéric Danis
a50b66651e bluez5: backend-native: Add log for call state changes
This also to track each call state changes.
2025-08-12 18:22:40 +03:00
Frédéric Danis
1ad3fdff8a bluez5: backend-native: Free command list queue on RFComm free
When RFComm conection is closed or lost, the pending commands should
be freed, and if a DBus message is attached an error reply should be
sent.
2025-08-12 11:35:02 +02:00
Pauli Virtanen
618d60a1f2 alsa: show correct value in api.alsa.period-num 2025-08-09 12:53:41 +03:00
George Kiagiadakis
22e80e228c bluez5: backend-native: reset hfp_hf_in_progress state on error reply
If a AT+CHLD command fails, we may get stuck in the "in progress" state
forever unless we clear the state here.
2025-08-09 09:24:02 +00:00
Pauli Virtanen
a39462a6c0 bluez5: support 44.1kHz rate for BAP LC3
liblc3 doesn't support 44.1kHz directly, but its authors write one
should just use some nearby rate instead. Do just that.
2025-08-09 11:30:40 +03:00
Wim Taymans
206a30d100 examples: the example generates UMP 2025-08-08 15:10:56 +02:00
Barnabás Pőcze
9aeba05e47 spa: libcamera: source: rework control setting
Instead of applying each control separately, collect them into a
`libcamera::ControlList`, and try to apply them at the end.

Furthermore, instead of doing a blocking loop invoke, use `spa_loop_locked()`
as it is sufficient to update `impl::ctrls`.

After this change control setting works in a more "atomic" way since every
control is parsed and checked before actually reaching the camera. It is
also detected if the given control is not supported by the camera.
2025-08-07 07:59:54 +00:00
Niklas Carlsson
30ba62e47c filter-graph: set NULL data support in LV2
In LV2, a port supports NULL data if the connectionOptional
property is set.
2025-08-06 12:09:13 +02:00
Niklas Carlsson
2ac708d916 filter-graph: add NULL data support per port
It would be good to define NULL support per port in e.g. LV2
plugins where sidechains are usually defined optional.
2025-08-06 12:08:23 +02:00
Carlos Rafael Giani
97a1609b29 module-rtp: Reset ring buffer contents when stream starts 2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
c9a8b8629f module-rtp: Limit actual max buffer size to an integer multiple of stride
Opus and MIDI code get TODOs added, since it is currently unclear how to
implement that fix for them.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
e5be9cce4f module-rtp: Reorder sync checks and resynchronization code
This fixes the case when synchronization is established but actually not
valid anymore. In such a case, the code would _first_ write to the ring
buffer (at the wrong position due to the invalid sync), and _then_ detect
the bogus synchronization. Reorder the code blocks to _first_ check the
current sync, then resynchronize if neeeded (or perform initial sync if
no sync is established yet), and _then_ write to the ring buffer.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
b8d98d03fe module-rtp: Fix timestamp check and add discontinuity check
Until now, the timestamp check was comparing the timestamp delta against
the value of the "quantum" variable. However, the timestamps use clock
samples as units, while the "quantum" variable uses nanoseconds. The
outcome is that this check virtually never returned true. Use the
spa_io_clock duration instead of that quantum nanosecond duration to make
the check actually work.

Also, do not just rely on vast timestamp deltas to detect discontinuities;
instead, check first for the presence of the SPA_IO_CLOCK_FLAG_DISCONT
flag to detect said discontinuities.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
2a460e18e3 module-rtp: Rename timestamp to actual_timestamp for clarity 2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
6c4cd0f1b2 doc: spa: Fix offset in driver documentation 2025-08-05 17:54:56 +00:00
Barnabás Pőcze
e6f767d41d spa: libcamera: source: use dynamic builder for controls
Use a dynamic spa pod builder when enumerating controls since previous
changes can report more information from any given control. Also increase
the stack buffer size to 4096 bytes.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
8673f17c0a spa: libcamera: source: provide value labels if available
For enumerated controls of type `libcamera::ControlTypeInteger32`, libcamera
provides the names of the enumerators, so add them to `SPA_PROP_INFO_labels`.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
e379267274 spa: libcamera: source: handle enum controls better
If the `libcamera::ControlInfo` object explicitly lists the values of a
control, then use those values when adding `SPA_PROP_INFO_type` to
construct an enumerated choice object.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
8d9e469e09 spa: libcamera: source: unify control range logic
If libcamera does not provide a default value, then the average of the
minimum and maximum values is taken. The same logic is duplicated for
`float` and `int32_t`, so move it into a function template.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
e9367443ac spa: libcamera: source: ignore array controls
Properly ignore array controls because they are not supported for now.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
66cc01ee2d spa: libcamera: source: rework bool control type info
`SPA_POD_CHOICE_Bool()` assumes that both true and false are available,
which may not be the case for libcamera controls, so manualy construct
the enumerated choice object and only add the actually available options.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
44c05cfa7b spa: libcamera: source: move control enumeration to loop
Remove the `goto`s and instead move everything into a loop.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
cc187b035b spa: libcamera: source: separate type info generation
Add a new function `control_details_to_pod()` that builds a
`SPA_TYPE_OBJECT_PropInfo` object describing a libcamera control.
2025-08-05 17:51:53 +00:00
Jan Grulich
3c759ae293 Add IWYU annotations
This allows to use clang-include-cleaner tool without <pipewire/foo.h>
headers being automatically added when <pipewire/pipewire.h> is included
instead.

See https://issues.webrtc.org/issues/422940461
2025-08-05 17:51:13 +00: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
c9c7552fed alsa: clear port before adding to free list
If we clear the port after adding, we will destroy the links into the
list and cause crashes later.
2025-08-04 11:02:02 +02:00
Pauli Virtanen
02aee17cc3 test: fix test library path and fix test-functional with ASAN
Set LD_LIBRARY_PATH to have processes spawned by test load the right
library.

Mark openal-info test skipped if ASAN is enabled. The problem is that
openal-info would need LD_PRELOAD to work properly then. Just disable
the test then.
2025-08-04 08:34:02 +00:00
Barnabás Pőcze
58d86cfb5f pw-cli: print pw_core errors
At the moment errors are printed using `pw_log_error()`, however, that does
not display them by default because `client.conf` sets `log.level=0`.

Use `fprintf()` and always print the errors.
2025-08-04 08:28:10 +00:00
Barnabás Pőcze
5ecf27681e pipewire: module-rt: acquire_rt(): return error if thread not found
Instead of implicitly acting on the current thread if the provided thread
handle is unknown, return an error. This behaviour is not depended on inside
pipewire, and if needed, special casing e.g. `thread == NULL` could be added,
but any random `thread` value shouldn't affect the current thread.
2025-08-01 21:42:32 +02:00
Pauli Virtanen
a346a7d42e doc: document more properties
Also add examples for customizing properties.
2025-08-01 16:20:27 +00:00
Wim Taymans
35b3c8c279 vban: truncate sess.name when too large 2025-08-01 18:17:21 +02:00
Barnabás Pőcze
8614fc45f8 spa: libcamera: manager: keep libcamera::CameraManager
At the moment, the camera manager shared pointer is released when the last
listener is removed, and recreated when the first listener is added. This
is the same behaviour that the alsa and v4l2 monitors implement with their
respective udev, inotify monitors.

However, for `libcamera::CameraManager`, this is likely not the best way
for multiple reasons:

  (a) it is a complex object with significant construction and starting cost,
      which includes starting threads and usually loading shared libraries;
  (b) usually one listener is added right after creating, and it is removed
      right before destruction, in which there are real no advantages;
  (c) the camera manager, being a shared resource, might very well be kept
      alive by some other component, in which case there is again not much
      real benefit.

So simplify the code by getting a camera manager reference at the beginning
and keeping it until the libcamera monitor is destroyed.

This also fixes a race condition where a hot-plugged camera might not have
been detected if the libcamera event was emitted between these two:

  collect_existing_devices(impl);
  start_monitor(impl);
2025-08-01 15:54:10 +00:00
Barnabás Pőcze
a36b8a273d spa: libcamera: manager: factor out hotplug event submission
The `impl::{add,remove}Camera` functions do the same thing except
for one value, the type of the hotplug event. Add a private method
to `impl` that implements the common parts.
2025-08-01 15:54:10 +00:00
Barnabás Pőcze
e0e8bf083d spa: libcamera: source: create eventfd before starting camera
An eventfd is used to signal the data loop from the libcamera request
completion event handler. Previously, this eventfd was created and
installed after the camera has been started and requests were queued.

This is problematic because it creates a small time frame where the
libcamera request completion handler will run in a state where the
eventfd is not fully set up.

Fix that by settup up the eventfd before the camera is started.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
49be2a1c52 spa: libcamera: source: generate camera config right away
Currently the plugin uses a single configuration during its entire lifetime.
So generate that configuration during initialization and hold on to it.

This makes the code a bit simpler, and also fixes issues stemming from missed
calls to `spa_libcamera_get_config()` as well as no error checking of
`libcamera::Camera::generateConfiguration()`.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
8c4f60af48 spa: libcamera: source: remove SPA_PROP_device{,Name}
`SPA_PROP_deviceName` is an empty string and setting it does nothing.

`SPA_PROP_device` is always the libcamera identifier of the camera,
and setting it has no effect whatsoever in contrast to other plugins
such as v4l2.

So remove them both for now.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
429c0e03a3 spa: libcamera: source: do not close fd
Currently the plugin does not support importing memory and uses
`libcamera::FrameBufferAllocator` to allocate memory. Every file
descriptor is managed by that object, so they must not be closed
manually.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
c167b98ff2 spa: libcamera: source: remove unused enum_fmt member
This was introduced by b2c38a2b3b ("libcamera: work on rewrite"),
but it has never been used.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
30ce210c2a spa: libcamera: source: prop_id_to_control(): do range check first
If it is a custom spa property, it will not be found in the lookup
table, so we can return immediately.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
07a4e593bb spa: libcamera: source: fix mapping of libcamera::ColorSpace::TransferFunction::Linear
`SPA_VIDEO_TRANSFER_GAMMA10` should be used to represent a
linear transfer function.

Fixes: 7e202a3844 ("spa: libcamera: add colorimetry support")
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
938195b19f spa: libcamera: source: simplify color space conversion
Instead of using an out parameter, just return the `spa_video_colorimetry`
object; and do the libcamera -> spa conversion in a single place, where
the data is actually added to the pod.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
a858290e4b spa: libcamera: source: avoid iterator overrun when enumerating controls
Do not overrun the iterator when skipping the initial couple items.
2025-08-01 15:41:16 +00:00
Barnabás Pőcze
6f058e6b0d spa: examples: local-libcamera: pass camera id to the plugin 2025-08-01 15:40:28 +00:00
Barnabás Pőcze
4e4086934c spa: examples: local-libcamera: do not set SPA_PARAM_Props
Setting `SPA_PROP_device` has no effect, do not do it.
2025-08-01 15:40:28 +00:00
Pauli Virtanen
e8fa7929b7 bluez5: use BT_PKT_SEQNUM for ISO packet sequence numbers
Use kernel BT_PKT_SEQNUM (likely in Linux v6.17) to provide the ISO
packets sequence numbers. Fall back to counting packets if kernel is too
old to support the feature.
2025-08-01 15:39:45 +00:00
George Kiagiadakis
79a069c886 bluez5: backend-native: add debug log in hfp_hf_remove_disconnected_calls() 2025-08-01 15:39:06 +00:00
George Kiagiadakis
5ccd1c5619 bluez5: backend-native: update hfp_hf_in_progress at the end of the CLCC update
When we skip the CIEV event in order to update the call list with CLCC,
we may receive multiple +CLCC events or even none, if the calls are
disconnected. To avoid any mistakes, update the hfp_hf_in_progress flag
after the CLCC update is entirely done.
2025-08-01 15:39:06 +00:00
George Kiagiadakis
e4b0f68e0b bluez5: telephony: implement asynchronous D-Bus calls
This removes the need to call poll() on the rfcomm socket in order
to wait for replies from the AG.

Use a queue to buffer all the commands that are to be sent to the AG
and match them to replies when they are received. Optionally associate
each command with a DBusMessage that is assumed to be a method call
from the telephony interface, which is then replied to when the rfcomm
command reply is received. Also associate each command with a state,
so that it is always deterministic what gets executed after the reply
is received.

On the telephony module, pass on the DBusMessage on the callbacks and
add a method to allow the receiver to send a reply. Only send FAILED
directly when the callback is not handled. Also, remove the return value
from the Dial() command (it was not advertised on the introspection
anyway) to make things easier.
2025-08-01 15:39:06 +00: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
88d7d5706a conf: fix priority of the overrides
A config file with a higher level should override one with a lower
level.

Fixes #4816
2025-08-01 10:49:26 +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
Pauli Virtanen
121608f040 bluez5: allow framing for BAP
There's actually no reason to disable framed qos presets.
2025-07-31 10:58:00 +00:00
Wim Taymans
8495bffee5 modules: use safer pod parsing for control sequence 2025-07-31 11:50:11 +02:00
Wim Taymans
28510f3117 bluez: safely parse the control data from buffers 2025-07-31 11:24:29 +02:00
Wim Taymans
f4ab704948 spa: use safe IO_Control parsing
The IO_Control areas are in shaed memory and need to use the parser to
safely extract the info.
2025-07-31 11:23:30 +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
4715e36a5c spa: don't free the mix_list ports
We can't move the mix_list ports to the free_list like that because the
elements in the list use a different list to link together. Also, we
don't need to free those ports at all because they will be freed when we
move the port_list to the free_list.
2025-07-31 10:20:59 +02:00
Wim Taymans
5743849b50 tools: use safer spa_pod_parser for control events 2025-07-30 19:08:36 +02:00
Wim Taymans
a3da53f66e alsa: fix seq compilation 2025-07-30 18:54:16 +02:00
Wim Taymans
7f7b4be82d alsa: use the safer pod parser for control events 2025-07-30 18:43:34 +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
6d07eaea1f seq: rework port handling
Dynamically allocate ports as we need them.
Use port lists to iterate active ports.
2025-07-30 17:32:02 +02:00
Wim Taymans
8f45cfcbc9 audiomixer: rework the port logic
Use port lists for faster and safer updates of the mixer ports.
2025-07-30 16:49:45 +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
Pauli Virtanen
847982eb0e resample: keep fractional part of in_rate when interpolating
When interpolating with rate correction != 1.0, don't floor the
resulting input rate to the nearest smallest integer.

This allows rate corrections < 1/in_rate to have some effect, and
reduces jumps in the response. One of the jumps is inconveniently
between rate=1.0 and rate=1.0+eps and will cause rate corrections to
oscillate if target rate varies close to 1.0.
2025-07-30 07:59:52 +00:00
Pauli Virtanen
244d5a1cc1 resample: use fixed point for resample phase and input rate
If phase is float, calculations in impl_native_in_len/out_len can
produce wrong results due to rounding error.

It's probably better to not be in the business of predicting
floating-point rounding, so replace this by fixed-point arithmetic.

Also make sure `offset+1` cannot overflow data->filter array in
do_resample_inter* due to float multiplication possibly rounding up.
2025-07-30 07:59:52 +00:00
Pauli Virtanen
3cade43cf3 test-resample: add test for floating point rounding producing bad in_len
If phase is float, calculations in impl_native_in_len/out_len don't
necessarily match with do_resample, because e.g.

    float phase0 = 7999.99;
    float phase = phase0;
    int frac = 8000, out_rate = 8000, n = 64, count = 0;
    for (int j = 0; j < n; ++j) {
        phase += frac;
        if (phase >= out_rate) {
                phase -= out_rate;
                count++;
        }
    }
    printf("count = %d\n", count);      /* count = 64 */

    count = (int)(phase0 + n*frac) / out_rate;
    printf("count = %d\n", count);      /* count = 65 */

don't give the same result.

Also add test where floating point multiplication rounding up to nearest
in

    float ph = phase * pm;
    uint32_t offset = (uint32_t)floorf(ph);

computation results to offset+1 > data->n_phases, accessing filter array
beyond bounds.  (The accessed value is still inside allocated memory
block, but contains unrelated values; the test passes silently.)
2025-07-30 07:59:52 +00:00
Pauli Virtanen
84e8d59782 resample: fix off-by-one in out_len calculation
Fix off-by-one and add test.
2025-07-30 07:59:52 +00:00
Carlos Rafael Giani
91ebfac75b module-rtp: Clear after reading in direct timestamp mode 2025-07-29 17:24:09 +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
3785896533 mixer: rework the control mixers to use the parser
Using the parser for the spa_pod_sequence in the data buffers is
required in order to safely read the pods while there could be
concurrent writes.

See #4822
2025-07-29 15:33:43 +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
e2c291d18e pw-top: reduce flicker when updating
Use wearase() instead of wclear() before redrawing

Fixes #4818
2025-07-29 14:57:04 +02:00
Wim Taymans
56e2d52b65 control: fix fastpath compilation 2025-07-27 17:17:55 +02:00
Wim Taymans
927ab0f4b8 control: improve port handling in control mixer
Use lists to manage the free, allocated and acitve mixer ports. We can
then avoid some checks and make things more threadsafe.
2025-07-27 16:51:52 +02:00
Wim Taymans
1957d3fb00 pulse: avoid a compiler warning 2025-07-25 17:37:56 +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
Wim Taymans
b991e9acc9 pod: check string zero byte only when parsing
The _is_type() macros should simply check the type in the header and if
the size is large enough to look into the type specifics. Further
validation of the values should be done when the value is retrieved.

Following this logic, the String zero byte check should be done in the
get_string() function.
2025-07-25 17:33:46 +02:00
Demi Marie Obenour
9e789c65c2 src: check that POD arrays have the correct size for their type
The parser does not check that POD arrays have the correct size for
their type, so the calling code must do that.

This also enumerates some of the code that cannot handle the size of the
values of an array not being the exact expected size for its type.
There is a lot of it.
2025-07-24 16:27:42 -04:00
Wim Taymans
0f6b365138 pod: don't call deref in reserve bytes
We already know that we could succesfully allocate enough space for the
bytes because we checked that before so simply move to the body of the
new bytes pod. We don't need to do the extensive checks we do in deref.
2025-07-24 18:35:21 +02:00
Wim Taymans
0c33101a42 pod: remove unused function 2025-07-24 18:22:14 +02:00
Wim Taymans
a85c24e9ca builder: support building pod + data + suffix
Add a function that can build a pod from a pod definition, a body data
and a suffix.

We can use this to build strings and bytes and arrays like the other
primitives, which makes it possible to add them to choices or arrays.

Fixes #4588
2025-07-24 16:23:54 +02:00
Wim Taymans
42b779974c module-rtp: don't leak opus codec and ptp_sender
Add a deinit() function and use it to free the opus codec we created in
init().

Also free the ptp_sender when it was created.
2025-07-24 13:16:15 +02:00
Demi Marie Obenour
a09bf57944 meson: Always use -fno-strict-aliasing and -fno-strict-overflow
SPA does not respect the C strict aliasing rules at all, so any code
that uses it must be built with -fno-strict-aliasing.  Furthermore,
there is code in SPA that compares pointers that point to different
objects, so -fno-strict-overflow is also needed.
2025-07-24 07:30:28 +00:00
Carlos Rafael Giani
2bcc8589fa module-rtp: Fix and improve direct timestamp mode and documentation
Direct timestamp mode was incorrectly using over/underrun detection logic
and fill level tracking logic that is actually meant for the other mode
(referred to from now on as "constant latency mode"). Over/underruns are
tracked implicitly in the direct timestamp mode, and the absolute fill
level is not relevant in that mode, since the latency is not needed to
be constant then.

Also improve log lines and the RTP module documentation to define these
buffer modes clearly and explain their differences and use cases.

Opus and MIDI code get TODOs added, since their direct timestamp mode
implementations still may be incorrect. Fixing those will be done in
a separate commit.
2025-07-24 07:28:53 +00:00
Martin Geier
f8b0d0a43c rtp: include stream delay to a read position
When a stream has some delay, a time t1 + delay has to be read in time
t1 to play it when expected.
Decrease target_buffer by delay to start playback sooner, so sound
is played at correct time when delay is applied.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-07-24 07:28:53 +00:00
Carlos Rafael Giani
1ed8f771bd doc: spa: Minor improvements to driver architecture documentation 2025-07-24 07:28:53 +00:00
Barnabás Pőcze
c7838cbbcb spa: node: io: fix typo in documentation
`SPA_IO_RATE_MATCH_ACTIVE` -> `SPA_IO_RATE_MATCH_FLAG_ACTIVE`
2025-07-23 21:26:29 +02:00
Pauli Virtanen
5fa137cc0d meson.build: make spa-json-dump available for subprojects
Add override that provides host binary for subprojects to use.

Also fix cross-compilation to use the host binary.
2025-07-23 12:19:21 +00:00
Wim Taymans
0b0912cc5b resample: optimize phase scaling
Precalculate the constant factor to avoid a division for each sample.
2025-07-23 14:11:11 +02:00
Wim Taymans
b52c490709 resample: fix compilation
Also fix a compiler warning in clang
2025-07-23 12:52:27 +02:00
Wim Taymans
c54d3764b2 stream: update the docs a little
Give some more information about the delay field and how it can be
negative.
2025-07-23 12:46:45 +02:00
Wim Taymans
d2a9141913 resample: avoid calculating GCD in rate updates
We don't actually need to calculate the GCD for each resampler rate
update. The GCD is only used to scale the in/out rates when using the
full resampler and this we can cache and reuse when we did the setup.

The interpolating resampler can work perfectly fine with a GCD of 1 and
so we can just assume that.
2025-07-23 12:23:20 +02:00
Wim Taymans
fcc49ad517 resample: reorder resample function setup
We also don't need to copy the resampler function name with each dynamic
function update, this is just for debugging.
2025-07-23 11:55:49 +02:00
Wim Taymans
685aed1de2 alsa: update resampler requested size before reading
spa_alsa_read is called from the source process function when we are a
follower and no buffer is ready yet.

Part of the rate correction was performed by the ALSA driver when it
woke up but now, the resampler has updated the requested size and we
need to requery it before we can start reading samples.

Otherwise, we end up with requested samples from before the rate update
and we might not give enough samples to the resampler. In that case, the
adapter will call us again and we will again try to produce a buffer
worth of the requested samples, which will xrun.
2025-07-22 16:48:43 +02:00
Niklas Carlsson
fc3a199ca2 filter-graph: fix index off by one in dsp_delay_c
Checking w + 1 > n_buffer means that w will go to n_buffer, which
in turn leads to reading buffer[2 * n_buffer].
2025-07-22 15:44:08 +02:00
Wim Taymans
5b436abef7 pod: improve compare function
Use the area to compare two rectangles. Use the width to break a tie.

This way the sorting is at least a bit more predictable and independent
of the order of the arguments.
2025-07-22 14:19:08 +02:00
Wim Taymans
495d6ba796 pod: remove some size checks
These are already done by the caller.
2025-07-22 14:09:10 +02:00
Wim Taymans
dd9d8038da client-node: close SyncObj fd as well
We also need to close the SynObj fd we got, just like we close any
DmaBuf or MemFd.

Make sure we get a compiler error when we add more items to the
data type enumeration later.

Fixes #4807
2025-07-22 14:00:09 +02:00
Wim Taymans
e91c541446 pod: disable padding when in body
Disable the padding to pod alignment for everything when we are building
the body of an array or choice.

This makes it possible to use bytes or strings or any other pod of a
fixed size as entries in arrays or choice.
2025-07-22 13:58:11 +02:00
Wim Taymans
b904cb14a9 pod: do size check before calling type/size/data functions
Assume that all the functions that take a type/size/data from a pod have
at least the right number of bytes in the data for the given type.
Callers need to ensure this.

Fix the callers of such functions to always make sure they deref a pod
type/size/body into something of at least the min size of the type.
2025-07-22 13:14:17 +02:00
Wim Taymans
0a52f959ac pod: add a function to return the min size of a type 2025-07-22 13:13:05 +02:00
Wim Taymans
a03bbc79fe pod: fix compilation 2025-07-22 12:20:05 +02:00
Demi Marie Obenour
05bd4547d0 pod: parser: avoid unneeded integer division
SPA_POD_CHOICE_N_VALUES involves an integer division, which is slow.
Replace it with subtraction and comparison.

No functional change intended.
2025-07-22 10:19:33 +00:00
Wim Taymans
da1d4fb30c pod: also check choice size before cast
Do a more thorough test of the choice type by not only checking the type
but also if the size is at least large enough to be able to cast it to
the pod_choice type and look at the contents.
2025-07-22 12:14:06 +02:00
Wim Taymans
ed7398a64a pod: use _deref and _frame in safe place
In the filter, don't _deref or use _frame before we are going to add
more pods to the builder. If we are using a dynamic builder, the
dereffed pod might become invalid when the memory is reallocated.

Instead, take the offset of the frame and deref later when we are not
going to add more things.
2025-07-22 10:06:07 +02:00
Wim Taymans
ff7fb675f1 pod: avoid overflow in _frame() 2025-07-22 09:43:50 +02:00
Karl Relton
9189b1d8b7 Add ACP for Logitech 407 USB PC Speaker set 2025-07-21 12:25:26 +00:00
Karl Relton
eac495f0e7 Option of analog or iec958 stereo output, both merging volume switches 2025-07-21 12:19:13 +00:00
Karl Relton
47e8984450 Upload New File 2025-07-21 12:17:40 +00:00
Wim Taymans
36f288f884 pod: require at least 1 choice value in _can_collect()
We can't collect the choice value when there is none so check for the
number of choice values in _can_collect() as well.
2025-07-21 10:14:39 +02:00
Barnabás Pőcze
e6e36c4d34 tests: endpoint: fix valgrind uninit warning
Previously, valgrind was warning that

  Syscall param sendmsg(msg.msg_iov[0]) points to uninitialised byte(s)

this was caused by uninitialized values being serialized for IPC.
Specifically, not all members of the `pw_endpoint_info` struct were
initialized, which caused uninitialized bytes to end up in the IPC
buffers due to the `pw_endpoint_emit_info()` in `endpoint_add_listener()`.

Fix that by initializing the missed `id` and `flags` members.
2025-07-20 18:36:20 +02:00
Wim Taymans
f2fb0b0aa5 alsa: update resample state in all cases
We need to manually recheck the resample state when the matching state
got updated.
2025-07-18 19:20:00 +02:00
Wim Taymans
5fba59b41d mixer-dsp: fix compilation with fastpath debug 2025-07-18 19:19:34 +02:00
Wim Taymans
ce2989891d alsa: init the bw_max value
Otherwise, rate matching doesn't work when it's left to 0.0.
2025-07-18 18:21:18 +02:00
Wim Taymans
5cd7b1de16 mixer-dsp: rework the port management
Keep a list of active ports in the port_list. These are all ports added
with add_port and not yet removed. When a port is removed, move it to
the free_list and reuse the port later when needed.

Update a mix_list of ports when a valid io is set on a port. This then
makes it possible to more efficiently and safely iterate the ports in
the processing loop.
2025-07-18 16:43:22 +02:00
Wim Taymans
ec5d2d2a29 audioconvert: rework the stage recalc a little
Use bits to capture the work that is needed. We clear the bit when
we added the stage, when all bits are cleared we have nothing more to
do. This avoids having to check multiple bookleans.

Make a helper function to calculate the destination buffer. When all
bits are cleared, we can use the output buffer.
2025-07-18 12:10:30 +02:00
Wim Taymans
8babd0bc4e audioconvert: remove unused field 2025-07-18 12:02:28 +02:00
Barnabás Pőcze
f2c878a2c1 meson.build: rework systemd related options
One issues is that the `systemd-{system,user}-service` feature options
do not anything without the `systemd` option. This makes it more
complicated to arrive at the desired build configuration since there
are 3^3 = 27 possible ways to set each of them, but if `systemd=disabled`,
then the other two are just ignored.

Secondly, the `systemd` option also influences whether or not libsystemd
will be used or not. This is not strictly necessary, since the "systemd"
and "libsystemd" pkg-config files might be split, and one might wish to
disable any kind of service file generation, but use libsystemd.

Solve the first issues by using the `systemd-{system,user}-service` options
when looking up the "systemd" dependency for generating service files. This
means that the corresponding option is in full control, no secondary options
are necessary. This means that the "systemd" dependency is looked up potentially
twice, but that should not be a significant issue since meson caches dependecy
lookups.

And solve the second issue by renaming the now unused `systemd` option to
`libsystemd` and using it solely to control whether or not libsystemd will
be used.

Furthermore, the default value of `systemd-user-service` is set to "auto" to
prevent the dependency lookup from failing on non-systemd systemd out of
the box. And the journal tests in "test-support" are extended to return "skip"
if `sd_journal_open()` returns `ENOSYS`, which is needed because "elogind"
ships the systemd pkg-config files and headers.
2025-07-18 09:46:17 +00:00
Carlos Rafael Giani
97996a6e20 module-rtp-sap: Take RTP dest port into account when matching sessions
This is important if several sessions use the same multicast IP address.
2025-07-18 10:54:04 +02:00
Carlos Rafael Giani
c504851dca alsa-compress-offload-sink: Improve write_queued_output_buffers comments 2025-07-18 10:53:59 +02:00
Carlos Rafael Giani
48716a72b1 alsa-compress-offload-sink: Remove unused variable 2025-07-18 10:53:52 +02:00
Carlos Rafael Giani
1c991a329e pw-cat: Use multiple encoded frames if single frames don't fill the quantum 2025-07-18 10:53:43 +02:00
Carlos Rafael Giani
14b242c737 node-driver: Make sure the discont clock flag does not remain set forever
If the timer was canceled, the discont flag needs to be set. But in the
next cycle, unless the timer was canceled again, that flag should not
remain set.
2025-07-18 10:52:13 +02:00
Melvin Manninen
f4f548fbe6 module-rtp-sap: Fix Message Identifier Hash generation for first session and update SDP on grandmaster change 2025-07-17 16:00:32 +00:00
Carlos Rafael Giani
bb022c1b84 node-driver: Handle realtime clock modifications
If the user alters the realtime clock (for example by using the "date"
command in the shell), and the node driver uses the realtime clock as
the timerfd clock, then the scheduled graph cycle invocation may not
take place, or may take place much later than planned, because the
timestamp that was passed to spa_system_timerfd_settime() is now invalid.
Configure the timer to automatically be canceled if the realtime clock
is modified so that the graph cycle can be rescheduled with an updated
timestamp that is actually usable with the altered realtime clock.
2025-07-17 13:13:34 +00:00
Wim Taymans
ece2890c8b meson: remove avutils as a ONNX dependency 2025-07-17 14:08:20 +02:00
Wim Taymans
efa4d31cfb meson: use libonnxruntime so that the .pc file can be found 2025-07-17 14:02:19 +02:00
Wim Taymans
ae226a12b6 CI: trigger rebuild 2025-07-17 13:47:59 +02:00
Wim Taymans
c38dc1cf72 CI: add onnxruntime 2025-07-17 13:29:03 +02:00
Wim Taymans
6605caa39e filter-graph: add ONNX plugin
It uses the onnxruntime library to parse the onnx file and construct a
neural network. It uses the label field to setup the plugin and how to
map the various tensors of the model to input, output, control and
notify ports.

Add an example config for how to use the silero VAD ONNX model with the
noise gate.
2025-07-17 13:16:00 +02:00
Wim Taymans
b3dddfed6a filter-chain: add Level control input port for noisegate
This makes it possible to use another volume measurement algorithm to
drive the noise gate, such as a VAD algorithm.
2025-07-17 12:12:24 +02:00
Wim Taymans
4b37f3db3d filter-graph: move loop out of the NULL check 2025-07-17 12:12:22 +02:00
Carlos Rafael Giani
eb3d14053d doc: spa: Add more docs about SPA_IO_Clock and driver operations 2025-07-16 10:58:48 +02:00
Carlos Rafael Giani
67711e899c audioadapter: Add more log lines 2025-07-16 10:58:48 +02:00
Wim Taymans
328e101f37 alsa: don't try to activate resampling with unknown rates
If the driver or our rate is not known yet, don't assume we will need to
resample.
2025-07-15 15:06:24 +02:00
Wim Taymans
0be61add02 Revert "spa: alsa: Try to get driver rate before setting up matching"
This reverts commit 019b53ace8.

This is a result of a different problem, that the rates are compared
when they are unset.
2025-07-15 14:52:31 +02:00
Wim Taymans
da9bd36cbb spa: return before entering the error branch
In the normal case we should not go into the error path.
2025-07-15 14:51:24 +02:00
Demi Marie Obenour
b8e29d471b module-rtp: Fix bounds checks in MIDI parsing
These are potential security problems.
2025-07-15 10:46:10 +02:00
Demi Marie Obenour
b04da87e38 pod: check that choices are not empty
Before using the contents of a choice, check that it is not empty to
avoid reading out of bounds.
2025-07-15 10:13:18 +02:00
Demi Marie Obenour
d37bdf5cbf pod: check for NULL strings in tag utils
SPA_POD_String allows SPA_TYPE_None PODs and turns them to NULL, so
check for them.
2025-07-15 10:13:18 +02:00
Demi Marie Obenour
edef57f6c3 pod: avoid modulo by 0
a % b is undefined behavior if b is 0.
2025-07-15 10:13:18 +02:00
Demi Marie Obenour
fb315b9050 *: Missing bounds checks in POD handling
There were missing bounds checks for ill-formed POD all over the place.
2025-07-15 10:13:17 +02:00
Demi Marie Obenour
7ac94f1a69 pod: ensure strings are NUL-terminated before calling strlen()
SPA_TYPE_String needs to be NUL-terminated, so check that in
spa_pod_compare_value().
2025-07-15 10:13:17 +02:00
Demi Marie Obenour
5bfc3e6b03 spa: v4l2: avoid integer wraparound to out of bounds read
I'm not sure if untrusted input can reach this point.
2025-07-15 10:13:17 +02:00
Barnabás Pőcze
2c2808fab1 spa: libcamera: manager: fix id allocation
There is an issue in the id allocation mechanism which can result
in the different devices having the same id. Specifically, consider
the scenario where there are only two cameras, which have just been
added. In this case `impl::devices` looks like this:

   (0, camA) | (1, camB) | (?, nullptr) | ...

Now assume that `camA` is removed, after which the array appears
as follows:

  (1, camB) | (1, nullptr) | (?, nullptr) | ...

Then assume that a new camera appears. When `get_free_id()` runs,
when `i == 1`, it will observe that `devices[i].camera == nullptr`,
so it selects `1` as the id. Leading to the following:

  (1, camB) | (1, camC) | (?, nullptr) | ...

This is of course incorrect. The set of ids must be unique. When
wireplumber is faced with this situation it destroys the device
object for `camB` when `camC` is emitted.

Fix this by simply not moving elements in the `devices` array,
leaving everything where it is. In which case the array looks
like this:

  (nullptr) | (camB) | (nullptr) | ... // after `camA` removal
  (camC) | (camB) | (nullptr) | ... // after `camC` appearance

Note that `device::id` is removed, and the id is now derived from
the position in `impl::devices`.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
db3d91ebeb spa: libcamera: use nullptr instead of NULL 2025-07-15 08:12:54 +00:00
Barnabás Pőcze
4fa11619a2 spa: libcamera: use C++ style casts 2025-07-15 08:12:54 +00:00
Barnabás Pőcze
bb8223bff1 spa: libcamera: use anon ns instead of static
Move most things into anonymous namespaces for internal linkage
instead of using `static`. This shortes declarations and makes it
hard to forget.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
cb71071d93 spa: libcamera: device: remove empty line 2025-07-15 08:12:54 +00:00
Barnabás Pőcze
e19a8bb5cd spa: libcamera: source: inline mmap_init()
The function has a single caller is essentially just a wrapper only
calling `mmap_init()`. So inline it into `spa_libcamera_alloc_buffers()`.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
561a9d6ebb spa: libcamera: source: set "corrupted" flag if applicable
If the libcamera `FrameMetadata` reports anything other than `FrameSuccess`,
then set `SPA_META_HEADER_FLAG_CORRUPTED`, notifying the application that
the frame may be unusable.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
0022fc90b7 spa: libcamera: source: use union for transferring control value
Use a union since only one member is active at a time, and use the
proper `libcamera::ControlType` enum to store the type instead of a
bare number. Also remove an unnecessary cast.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
f94f4de6ff spa: libcamera: source: simplify control mapping
Remove the `impl` parameter as it is not used, and use C++ range
based for loops.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
311b3cc37f spa: libcamera: source: do not make expensive queries multiple times
`StreamFormats::pixelformats()` and `StreamFormats::sizes()` both
return newly created `std::vector`s, so do not call them multiple
times.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
489cc49937 spa: libcamera: source: simplify format lookup
Use range based for loops instead of indices.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
0ea7dc9f19 spa: libcamera: source: use enum types
Use the appropriate enum types instead of bare `uint32_t`,
this provides better type safety in C++.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
f53ac8d57c spa: libcamera: source: handle camera acquire failure
Check the return value of `Camera::acquire()` and return the error
if that fails.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
1a1cf55efb spa: libcamera: inline libcamera-utils.cpp
The file is not useful without `libcamera-source.cpp` because it
uses symbols only defined there. And being a non-self-contained
source file, it also breaks clangd. So move its contents directly
to `libcamera-source.cpp`. This makes the file about 2200 lines long,
but I feel that is still manageable (and it is by far not the longest).
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
5a9cdd724f spa: libcamera: clean up includes
Remove some unnecessarily includes.
2025-07-15 08:12:54 +00:00
Barnabás Pőcze
5f4f4b5dd3 spa: libcamera: use lock when acquiring CameraManager
Make `libcamera_manager_acquire()` thread safe by locking a mutex
when the `CameraManager` instance is created and started.
2025-07-15 08:12:54 +00:00
Pauli Virtanen
f073a1a59b ci: add spandsp & liblc3 2025-07-12 19:59:33 +00:00
Pauli Virtanen
cee0c39b00 bluez5: fix decode-buffer buffering threshold
The minimum is the number of requested samples, not duration, which can
be different when resampling.
2025-07-12 19:59:33 +00:00
Pauli Virtanen
ff81fc9f7b bluez5: fix ISO sequence numbering
Pass zero-length packets to the codec. BAP/ISO may use these to indicate
missing data.

Fix A2DP codecs to not parse input with spa_return_val_if_fail, that's
meant for assertions. Just return -EINVAL directly, it's normal that
input data may contain garbage.
2025-07-12 19:59:33 +00:00
Pauli Virtanen
02d5d9bc1f bluez5: sco-io: remove unnecessary variable 2025-07-12 19:59:33 +00:00
Pauli Virtanen
87843366ce bluez5: add PLC for MSBC using spandsp
Use spandsp as optional dependency for MSBC codec, for providing PLC.
2025-07-12 19:59:33 +00:00
Pauli Virtanen
90a1b35017 bluez5: media-source: support codec-provided packet loss concealment
If packet sequence number jumps ahead, or we would underflow, use
codec-provided packet loss concealment to produce some audio data.

When we produce it during underflow, skip the corresponding number of
sequence numbers of future packets.

If codec doesn't have PLC, keep the previous behavior (pad with zeros,
buffering pauses to wait for data).
2025-07-12 19:59:33 +00:00
Pauli Virtanen
d0680a2b3d bluez5: support packet loss concealment in codecs
LC3 and Opus have built-in support for packet loss concealment.

Add codec interface for that, and implement for LC3.

Extend media_codec interface so that packets not aligned with socket
reads can be handled, as in HFP. This is required for correct sequence
number counting, and for being able to run codec PLC *before* decoding
the next correctly received packet.
2025-07-12 19:59:33 +00:00
Pauli Virtanen
a2ede93479 bluez5: report ISO latency correctly and refresh when transport starts 2025-07-12 19:57:22 +00:00
Pauli Virtanen
5e79d0fb01 bluez5: fix compilation and warnings 2025-07-12 19:57:22 +00:00
Pauli Virtanen
d10249d0ce bluez5: allow faster rate matching
Bump up DLL maximum rate difference and reduce averaging time.
2025-07-12 19:57:22 +00:00
Pauli Virtanen
2c70c13cc3 bluez5: rate match ISO only from process()
Update rate matching only once per process(). This ensures all nodes in
the group update their rate matching in the same way.

Also account for audio data in ISO output buffer in the reference time.
2025-07-12 19:57:22 +00:00
Pauli Virtanen
ad90a2d0ac bluez5: take clock rate difference into account in get_reference_time()
The calculations is in system clock domain, so when converting from
samples/duration to time rate difference should be accounted.

This does not have much effect in practice.
2025-07-12 19:57:22 +00:00
Pauli Virtanen
30047f232b bluez5: account for driver clock rate difference in rate matching
The rate matching calculations are done in the system clock domain.  If
the driver ticks at a different rate, the correction factor needs to be
adjusted by the rate_diff.

This fixes ISO streams getting out of sync with each other when target
delay changes. This happens because typically one of them is the driver
and the other follower. Driver adjust clock rate, and follower does its
own adjustment *on top of that* so it rate matches more or less at
double speed.  (The DLL of the follower to some degree corrects for
this, but can't do that when hitting RATE_CTL_DIFF_MAX and moreover it
acts with a delay.)
2025-07-12 19:57:22 +00:00
Pauli Virtanen
ddc023b883 bluez5: media-sink: make ISO target latency scale with quantum
The ISO target latency should scale with graph quantum, as jitter in the
graph processing time probably is proportional to the quantum.
2025-07-12 19:57:22 +00:00
Barnabás Pőcze
90c0d8c225 pipewire: module-rt: use pw_thread_utils_join()
`pw_thread_utils_create()` is used to create the thread, so use
the corresponding `pw_thread_utils_join()` instead of just
`pthread_join()`.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
a55561dcba pipewire: module-rt: destroy mutex and condition variable 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
0923e12fa3 pipewire: module-rt: have just one impl_thread_utils
There are two definitions depending on `#ifdef HAVE_DBUS`,
however, the two definitions are indentical, so remove one.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
b124385fac pipewire: module-rt: remove sched_set_nice()
It has only a single caller, so inline it because
there is not much point in keeping it separate.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
b71d0224db pipewire: module-rt: remove check for impossible condition
Neither `sched_set_nice()` nor `pw_rtkit_make_high_priority()`
(should) ever return a positive number, so that case is not
possible; remove it.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
7a336645fb pipewire: module-rt: get_rtkit_priority_range(): return void
This function cannot fail, so make it return `void`.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
801ac5ced8 pipewire: module-rt: simplify check_rtkit()
The return value is always 0, and the `impl` parameter
is not used, so ues the return value to return the boolean
result instead of an out parameter, and get rid of the
unused argument.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
10161407ff pipewire: module-rt: move RLIMIT_RTTIME compat definition
Move it next to the other macros.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
f0579b9b67 pipewire: module-rt: deduplicate log message 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
c4984e33b2 pipewire: module-rt: use spa_autoptr for properties 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
3b4f37ac92 pipewire: module-rt: fix function brace style 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
7eb98a31bb pipewire: module-rt: define SCHED_RESET_ON_FORK if not available
Instead of using a new macro with the `PW_` prefix, simply define
`SCHED_RESET_ON_FORK` to be `0` when it is not defined; as the
prefixed variant can be a bit confusing.
2025-07-12 19:55:34 +00:00
Barnabás Pőcze
279b7ee698 pipewire: module-rt: use "tid" instead of "pid" for thread ids 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
13fe4a5a57 pipewire: module-rt: use sizeof(variable) instead of sizeof(type) 2025-07-12 19:55:34 +00:00
Barnabás Pőcze
ca47d0ef15 spa: vulkan: map VK_INCOMPLETE to ENOSPC
`VK_INCOMPLETE` means "A return array was too small for the result",
so map it to `ENOSPC` since that describes it better than `EBUSY`.
2025-07-12 19:54:14 +00:00
Barnabás Pőcze
72f1719c95 pipewire: thread: check sched_get_priority_*() return value
The function can report errors, so let's propagate them.
2025-07-12 19:53:45 +00:00
Barnabás Pőcze
d17f68c047 pipewire: thread: impl_join(): return negative error code
`pthread_*` functions return a positive error code, but
a negative one is expected, so negate the return value.
2025-07-12 19:53:45 +00:00
Barnabás Pőcze
331bb2f1ed spa: debug: SPA_TYPE_Id is unsigned
The underlying type of `SPA_TYPE_Id` is `uint32_t`, so access
and print it as such.
2025-07-12 19:52:43 +00:00
Barnabás Pőcze
49d9d5e618 spa: param: video: add missing type info for color params
Add the missing type info for:

  * SPA_FORMAT_VIDEO_colorRange
  * SPA_FORMAT_VIDEO_colorMatrix
  * SPA_FORMAT_VIDEO_transferFunction
  * SPA_FORMAT_VIDEO_colorPrimaries
2025-07-12 21:18:23 +02:00
Arun Raghavan
51d4d5ec3c gst: pipewiresrc: Expose cursor position as a ROI meta 2025-07-11 11:57:59 -04:00
Frédéric Danis
067e29543a bluez5: backend-native: Fix call held hangup
Currently it's not possible to hangup a call place on hold, and
request user to swap calls before been able to hangup.
2025-07-11 10:42:03 +02:00
Wim Taymans
74e576c31a filter-graph: don't pass NULL label around
lv2 does not have a label, make sure we pass "" around like befor
because code does not expect this to be NULL.
2025-07-10 18:10:51 +02:00
Wim Taymans
a188f1d29f pod: remove alignment checks
We currently often create pods in a uint8_t buffer, which is not aligned
to 8 and might cause deref and other problems.

We should either align the buffer we write into or maybe make the
builder add some padding before the buffer to align it. We have to be
careful with that when we assume the buffer start is the beginning of
the pod..

Fixes #4794
2025-07-10 16:56:26 +02:00
Wim Taymans
20a4aa8cf9 modules: remove v0 protocol support 2025-07-10 16:26:01 +02:00
Pauli Virtanen
ae7a893ce9 bluez5: aac: fix for A2DP v1.4 using rfa bits for more channels
A2DP v1.4 uses the rfa bits for adding 5.1 and 7.1 configurations.
Clear those bits properly when sending configuration, in case remote
device sets them.
2025-07-10 14:12:15 +00:00
Robert Mader
7e202a3844 spa: libcamera: add colorimetry support
Libcamera equivalent to 41b831d0f ("spa: v4l2: add colorimetry support")
2025-07-10 14:11:41 +00:00
Demi Marie Obenour
c54fdb76f8 protocol-native: check for NULL strings
SPA_POD_String allows NULL strings, so check for them.
2025-07-10 14:08:56 +00:00
Demi Marie Obenour
adb3a55703 protocl-native: v0: Fix integer overflow to buffer overflow
Too many dict items could cause an integer overflow leading to a
stack-based buffer overflow.
2025-07-10 14:08:15 +00:00
Demi Marie Obenour
9a66938283 pulse: don't ignore return value
If a function can fail don't pretend it succeeded.
2025-07-10 14:06:05 +00:00
Demi Marie Obenour
3c3ead2784 gst: whitespace fix
No functional change.
2025-07-10 14:05:23 +00:00
Demi Marie Obenour
32b8e5f500 src: use correct format string for uint32_t
<inttypes.h> provides the correct and portable format string to be used.
2025-07-10 14:03:44 +00:00
Demi Marie Obenour
b3bf5be1f6 *: Avoid macros that use casts where possible
Use direct field access when the type is known, instead of a macro that
includes a cast.

These were missed in e4fcbef89a.
2025-07-10 14:02:55 +00:00
Barnabás Pőcze
5cf84fa3fe spa: debug: pod: print custom properties with more detail
Previously, custom object properties were printed as "unknown",
and the offset (wrt. `SPA_PROP_START_CUSTOM`) was not displayed.
A custom property is distinct from an "unknown" one. Being able
to quickly differentiate the two is useful. Furthermore, knowing
the custom property id (i.e. the actual numeric id minus
`SPA_PROP_START_CUSTOM`) is also very helpful.

To address the above, print a custom property (i.e. anything with
an id at least `SPA_PROP_START_CUSTOM`) as follows:

  Spa:Pod:Object:Param:Props:Custom:123

where the last component is the custom property id.
2025-07-10 14:01:50 +00:00
Barnabás Pőcze
4a92ec35a6 spa: debug: pod: use the appropriate format specifiers
Use the appropriate format specifiers wrt. the signedness of the type,
as well as use the `PRI*N` macros for the `[u]intN_t` types.
2025-07-10 14:01:50 +00:00
Wim Taymans
b4f97c62c6 filter-graph: support more complicated labels
If we see a container as the label, copy the whole container and use
that as the label.

The label is used to construct a plugin description.
2025-07-10 13:47:29 +02:00
Wim Taymans
5ca74996f0 filter-graph: allow setting a fixed rate
It's possible to make the filter streams resample to a specific rate
before running the graph.
2025-07-10 13:47:23 +02:00
Arun Raghavan
eec1ac20b7 spa: aec: webrtc: Expose echo canceller mobile_mode
Significantly better CPU performance in lieu of canceller quality. Not
implemented for 0.x series, as there's a lot more to enable there (such
as routing modes), and I am hoping to drop support for those versions
before too long.
2025-07-09 13:02:18 -04:00
Arun Raghavan
477674740e spa: aec: webrtc: Drop outdated comment
The Intelligibility enhancer was removed, so the FIXMEs are irrelevant.
2025-07-09 12:48:24 -04:00
Arun Raghavan
a328e0ae28 spa: audioconvert: Avoid reading past filter-graph param name end
Ensure we have at least a `.` after `audioconvert.filter-graph`, so we
don't try to read past the end if it does not exist.

Also document in the param name that an index is expected.
2025-07-09 15:20:09 +00:00
Arun Raghavan
8f429ac04b spa: aec: webrtc: Actually enable echo cancellation for 2.0 2025-07-09 08:54:36 -04:00
Wim Taymans
e8dbd328d8 doc: fix a typo 2025-07-09 14:13:56 +02:00
Wim Taymans
241147968e doc: add FOSDEM talk 2025-07-09 14:13:34 +02:00
Jonas Holmberg
85ff73d690 echo-cancel: reset buffers when deactivating
Reset buffers when deactivating to avoid having old data in the
ringbuffers, which also adds latency when activated again.

Clear sink_ready and capture_ready when resetting buffers to avoid
calling process() before there is new data to process.
2025-07-09 10:20:51 +02:00
Wim Taymans
0efd0258a7 filter-graph: rename the plugin files
Move the plugin prefix to the front like everywhere else and this also
makes it easier to spot the plugins when listing the directory.
2025-07-08 16:18:13 +02:00
Robert Mader
9debb4b814 gst: pipewireformat: Validate fourcc before converting to string
gst_video_dma_drm_fourcc_to_string() asserts when called with
DRM_FORMAT_INVALID.
2025-07-08 11:38:28 +00:00
Frédéric Danis
80d44e8f39 bluez5: backend-native: Fix incorrect dial number management
When dialing an incorrect phone number some phones (e.g. iOS 18.5)
replies with OK but never send +CIEV updates, so there's no way to
know that the dial is not in progress and the call object should be
removed.

This change waits for +CIEV event to create the call object.
2025-07-08 11:37:45 +00:00
Albert Sjolund
2581575bd1 gst: fix leak in sink_update_params
buffer_pool_get_config returns a copy of the config structure, but it is
never freed in this function. Add a gst_structure_free to fix the leak
2025-07-08 13:07:44 +02:00
Wim Taymans
d3eb06ab74 pod: improve array copy function
Make a new function to also returnt he child size and type.

Make a new function that accepts the array item size. Check that the
array item size and destination item size match before memcpy the array
contents. This avoids overflowing the target array with a malformed
array pod.
2025-07-08 10:11:11 +02:00
Wim Taymans
ce2f9eebb4 pod: avoid checking size or alignment
For the embedded children, they will always be aligned. We can also
avoid the max size checks for children because this is already checked
for the parent and with the remaining size check.

For arrays and choice we simply don't get any elements in the array when
the sizes are too large.
2025-07-08 10:06:51 +02:00
Wim Taymans
289b33281f pod: check size before getting pod contents
Before accessing the pod contents, check if the size is at least what we
expect it to be or else we might read out of bounds.
2025-07-07 19:40:24 +02:00
Julien Massot
8aa836d588 alsa-pcm: add support for api.alsa.dll-bandwidth-max
In USB Audio Class 2 (UAC2) setups, pitch control is handled by
feedback endpoints. The host adjusts its data rate accordingly.

When pitch control is active (pitch_elem), applying the default
delay-locked loop (DLL) bandwidth can lead to instability and
oscillations around the target rate.

This patch adds a new parameter, api.alsa.dll-bandwidth-max, to
configure the maximum DLL bandwidth. It introduces a new field
in the ALSA state to store this value.

By default, it uses SPA_DLL_BW_MAX, but when pitch control is in
use, setting it to a lower value (e.g. 0.02) helps ensure better
stability, based on empirical testing.
2025-07-07 10:40:11 +00:00
Wim Taymans
deb7dddbef test: format float values with .
Depending on the locale, the decimal separator can be , or .
We need it to be . in all cases or else the checks for the expected
value might fail.
2025-07-07 12:09:55 +02:00
Wim Taymans
5f4b4b02f9 pod: remove the ALIGNED from the pod struct
We don't really want to do this here otherwise structs that include a
pod will be padded so that an array of those structs will be aligned.

This makes a test case fail where we have a struct with a choice_body
followed by 3 uint32_t enum values. The size with and without the
aligned attribute is different.
2025-07-07 12:07:05 +02:00
Wim Taymans
a0f5c4153f builder: avoid oveflow 2025-07-07 10:38:56 +02:00
Wim Taymans
8554c9d02a pod: enforce max pod size
Set a max pod size and add some more over and underflow checks
2025-07-07 10:38:56 +02:00
Wim Taymans
2011474936 pod: improve type checks some more 2025-07-07 10:38:56 +02:00
Demi Marie Obenour
e4fcbef89a pod: Improve type-safety in SPA POD code
Use direct field access when the type is known, instead of a macro that
includes a cast.
2025-07-07 10:38:56 +02:00
Wim Taymans
aa2289a25b pod: check pod alignment
Make a SPA_POD_ALIGN = 8 and make sure all pods are aligned to it. Use
the new constant to pad and check alignment. Make some new macros to
check for the pod type, alignment and minimal size.
2025-07-07 10:38:56 +02:00
Wim Taymans
b75ed93e51 pod: improve spa_pod_from_data()
spa_pod_from_data() is now safe against integer overflow.
2025-07-07 10:38:56 +02:00
Jonas Holmberg
a0beb30ba8 echo-cancel: drop if playback is not streaming
capture and sink streams may start before playback stream so process()
may fail to dequeue a playback buffer. In that case advance the read
pointers to avoid building up latency in the ringbuffers.
2025-07-03 19:02:59 +00:00
Arun Raghavan
019b53ace8 spa: alsa: Try to get driver rate before setting up matching
In some cases, it is possible that the follower shares a clock with the
driver, but the driver rate is not known when the follower is assigned
to the driver. If this happens, then state->driver_rate is 0, and when
setting the format, we might think that we need to resample (because
follower rate != driver rate). This can cause us to incorrectly halve
the period size for the node.

This was introduced in commit 0b67c10a9c,
which forces reevaluation of matching status on driver change.

To avoid this, let us also probe for the driver rate when updating the
matching status, so we can make the update more accurate.
2025-07-03 19:02:02 +00:00
Wim Taymans
ef5d9ff028 filter-graph: add a simple noise gate 2025-07-03 20:58:00 +02:00
Wim Taymans
616db9809e module-rtp: add some rate limit to send/recv errors 2025-07-03 20:57:49 +02:00
Wim Taymans
47ee9ef10a module-rtp: set the EMPTY flag on empty buffers
And make sure other flags are reset.
2025-07-03 20:57:19 +02:00
Arun Raghavan
70aaec0ac4 spa: v4l2: Drop unused variable
Fixes warning:

[186/359] Compiling C object spa/plugins/v4l2/libspa-v4l2.so.p/v4l2-source.c.o
In file included from ../spa/plugins/v4l2/v4l2-source.c:164:
../spa/plugins/v4l2/v4l2-utils.c: In function ‘spa_v4l2_enum_format’:
../spa/plugins/v4l2/v4l2-utils.c:1103:22: warning: unused variable ‘drop_next’ [-Wunused-variable]
 1103 |                 bool drop_next = false;
      |                      ^~~~~~~~~
2025-07-03 10:07:54 -04:00
Julian Bouzas
a8b9ce2050 alsa: add option to disable pro-audio profiles
Some devices might have nonfunctional 'Pro Audio' sound. This patch adds a
new 'api.acp.disable-pro-audio' option to disable pro-audio profile entirely.
2025-07-02 08:11:48 -04:00
Wim Taymans
653e1578a1 audioconvert: use faster clear when dealing with empty buffers
When we are converting an empty buffer, use the more efficient
clear function.
2025-07-02 10:34:00 +02:00
Wim Taymans
0817001728 audioconvert: add clear function
Sets all samples to 0 in the target format.
2025-07-02 10:27:26 +02:00
Wim Taymans
3ff0c270dd echo-cancel: send capture/source latency correctly
Input latency received on the source (output stream) should be
propagated on the input stream (capture).
2025-06-30 15:48:20 +02:00
Wim Taymans
f93b3b23a3 loop: fix use after free case
Because we can now destroy sources (and free the source structure) by
simply holding the lock, there is a window where we might access the
freed source.

When we in iterate release the lock and go into the epoll, another
thread might acquire the lock and delete the fd from epoll. This might
happen right after epoll detected activity on the fd. When iterate
manages to acquire the lock again, it will process to dispatch the
active fd and deref the ep.data pointer, which is now pointing to freed
memory.

Fix this by incrementing a removed_count whenever we remove a source.
Check the counter if it was the same as before the epoll otherwise we
can't assume all sources are alive still. Return in that case as if
there were no fds to poll. The caller should reenter the iterate at some
point and we will return all the fds with activity, minus the one that
got destroyed. We need to give control to the caller because part of the
removal could be to stop the loop iteration all together.
2025-06-30 12:44:15 +02:00
Sam James
e9a0ac1346 spa: allow disabling deps via -Debur128/-Dudev
With .enabled(), Meson doesn't have some magic that packagers rely on
to explicitly disable finding a dependency if an option is off. Drop
the unnecessary .enabled() accordingly.
2025-06-28 07:55:54 +00:00
Sam James
69eaa6d098
ci: add fftw 2025-06-28 08:23:59 +01:00
Sam James
64b7a8990e
meson: add fftw option
Packagers need to have a way to control whether a dependency is used
even if it's installed/available.
2025-06-28 02:59:03 +01:00
Michael Olbrich
a77c1cbd0b gst: pipewireformat: enforce DMA_DRM when possible
with memory:DMABuf, DMA_DRM should be used as 'format'. So only add
formats to 'format' if there is no equivalent drm format.
2025-06-27 12:57:40 +00:00
Michael Olbrich
7795e06563 gst: add colorimetry support 2025-06-27 12:57:01 +00:00
Michael Olbrich
41b831d0f8 spa: v4l2: add colorimetry support 2025-06-27 12:57:01 +00:00
Michael Olbrich
6294cbeb68 spa: add helper to determine if a video format is RGB 2025-06-27 12:57:01 +00:00
Michael Olbrich
20cdc9155f spa: video/color: add some more transfer functions and color primaries 2025-06-27 12:57:01 +00:00
Michael Olbrich
4c5e3f9015 spa: video/color: drop 'since' comments
These are GStreamer versions that make no sense here.
2025-06-27 12:57:01 +00:00
Wim Taymans
9a6f8d31dc loop: unlock the lock when blocking on invoke
When we are the owners of the loop lock and we are not in the loop
thread itself, release all locks so that the loop can start processing
our invoke items and we get a chance to make progress. After that
re-acquire the locks.

This can happen when you change some of the core loop_locked() calls to
blocking _invoke functions that are called with the loop locked.

We have all core blocking invoke functions removed now so this is not
actually going to be used but just in case an application tries to
blocking invoke while locking the loop, this will now at least do
something else than deadlock.
2025-06-26 14:23:36 +02:00
Michael Olbrich
17c755714d v4l2: allow negotiation with modifier
This assumes that the modifier is always 'linear'. That is not quite
correct for all V4L2 formats. But PipeWire only uses input devices and
other modifiers are very unlikely.

This makes it possible to use DMABUFs with the GStreamer pipewiresrc.
2025-06-26 09:21:00 +00:00
Harald Sitter
1541ce3368 Revert "alsa: add Teufel Cage Pro mapping"
This reverts commit b57b87abbb.

It turns out this device is subtily different and doesn't work with the
current profile configurations. A UCM profile was added to alsa-ucm-conf
instead.
2025-06-26 09:19:09 +00:00
Wim Taymans
c045767252 stream: improve drain
Make sure we safely stop draining the stream by using the loop lock.

Always stop draining when we change the state of the stream.
The idea is that you either wait for the drain signal or cancel the
pending drain early with a new set_active() call.
2025-06-25 13:07:16 +02:00
Wim Taymans
a9cece3c2e audioconvert: remove unused field 2025-06-25 10:37:56 +02:00
Wim Taymans
dd6c9de604 tests: set the flags on buffers correctly 2025-06-25 10:34:50 +02:00
Wim Taymans
8a09bacdf6 audioconvert: map buffers with right prot 2025-06-25 10:31:39 +02:00
Wim Taymans
bd7ce5c7fa pulse-server: only react to state changes when not corked
When we are starting or corked we don't emit suspend/resume caused
by state changes.
2025-06-25 10:31:32 +02:00
Wim Taymans
bcb9ff20fd audioconvert: mark output as not empty when draining
When we are draining, we use an empty input buffer but then we push out the
remaining samples out of filters and we can't assume they are empty.
2025-06-25 10:31:24 +02:00
Wim Taymans
d093402d97 filter-graph: compare with float to avoid conversion 2025-06-24 13:46:30 +02:00
Wim Taymans
fa52a596f4 audioconvert: undef the right function 2025-06-24 13:46:08 +02:00
Wim Taymans
5c8e1ab7b6 jack: only update port name for other ports
Don't try to check for renames of our own port, we cause that
ourselves.

Also use the name of the port to find our ports.
2025-06-24 13:44:53 +02:00
yay me
b2edefbc4c po: Add Arabic translation 2025-06-24 07:00:17 -04:00
Elliot Chen
43441a4d69 pipewiresrc: fix sending last buffer failure if waiting operation exits in advance 2025-06-23 16:16:13 +00:00
Wim Taymans
4b236f8274 stream: fix a typo 2025-06-23 11:34:43 +02:00
Arun Raghavan
220b037683 pulse-server: Implement stream suspended callback 2025-06-23 09:19:10 +00:00
Wim Taymans
fd2db174c1 pipewire: update global properties
When the properties of an object change, update the properties on the
global as well. There is no way to notify clients of a changed global
but they are supposed to listen to the object specific events for that.
The global properties are meant to be a snapshot at the time of
enumerating the registry and can change later.
2025-06-23 10:42:47 +02:00
Pauli Virtanen
7fd05e7eaa bluez5: drop old SCO fragment data when sink starts
Any pending SCO fragment data should be cleared when sink starts, so
that we don't send out any old data.
2025-06-21 16:13:57 +03:00
Pauli Virtanen
665a27f281 bluez5: replace sco-source with media-source
Change media-source to use sco-io for HFP codecs.

Replace sco-source with media-source.

sco-source is mostly copypaste from media-source, only differed in the
IO handling.
2025-06-21 16:08:30 +03:00
Pauli Virtanen
5b4e9dc33e bluez5: replace sco-sink with media-sink
Change media-sink to use sco-io for HFP codecs.

Move SCO fragmentation to sco-io side.

Replace sco-sink with media-sink.

sco-sink is mostly copypaste from media-sink, and only differed in the
fragmentation detail, which can as well be handled on sco-io side.
2025-06-21 16:08:30 +03:00
Pauli Virtanen
f9b0bf3f95 bluez5: limit CVSD block size
Don't try to write data in too large blocks.

This controls the maximum amount of data to send at once. sco-io will
buffer and fragment packets to the right size.

Previously in sco-sink, SO_SNDBUF was not set, so there could be a
longer queue in the socket.
2025-06-21 16:08:30 +03:00
Wim Taymans
2f74789a92 jack: support port_rename callbacks
Look at the port name in the port_info properties and emit the
port_rename callback when it changes.

Fixes #4761
2025-06-20 16:28:26 +02:00
Wim Taymans
f3ff25c936 alsa: don't log unknown events with info
Debug is good enough
2025-06-20 15:49:17 +02:00
Pauli Virtanen
b91864eb37 bluez5: don't crash on codecs without caps_preference_cmp
E.g. LDAC doesn't have that. Add the missing guard that was accidentally
dropped in the rewrite.

Also explicitly filter out non-A2DP/BAP codecs that can't be used in
ensure_media_codec
2025-06-19 12:03:13 +00:00
Wim Taymans
cad0523617 audioconvert: refactor volume ramping
We don't actually have to store the ramp parameters so allocate them on
the stack and then use them to generate the sequence.

Make it possible to generate a sequence into a custom buffer as well.

Make sure we use the right rate (the graph rate) to calculate the number
of samples when converting from time to samples.
2025-06-19 11:16:34 +02:00
Wim Taymans
8047a37b02 spa: remove control type from formats
We just want to negotiate the control stream, we don't really care
about what is in the control stream.
2025-06-18 15:23:16 +02:00
Wim Taymans
2e18d5f70c doc: update pw-cli man page
Fixes #4744
2025-06-18 15:18:09 +02:00
Wim Taymans
343509abdf pw-cli: add type info to variables
Add type info to variables. This way we can avoid doing things on
variables of the wrong type.

Add a list-vars command to list the currently registered variables and
their type.

Fixes #4746
2025-06-18 15:02:20 +02:00
Wim Taymans
b51755bc8b pulse-server: add stream_properties for RTP streams 2025-06-18 12:29:39 +02:00
Wim Taymans
54923bf5bd alsa: remove UMP negotiation constraint
Otherwise we won't be able to negotiate with a port that only wants old
style midi.

Instead just negotiate the control link, conversion to old style midi
will be done in the control mixer for the old client.

Fixes #4759
2025-06-18 10:10:10 +02:00
Wim Taymans
7ce9b0daec spa-json-dump: fix compilation 2025-06-17 18:08:36 +02:00
Wim Taymans
b67226fa0c spa-json-dump: add -i and -s options
Add -i option to change the indentation
Add -s option to generate simplified SPA JSON
2025-06-17 17:27:10 +02:00
Wim Taymans
a6199c92a4 filter-graph: make sure strdupa is defined
Fixes #4756
2025-06-17 15:17:47 +02:00
Harald Sitter
b57b87abbb alsa: add Teufel Cage Pro mapping 2025-06-17 11:33:38 +00:00
Wim Taymans
f2905c74ed alsa-udev: support alsa.use-ucm
Make a new alsa.use-ucm option that sets api.alsa.use-ucm on the device
it creates (when set).

There is some documentation floating around (thr arch wiki) with this
property.

See #4755
2025-06-17 12:54:39 +02:00
Wim Taymans
58aab3e16b pw-dump: add -i and -s options
-i can be used to configure the indentation (default 2)
-s can be used to output simplified SPA JSON
2025-06-17 11:01:28 +02:00
Wim Taymans
953b0f81ad filter-graph: make sure M_PIf is defined 2025-06-17 09:25:54 +02:00
Wim Taymans
0b2b723a0e filter-graph: add a zeroramp plugin
The filter detects unnatural gaps (consisting of 0.0 values) and will
ramp-down or ramp-up the volume when entering/leaving those gaps.

This makes it filter out the pops and clicks you typically get when
pausing and resuming a stream.

See #4745
2025-06-17 09:14:18 +02:00
Frédéric Danis
75b4c3379d bluez5: hfp-hf: If available use AT+CLCC only to update calls state 2025-06-16 09:17:21 +02:00
Frédéric Danis
2cb678edb3 bluez5: hfp-hf: Remove disconnected calls from call list
After AT+CLCC command completion, the calls which has not been listed
should be removed.
This list the calls returned by AT+CLCC to be able to find the ones which
has not been listed but still in the call_list.
2025-06-16 09:17:20 +02:00
Frédéric Danis
931b6d9ad8 bluez5: hfp-hf: Fix condition for hfp_hf_swap_calls
AT+CHLD=2 can be called even if there is no active call, the only
condition is to have at least one held call.
2025-06-16 09:10:50 +02:00
Pauli Virtanen
3922247356 bluez5: sco-source: pass read mtu to codec 2025-06-15 14:35:32 +03:00
Pauli Virtanen
b869305282 bluez5: fix CVSD decode()
"Decoding" in CVSD should just copy bytes, packets may be any size.
2025-06-15 14:20:39 +03:00
Pauli Virtanen
dc618d37c6 modules: fix missing free/close and length checks
Fix some missing free and close.

Fix not checking length of received netjack data.
2025-06-14 15:24:05 +03:00
Pauli Virtanen
baadda3b67 tools: fix some missing free/close 2025-06-14 15:21:29 +03:00
Pauli Virtanen
3539374ba7 spa: alsa: fix some coverity warnings
NULL checks.

Change pa_x* malloc functions act like the pulseaudio ones: assert on
failure, as code assumes that.
2025-06-14 14:38:26 +03:00
Pauli Virtanen
7f2bdab8ea bluez5: fix some coverity issues
Missing null pointer checks, wrong array indices, uninitialized/unused
variables.
2025-06-14 14:34:55 +03:00
Pauli Virtanen
26b09b0ee3 bluez5: temporarily remove BAP nodes when another device is switching
Unicast BAP codec switch requires CIG reconfiguration, which cannot be
done if there is an acquired transport.

When doing BAP codec switch, disable nodes of other devices sharing the
same CIG.

To avoid problems with node start/stop, just remove and re-add them.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
3ed969144a bluez5: bap: prefer 32 kHz in/out for duplex configuration
I'm not aware of any devices that support 48 kHz output in duplex
configuration, so disable that for now.

Doing this properly requires catching errors when on transport Acquire,
and switching to another configuration if the error was due to bad
configuration.

Due to how BAP specification works, it's not necessarily possible to
know whether a configuration was really accepted at earlier stage, and
anyway there's no proper error -> reconfiguration handling currently on
BlueZ side either.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
209820bab8 bluez5: add separate BAP sink/source/duplex profiles
If device supports duplex, show also separate sink-only/source-only
profiles.

Devices don't necessarily support high-quality audio in duplex profile,
so add sink/source only profiles.

This is also a workaround for the current situation that devices may
signal duplex support, but the attempted duplex configuration fails to
work.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
8795298f69 bluez5: implement BAP ucast reconfiguration
Use SelectProperties() DBus API to reconfigure BAP unicast setup.

Add support to spa_bt_ensure_codec() to select whether to configure as
sink/source/duplex.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
592a97a7b0 bluez5: keep BAP endpoint properties in spa_bt_remote_endpoint
Make QoS, Context etc. always up to date in spa_bt_remote_endpoint.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
6e0970c14b bluez5: simplify codec switch code
Simplify codec switching code: determine what switch to perform
immediately in spa_bt_device_ensure_media_codec().

The previous code doing "fallback" switching to various codecs is not
useful, as A2DP generally disconnects on the first failure and all
remote endpoints disappear.

Add iteration over multiple endpoints, for reconfiguring both source and
sink directions at the same time.  This is in preparation of supporting
BAP reconfiguration (for A2DP there's usually only one direction
connected at a time).
2025-06-13 22:16:03 +00:00
Pauli Virtanen
a30d385636 bluez5: reduce debug spam 2025-06-13 22:16:03 +00:00
Pauli Virtanen
64f2f38ec4 bluez5: support LC3-24kHz HFP codec available on some Apple devices
Add support of HFP codec used on eg Apple AirPods 3+, transporting LC3
mono @ 24kHz
2025-06-13 22:15:29 +00:00
Pauli Virtanen
6982bb8c7f bluez5: backend-native: set best codec also when retrying on timeout
Try again setting best available codec, not MSBC, when retrying if no
response to previous +BCS: command.
2025-06-13 22:15:29 +00:00
Martin Geier
d04ee91714 plugins: alsa: increase follower write synchronization when htimestamps are enabled
alsa_write_sync can insert or remove some data from alsa when
resynchronization is needed.
Avail and delay are equal when high precision timestamps are not allowed.
When the high precision timestamps are enabled, the delay is avail
adjusted to current_time.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-06-13 22:14:34 +00:00
Pauli Virtanen
7e135a5235 bluez5: fix compilation 2025-06-13 21:06:08 +03:00
Pauli Virtanen
df591638a5 bluez5: indicate codec support status for ofono/hsphfpd
Indicates codecs properly.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
52fc22a76b bluez5: make sure mandatory codecs are always enabled
It should not be possible to disable mandatory codecs: csvd, sbc, lc3
2025-06-13 17:51:16 +00:00
Pauli Virtanen
9f34e962a6 bluez5: backend-native: don't hardcode available HFP codecs
Remove most hardcoding of possible HFP codecs. Instead, get what is
available from codec lists.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
83f6d719b1 bluez5: remove HFP codec id from transports
Make HFP codec id backend/codec internal detail. Remove
spa_bt_transport::codec field which is now unused.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
3f9fb8d664 bluez5: bluez5-device: reduce special casing of HFP codec related things
Get most information items out from media_codec properties, avoid
referring to HFP codec ids.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
defcea02fa bluez5: convert sco-sink to media_codec API
Use codecs via media_codec in sco-sink instead of implementing the
encoding in-place.

In future, media-sink could replace sco-source to reduce code
duplication.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
1c5895f625 bluez5: convert sco-source to use media_codec API
Use codecs via media_codec in sco-source instead of implementing the
decoding in-place.

Also slightly adjust media-source decode semantics.

In future, media-source could replace sco-source to reduce code
duplication.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
123f937701 bluez5: backend-hsphfpd: set media_codec on created transports
Set media_codec on created transports.

Also avoid using the HFP codec id in spa_bt_transport::codec
2025-06-13 17:51:16 +00:00
Pauli Virtanen
61b0ea4589 bluez5: backend-ofono: set media_codec on created transports
Set media_codec on created transports.

Also avoid using the HFP codec id in spa_bt_transport::codec
2025-06-13 17:51:16 +00:00
Pauli Virtanen
13256e9083 bluez5: backend-native: set media_codec on created transports
Set media_codec on created transports.

Also avoid using the HFP codec id in spa_bt_transport::codec
2025-06-13 17:51:16 +00:00
Pauli Virtanen
62bec49c27 bluez5: add spa_bt_get_hfp_codec() / spa_bt_get_media_codecs()
These are for HFP backends to get media codecs.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
e6f5fb12a3 bluez5: add HFP codecs in the media codec API
Add copy of HFP codec implementations in the media codec API.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
4e0d0c5f0b bluez5: replace codec->bap/asha flags with codec->kind enum
Indicate codec type with enum instead of bool flags.  This is in
preparation of moving also HFP to media codecs.
2025-06-13 17:51:16 +00:00
Wim Taymans
83c644fe09 pulse-server: mark empty buffers
This makes it use some more optimal paths in the mixer.
2025-06-13 18:07:55 +02:00
Wim Taymans
3d1c9f1cce modules: update Props and ProcessLatency
When setting Props or ProcessLatency on a stream, it doesn't actually
remember the values that were set so we need to manually update them.

See #4731
2025-06-13 12:46:40 +02:00
Wim Taymans
3d8a19af33 filter-chain: we manage the state from the playback stream 2025-06-13 11:58:42 +02:00
Elliot Chen
72e0fe0479 pipewiresrc: add provide clock property 2025-06-13 08:10:20 +00:00
Christian Glombek
baf0b0b9e1 50-raop.conf.in: Add a condition that allows for disabling module 2025-06-13 08:08:31 +00:00
Wim Taymans
c1b5fb19ea spa: add volume_ramp_scale enum type info
And link it to the SPA_PROP_volumeRampScale property
2025-06-13 10:06:09 +02:00
Wim Taymans
c2eb173fdc spa: make the wave, pattern and ditherType Int
Properties of type Id should have a type of the enum with the possible
values associated with them.

The other types that don't have a fixed enumeration but are usually
mapped to some constant/description with PropInfo should be Int.

Fixes !2399
2025-06-13 10:06:09 +02:00
Frédéric Danis
f6fc307638 bluez5: backend-native: Support legacy audio connection
This allows to connect the SCO link with old HFP AG devices which
doesn't support the codec negotiation.
The audio connection could be done even without an ongoing call.
2025-06-13 07:47:18 +00:00
Wim Taymans
d238fc8199 doc: fix a typo 2025-06-13 09:21:51 +02:00
ZZyVSmOzMz OZaAEBlUIZ
0e8a8e9844 filter-chain: add dolby pro logic ii sink 2025-06-12 17:18:21 +00:00
ZZyVSmOzMz OZaAEBlUIZ
d07a383d6e filter-chain: use only builtin filter for dolby surround sink 2025-06-12 17:18:21 +00:00
Wim Taymans
fa8208eeef tools: make some things configurable
Things like indentation and simplified spa layout are behind an if 0
but wil some option parsing this could be improved.
2025-06-12 17:16:27 +02:00
Wim Taymans
4c1be71773 modules: Propagate the combine latency
When we get latency on the combine stream, forward it to all
streams after setting the per stream compensate latency (if any).

See #4731
2025-06-12 16:36:51 +02:00
Wim Taymans
549f3fc46f module-combine: use a better empty property string
The empty string fails to parse as a properties, use "{}" instead.
2025-06-12 16:35:49 +02:00
Wim Taymans
046fdad4ee modules: improve latency handling
Now that the stream remembers the latency for us, we can only care
about the other latency.

So, if we get (output) latency on an input port/stream, we add our
own latency and then set it on the output port/stream. We do the
same for input ports.
2025-06-12 15:20:18 +02:00
Wim Taymans
92243038c1 stream: handle Latency params better
LOCK the Latency param we get from the peer so that we don't remove it
when we update our own port latency. Also don't remove our port latency
when we get an update from the peer.

This essentially keeps the update/clear of the upstream and downstrem
latencies separate and makes it easier to implement the latency
logic in the pw-stream.

When a filter receives a Latency event on a port, it can simply update
the other port latency and none of the peer latencies are removed.
2025-06-12 15:02:17 +02:00
Wim Taymans
2393be4543 spa: add SPA_LATENCY_INFO_UNSET
Add a initializer for an unset latency info. Use this for combining
latency info.
2025-06-12 12:12:28 +02:00
Wim Taymans
5480a1382f modules: always update latency params
Even if the latency didn't change, the current pw-stream
implementation will have wiped all Latency params away and we want
to put them back in all cases.

See #4731
2025-06-11 16:26:03 +02:00
David Turner
3a0ffe21e6 libcamera: Default to auto-focus & auto-exposure
libcamera says that cameras should default to manual focus mode.  This
means that unless pipewire clients specifically change this control,
users with an autofocus-capable camera are left with an out-of-focus
image.  This patch sets the autofocus mode to continuous and enables
auto-exposure (as the default for this is unspecified).

Testing with an imx708 on Raspberry Pi OS on a Raspberry Pi 4, before
this patch the image was generally out of focus in Firefox/webrtc, after
this patch autofocus works correctly.
2025-06-11 13:56:26 +00:00
Wim Taymans
82229b3d87 modules: make sure we deactivate the graph safely
Use the loop lock to ensure the loop is not using the graph anymore when
the deactivate or reset it.
2025-06-11 15:21:26 +02:00
Wim Taymans
3fdcf0d34c alsa: reset alsa_sync when linked
When a linked node needs to be resynced we actually never clear the
flag or reset the dll. Move the code around so that it still does
the reset of the flag and dll without actually doing the resync in
the ringbuffer when it is a linked node.
2025-06-11 13:06:54 +02:00
Wim Taymans
524da5962d alsa: reset dll in prepare
When we do_prepare, always reset the dll. We already set the alsa_sync
field but that is only used by followers to resync in some cases.

When reseting the dll, we also reset the next_time and base_time values,
we however need to do this before calculating the error in update_time
when we are the driver in IRQ mode or else we get some crazy error
that distorts the rate estimation.
2025-06-11 13:03:18 +02:00
Wim Taymans
b0462cb5de filter-chain: do graph reconfigure in playback state change
Because we do the processing of the graph in the playback process
function, only do graph reset and reconfigure from the playback state
change so that we don't have process and state change at the same time
and crash.
2025-06-11 11:43:13 +02:00
Wim Taymans
c08ef84745 modules: initialize the latency params
Otherwise we get nonsense values for the direction.

See #4731
2025-06-11 10:17:32 +02:00
Wim Taymans
190d49d874 loop: add docs about the locking 2025-06-10 18:00:01 +02:00
Wim Taymans
a2f2bded0b modules: update latency handling in example filter 2025-06-10 16:48:49 +02:00
Wim Taymans
b6b61a956f modules: implement Latency according to docs
Make one function to update the Latencies on all streams. We need to do
this because if one of the process or latency params change, it
influences the latency params on all streams.
2025-06-10 16:48:49 +02:00
Martin Geier
4976ac7ef9 alsa-pcm: add dsd bit order parameter
Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-06-10 16:28:48 +02:00
Martin Geier
9afa0cd270 alsa-pcm: enable interrupts after alsa recovery
Interrupts are disabled in alsa_irq_wakeup_event -> playback_ready method
to not produce another wakeups when waiting for a new data. Interrupts are
enabled again when a new data arrives in a method spa_alsa_write.
In rare cases, when there is multiple streams providing data and one of
them is disconnected, a new data fails to be delivered and the spa_alsa_write
is not called. Not providing data produces underrun and alsa-pcm invokes
recovery process. Recovery process starts a new playback, but without interrupts
enabled is graph not triggered and new data are not delivered (to enable
interrupts). Recovery process keeps running in loop.
Now the interrupts are enabled again after the recovery and the starvation
should not occur.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-06-10 16:28:46 +02:00
Martin Geier
c2e539b780 module-combine-stream: flush data in paused state
When stream is paused, internal delay buffers were cleared, but some
data could stay in stream output queue. Without a flush, these data where
played in front of a new data.
Patch was inspired by 64d6ff4184 fixing the
same issue in a filter-chain module.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-06-10 16:28:43 +02:00
Martin Geier
ff3bc8818f module-combine-stream: update latency right before playback starts
Combine stream selects the biggest latency from all output streams and sent
the latency upstream. To select the biggest latency, each stream needs to have
the sample rate and the quantum size set.
The combine stream recalculates the latency in the latency changed callback
or during data processing.
Stream sets the sample rate and the quantum size in a copy_position call
which is normally called during processing the output data or when state
changes to streaming.
Before this change, it wasn't guarantee the copy_position was called for
each stream already and latency in the combine stream was selected from
random stream.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2025-06-10 16:28:40 +02:00
Wim Taymans
88963e9a9c Revert "loop: deprecate the hooks"
This reverts commit 550ec8c2a4.

Before hooks are still useful when integrating other fds in the pipewire
main loop.
2025-06-10 13:08:45 +02:00
Wim Taymans
550ec8c2a4 loop: deprecate the hooks
They were mostly useful for locking and unlocking but since that is
builtin right now, we should remove those eventually.
2025-06-10 12:01:20 +02:00
Wim Taymans
8e32afb863 loop: don't call the hooks around blocking wait
The hooks were previously used to unlock the loop but now that the
lock is handled inside the loop itself and we don't unlock before the
blocking read anymore, we should also not call the hooks.

The blocking invoke function is not meant to be called with any of the
loop context locks acquired in order to avoid a deadlock. Make this (and
other blocking risks) clear in the documentation.

See #4472
2025-06-10 11:57:38 +02:00
Wim Taymans
feba1fd260 meson: fix avfilter dependency 2025-06-10 11:23:15 +02:00
Wim Taymans
a78e97a53b filter-chain: document ffmpeg plugin 2025-06-10 10:55:45 +02:00
Wim Taymans
8c68537446 filter-graph: clean up descriptor memory 2025-06-10 10:55:45 +02:00
Wim Taymans
41cafb4d2f filter-graph: add avfilter multichannel support
Use the port name extension to set the channel layout on the ports.

Add latency measurement and reporting.
2025-06-10 10:55:45 +02:00
Wim Taymans
2f51b9a5d9 filter-graph: add multiple in/out support for avfilter
Make one buffersrc for each input and configure it to mono. Try to guess
the channel position from the port name or use the config option and
fall back to FC (MONO) if unspecified.

Make one buffersink for each output and place a format converter in
front of it. Configure the converter to produce 1 channel with a layout
guessed from the port name or from the config.

With this we can use channelsplit and amerge to create multichannel
streams for avfilter plugins.
2025-06-10 10:55:45 +02:00
Wim Taymans
94116901ce filter-graph: add an ffmpeg plugin
Allows for using an ffmpeg filter-graph as a filter-graph node.
2025-06-10 10:55:45 +02:00
Wim Taymans
9b36e576cb alsa: handle NULL io
It is possible that the port io is set to NULL when the node is
negotiating or destroying.

Fixes #4734
2025-06-10 10:54:36 +02:00
Jonas Holmberg
930f2f3e2d gst: deviceprovider: take a ref to devices
When _probe() is called, take a ref to the newly created devices instead
if sinking the floating ref, since gst_clear_object() is called when
core is disconnected. Otherwise the devices will be freed before the
caller gets them.

Fixes the following assert in the caller:

g_object_is_floating: assertion 'G_IS_OBJECT (object)' failed

Or sometimes a segfault with the backtrace:

0  g_type_check_instance_is_fundamentally_a (type_instance=type_instance@entry=0x116c1b0, fundamental_type=fundamental_type@entry=80) at /usr/src/debug/glib-2.0/2.84.0/gobject/gtype.c:3918
1  0xb6d40cc6 in g_object_is_floating (_object=0x116c1b0) at /usr/src/debug/glib-2.0/2.84.0/gobject/gobject.c:3843
2  0xb6bc4c74 in gst_device_provider_get_devices (provider=0x109ba00) at /usr/src/debug/gstreamer1.0/1.24.12/gst/gstdeviceprovider.c:426
2025-06-09 16:50:18 +02:00
Wim Taymans
b51d3d7e8b filter-graph: ignore ports without descriptor
Ports without a descriptor are to be ignored. They also don't have
a node associated with them so don't try to get its latency.

Fixes #4700
2025-06-09 11:44:06 +02:00
Wim Taymans
4f3a2d723b filter-graph: add a pipe filter 2025-06-06 13:00:29 +02:00
Arun Raghavan
420c510d47 spa: loop: Fix potential uninitialised result 2025-06-06 12:50:56 +05:30
Wim Taymans
e43324a186 filter-graph: remove a memcpy and some cleanups
We don't need to memcpy if we swap between 2 buffers for overlap.

Remove a duplicate variable.
2025-06-05 11:35:32 +02:00
Wim Taymans
7ef8dc4dee filter-graph: a 64 tap hilbert function is a better default
1024 taps for the default hilbert functions seems excessive, use 64
instead.
2025-06-05 11:21:56 +02:00
Wim Taymans
efb1208b97 filter-graph: use spa_memcpy to make it instrumentable 2025-06-05 11:21:28 +02:00
Christian Glombek
113e22cb72 raop: don't set improper media.format 2025-06-03 19:39:43 +02:00
Christian Glombek
6e64d5da47 raop: set mtu to 1448 by default 2025-06-03 19:39:41 +02:00
Wim Taymans
457b1c2e1e filter-graph: run when both in and out != NULL
The check got reverted in 8ee51cd88f
2025-06-03 17:54:06 +02:00
Arun Raghavan
56c6e19f99 Revert "spa: loop: Change get_time() timeout to unsigned"
This reverts commit c515f9bf8e. The PW
APIs use int64_t (partly because SPA_NSEC_PER_SEC is an LL), and we
don't want to change already public API.
2025-06-03 15:20:15 +05:30
Arun Raghavan
c515f9bf8e spa: loop: Change get_time() timeout to unsigned
A signed value doesn't really make sense in this context, so let's keep
it unsigned so the semantics are clear. This does break the interface,
but should be okay since it's not in a release yet.
2025-06-03 09:39:30 +00:00
ValdikSS
187df01b5e bluez5: aac: disable Perceptual Noise Substitution for MPEG-2 profile
When the Bluetooth earphones claim to support AAC `MPEG-2 AAC LC` type only,
PipeWire encodes audio using MPEG-4 FDK-AAC profile which enables unsupported
Perceptual Noise Substitution (PNS) encoder feature.

Use AOT_MP2_AAC_LC pseudo-profile which is AOT_AAC_LC with PNS disabled.
2025-06-03 09:38:28 +00:00
Wim Taymans
38a3ebdca1 adapter: use the right default when filtering default
We should prefer the value of the follower when fixating to the
PortConfig format.

To make this actually work we need to be able to check if the value is
within the configured ranges. Implement the check for all types by
simply comparing the memory. This should then work also for checking
arrays, such as channel positions.
2025-06-03 11:35:59 +02:00
Wim Taymans
a5e63102d9 alsa: unlock pending drain in drop
When we set activated=false, signal the thread because it might be
waiting in drain.

See #4728
2025-06-02 19:14:45 +02:00
Wim Taymans
f65f5cf866 stream: make ticks continuous on DISCONT
A discont of the clock does not mean a discont in the stream, so keep
the ticks continuous.
2025-06-02 12:23:53 +02:00
Carlos Rafael Giani
abb55697c1 spa: Add SPA_IO_CLOCK_FLAG_DISCONT 2025-06-02 10:04:13 +00:00
Carlos Rafael Giani
5dd65dccf3 spa: Improve spa_io_clock flags documentation 2025-06-02 10:04:13 +00:00
Wim Taymans
13105a8e64 pulse-server: Implement record PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
Also implement the flag for record streams, where it is more usually
used, like in pavucontrol to disable starting a network source.
2025-06-02 11:48:01 +02:00
Arun Raghavan
60669920f0 pulse-server: Implement PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
We do this by setting the node as passive.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4255
Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4726
2025-06-02 14:38:22 +05:30
Sam James
2cec77e7df *: unify config.h handling
config.h needs to be consistently included before any standard headers
if we ever want to set feature test macros (like _GNU_SOURCE or whatever)
inside. It can lead to hard-to-debug issues without that.

It can also be problematic just for our own HAVE_* that it may define
if it's not consistently made available before our own headers. Just
always include it first, before everything.

We already did this in many files, just not consistently.
2025-05-30 10:24:13 +00:00
Wim Taymans
50fe63ea76 examples: exit early when no longer running
When we are no longer running after the eventfd was signaled, stop
producing samples.
2025-05-30 12:17:41 +02:00
Wim Taymans
fecf1bcba4 thread-loop: remove the event
We don't need the event to wake up and stop the thread loop, we can
simply use _invoke() of the loop implementation, like we do for the
data loop.
2025-05-30 12:12:03 +02:00
Wim Taymans
820e0fccb1 loop: we can't actually use locked to stop the loop
We need to signal the event and wake up the loop to actually make it
stop and joinable.
2025-05-30 12:07:47 +02:00
Wim Taymans
c45d667934 loop: spa_loop_invoke -> spa_loop_locked where possible
When we simply need to change some state for the code executed in the
loop, we can use locked() instead of invoke(). This is more efficient
and avoids some context switches in the normal case.
2025-05-30 11:59:35 +02:00
Sam James
b943c31fd8
*: don't include standard C headers inside of extern "C"
Including C headers inside of `extern "C"` breaks use from C++. Hoist
the includes of standard C headers above the block so we don't try
to mangle the stdlib.

I initially tried to scope this with a targeted change but it's too
hard to do correctly that way. This way, we avoid whack-a-mole.

Firefox is working around this in their e21461b7b8b39cc31ba53c47d4f6f310c673ff2f
commit.

Bug: https://bugzilla.mozilla.org/1953080
2025-05-30 09:48:28 +01:00
Carlos Rafael Giani
e2731914ad pw-cat: Document numeric WMA constants 2025-05-29 22:24:31 +02:00
Carlos Rafael Giani
7341cc401b pw-cat: Add support for AC3, EAC3, TrueHD, DTS, MPEG-H 2025-05-29 22:24:07 +02:00
Carlos Rafael Giani
5db9bca75c spa: add AC3, EAC3, TrueHD, DTS, MPEG-H formats 2025-05-29 21:41:51 +02:00
Carlos Rafael Giani
bd25614cb9 spa: Include Opus in compressed.h header
Opus is a compressed format.
2025-05-29 20:51:49 +02:00
Carlos Rafael Giani
cef14695b6 spa: Fix iec958 docs 2025-05-29 20:47:36 +02:00
Carlos Rafael Giani
6f197484fc spa: Fix AAC stream format docs 2025-05-29 20:47:02 +02:00
Carlos Rafael Giani
592c7c404c spa: Add channel mode to mp3 audio info and add channel mode docs 2025-05-29 20:46:46 +02:00
Arun Raghavan
2042a0483b ci: Add an x86 build
Fairly minimal for now to save time, but we can add more deps and cover
more code as needed. We don't test or install as this isn't a native
build and we just want to make sure it builds for now.
2025-05-29 08:29:34 +00:00
Wim Taymans
34796d5bb8 loop: keep a free_list of sources
When a source is destroyed, move it to a free_list and reuse the memory
when a new source is made. This way we can avoid doing a free() from
the epoll thread.
2025-05-29 10:17:16 +02:00
Wim Taymans
f2452a6af7 spa: some more invoke -> locked calls 2025-05-29 10:17:16 +02:00
Wim Taymans
f7fdafc203 loop: add method to run a function with the lock
Convert some _invoke to _locked
2025-05-29 10:17:16 +02:00
Wim Taymans
fb49e0795c loop: move thread-loop to support loop
Add more synchronization primitives to spa loop so that we can replace
the thread-loop with it.
2025-05-29 10:17:16 +02:00
Wim Taymans
cd1d9ceff1 context: make data loop prio-inherit 2025-05-29 10:17:16 +02:00
Wim Taymans
65cbbf1a02 spa: add locking to the loop
We can add a PTHREAD_PRIO_INHERIT lock to the loop to protect the
callbacks and then use this to update shared data in an RT-safe way.

This can avoid some invoke calls that require a context switch but
also due to the nature of epoll cause locking in the kernel with non-RT
guarantees.

Because we use PRIO_INHERIT, the code executed in the lock must not use
any RT-unsafe functions.
2025-05-29 10:17:16 +02:00
Carlos Rafael Giani
d258892392 module-rtp: Retry starting stream if this failed with ENODEV errno
ENODEV is not a fatal error, and trying again later to set up the
socket usually succeeds. Do such retries with a timer.
2025-05-28 17:19:57 +02:00
Carlos Rafael Giani
71c0c8e34c module-rtp: Rename timer to standby timer in rtp source
This results in clearer code, and makes it easier to add more timers
to the module in the future.
2025-05-28 17:19:57 +02:00
Carlos Rafael Giani
023525eca2 rtp: aes67: Document sess.ts-direct property and set it to true for AES67 2025-05-28 17:19:57 +02:00
Carlos Rafael Giani
2fe77c47e1 spa: tools: spa-inspect: Output more detailed dlopen and dlsym errors
When writing a custom SPA plugin, it is very useful to get more detailed
errors related to libdl. One common error is that a symbol is not present
because a related library was not properly linked into the plugin. With
this change, the error will tell the user about the exact missing symbol.
2025-05-28 17:19:57 +02:00
Wim Taymans
d9b742cfda bluez: avoid some compiler warnings 2025-05-28 15:15:25 +02:00
Wim Taymans
a1be639894 filter-graph: add log feature to lv2 plugins 2025-05-28 15:02:53 +02:00
Wim Taymans
3f99c6f259 filter-graph: use new map/unmap URIs
Don't use the legacy ones.
2025-05-28 15:02:53 +02:00
Jonas Holmberg
51d9bdd9cb pod: declare offset as unused in spa_pod_builder_bytes_end()
Fixes compiler warning:

/usr/include/spa-0.2/spa/pod/builder.h:357:69: error: unused parameter 'offset'
[-Werror=unused-parameter]
2025-05-28 09:56:11 +02:00
Wim Taymans
e126f9bcbf adapter: only clear the NEED_CONFIGURE flag when mode != none
As long as we are in the 'none' PortConfig mode, we set the NEED_CONFIGURE
flag.

This fixes early start in audioadpter nodes because PortConfig is set to
none at init time and this used to clear the NEED_CONFIGURE flag, which
would start the node before the session manager could to a PortConfig
and cause a -22 error.
2025-05-27 15:38:51 +02:00
Wim Taymans
548fa0ec48 adapter:handle -ENOENT when enumerating buffers
When the follower has no buffer suggestion, it can return -ENOENT, which
should not generate an error but simply use the converter buffer
suggestion instead.
2025-05-27 15:00:43 +02:00
Wim Taymans
417a72365e adapter: negotiate from target to follower
Now that the filter functions prefer the filter default value, use the
target object as a filter for buffer allocation as well.
2025-05-27 09:30:52 +02:00
Wim Taymans
96007dc576 pw-cat: mode SYSEX mode out of ffmpeg define 2025-05-26 19:24:23 +02:00
Robert Mader
e81fb77322 gst: src: Change DEFAULT_MIN_BUFFERS back to 1
The change from 1 to 8 was done without justification in the commit
message and possibly for debug purposes. Unfortunately it breaks
negotiation with the libcamera virtual pipeline, which defaults to
4 buffers.

Set the the value to 1 again as successful negotiation - even with an
unusually low number of buffers - is usually more desirable than an
error.

Fixes: 98b7dc7c0 ("gst: don't do set_caps from the pipewire callback")
2025-05-25 04:03:06 +02:00
Wim Taymans
737ca4ee7b tools: add sysex play option in pw-cat
This makes it possible to upload raw midi (sysex) into the graph.
2025-05-23 16:52:22 +02:00
Wim Taymans
564c9b1ba5 Use "8 bit raw midi" for control ports again
There is no need to encode the potential format in the format.dsp of
control ports, this is just for legacy compatibility with JACK apps. The
actual format can be negotiated with the types field.

Fixes midi port visibility with apps compiled against 1.2, such as JACK
apps in flatpaks.
2025-05-23 16:46:13 +02:00
Wim Taymans
617f1b8a38 pod: add bytes start/append/end functions
Add functions to dynamically start and build a bytes pod.
2025-05-23 16:41:00 +02:00
Wim Taymans
d37f213236 docs: fix some typos 2025-05-23 16:40:20 +02:00
Wim Taymans
5e81ff8ede filter-chain: manage graph from source only
Only react to the capture stream state change and format changes. The
playback and capture streams change state somewhat concurrently and so
the graph state might not be consistent.

Because only the capture stream will trigger the playback stream and
start the processing, we can safely react to capture stream changes
only.
2025-05-21 15:23:00 +02:00
Wim Taymans
ccb7a51c3a filter-graph: add support for lv2 State
If the lv2 plugin supports State restore, use it to load state from the
config section in the lv2 plugin definition.
2025-05-21 15:19:23 +02:00
Wim Taymans
f7eab4172e client-node: let all events go to the node
Just pass all events to the node and only error out when they return an
error value.

Make sure we pass the result values of the command around.
2025-05-20 11:47:10 +02:00
Wim Taymans
12f8ca664b adapter: log command errors when no converter 2025-05-20 10:42:59 +02:00
Wim Taymans
7dc1d28b2c node: add User command and event
Add a User command and event id with a String property called 'extra' to
make it possible to send arbitrary User defined commands and events.
Also makes it possible to make User commands in pw-cli.

pw-cli c 86 User '{ extra="{ test: foo }" }'
2025-05-20 10:32:10 +02:00
Christian Glombek
5a54ecd8df daemon/pipewire.conf.avail: Add snippet enabling module-raop 2025-05-19 18:28:10 +02:00
Wim Taymans
b80189c3dd adapter: handle -ENOTSUP for commands
When using custom commands, the converter might return -ENOTSUP and
we should ignore this.
2025-05-19 17:23:30 +02:00
Wim Taymans
b9a8bb15a4 impl-link: fix feedback handling
If a link is a feedback link, we just need to swap the input/output
scheduling dependency.

Don't swap input/output nodes (without swapping ports) because then we
will be querying the wrong node/port pair when negotiating and cause
errors.

See #4706
2025-05-19 09:45:05 +02:00
Arun Raghavan
9ff1c93ab1 media-sink: Set up ASHA source after setting transport state
We need to make sure the state is available when the source starts, so
that it does not assert in flush_data()
2025-05-17 10:25:37 -04:00
Wim Taymans
e5afc939e8 libcemara: take care of index offset when enumerating controls
Add an index offset when enumerating controls. We insert 2 properties
before enumerating the controls so the index of the first control needs
to have an offset of 2.
2025-05-17 14:05:23 +02:00
Robert Mader
e387772dc2 v4l2: Re-enable first buffer skip for jpeg types
The workaround is typically needed with usb-cameras using jpeg streams.
Re-enabling the skip shouldn't affect what the commit was trying to do,
i.e. fix encoded streams like h264 etc.

Fixes: bcf0c0cf8 (v4l2: only skip buffer for raw formats)
2025-05-17 10:53:08 +00:00
Pauli Virtanen
1e18cded75 bluez5: iso-io: improve latency logic
If kernel socket queues for different streams get out of sync, it will
mess up time alignment of different streams. If that happens, flush to
resync.

If total latency becomes too large, flush queue.

Get accurate queue sizes from tx timestamping.
2025-05-17 10:51:37 +00:00
Pauli Virtanen
489e4b6bd2 bluez5: latency tracking also for A2DP, use it for unsent size
Use TX timestamping to figure out the accurate amount of unsent data,
including controller buffers.  SIOCOUTQ does not report accurate data
size as it includes overheads.
2025-05-17 10:51:37 +00:00
Pauli Virtanen
897748759e bluez5: update timestamping code to match kernel & bluez
Update code to match the final version landed in mainline Linux 6.15
2025-05-17 10:51:37 +00:00
Pauli Virtanen
e375364c87 bluez5: fix device set profile/route enumerations
Now that we have ASHA & BAP, this->device_set now refers to the device
set of the active profile.  It cannot be used to produce
EnumProfile/EnumRoute.

Fix this by computing the device set for given profile(s) as needed.
2025-05-17 10:50:15 +00:00
Barnabás Pőcze
01d1e29402 spa: vulkan: simplify kernel version parsing
Use a single `sscanf()` instead of multiple `strtok()`, `atoi()` calls.
After this change all three components are required to be present.
2025-05-14 18:37:54 +02:00
Wim Taymans
2771c435fd doc: fix end of page for tag doc 2025-05-14 18:23:41 +02:00
Wim Taymans
218f25088c convert: place the right id in the portconfig format 2025-05-14 18:21:39 +02:00
Barnabás Pőcze
6712d9c3db pipewire: module-raop-discover: fix typo in documentation
roap -> raop
2025-05-14 17:59:41 +02:00
Wim Taymans
9b316f6deb filter-graph: remove port check
Remove the port number check, we never call this with an invalid port
number and the check was wrong for the sofa_plugin.

Fixes #4700
2025-05-14 17:04:06 +02:00
Barnabás Pőcze
a0eb12e4be ci: specify explicit dependencies between jobs
Use `needs` to specify job dependencies explicitly instead of relying on
stages for ordering. This allows jobs from multiple stages to run concurrently
without having to wait for unrelated jobs in earlier stages.

See https://docs.gitlab.com/ci/yaml/#needs for more information.
2025-05-14 09:41:44 +00:00
Wim Taymans
b957d74eb6 doc: fix bad filename 2025-05-14 11:40:32 +02:00
Wim Taymans
26099f4c29 doc: add doc about Tag params 2025-05-14 11:28:16 +02:00
Wim Taymans
093b3eea21 audioconvert: implement graph latency reporting
Keep per graph latency. Sum all the graph latencies together and keep
this around as the process-latency.

Refactor the port latency setter. Make a function to recalculate the
latency of all other ports. Take into account the graph latencies.

Update the port latencies when the total graph latency changes.
2025-05-14 09:21:31 +02:00
Wim Taymans
c334bfb0bb audioconvert: do params after init of the node
First do the essential properties to set up the node, then set up the
node and then parse the params. The params might do some setup that
relies on a completely configured node, such as emit events.
2025-05-14 09:19:17 +02:00
Wim Taymans
37bf571db3 audioconvert: keep the graph latency around 2025-05-13 15:27:17 +02:00
Wim Taymans
ca032152b1 doc: improve formatting 2025-05-13 15:17:56 +02:00
Wim Taymans
b71216af70 doc: add document about latency handling 2025-05-13 15:01:00 +02:00
Wim Taymans
6b3681938b pw-dump: don't do raw mode when streaming
pw-dump | less -RS is a common thing and raw mode is not helpful.
2025-05-13 14:59:51 +02:00
Wim Taymans
08efc1171c pw-dump: disable indent in raw mode as well 2025-05-13 10:37:00 +02:00
Kirill
1f16f949ec Apply 1 suggestion(s) to 1 file(s)
Co-authored-by: Barnabás Pőcze <pobrn@protonmail.com>
2025-05-13 08:27:29 +00:00
dartvader316
d599936925 pw-dump: add raw json elements output option 2025-05-13 08:27:29 +00:00
Taruntej Kanakamalla
882542e001 gst: sink: minor type fix 2025-05-12 21:31:30 +00:00
Wim Taymans
b47d28bad6 profiler: use doubles in profiler.log
Don't truncate the measurements when we convert to usec but keep the
fractional part to get a more accurate graph.
2025-05-12 17:23:35 +02:00
Wim Taymans
4f53136891 netjack2: reverse send/recv roles in driver/manager
The params contain the send/recv streams from the point of view of the
manager (and not the driver as was assumed before). This means we need
to swap send/recv in the driver, not the manager.

This makes things interoperate with JACK/netjack2.

See #4666
2025-05-12 12:57:11 +02:00
Pauli Virtanen
1445843ced modules: get also instance id for flatpak apps
Add "pipewire.access.portal.instance_id" property for distinguishing
Flatpak application instances from each other.
2025-05-12 09:40:32 +00:00
Barnabás Pőcze
09a5b7ee35 ci: do not install libv4l
`libv4l` has not been necessary for a long time, so drop it.
2025-05-12 09:39:35 +00:00
Wim Taymans
2420c3a8c8 convert: refactor node_set_param functions
Move them to their own function to make the main function shorter.

Also make sure we emit the new ports first and then the node info.
2025-05-12 11:39:02 +02:00
Wim Taymans
8dfa086c3c audioconvert: refactor params
Move the param enumeration code out of the main enum function.

Emit node events after completion of the set_param functions to ensure
we only emit things once.
2025-05-12 11:39:02 +02:00
Pauli Virtanen
e5d0dd2020 bluez5: enable asha device set only if there's a device set
Now that ASHA uses device set, no need to special case here.
2025-05-11 16:14:40 +03:00
Wim Taymans
436195f05f control: only convert midi/UMP, pass other control types
We should only try to convert MIDI/UMP when the port doesn't support it
but let all the other control types pass through.

Fixes #4692
2025-05-09 09:34:34 +02:00
Taruntej Kanakamalla
608bf93f7a gst: sink: minor formatting fixes
follow up of !2337
2025-05-09 07:13:36 +00:00
Sanchayan Maity
a5a6973472 bluez5-dbus: Fix another build failure on 32-bit system 2025-05-09 07:09:26 +00:00
Wim Taymans
f068e4ba85 alsa: rework the channel params
Avoid adding a None choice, just add one single value without a choice
when the min == max. In that case we can also add a channel position.
2025-05-08 18:17:45 +02:00
Wim Taymans
2d8080cbde alsa: only use default rate and channels when valid
Check the user provided rate and channels and only use them to limit the
rate and channels when they are valid.
2025-05-08 18:16:53 +02:00
Wim Taymans
ff0d6d5677 alsa: clamp audio.channels to MAX_CHANNELS
So that we don't end up trying to use too many channels later on.
2025-05-08 18:14:02 +02:00
Wim Taymans
b2695f86cf alsa-pcm: handle and warn about a driver bug wrt channels
If the driver returns a larger min than max channel count, log a warning
and swap the two numbers.

See #4687
2025-05-08 16:01:18 +02:00
Taruntej Kanakamalla
d5e2cc94cd gst: sink: update clock before every trigger process
Get the clock pointer using the io_changed stream event.
and update the clock before triggering the process

The clock needs to be updated in the data loop thread
and before triggering the process so move the calls to
`pw_stream_trigger_process` from gstreamer thread context
into the data loop thread context by invoking a callback
and update the clock inside the data loop callback
before the trigger
2025-05-08 18:57:44 +05:30
Wim Taymans
bca83c8eee filter-graph: fix lv2 latency hint 2025-05-08 12:17:38 +02:00
Wim Taymans
68c5f41708 filter-graph: fix port find logic
We need both ports to be NULL (failed to find the ports as audio ports)
when we try to link control/notify ports.
2025-05-08 12:15:58 +02:00
Wim Taymans
46f5740604 filter-graph: warn about unaligned streams
Keep track of min/max latencies and warn when streams are unaligned.
2025-05-08 10:52:57 +02:00
Wim Taymans
8e4c211a80 filter-graph: add latency reporting to the sofa plugin 2025-05-07 17:19:38 +02:00
Wim Taymans
8bcf0460d1 filter-graph: add latency option to the convolver
Sometimes you want to use the convolver as a delay without adding
latency so add a latency option to tweak the automatic latency
reporting. Use this in the upmix rear delay filters.
2025-05-07 17:18:15 +02:00
Wim Taymans
8ee51cd88f filter-graph: add latency support for the delay plugin 2025-05-07 16:55:44 +02:00
Wim Taymans
dbca286de8 filter-graph: add latency reporting to the convolver 2025-05-07 16:37:14 +02:00
Wim Taymans
e545efdb6e filter-chain: implement filter-graph latency
Collect the latency of the graph in filter-chain. We do this by first
inspecting the LATENCY ports on the plugins and us the notify value as
the latency on the node.

We then walk the graph from source to sink and for each node take the
max latency of all linked upstream peer nodes. We end up with the max
latency of the graph and emit this in the graph properties.

We then listen for the graph latency property and use that to update the
process_latency of the filter-chain, which will then update the latency
on the filter-chain ports.

Fixes #4678
2025-05-07 16:00:41 +02:00
Wim Taymans
d277b3b62e filter-graph: add a LATENCY hint for control ports
Some ports can have latency information about the plugin, mark those
ports with the LATENCY HINT.

Also decouple the LADSPA hint flags from the SPA ones.
2025-05-07 16:00:41 +02:00
Wim Taymans
5a4e8bb45e filter-graph: ensure we can call setup_graph multiple times
We need to reset the fields used for sorting so that we can run the
setup_graph code multiple times.
2025-05-07 16:00:41 +02:00
Wim Taymans
a30a988606 filter-graph: remove useless check 2025-05-07 16:00:41 +02:00
Sanchayan Maity
42b9b0eb4c bluez5-dbus: Fix the audio channel position for ASHA
For stereo to work, we need to advertise the channel position based on
whether the side is left or right.
2025-05-07 18:29:01 +05:30
Wim Taymans
5bf3a0c454 filter-graph: add a debug node
Add a node that logs audio or control data to the log.
2025-05-07 10:44:57 +02:00
Guido Günther
958ae36717 spa: Add default: statements
This allows to use the library in projects that use `-Wswitch-default`
without any

 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wswitch-default"
 #pragma GCC diagnostic pop

This is useful as as the header is being pulled in via
pipewire/wireplumber headers into projects that might have this warning
enabled and would otherwise fail to build with -Werror.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-07 07:42:39 +00:00
Frédéric Danis
27fecd3c56 bluez5: backend-native: Fix hangup of waiting call
3-way incoming calls are created in waiting state. When those calls are
hang-up before being active, the +CIEV: (callsetup = 0) should also be
managed for waiting calls.
2025-05-07 07:41:28 +00:00
Sanchayan Maity
afa7ebc032 media-sink: Drop packet if send fails for ASHA
One of the ideas behind retrying the sending of a failed packet with the
poll callback was to make sure that we do not end up with missing seqnums
by missing received credit due to some jitter.

However, the rate matching behaviour for ASHA is not clear and we do not
seem to face problems in local testing by just dropping the packet.
2025-05-07 07:39:46 +00:00
Sanchayan Maity
e68111b4aa media-sink: Fix sequence number sync for ASHA
The two sides of a ASHA pair rarely if ever start together and the
sequence number was always a bit off due to the stateful nature of
reset_buffer and ASHA needing the sequence number to be matched to
the other side.

Simplify this by setting the sequence number for ASHA just before
flushing.
2025-05-07 07:39:46 +00:00
Sanchayan Maity
a419f69bbb bluez5-device: Refactor device_set_update for ASHA & BAP 2025-05-07 07:39:46 +00:00
Wim Taymans
445ca819ce bluez: fix format specifier
zu is for size_t, PRIu64 is for uint64_t
2025-05-07 09:38:24 +02:00
Sanchayan Maity
d96485190d bluez5: media-sink: Fix format specifier for log
This should fix the build on 32-bit systems.
2025-05-07 13:02:10 +05:30
Wim Taymans
8c8fd97698 filter-chain: support ProcessLatency
Allow setting ProcessLatency on the nodes and add this latency to the
reported Latency.

See #4678
2025-05-06 19:15:16 +02:00
Wim Taymans
20246b5c0e netjack2: add driver.mode again
This configures the default number of audio and midi ports per stream
to 0 depending on the mode.

Improve docs a little.

See #4666
2025-05-06 10:44:14 +02:00
Wim Taymans
0ebf664515 videoconvert: refactor add_video_formats
Rework the function a little so that it can take a list of formats and
only add the supported formats from that list and only once. It can
optionally select only the DSP formats.
2025-05-06 10:07:09 +02:00
Wim Taymans
df2369f6e1 videoconvert: fix enum format for control and dsp ports
They just have 1 format object.
2025-05-06 09:28:13 +02:00
Wim Taymans
6161cb3ec5 videoadapter: disable ffmpeg converter by default again 2025-05-05 13:19:54 +02:00
Wim Taymans
1904521a4d videoconvert: add PeerFormats support
Make a new PeerFormats param that can be set on ports to let it know
about the possible peer formats. This can be used by converters to calculate
an optimum conversion.

make the videoadpter query the follower formats, simplify them and then
set them as PeerFormats on the converter.

Implement peerformats in videoconvert. This makes EnumFormat on the port
depend on the negotiated format of the peer. It will suggest a Format
that most closely matches the current negotiated format with the available
PeerFormats. This then makes it possible to negotiate to the format that
would require the least amount of conversions.
2025-05-05 12:59:06 +02:00
Wim Taymans
46d376cb78 videoconvert: pass the param id to enum functions 2025-05-05 12:54:41 +02:00
Wim Taymans
80f700876d videoconvert: refactor enum_params
Move the enum_param implementation out of the main enum_param loop.

This makes it easier to read the individual functions.
2025-05-05 12:45:41 +02:00
Wim Taymans
aedbe51043 videoconvert: move get_format around 2025-05-05 12:12:09 +02:00
Wim Taymans
6373827a40 videoconvert: use a table for format conversion
Use a table with format conversion values so that we can also use
flags for the formats.
2025-05-05 12:10:02 +02:00
Wim Taymans
86dd937857 videoconvert: move event emission at end of functions
Make a function to emit all pending events and trigger it at the end of
operations that can change params.
2025-05-05 11:54:18 +02:00
Wim Taymans
77e6471a04 videoconvert: free codec resources
Free encoder and decoder resource properly when we renegotiate.
2025-05-05 11:20:15 +02:00
Wim Taymans
4dd98b4ff8 videoconvert: Use converter direction from properties 2025-05-05 11:19:15 +02:00
Wim Taymans
df52086c47 videoconvert: always restore old change_mask 2025-05-05 11:17:23 +02:00
Wim Taymans
399ff82ab2 adapter: always negotiate from convert to follower
Make the converter format a higher priority in all cases. The converter
has been negotiated first and is able to make a better suggestion for
the ideal format in all cases.
2025-05-05 10:33:07 +02:00
Wim Taymans
14eb03a821 videoconvert: Enumerate follower params better
Make sure we increment the next counter even when we are in passthrough
mode or the property is not readable.
2025-05-05 10:31:37 +02:00
Wim Taymans
faf5ae0c2f impl-link: improve negotiation
Make a function to create a filter. This is a pod that has all valid
defaults fixated and the invalid ones left unfixated.

Use this filter is a first attempt to negotiate a link format. The
effect is that a format will be chosen first that matches all the valid
defaults as much as possible instead of negotiating to the first thing
that matches.

Suppose we have a higher priority port with the format:

 foo/bar
    key: { default:1024, min:1, max:2048 }

And another port with two params:

 foo/bar
    key: 512
    rate: 2/1
 foo/bar
    key: 1024
    rate: 30/1

By first trying key: 1024 we negotiate to the more specific second property
with the higher rate.
2025-05-05 10:12:26 +02:00
Wim Taymans
9255e07c3a pod: move related functions closer to eachother 2025-05-05 10:04:26 +02:00
Wim Taymans
2940c9ff7b examples: add rate as a constant 2025-05-05 09:45:57 +02:00
Pauli Virtanen
584ea400c3 bluez5: fix spelling "Headphone" -> "Headphones"
"Headphone" is usually plural
2025-05-05 07:45:24 +00:00
Pauli Virtanen
270eda63a9 bluez5: different icon for A2DP & HFP output routes
Set different icons for A2DP & HFP output routes, so that they look
different (in Gnome).

Don't call the non-HFP output route as "headset" or "handsfree" in this
case, to be less ambiguous about microphone availability.

Also set device.icon-name for the device too.
2025-05-05 07:45:24 +00:00
Sanchayan Maity
9586ef891e bluez5: Use device set for ASHA
While ASHA does not really use the D-Bus device set interface
but since ASHA has a device-wide HiSyncId and needs to handle
left and right side via a combine sink, use the device set
notion for ASHA as well.
2025-05-05 07:43:34 +00:00
Sanchayan Maity
1b6830f68f bluez5: media-sink: Improvements for ASHA
Clean up as per feedback from Pauli and Barnabás.
2025-05-05 07:43:34 +00:00
Arun Raghavan
b02b69b271 bluez5: media-sink: Drop a redundant ASHA state variable 2025-05-05 07:43:34 +00:00
Arun Raghavan
ce8abfc5cc bluez5: media-sink: Refine ASHA other-side timer setup further
Let's just directly use the next timer value from the other side
directly, and the reference time as well to calculate the expected next
sample position we want to send from on this side.
2025-05-05 07:43:34 +00:00
Arun Raghavan
c5b5476aa4 bluez5: media-sink: Skip samples to align audio data for ASHA
For ASHA, we want the media sinks to send packets where the ASHA packet
sequence number corresponds to time position of audio in that packet.
2025-05-05 07:43:34 +00:00
Arun Raghavan
efb4a1df25 bluez5: media-sink: Snap timer to ASHA connection interval
For ASHA stereo, the timer for flushing packets on both sides of a
pair should be as closed to each other as possible.

Also set seqnum before first flush so other side sends the correct
packets at the start.
2025-05-05 07:43:34 +00:00
Arun Raghavan
4d22296d3a bluez5: media-sink: Use reference time for ASHA sequence numbers
This improves the sequence number generation by tying it to
get_reference_time.
2025-05-05 07:43:34 +00:00
Sanchayan Maity
24843a73c0 bluez5: media-sink: Support for ASHA stereo 2025-05-05 07:43:34 +00:00
Sanchayan Maity
69b5fe8395 bluez5: g722: Do not set sequence number in start_encode
In ASHA, we might need to sync sequence numbers between
left and right side media sink. If the sequence number
is added in start encode, it becomes difficult to set
the sequence number again when a call to reset_buffer
in media sink might have happened already.

This effectively reverts commit ab5f81b9a.
2025-05-05 07:43:34 +00:00
Sanchayan Maity
db47c3e442 bluez5-device: Expose HiSyncId and Side information on ASHA node 2025-05-05 07:43:34 +00:00
Sanchayan Maity
74fe7728d2 bluez5: media-sink: Set up node group for ASHA
ASHA devices with the same HiSyncId should use the same
node group/driver.
2025-05-05 07:43:34 +00:00
Sanchayan Maity
8120493edb bluez5-dbus: Track ASHA HiSyncId & Side information in transport
ASHA devices with the same HiSyncId are a pair and this
will be used later on to set them up together with a
combine sink like device set for BAP. Side information
is required for channel information when setting up the
combine sink.
2025-05-05 07:43:34 +00:00
Frédéric Danis
612cbf5176 bluez5: hfp-hf: Fix HFP HF states
hfp_hf_slc1 is not used so remove it, and rename hfp_hf_slc2 to
hfp_hf_clcc to be consistent with other states.
2025-05-05 07:41:06 +00:00
Frédéric Danis
533c67710e bluez5: backend-native: Fix rfcomm_send_volume_cmd()
This function always returns true. Change to not returning anything.
2025-05-05 07:41:06 +00:00
George Kiagiadakis
8e62b08e58 bluez5: hfp-hf: don't change hf_state after sending AT+BCS
The +BCS event may interrupt any of the initialization commands after
SLC is established and by changing the state here we may lose track
of the initialization sequence.

There is no reason to have the hfp_hf_bcs state anyway. If the
initialization sequence is over, we can remain in the hfp_hf_vgm state.
2025-05-05 07:41:06 +00:00
Stefan Binding
7f07448a80 spa: acp: Allow Volume control which supports mute to be used as a hardware mute
Some devices have a hardware volume control, but not a dedicated
hardware mute control. In some of these cases, the volume control is
described as having a hardware mute when volume is 0. This is described
in the TLV information of the volume control, when the
SNDRV_CTL_TLVD_DB_SCALE_MUTE flag is set in the TLV structure.
If set, alsa-lib will set the minimum dB value to -99999.99dB, which
can be detected inside PipeWire.

PipeWire can then use this hardware volume control to apply hardware
mute, when set.

In order to be able to set volumes and mutes separately, changing the
volume whilst muted will save the value, but not write it to the
hardware. When the device is unmuted, the saved value will be restored.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
2025-05-05 07:40:29 +00:00
Arun Raghavan
21a468a9cd gst: Add H.265 support
Same as H.264 for now, we might eventually want to add more stream
formats etc.
2025-05-05 07:38:25 +00:00
Arun Raghavan
39e079d8ac spa: video: Add H.265 as a format
Quite similar to H.264.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4674
2025-05-05 07:38:25 +00:00
George Kiagiadakis
92643f77f9 bluez5: backend-native: fix sco HUP|ERR debug message
Print the error in td->err (the SO_ERROR) or else let the user know
this is a regular hangup. The previous printout was always reporting
EAGAIN (remainder in errno from the event loop code, I suppose)
as an error, without any real data.
2025-05-02 16:12:23 +03:00
Wim Taymans
2ea8d3430c tools: add c key to reset ERR counters
Reset the ERR counters when pressing the c key. This only makes the
current pw-top start counting from 0 again, it does not change anything
globally on the server. It's still usefull because you can use it to
let it count the number of new errors since the keypress.
2025-04-30 15:10:15 +02:00
Wim Taymans
8d3cb2cd84 filter-graph: clean control_port array on unload
Because we created it when we loaded the graph.
2025-04-30 13:18:34 +02:00
Wim Taymans
aa67998e26 filter-graph: process controls after loading the graph
Do some of the counting of the nodes and controls when we add a node
to make things easier later.

Do the setup of the graph controls after loading the graph because we
know exactly how many controls we will have.

Fixes controls being unavailable until the filter-graph is activated.
2025-04-30 12:21:39 +02:00
Wim Taymans
237c0197c6 filter-chain: add props only once
Only add the properties offset in the builder after we actually got a
property or else we end up with the same property twice.
2025-04-30 12:20:31 +02:00
Wim Taymans
664359a020 netjack2: use strncpy to copy the header
It pads the remaining bytes in the header with 0 bytes so that the
memory doesn't contain uninitialized data.
2025-04-30 11:02:58 +02:00
Wim Taymans
a9083c7519 netjack2: improve shutdown
Destroy the sources from the io handler immediately when there is an
error so that we don't end up in endless error wakeups.

Schedule the free from the main loop and make sure only one can ever
run.
2025-04-30 11:00:42 +02:00
Wim Taymans
743d86500c netjack2: fix trace_fp compilation 2025-04-29 18:36:54 +02:00
Wim Taymans
6e8db1cd4a netjack2: handle connection errors in more cases 2025-04-29 18:09:02 +02:00
Wim Taymans
c7b318523d netjack2: set timeout to sane value again 2025-04-29 17:35:40 +02:00
Wim Taymans
3856d29646 netjack2: implement driver and manager roles correctly
The manager is actually not supposed to decide much about the number of
audio and midi ports. It should just suggest a default when connecting
driver doesn't know.

Add a audio.ports parameters to manager and driver to suggest/ask for
the amount of audio ports. Let the audio.position/audio.channels be a
specification of the channel mask in case it matches the requested
channels, otherwise use AUX channels for the ports.

This means that we must derive the mode (sink/source/audio/midi) from
the ports that are negotiated in the manager and the driver, so delay
this until after negotiation.

Make sure all the possible modes work. For midi only streams, we can't
wait for the session manager to perform a PortConfig so do that
ourselves. Make sure we only use a source trigger when we have a sink.

Fixes #4666
2025-04-29 17:17:14 +02:00
Wim Taymans
18a5f884be netjack2: make function to clear events
Make a separate function to clear events instead of passing NULL as the
midi buffer and segfaulting.
2025-04-29 16:26:30 +02:00
Wim Taymans
78fe234bfe netjack2: copy the node.group to streams
Just in case we want them to be scheduled in the same group.
2025-04-29 09:17:35 +02:00
Wim Taymans
40dbc5f00f netjack2: keep per stream io_position
And handle the trigger failure with a warning and fallback.
2025-04-29 09:16:54 +02:00
Wim Taymans
3d6e77e96d netjack2: warn when the trigger fails 2025-04-29 09:16:01 +02:00
Wim Taymans
07f033c8da netjack2: keep position io per stream
Keep a position info for the stream it was set and then use the position
info for the stream that is driving the graph. Otherwise we might use a
destroyed position info.
2025-04-28 12:23:15 +02:00
Wim Taymans
b6cb76bf8d netjack2: implement ifname in the driver
See #4666
2025-04-28 11:13:33 +02:00
Wim Taymans
93ee66dcab netjack2: Improve docs
Remove unused option.
Clarify that channels and midi port are chosen by the server.

See #4666
2025-04-28 11:12:48 +02:00
Wim Taymans
84c18df626 ebur128: fix port name
Fixes #4667
2025-04-28 09:51:20 +02:00
Wim Taymans
14f48c7a1c acp: probe max 192 channels
Thr 256 channel probe can cause overflows because we use uint8_t for the
channel count in some places.

Fixes #4669
2025-04-28 09:47:43 +02:00
Wim Taymans
7e4dd9524f alsa-seq: add the source only on success
Otherwise if we have an error with the timerfd, we have the source fd
added and we close the device.
2025-04-28 09:47:22 +02:00
Wim Taymans
41665e6bb8 examples: handle I420 and IYUV formats
They are represented in PipeWire with 3 planes now.
2025-04-24 11:18:12 +02:00
Wim Taymans
7d6e2a6417 impl-link: refactor format negotiation
Make a new port_info structure that holds the link port information for
input and output. We can use this in some places and remove some
redundant code.

We can also pass a reference to this port_info as the work-queue
object, which makes it more natural to find the associated port info in
the various work queue callbacks.

Move the private pw_context_find_format to the link implementation,
where is it actually used.

Rework the format negotiation code to use an array of 2 port_info
structures with the two ports to negotiate. The negiotiation will
always use the first port_info as higher priority.

Make sure a driver port has a lower priority than the other port. We want
to negotiate the source/sink to something close that what is
provided/requested by the client. The client can always adapt to the
driver port format fields by giving a "don't care" value for the format
property (either unspecified or with an out of range default value).
2025-04-24 11:17:49 +02:00
Wim Taymans
abfad78fb3 pod: swap inputs for filter when invalid default
We usualy want to prefer the filter default value. When this value is
not within the valid range/alternatives, swap the logic and prefer the
defaults of the other pod.

This way we can have a filter with an invalid default that will then use
the preference of the other pod but still enforce some bounds.
2025-04-24 11:14:51 +02:00
Wim Taymans
8b01fce2bc filter: remove unused function 2025-04-24 11:09:40 +02:00
Wim Taymans
19f6d83fa2 pod: move some filter functions to compare 2025-04-24 11:09:09 +02:00
Wim Taymans
1cca24c585 videoconvert: consume input buffer in all cases
Return the input buffer when we get some error so that the other side
can send new data.
2025-04-24 10:58:04 +02:00
Wim Taymans
bcf0c0cf89 v4l2: only skip buffer for raw formats
We don't want to skip the first buffer for encoded formats because it
can contain the encoding parameters, in the h264 case, for example.
2025-04-24 10:57:49 +02:00
Wim Taymans
d1d580cafa pod: move common check outside of the loop 2025-04-24 10:44:20 +02:00
Wim Taymans
4774178c68 pod: struct has spa_pod as the body 2025-04-24 10:42:20 +02:00
Wim Taymans
2f21b27397 filter: build result in separate builder and copy
Build the filtered result into a new separate builder and copy it into
the result builder afterwards. This ensures the memory of the old
builder does not suddenly change when it gets reallocated.
2025-04-24 10:41:05 +02:00
Wim Taymans
205ee5b6b0 dynamic: add _continue
The continue functions takes a builder as the argument and makes a new
builder that starts from the old builder memory. If the old builder was
dynamic, the new one will also be dynamic. Because it's a separate
builder, the memory of the old builder will not be reallocated when
extended.

This makes it possible to freely read the memory from the old builder
while we construct the result in a new builder without having to worry
about reallocating the memory of the old builder. When the new object is
completed, it can then be copied into the old builder.
2025-04-24 10:40:59 +02:00
Wim Taymans
336a5d1ded ump: fix program change 2.0 to 1.0 conversion
The program change byte should not be shifted an extra bit, unlike all
the other messages.

Fixes #4664
2025-04-24 10:25:39 +02:00
Anders Jonsson
14f55663bf po: Update Swedish translation 2025-04-23 00:03:23 +00:00
Philippe Normand
2e409c0237 gst: src: Attach video meta when receiving DMABufs from PipeWire
Fixes getDisplayMedia() in WebKitGTK after regression introduced by:
https://gitlab.freedesktop.org/pipewire/pipewire/-/merge_requests/2330
2025-04-22 10:48:00 +01:00
Pauli Virtanen
46c4261998 bluez5: fix cmsg align in spa_bt_recmsg & smaller buffer 2025-04-21 14:46:58 +03:00
Pauli Virtanen
0d61cc1b1d bluez5: use kernel-provided RX timestamps
Use kernel-provided packet reception timestamps to get less jitter in
packet timings. Mostly matters for ISO/SCO which have regular schedule.

A2DP (L2CAP) doesn't currently do RX timestamps in kernel, but we can as
well use the same mechanism for it.
2025-04-21 10:22:50 +00:00
Pauli Virtanen
081116906d bluez5: bap: allow configuring server locations/context
Add configuration options for the BAP/PACS sink and source endpoint
location (= channel positions) and context settings.

Although BlueZ associates these with individual endpoints, in the PACS
spec they are actually device-global, so configure directly in monitor
settings.
2025-04-20 20:34:35 +03:00
Arun Raghavan
a4148c80b4 Makefile: Fix up shell/run rules 2025-04-18 14:05:12 -04:00
Arun Raghavan
31069b2626 Don't log to systemd during development
Can get a bit spammy if we're doing verbose logging.
2025-04-18 12:28:23 -04:00
Arun Raghavan
ebe9381236 gst: handle blocks and size allocation for encoded format
In case of encoded video we get n_planes as 0 from the video info so
passing that as n_datas is failing during the buffer negotiation. Make
sure to use an appropriate value based on whether we have raw video or
not.

Co-authored-by: Taruntej Kanakamalla <taruntej@asymptotic.io>
2025-04-17 15:21:38 -04:00
Wim Taymans
55f71520db midifile: unpack the UMP SysRT bytes correctly
They are packed in a native endian uint32_t so read it like that and
then use shifts to get the right bytes.
2025-04-16 18:33:36 +02:00
Simon Ruderich
c4a88dfe6c midifile: decode UMP SysRT messages 2025-04-16 17:57:44 +02:00
Wim Taymans
57326d65d9 ebur128: work around libebur128 bug
Versions 1.2.5 and 1.2.6 don't scale the window in ms correctly, leading
to excessive memory allocation, so work around this here.
See https://github.com/jiixyj/libebur128/pull/132

Fixes #4646
2025-04-14 11:35:35 +02:00
Vinit Mehta
3140ede326 bluez5: Fix return status for parse_qos_settings 2025-04-14 07:26:28 +00:00
Pauli Virtanen
e9dae61cca bluez5: simplify BAP settings parsing and use device settings for them
Parse BAP settings in a single place, and simplify QoS customization a
bit.

Ensure the selected preset gets selected.

For all the BAP codec settings, use device settings instead of global
monitor ones.
2025-04-14 07:26:28 +00:00
Vinit Mehta
6e57510d6b doc: Add BAP QoS config & select option
This adds configuration options for BAP unicast QoS based on user
config parameters
2025-04-14 07:26:28 +00:00
Vinit Mehta
55372a41b1 bluez5: Add support to select BAP QoS config
The current BAP QoS configuration allows to register a sampling
frequency based on the configuration done using wireplumber configuration.
However, for a scenario were the user need to use a specific SDU framelength
it cannot be done as the select_bap_qos function selects the QOS based on
priority and hence it will use the best possible config rather than the user
configured.

This PR adds option to select the QoS set based on user configured value. If
the remote device doesn't have the user configured capabilities it will always
use the best priority config.

Further, this change also allows the user to set RTN, Latency, Delay QoS config
for certain use case to have controller use optimum bandwidth usage.

Below are the example configuration on setting LC3 capabilities in config file:

bluez5.bap.set_name = "48_2_1"
bluez5.bap.rtn = 5
bluez5.bap.latency = 20
bluez5.bap.delay = 40000
bluez5.framing = false
2025-04-14 07:26:28 +00:00
Vinit Mehta
d22a4d60b3 doc: Add BAP QoS config & select option
This adds configuration options for BAP unicast QoS based on user
config parameters
2025-04-14 07:26:28 +00:00
Vinit Mehta
6dfb164cab bluez5: Add support to configure & select BAP QoS config
The current BAP unicast QoS configuration allows to register a sampling
frequency based on the configuration done using wireplumber configuration.
However, for a scenario were the user need to use a specific SDU framelength
it cannot be done as the select_bap_qos function selects the QoS based on
priority and hence it will use the best possible config rather than the user
configured.

This PR adds option to select the QoS set based on user configured value. If
the remote device doesn't have the user configured capabilities it will always
use the best priority config.

Further, this change also allows the user to set RTN, Latency, Delay QoS config
for certain use case to have controller use optimum bandwidth usage.

Below is the example for the options that can be configured & selected
in config file:

bluez5.bap.set_name = "48_2_1"
bluez5.bap.rtn = 5
bluez5.bap.latency = 20
bluez5.bap.delay = 40000
bluez5.framing = false
2025-04-14 07:26:28 +00:00
Kenny Levinsen
558721efc2 audioconvert: Increase param length limit to 4096
Parameter values read into a 512 byte long buffer, which is insufficient
for medium to long filter-graph parameters.

Increase the buffer to 4096 bytes to give some wiggle-room.
2025-04-11 20:03:25 +00:00
Christian Glombek
9e3f9607a6 raop: Add fp_sap25 encryption type
Add support for FairPlay SAP v2.5 (encryption type 5) type devices such as Apple Home Pod Minis.

Apparently only these devices require the `POST /feedback` heartbeat, so fix that.
2025-04-10 23:13:46 +02:00
Pauli Virtanen
4c51e6518b bluez5: ldac decoding support
Add support for LDAC decoding, if libldac decoder is available.
2025-04-10 13:22:57 +00:00
Pauli Virtanen
bbe1587f71 bluez5: fix volume ids
Node ids don't map directly to volume ids. Fix the indexing.
2025-04-09 07:50:30 +00:00
fossdd
b15ec9bec9 doc: fix typo in pw-link(1) 2025-04-09 07:48:10 +00:00
Pauli Virtanen
42b92a3487 pw-loopback: add missing --channel-map long option 2025-04-09 07:47:32 +00:00
Sanchayan Maity
bb1bb07f6c gstpipewiresrc: Handle stream being disconnected
When PW source is used with something like Camera and the camera is
disconnected, all buffers are removed and stream will be paused.

When using PW sink with source, the sink side pipeline can go to EOS.
This again results in all the buffers being removed and stream being
paused on the source side. PW source side pipeline can also crash if
the sink was in the middle of frame copying a buffer to render which
got removed.

Handle this scenario by sending a flush-start event at the start of
buffer removal and flush-stop at the end followed by an end of stream
or pipeline error depending on user selection.
2025-04-09 07:45:27 +00:00
Pauli Virtanen
e9a2406314 CI: bump to Fedora 41
Fedora 40 EOL is next month, and newer Doxygen version is better for
docs.pipewire.org.
2025-04-06 12:12:59 +03:00
Pauli Virtanen
e3122a8555 doc: add links to docs of other versions 2025-04-05 14:36:43 +03:00
Pauli Virtanen
b8ad9acbc7 CI: build also 1.4 docs 2025-04-05 11:27:32 +00:00
Wim Taymans
e355df3785 channelmix: fix channel_mask bits iteration
Iterate the number of bits in the channel mask based on the number of
bits in the mask, not the max amount of channel positions.
2025-04-04 17:06:43 +02:00
Wim Taymans
a99ed4da2a raop: fix byte array initialization
Initialize the byte array with bytes instead of a string because the 0
byte at the end of the string does not fit in the array and causes a
compiler warning.
2025-04-04 16:12:41 +02:00
Wim Taymans
031014bbab acp: remove channel limit from API
Internally bump the channel limit and allocate the channel map
dynamically.
2025-04-04 15:46:03 +02:00
Wim Taymans
8205038ffb buffers: increase max datas limit
Increase the max amount of buffer datas allowed.
2025-04-04 15:46:03 +02:00
Wim Taymans
a9f12537d1 pulse: clamp channel numbers to right values
When converting between pipewire and pulse channelmaps, make sure we
clamp the channel numbers to the the right limit.
2025-04-04 15:46:03 +02:00
Wim Taymans
722776cf65 Remove some hardcoded channel number values
Mostly related to the number of channels.
2025-04-04 15:46:03 +02:00
Wim Taymans
5cfd461ba2 alsa: Use the configured max channels
Don't hardcode the max channels to 64 but use the globally configured
SPA_AUDIO_MAX_CHANNELS value.
2025-04-04 15:46:03 +02:00
Quentin
9d6098f8c6 Small changes, more natural sounding 2025-04-03 23:31:55 +00:00
Sanchayan Maity
77143e54d9 gstpipewiresrc: Fix re-linking for audio
For a pipeline like below, we might want to dynamically switch the audio
source.

gst-launch-1.0 -e pipewiresrc autoconnect=false ! queue ! audioconvert ! autoaudiosink

On switching to a different audio source, any one of driver, quantum
or clock rate might change which changes the return `result` value of
gst_pipewire_clock_get_internal_time.

This can result in the basesrc create function incorrectly waiting in
gst_clock_id_wait. We post clock lost message to fix this. In the case
of gst-launch, it will set the pipeline to PAUSED and then PLAYING to
to force a new clock and a new base_time distribution.

Without the clock lost message, the following can be seen

before re-linking to a different source
0:00:30.887602864 79499 0x7fffe8000d40 DEBUG              GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:17.024565416 now 0:00:17.024109144 diff (time-now) 456272

after re-linking to a different source
0:00:45.790843245 79499 0x7fffe8000d40 DEBUG              GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:31.927694059 now 0:00:17.066883864 diff (time-now) 14860810195

With the clock lost message, the following can be seen

before re-linking to a different source
0:01:09.336533552 89461 0x7fffe8000d40 DEBUG              GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:58.198536772 now 0:00:58.197444926 diff (time-now) 1091846

after re-linking to a different source
0:01:21.659827958 89461 0x7fffe8000d40 DEBUG              GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:28:24.853517646 now 0:28:24.853527204 diff (time-now) -9558

Note the difference in `time` and `now` fields of the above log message.

This is easy to reproduce by using a pipewiresink as the audio source
with a pipeline like below, as one of the sources during switching.

gst-launch-1.0 -e audiotestsrc wave=ticks ! audioconvert ! audio/x-raw,format=F32LE,rate=48000,channels=1 !
pipewiresink stream-properties="props,media.class=Audio/Source,node.description=pwsink" client-name=pwsink

Applications need to handle the GST_MESSAGE_CLOCK_LOST message in their
bus handlers.
2025-04-03 19:20:34 +05:30
Arun Raghavan
dd683176c2 gst: sink: Set provide clock flag if not in provide mode
Handle a theoretical corner case of an element that is first started
with mode=provide, and then restarted without mode=provide.
2025-04-03 06:59:31 -04:00
Wim Taymans
832c5a6d25 fix printf modifier for gsize
Fixes #4641
2025-04-02 13:25:31 +02:00
Wim Taymans
5c547d58d1 adapter: handle builder overflow 2025-04-02 10:39:34 +02:00
Taruntej Kanakamalla
ee2c6eb41e gst: sink: Manage buffer pool memory manually
Let's make sure we own the memory in buffers, so that we can be
resilient to the PW link going away. This currently maintains the status
quo of copying data into the pipewirepool for sending to the remote end,
but moves the allocation of buffers so that ownership is maintained by
the sink in all cases.

There are some tricky corners, especially with bufferpool vs. buffers
param negotiation -- bufferpool parameters can be negotiated in
GStreamer before the link even comes up, so we try to adapt the buffers
param to use the negotiated value. For now, that is more brittle than
tying those two aspects together. We can revisit this if we can find a
way to tie pipeline state and link state more closely.

Co-authored-by: Arun Raghavan <arun@asymptotic.io>
2025-04-02 08:20:38 +00:00
Arun Raghavan
1b258f4ecc gst: sink: Only add VideoCrop meta for video 2025-04-02 08:20:38 +00:00
Wim Taymans
774f9cbb80 videconvert: fix compilation on 32 bits 2025-04-02 10:15:37 +02:00
Wim Taymans
bf952a6e4b videoconvert: improve setup of DSP mode
Parse and use DSP formats.

Redo the conversion setup when the formats changed. We usually do this
when starting the node but the formats can change while running as well.
2025-04-01 16:35:32 +02:00
Wim Taymans
da69bddb95 adapter: Improve convert setup
Always do configure_convert, even when the passthrough state didn't
change, for example when going from none to convert.
2025-04-01 16:31:25 +02:00
Wim Taymans
1adc9e5445 videoadapter: init the builder for each param
Or else we keep on adding items until we overflow.
2025-04-01 16:24:40 +02:00
Wim Taymans
aca673b3ab impl-link: improve debug log
Log the format after we patch it up and log some context lines.

Move some info log to debug.
2025-04-01 10:19:40 +02:00
Wim Taymans
94910f77c9 pod: handle builder overflows
When the builder is overflowed, we might get a NULL pod. This is a valid
situation that we need to handle because it can be used to get the
required builder buffer size.
2025-04-01 10:18:05 +02:00
Wim Taymans
5c5075f4d6 videoconvert-ffmpeg: copy complete passthrough buffer data
We also need to copy the data type, flags and sizes.
2025-03-28 16:10:42 +01:00
Wim Taymans
b23161d772 videoconvert: always put frame size on Format param
We can now set the 0x0 frame size as the default as a wildcard.
2025-03-28 16:09:36 +01:00
Wim Taymans
5f4c0cdd1e improve debug and error reporting a little 2025-03-28 16:08:57 +01:00
Wim Taymans
ae1bbc93d8 videoconvert: return error on invalid formats 2025-03-28 16:08:19 +01:00
Wim Taymans
dba31d7e2a videoadapter: use the supported dataType in Buffer param
Get the dataType field from the Buffer param. This is a mask of the
supported data types for the buffers. Pass this to the allocating node
if there is one, otherwise use MemPtr as the allocated format.
2025-03-28 16:04:54 +01:00
Wim Taymans
d0c4b491da v4l2: handle nearest set_format
The set_format function can return 1 when the format was adjusted to the
nearest supported format so return this from the port_set_param
function.

This instructs the adapter to recheck the configured format so that it
can store the adjuted format on the converter.
2025-03-28 16:00:51 +01:00
Wim Taymans
b501290bd5 audioconvert: support DYNAMIC data again
Because we advertize on out ports that we support DYNAMIC data, we need
to read the data pointer directly from the buffer and only fall back to
our cache (mmaped) pointer when it is NULL.

With DYNAMIC data, the peer element (mixer-dsp) directly copies the
input data pointer into the buffer data in the processing loop in order
to avoid a memcpy when there is no mixing needed.
2025-03-27 17:00:11 +01:00
Wim Taymans
328718f958 audioconvert: add support for buffer data mmap
When there is no data and the buffer is mmapable, try to mmap it. Unmap
again when clearing the buffers.

Use the mmaped data pointer of the buffer when processing.
2025-03-27 15:37:19 +01:00
Wim Taymans
9ceb4310f8 videoconvert: unmap buffer memory as well
Set a flag when we mmaped the buffer memory so that we can unmap it
again when clearing the buffers.
2025-03-27 15:21:12 +01:00
Wim Taymans
abc03ec810 adapter: fix buffer alloc order
Prefer to let the follower allocate buffers. If we are allocating
buffers, first do use_buffers on the allocating node or else the
non-allocating node just ends up with NULL buffers.
2025-03-27 09:29:52 +01:00
Wim Taymans
afb4a2f49c Revert "gst: src: Minor fix for offsets"
This reverts commit 4c200183b9.

The offset is already applied when we share/copy the memory in the
target buffer.
2025-03-26 17:56:14 +01:00
Wim Taymans
479ba33685 videoconvert-ffmpeg: support transcoding
When the input and output is an encoded format but the dimensions are
different, do a decode, scale and encode.
2025-03-26 17:52:26 +01:00
Wim Taymans
f8dcf32c8d videoconvert-ffmpeg: fix passthrough mode
Keep the passthrough flag up to date when we unset a port format or when
it changes.

We should only fill in the buffer data/fd when the ALLOC flag is set.

We should only take the passthrough input buffer as output when we are
in passthrough mode.

Copy the header metadata.
2025-03-26 17:52:26 +01:00
Wim Taymans
2873d7a6cc adapter: add Header metadata by default
Firefox needs this but we should eventually check the Meta Params to
decide on this.
2025-03-26 17:52:26 +01:00
Arun Raghavan
d7cb68bfc7 gst: pool: Some refinements to min/max handling
A number of changes for correctness.

  1) We expose the actualy min and max values we support in the
     allocation query.

  2) We don't support max_buffers as 0, as unlimited buffers is not an
     option

  3) In ParamBuffers, we request the max_buffers from bufferpool config,
     as we cannot dynamically allocate buffers
2025-03-26 12:08:35 -04:00
Arun Raghavan
5ef13489db gst: sink: Correctly set size and offset on planar data
We need to make sure the memory sizes are correctly initialised so the
meta makes sense, and we don't copy the meta from the input buffer as
that doesn't make sense given we have our own meta already.
2025-03-26 12:08:35 -04:00
Arun Raghavan
dfdc3e333a gst: sink: Minor style consistency fixup 2025-03-26 09:51:53 -04:00
Arun Raghavan
4c200183b9 gst: src: Minor fix for offsets
I don't see any actual usage of left/top padding (yet), but we should
account for chunk offset in addition to the overall size.
2025-03-26 09:26:38 -04:00
Wim Taymans
cc6081b70d gst: fix video metadata offsets
The offsets in GStreamer are always offsets into the buffer memory where
the plane starts so set this to the accumulated plane sizes.
2025-03-26 12:30:41 +01:00
Wim Taymans
241ec04d88 videoconvert: support planar formats
Keep track of the per-place strides and sizes and use that to fill the
output buffer.
2025-03-26 12:29:26 +01:00
Wim Taymans
ea7cfb9e94 audioconvert: make sure the converter is in None mode
The audioconverter starts in Convert mode, so make sure it goes to the
None mode before we attempt to reconfigure ourselves.

Also remove the ports on audioconvert when going to None mode. This used
to somewhat work because we configured it in DSP mode without any
params, which is like None without ports.
2025-03-26 10:26:41 +01:00
Wim Taymans
636e123fdd videoconvert-ffmpeg: set better size suggestion
Use a better suggestion for the buffer size.
2025-03-26 09:54:12 +01:00
Wim Taymans
5fb9716ce7 gst: require a buffer size of at least 1
Setting the default size to 0 and outside of the min/max range now means
that there is no suggestion for the size and it should use the
suggestion of the peer.
2025-03-26 09:52:22 +01:00
Wim Taymans
beb075c5a6 adapter: only use DYNAMIC buffer data when supported 2025-03-26 09:51:09 +01:00
Wim Taymans
6015fa353a adapter: call reconfigure_mode instead of configure_convert
configure_convert does not set up the current mode, so call the more
complete reconfigure_mode to set the initial converter mode.
2025-03-26 09:43:58 +01:00
Wim Taymans
aea77dc055 spa: avoid duplicate default value
When filtering an enum/none against a range/step, make sure we don't add
the default value twice.
2025-03-26 09:41:45 +01:00
Arun Raghavan
439d5d04fe gst: sink: Don't provide clock in provide mode
Counter-intuitive as it seems, when we are driving the clock, we can't
also provide a clock from PipeWire to the pipeline -- we need the
pipeline to drive the graph.

So we make the mode control whether we provide a clock or not.
2025-03-25 21:38:15 +00:00
Sanchayan Maity
3c62d29a55 gstpipewiresrc: Fix re-linking
When using PW source, one might want to dynamically link PW source to
a different source. Setting possible_caps to NULL prevents the caps
intersect from returning a successful result on format change. Do not
set possible_caps to NULL as we get that from peer caps which should
stay the same ideally for the duration of pipeline run. That allows
re-linking PW source any number of times with a pipeline like below.

gst-launch-1.0 pipewiresrc autoconnect=false ! queue ! video/x-raw,format=YUY2 ! videoconvert ! xvimagesink

The above pipeline can be made to switch between a camera source and a
screen capture source like wf-recorder.

Note that this fix only improves the status quo and won't work if the
peer caps change due to a re-negotiation.
2025-03-25 17:49:13 +00:00
Arun Raghavan
4ae348254e ci: Bump to latest ci-templates 2025-03-25 17:27:48 +00:00
Sanchayan Maity
eb534b4515 gst: pipewiresrc: Fixate caps if intersect did not return fixated caps
We might end up in a situation where depending on the pipeline,
intersect might not give us fixated caps.

Possible example of such a pipeline can be below.

gst-launch-1.0 -e pipewiresrc target-object=<path> ! audioconvert !
audio/x-raw,format=S16LE,rate=48000,channels=2 ! lamemp3enc !
filesink location=test.mp3

This results in non-fixated caps like below when intersecting caps from
format param and possible_caps which depends on what we have downstream
in the pipeline.

audio/x-raw, layout=(string)interleaved, format=(string)S16LE, rate=(int)48000, channels=(int)2, channel-mask=(bitmask)0x0000000000000003;
audio/x-raw, layout=(string)interleaved, format=(string)S16LE, rate=(int)48000, channels=(int)2

To fix this, fixate the caps explicitly.
2025-03-25 15:47:28 +00:00
Philippe Normand
d37b0b4cd2 gst: deviceprovider: Fix a leak and a heap-use-after-free
The device passed to gst_device_provider_device_add() is transfer:floating, so
we need increase its ref, otherwise the pointer we keep internally will be a
dangling ref.

Also gst_device_provider_device_remove() doesn't actually release the device, so
we have to do it ourselves.

Fixes #4616
2025-03-25 15:33:43 +00:00
Wim Taymans
1515e46d50 ffmeg: fix default number of buffers
Make the MAX buffers different from the min and make sure the default
value is between min and max.
2025-03-25 16:19:50 +01:00
Wim Taymans
437e486d6e spa: improve filter Enum and None results
When we construct an Enum, check if we only added 1 value and remove the
duplicate default value we added. If we added more values, promote the
choice to an enum.
2025-03-25 16:17:38 +01:00
Wim Taymans
4ddb17c4b5 videoconvert: don't load the dummy converter
Just don't load any converter at all, the dummy converter has some
issues.
2025-03-25 15:14:03 +01:00
Philippe Normand
e584cee066 gst: src: Fix buffer pool handling in case of caps renegotiation
In case negotiation is first attempted with unfixed caps, bufferpool support was
unconditionally disabled. Then at a second caps negotiation attempt it wasn't
restored according to the property value.
2025-03-25 12:50:42 +00:00
Arun Raghavan
14b7b31bd9 videoadapter: Use dummy converter by default
The ffmpeg converter doesn't quite work yet for planar formats at least,
so let's leave the dummy as the default till that works.
2025-03-25 08:26:29 -04:00
Wim Taymans
7da66f8a5f spa: simplify filtering 2025-03-25 12:57:40 +01:00
Wim Taymans
fff8f63c0e spa: reject impossible ranges after filtering 2025-03-25 12:50:30 +01:00
Wim Taymans
64b2792d61 spa: refactor range/step check 2025-03-25 12:41:44 +01:00
Wim Taymans
77b23c619e spa: Improve Range/Step code readability
Use min,max,step variables to store the choice values for better
readability.
2025-03-25 11:58:53 +01:00
Wim Taymans
4b3be9cc9b spa: merge Range and Step filter together
They share all of the code and the step just has an extra check for
the step values.
2025-03-25 11:47:28 +01:00
Wim Taymans
b238c9d7a1 pw-cat: improve sndfile file format debug info
Print the endianness, container name and the sample format nicely
instead of dumping the hex values.
2025-03-24 18:49:41 +01:00
Wim Taymans
dda60fb374 pw-cat: prefer AU format when using stdin/stdout
WAV is actually not usable for streaming output by sndfile.

See #4629
2025-03-24 17:54:32 +01:00
Wim Taymans
367e756ebe videoconvert-ffmpeg: remove debug 2025-03-24 11:45:29 +01:00
Wim Taymans
824354f38e videoadapter: sync with audioadapter 2025-03-24 11:45:11 +01:00
Wim Taymans
7e67daa292 audioadapter: negotiate formats from output to input
Try to avoid conversions by taking the output port format and using that
as a filter for the input port format.

Because filtering pods prefer the values of the filter, this will prefer
the output format values and thus avoid conversions.
2025-03-24 11:39:20 +01:00
Wim Taymans
de54cfc475 audioconvert: improve tmp buffer allocation
Use per port allocated memory so that we can easily increase the size
and add more buffers. This is necessary when we add filter-graphs that
require more ports.
2025-03-21 15:18:54 +01:00
Sanchayan Maity
b8d5334462 gst: pipewireformat: Do not use RANGE if values are equal
This fixes assertion from the underlying gst_value_collect_int_range
when using gst_caps_set_simple with range types when the values are
equal.
2025-03-21 16:18:28 +05:30
Pauli Virtanen
6fe1c6d67b alsa: seq: double-check midi client version
Check midi client version after setting it, to see if it was really
successfully set.  Old kernels without UMP don't know about the midi
version fields, so snd_seq_set_client_midi_version() appears to fail
silently there.
2025-03-20 21:39:40 +02:00
Pauli Virtanen
e0938303e6 acp: Sennheiser GSX stereo profile
The card can output at higher sample rates in stereo profile, so add
that.
2025-03-20 12:24:56 +00:00
Robert Mader
2625983a23 systemd: Depend on dbus.service
Solution suggested by Xi Ruoyao.

The dbus user service is required for various features - the summary says:
'dbus (Bluetooth, rt, portal, pw-reserve)'

On session logout the dbus service gets shut down while the Pipewire one
relies on a timeout. If a user logs in again before PW timed out, the
later stays alive but doesn't handle re-connecting to the dbus service
of the new session, breaking the camera portal and potentially other
features.

Thus hard-depend on the dbus service (if enabled at build time) and thus
shut down together with it.
2025-03-20 12:23:22 +00:00
Wim Taymans
923b8b48ec alsa-seq; enable UMP again when we can
It got accidentally disabled for debugging
2025-03-20 12:55:09 +01:00
Wim Taymans
7662a01f85 examples: warn when texture locking fails
New SDL seems to fail when locking YUY2 now.
2025-03-20 11:21:56 +01:00
Wim Taymans
4e0545aa04 videoconvert: get the correct strides
Use ffmpeg to get the right stride for the negotiated format instead of
using a wrong hardcoded value.
2025-03-20 10:57:26 +01:00
Wim Taymans
6f8a814f29 pod: use default value of filter
When using a filter, it makes more sense to use the default value
of the filter as a first attempt.

One case is in adapter when we try to find a passthrough format first. The
audioconverter suggests a default rate of the graph rate but the follower
filters this out for another unrelated default value and passthrough is not
possible (altough it would be because the default value of the filter is
in the supported follower range).

Fixes #4619
2025-03-19 17:53:05 +01:00
Wim Taymans
a460842769 netjack2: fix the large midi events offset
The midi events have their large data offsets relative to the start of
the buffer and the large data is at the end of the buffer. Because we
copied it down, right after the events, but we didn't adjust the
offsets, calculate a correction offset when unpacking the events.
2025-03-19 17:53:05 +01:00
Wim Taymans
e3a068de7d netjack2: set correct max midi buffer size
It depends on the negotiated period size, not the graph quantum.
2025-03-19 17:53:05 +01:00
Wim Taymans
3be88eacb8 netjack2: copy large midi events to the end of the buffer
There is no need to keep an extra free byte at the end and it will cause
us to lose a byte when we copy the large midi events down.
2025-03-19 17:53:05 +01:00
Wim Taymans
795e917716 jack: write midi events to end of buffer
There is no need to keep one extra byte at the end of the buffer,
we can write the event up to the last byte.
2025-03-19 17:53:05 +01:00
Wim Taymans
bcde5cbd8a audioconvert: rework the filter-graphs a little
Use a simple free/active linked list for the filter-graphs and insert
the new filters in the right position in the list. Then simply copy the
list to an array for the processing thread.

when reconfiguring, set up all the filters again because the number of
channels might have changed.
2025-03-19 17:53:05 +01:00
Wim Taymans
de2ab7cac9 filter-graph: add support for channel positions
Make it possible to define a channel position in filter-graph.
Use the channel positions to perform the final channelmix.
2025-03-19 17:53:05 +01:00
Wim Taymans
9b2b420cf5 spa: we need ALSA >= 1.2.11 for snd_seq_ump_ev_clear() 2025-03-19 17:53:05 +01:00
Wim Taymans
91806ff747 netjack: handle overflow in midi buffer append 2025-03-19 17:53:05 +01:00
Wim Taymans
33584dae1d ump: handle sysex from UMP to MIDI1 better
SysEx in UMP can span multiple packets. In MIDI1 we can't split them up
into multiple events so we need to collect the complete sysex and then
write out the event.

Fixes SysEx writes to ALSA seq by running the event encoder until a
valid packet is completed.

Also fixes split MIDI1 packets in the JACK API when going through the
tunnel or via netjack.
2025-03-19 17:53:05 +01:00
Wim Taymans
ada2146692 jack-tunnel: improve port names
Prefix midi port names with midi_ and number ports from 1 instead
of 0.
2025-03-19 17:53:05 +01:00
Wim Taymans
a241495eaf jack-tunnel: support passing port names to link
Add jack.connect-audio and jack.connect-midi to specify an array of port
names to link to instead of the default phyisical ports.

Also actually fixes linking the midi ports correctly.
2025-03-19 17:53:05 +01:00
Wim Taymans
74035f0a34 rtp-sdp: format ptime in the C locale
Don't place locale dependent strings in the SDP.

Fixes #4615
2025-03-19 17:53:04 +01:00
Wim Taymans
21e9fdf8ad conf: add a jack-tunnel config snippet
The minimal config might want to enable JACK as a backend so add
an example config for this.
2025-03-19 17:53:04 +01:00
Sanchayan Maity
d329dac6ba gst: Do not use video only info for SPA_PARAM_BUFFERS_blocks
We mistakenly used video only info for setting SPA_PARAM_BUFFERS_blocks,
which would be completely incorrect for audio.

Fixes 6c9ada270.
2025-03-14 12:41:38 +00:00
Wim Taymans
4ffa82b590 jack: add another node name fallback
Use the object-path as a fallback name for the node.
2025-03-14 13:28:48 +01:00
Wim Taymans
4e421e0012 audioadapter: return error code from set_param 2025-03-14 13:26:21 +01:00
Wim Taymans
f1ed12fc8d audioconvert: PortConfig only needs channels and position 2025-03-14 13:25:45 +01:00
Wim Taymans
f0e09ae363 filter-graph: make the filter-graph ports dynamic
When parsing the graph, parse the input and output port names into
a separate string array. This was we can keep them around when
setting up the graph.

Instead of setting up the graph right after loading it, do the graph
setup when we activate the graph. This makes it possible to pass the
input channels to the filter-graph and let it create the right amount of
plugins and ouput channels.

When setting up the graphs in the audioconverter, pass the current
number of channels as the input to the graph and keep track of the
channels that each filter produces.

This way we can also load a custom upmix or downmix graph, for example.
2025-03-14 10:10:18 +01:00
Wim Taymans
76619eaa1d audioconvert: fix the filter-graph samplerate
The filter graph runs before or after the resampler depending on the
direction of the conversion.
2025-03-14 10:03:44 +01:00
Pauli Virtanen
bd3a8b594f spa: acp: indicate ALSA UCM profile errors in UIs
Add "[ALSA UCM error]" to the end of card description, to indicate
something is wrong.
2025-03-13 21:25:55 +00:00
Pauli Virtanen
4338189f76 spa: acp: allow also too few channels in SplitPCM configs
GoXLR Mini has different numbers of channels actually available (21, 23,
or 25) depending on its firmware/etc, but its UCM profile specifies
always 23. The count can then be bigger or smaller than what is actually
available.

Fail a bit more gracefully in the case of too few channels: create all
the split devices specified by the profile. The channels that aren't
actually available in HW just won't get routed anywhere.

ALSA upstream IIUC is saying that the channel counts should be fixed, so
spew warnings that say the UCM profiles are wrong if they look wrong.
2025-03-13 21:25:55 +00:00
Sanchayan Maity
6c9ada270b gst: Fix handling of video planar formats
Tiled formats are not tested and supported yet.
2025-03-13 18:53:23 +05:30
sunyuechi
60981494d6 Add x86 CPU check in meson.build for clang build fix
have_avx = cc.has_argument(avx_args)

gcc generates an error when AVX is unsupported, whereas clang only
produces a warning.

Thus, using Clang on the RISC-V platform incorrectly enables AVX file
compilation, leading to build failures.
2025-03-12 20:49:26 +00:00
Frédéric Danis
1af1fc846c bluez5: backend-native: Add volume support to HFP HF
The volume synchronization could be done even if there's no audio link
and so no transport opened.

This patch allows to send the Speaker (AT+VGS) and Microphone (AT+VGM)
commands at the end of the SLC. And to exchange volume updates using the
telephony DBus interface, even without a transport.
2025-03-12 11:01:50 +01:00
Wim Taymans
48a32e4ced loop: remove return from function returning void
Fixes #4603
2025-03-11 16:34:28 +01:00
Wim Taymans
6598938f12 doc: update MIDI doc 2025-03-11 16:31:08 +01:00
Wim Taymans
8e8306cad8 doc: link to the protocol message documentation 2025-03-11 16:26:06 +01:00
Wim Taymans
b997ff8ac1 devolpment is 1.5.0 2025-03-11 15:14:03 +01:00
Wim Taymans
bf3c7aa6e1 alsa-seq: fix UMP output
We need to set the UMP flag, which is done with
snd_seq_ev_set_ump_data() to make it output the midi data.
2025-03-11 13:29:38 +01:00
Wim Taymans
ff08c28b62 alsa-seq: avoid uninitialized warning 2025-03-11 12:33:08 +01:00
Wim Taymans
badd8691bd audioconvert: remove some unused fields 2025-03-11 11:52:52 +01:00
Wim Taymans
d43fb09ea1 audioconvert: configure resample channels correctly
Depending on the direction of the conversion, we run the resampler
before or after the channelmix. This means we need to use the channel
count before or after the channelmixer instead of always using the
channels after channelmixing.

Fixes #4595
2025-03-11 11:50:48 +01:00
Pauli Virtanen
a503244c10 spa: avoid casting between snd_seq_event_t & snd_seq_ump_event_t
Although the two structs have same initial sequence, it's not really
correct to cast between their pointers. Alsa-lib also does this only
internally, but not in API.
2025-03-10 18:12:54 +00:00
Pauli Virtanen
fd5bd5ca6e spa: fix ALSA UMP support detection in meson 2025-03-10 18:12:54 +00:00
Pauli Virtanen
4379cf446f spa: alsa: support also MIDI-1.0 IO for ALSA seq
Support also non-UMP IO with ALSA seq, in case either alsa-lib or the
kernel does not have UMP enabled.

Add configuration option "api.alsa.seq.ump" for optionally turning UMP
I/O off, for easier debugging.
2025-03-10 18:12:54 +00:00
Nikolay Borodin
6620c6cde1 spa: alsa: allow building without UMP in libalsa
Allow building with older libalsa releases that don't have UMP.
2025-03-10 18:12:54 +00:00
msizanoen
9bc29b4b37 systemd: Disable pipewire user services for root
The `access(2)` based multi-user mediation mechanism doesn't quite work
for the root user, which may cause it to conflict with a running
foreground user session. Prevent this by not running the user service at
all for the root user, which nobody should be doing anyway.
2025-03-10 20:10:31 +07:00
Jan Grulich
4442ab007f stream: don't emit process when disconnecting
Commit b160a72018 introduced this change
before, but it was omitted in e1e0a886d5.

This makes again sure we don't call process callback while disconnecting
stream.

Fixes #3314
2025-03-10 13:23:10 +01:00
Pauli Virtanen
5c1d6fb5ad spa: acp: make spa-acp-tool debug output easier to read
Include log level, file/line numbers, and indent messages for debug
levels.
2025-03-09 16:15:56 +02:00
Pauli Virtanen
6d51b4bb11 spa: acp: be more noisy when UCM profiles fail to be supported
Generally ALSA UCM profiles should all work as they're supposed to be
device-specific, so be more noisy when the profile fails to be supported
due to the PCM device failing to open.

Some logging on the probe outcome in failure case also makes
spa-acp-tool etc. log output easier to read.
2025-03-09 13:10:37 +02:00
Pauli Virtanen
bc890d3b83 spa: acp: in SplitPCM probe channel count and allow excess
In SplitPCM mode, Focusrite Scarlett Gen 4 (USB 1235:8218) UCM profile
specifies "CaptureChannels 2" for the Mic1/2 inputs, but
snd_pcm_hw_params_set_channels(2) fails for the HW device.

Fix by not requiring the channel count to be exact for SplitPCM, but
also allow larger numbers of channels than what UCM profile specifies.
2025-03-09 13:04:26 +02:00
Jan Palus
ef023916b9 module-roc: require roc >= 0.4.0
3270bd4 introduced changes reyling on features from roc 0.4.0
(upstream commit: d18d342)
2025-03-07 08:35:42 +00:00
Frédéric Danis
0e92ab9307 bluez5: backend-native: Fix 3way active call hangup
HFP/HF/TWC/BV-03-C test, which setup an active and a held calls,
expects to receive AT+CHLD=1 (release and swap calls) instead of
AT+CHUP on active call hang up request.

As this changes the active call to disconnected and held call to
being active, the call states should be managed in hfp_hf_hangup
instead of waiting for +CIEV (callheld=0) event which will drop
the previously held call before AT+CLCC reply can inform this call
is now active.
2025-03-07 08:31:24 +00:00
Frédéric Danis
90b95ae065 bluez5: backend-native: Fix incoming call crash
HFP/HF/TWC/BV-01-C test creates an incoming call as soon as the SLC is
completed, i.e. a +CIEV: <callsetup>,1 event just after AT+CHLD=? reply
has been received. This try to parse the rfcomm->telephony_ag->call_list
which has not yet been created.

This commit move the telephony_ag creation to the SLC completed event.
2025-03-07 08:31:24 +00:00
Frédéric Danis
be1fc5f3a6 bluez5: backend-native: Fix ECNR support in HFP HF SDP record
Sending AT+ECNR is supported by the native backend
2025-03-07 08:31:24 +00:00
Wim Taymans
22951a9b87 protocol: document to client-node communication flow a little 2025-03-06 16:52:27 +01:00
607 changed files with 37386 additions and 22406 deletions

View file

@ -18,8 +18,8 @@ stages:
variables:
FDO_UPSTREAM_REPO: 'pipewire/pipewire'
# ci-templates as of Jan 27th 2022
.templates_sha: &templates_sha 0c312d9c7255f46e741d43bcd1930f09cd12efe7
# ci-templates as of Mar 25th 2024
.templates_sha: &templates_sha ef5e4669b7500834a17ffe9277e15fbb6d977fff
include:
- project: 'freedesktop/ci-templates'
@ -31,12 +31,15 @@ include:
- project: 'freedesktop/ci-templates'
ref: *templates_sha
file: '/templates/alpine.yml'
- project: 'freedesktop/ci-templates'
ref: *templates_sha
file: '/templates/debian.yml'
.fedora:
variables:
# Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2024-12-10.0'
FDO_DISTRIBUTION_VERSION: '40'
FDO_DISTRIBUTION_TAG: '2025-10-22.0'
FDO_DISTRIBUTION_VERSION: '42'
FDO_DISTRIBUTION_PACKAGES: >-
alsa-lib-devel
avahi-devel
@ -45,6 +48,7 @@ include:
dbus-devel
doxygen
fdk-aac-free-devel
file
findutils
gcc
gcc-c++
@ -55,6 +59,7 @@ include:
gstreamer1-plugins-base-devel
jack-audio-connection-kit-devel
libasan
liblc3-devel
libcanberra-devel
libebur128-devel
libffado-devel
@ -64,7 +69,6 @@ include:
libubsan
libusb1-devel
lilv-devel
libv4l-devel
libva-devel
libX11-devel
ModemManager-devel
@ -76,6 +80,7 @@ include:
sbc-devel
ShellCheck
SDL2-devel
spandsp-devel
systemd-devel
vulkan-loader-devel
webrtc-audio-processing-devel
@ -87,6 +92,9 @@ include:
openal-soft
readline-devel
pandoc
fftw-libs-single
fftw-devel
onnxruntime-devel
# Uncommenting the following two lines and disabling the meson entry above
# will re-enable use of Meson via pip but please consider using a newer distro
# image first or making the build system compatible instead! This is because
@ -101,7 +109,7 @@ include:
.ubuntu:
variables:
# Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2024-01-12.0'
FDO_DISTRIBUTION_TAG: '2025-05-10.0'
FDO_DISTRIBUTION_VERSION: '22.04'
FDO_DISTRIBUTION_PACKAGES: >-
debhelper-compat
@ -122,7 +130,6 @@ include:
libsnapd-glib-dev
libudev-dev
libva-dev
libv4l-dev
libx11-dev
meson
ninja-build
@ -138,10 +145,34 @@ include:
# FDO_DISTRIBUTION_EXEC: >-
# pip3 install meson
.debian:
variables:
# Update this tag when you want to trigger a rebuild
BASE_TAG: '2025-08-10.0'
FDO_DISTRIBUTION_VERSION: 'trixie'
FDO_DISTRIBUTION_PACKAGES: >-
build-essential
dpkg-dev
findutils
git
meson
.debian-archictectures:
parallel:
matrix:
- ARCH:
- amd64
- arm64
- armhf
- i386
- ppc64el
- riscv64
- s390x
.alpine:
variables:
# Update this tag when you want to trigger a rebuild
FDO_DISTRIBUTION_TAG: '2024-09-20.0'
FDO_DISTRIBUTION_TAG: '2025-03-25.0'
FDO_DISTRIBUTION_VERSION: '3.20'
FDO_DISTRIBUTION_PACKAGES: >-
alsa-lib-dev
@ -210,7 +241,8 @@ include:
- echo "Building with meson options $MESON_OPTIONS"
- meson setup "$BUILD_DIR" --prefix="$PREFIX" $MESON_OPTIONS
- meson compile -C "$BUILD_DIR" $COMPILE_ARGS
- meson test -C "$BUILD_DIR" --no-rebuild
- echo "Running tests with meson options $MESON_TEST_OPTIONS"
- meson test -C "$BUILD_DIR" --no-rebuild $MESON_TEST_OPTIONS
- meson install -C "$BUILD_DIR" --no-rebuild
artifacts:
name: pipewire-$CI_COMMIT_SHA
@ -226,6 +258,18 @@ container_ubuntu:
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
container_debian:
extends:
- .debian
- .debian-archictectures
- .fdo.container-build@debian
stage: container
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
FDO_DISTRIBUTION_TAG: "$BASE_TAG-$ARCH"
FDO_DISTRIBUTION_EXEC: >-
./.gitlab/ci/setup-debian-cross-container.sh "$ARCH"
container_fedora:
extends:
- .fedora
@ -258,9 +302,54 @@ build_on_ubuntu:
- .fdo.distribution-image@ubuntu
- .build
stage: build
needs:
- job: container_ubuntu
artifacts: false
variables:
MESON_OPTIONS: "-Dsession-managers=[] -Dsnap=enabled"
build_on_debian:
extends:
- .debian
- .debian-archictectures
- .not_coverity
- .fdo.distribution-image@debian
- .build
stage: build
needs:
- job: container_debian
artifacts: false
# ideally
# parallel:
# matrix:
# - ARCH: "$ARCH"
# however https://gitlab.com/gitlab-org/gitlab/-/issues/423553
# ("Expand variables in `needs:parallel:matrix`")
variables:
FDO_DISTRIBUTION_TAG: "$BASE_TAG-$ARCH"
# see /.gitlab/ci/setup-debian-cross-container.sh for installed packages
MESON_OPTIONS: >-
--cross-file /opt/meson-$ARCH.cross
-D c_args=['-UFASTPATH']
-D cpp_args=['-UFASTPATH']
-D auto_features=enabled
-D session-managers=[]
-D bluez5-backend-native-mm=enabled
-D bluez5-codec-lc3plus=disabled
-D bluez5-codec-ldac=disabled
-D bluez5-codec-ldac-dec=disabled
-D libcamera=disabled
-D roc=disabled
-D snap=disabled
-D systemd-user-service=disabled
-D systemd-system-service=disabled
-D onnxruntime=disabled
-D vulkan=enabled
-D ffmpeg=enabled
-D pw-cat-ffmpeg=enabled
MESON_TEST_OPTIONS: >-
--timeout-multiplier=2
.build_on_fedora:
extends:
- .fedora
@ -268,6 +357,9 @@ build_on_ubuntu:
- .fdo.distribution-image@fedora
- .build
stage: build
needs:
- job: container_fedora
artifacts: false
build_on_fedora:
extends:
@ -318,11 +410,13 @@ build_on_fedora_html_docs:
-Dsndfile=enabled
-Dsession-managers=[]
before_script:
- git fetch origin 1.0 1.2 master
- git fetch origin 1.0 1.2 1.4 master
- git branch -f 1.0 origin/1.0
- git clone -b 1.0 . branch-1.0
- git branch -f 1.2 origin/1.2
- git clone -b 1.2 . branch-1.2
- git branch -f 1.4 origin/1.4
- git clone -b 1.4 . branch-1.4
- git branch -f master origin/master
- git clone -b master . branch-master
- !reference [.build, before_script]
@ -335,6 +429,10 @@ build_on_fedora_html_docs:
- meson setup builddir $MESON_OPTIONS
- meson compile -C builddir doc/pipewire-docs
- cd ..
- cd branch-1.4
- meson setup builddir $MESON_OPTIONS
- meson compile -C builddir doc/pipewire-docs
- cd ..
- cd branch-master
- meson setup builddir $MESON_OPTIONS
- meson compile -C builddir doc/pipewire-docs
@ -354,6 +452,9 @@ build_on_alpine:
- .fdo.distribution-image@alpine
- .build
stage: build
needs:
- job: container_alpine
artifacts: false
variables:
MESON_OPTIONS: "-Dsession-managers=[] -Dsnap=disabled -Dlogind=enabled -Dlogind-provider=libelogind"
@ -362,13 +463,13 @@ build_all:
extends:
- .build_on_fedora
variables:
# Fedora doesn't have libfreeaptx, lc3plus, lc3, or roc
# Fedora doesn't have libfreeaptx, lc3plus, or roc
# libcamera has no stable API, so let's not chase that target
MESON_OPTIONS: >-
-Dauto_features=enabled
-Dbluez5-codec-aptx=disabled
-Dbluez5-codec-lc3plus=disabled
-Dbluez5-codec-lc3=disabled
-Dbluez5-codec-ldac-dec=disabled
-Droc=disabled
-Dlibcamera=disabled
-Dsession-managers=[]
@ -488,6 +589,9 @@ build_with_coverity:
- .fdo.suffixed-image@fedora
- .build
stage: analysis
needs:
- job: container_coverity
artifacts: false
script:
- export PATH=/opt/coverity/bin:$PATH
- meson setup "$BUILD_DIR" --prefix="$PREFIX"
@ -563,8 +667,9 @@ check_missing_headers:
- .not_coverity
- .fdo.distribution-image@fedora
stage: analysis
dependencies:
- build_on_fedora
needs:
- job: build_on_fedora
artifacts: true
script:
- export PREFIX=`find -name prefix-*`
- ./.gitlab/ci/check_missing_headers.sh
@ -573,18 +678,18 @@ pages:
extends:
- .not_coverity
stage: pages
dependencies:
- build_on_fedora_html_docs
needs:
- job: build_on_fedora_html_docs
artifacts: true
script:
- mkdir public public/1.0 public/1.2 public/devel
- mkdir public public/1.0 public/1.2 public/1.4 public/devel
- cp -R branch-1.0/builddir/doc/html/* public/1.0/
- cp -R branch-1.2/builddir/doc/html/* public/1.2/
- cp -R branch-1.4/builddir/doc/html/* public/1.4/
- cp -R branch-master/builddir/doc/html/* public/devel/
- (cd public && ln -s 1.2/* .)
- (cd public && ln -s 1.4/* .)
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == 'master'
- if: $CI_COMMIT_BRANCH == '1.0'
- if: $CI_COMMIT_BRANCH == '1.2'

View file

@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -ex
packages=(
# libapparmor-dev
libasound2-dev
libavahi-client-dev
libavcodec-dev
libavfilter-dev
libavformat-dev
libbluetooth-dev
libcanberra-dev
libdbus-1-dev
libebur128-dev
libfdk-aac-dev
libffado-dev
libfftw3-dev
libfreeaptx-dev
libglib2.0-dev
libgstreamer1.0-dev
libgstreamer-plugins-base1.0-dev
libjack-jackd2-dev
liblc3-dev
liblilv-dev
libmysofa-dev
libopus-dev
libpulse-dev
libreadline-dev
libsbc-dev
libsdl2-dev
# libsnapd-glib-dev
libsndfile1-dev
libspandsp-dev
libssl-dev
libsystemd-dev
libudev-dev
libusb-1.0-0-dev
libvulkan-dev
libwebrtc-audio-processing-dev
libx11-dev
modemmanager-dev
)
arch="$1"
export DEBIAN_FRONTEND=noninteractive
sed -i \
's/^Components:.*$/Components: main contrib non-free non-free-firmware/' \
/etc/apt/sources.list.d/debian.sources
dpkg --add-architecture "$arch"
apt update -y
pkgs=( "crossbuild-essential-$arch" )
for pkg in "${packages[@]}"; do
pkgs+=( "$pkg:$arch" )
done
apt install -y "${pkgs[@]}"
meson env2mfile --cross --debarch "$arch" -o "/opt/meson-$arch.cross"

View file

@ -23,6 +23,7 @@ run: all
PIPEWIRE_CONFIG_DIR=$(BUILD_ROOT)/src/daemon \
ACP_PATHS_DIR=$(SOURCE_ROOT)/spa/plugins/alsa/mixer/paths \
ACP_PROFILES_DIR=$(SOURCE_ROOT)/spa/plugins/alsa/mixer/profile-sets \
PIPEWIRE_LOG_SYSTEMD=false \
$(DBG) $(BUILD_ROOT)/src/daemon/pipewire-uninstalled
run-pulse: all
@ -32,6 +33,7 @@ run-pulse: all
PIPEWIRE_CONFIG_DIR=$(BUILD_ROOT)/src/daemon \
ACP_PATHS_DIR=$(SOURCE_ROOT)/spa/plugins/alsa/mixer/paths \
ACP_PROFILES_DIR=$(SOURCE_ROOT)/spa/plugins/alsa/mixer/profile-sets \
PIPEWIRE_LOG_SYSTEMD=false \
$(DBG) $(BUILD_ROOT)/src/daemon/pipewire-pulse
gdb:

201
NEWS
View file

@ -1,3 +1,201 @@
# PipeWire 1.5.81 (2025-10-16)
This is the first 1.6 release candidate that is API and ABI
compatible with previous 1.4.x, 1.2.x and 1.0.x releases.
In addition to all the changes backported to 1.4.x, this release
also contains some new features:
## Highlights
- The link negotiation code was refactored and improved.
Applications now have more options for selecting the default
values and restricting the available options. The default
negotiation code will now attempt to better match the application
suggested values.
- The loop now has support for locking with priority inversion. Most
of the code was updated to use the locks instead of invoke to
get proper concurrent updates with the loop. The Thread loop
functionality of locks, signal and wait was moved to the SPA loop.
This guarantees better real-time behaviour because inter-thread
synchronization does not have to pass eventfd/epoll.
- The control stream parser was rewritten to be safe against concurrent
updates while parsing, which can occur when parsing shared memory.
It also has extra checks to avoid integer overflows and undefined
behaviour.
- MIDI 2.0 clip support was added to the tools.
- Bluetooth ASHA (Audio Streaming for Hearing Aid) support was added.
- The ALSA node setup was tweaked to provide low latency with the ALSA
Firewire driver.
- Better support for explicit sync. It is now possible to negotiate
extra features to know if a consumer will signal the sync objects and
implement a fallback using a reliable transport.
- Many bug fixes and improvements.
## PipeWire
- Avoid process calls in disconnect in pw-stream. (#3314)
- Disable PipeWire services for root.
- The link negotiation was refactored and improved. Drivers now
always have a lower priority in deciding the final format.
- Backwards compatibility with the v0 protocol was removed.
- pw-stream and pw-filter will now refuse to queue a buffer that
was not dequeued before.
- Object properties will now be updated on the global as well.
- The priority of config overrides is correct now. (#4816)
- Async links now correctly report 1 extra quantum of latency.
- node.exclusive and the new port.exclusive flag are now enforced
by PipeWire itself.
- A new timer-queue helper was added to schedule timeouts.
- node.terminal and node.physical properties are now copied to the
ports to make it possible to create virtual sources and sinks
for JACK applications.
- Port properties will now be dynamically updated when the node
properties they depend on are updated.
- Passive leaf nodes are now handled better. Now they will also
run when the peer is active. (#4915)
- Reliable transport has been added for output ports. This can be
used in some cases if the producer wants to ensure buffers are
consumed by a consumer. (#4885)
- Context properties now support rlimit.<resource> properties to
configure rlimits. (#4047)
## Modules
- Close SyncObj fds.
- module-combine-stream has better Latency reporting.
- The JACK tunnel can now optionally connect ports.
- module-loopback has better Latency reporting.
- A Dolby Surround and Dolby Pro Logic II example filter config
was added.
- Filter-chain can now resample to a specific rate before running the
filters. This is useful when the filter-graph needs to run at a
specific rate.
- Avahi-poll now uses the timer-queue to schedule timeouts.
- Modules are ported to timer-queue instead of using timerfd directly
for non-realtime timers.
## SPA
- The loop now has support for locking with priority inversion. Most
of the code was updated to use the locks instead of invoke to
get proper concurrent updates with the loop. The Thread loop
functionality of locks, signal and wait was moved to the SPA loop.
- UMP to Midi 1.0 conversion was improved, some UMP events are now
converted to multiple Midi 1.0 messages. (#4839)
- The POD filter was refactored and improved. It is now possible to
use the default value of the output by specifying an invalid input
default value.
- The POD parser was made safe for concurrent updates of the memory
it is parsing. This is important when the POD is in shared memory
and the parser should not access invalid memory.
- Some hardcoded channel limits were removed and now use the global
channel limit. More things can dynamically adapt to this global
limit. The max number of channels was then bumped to 128.
- The POD builder is safe to use on shared memory now and tries to
avoid many integer overflows.
- Most debug functions are safe to be used on shared memory.
- User specified Commands and Events are now possible.
- The SPA_IO_CLOCK_FLAG_DISCONT was added to spa_io_clock to signal
a discont in the clock due to clock change.
- AC3, DTS, EAC3, TRUEHD and MPEGH now have helper parser functions.
- H265 was added as a video format. (#4674)
- SPA_PARAM_PeerFormats was added to let a port know about its peer
formats in order to better filter possible conversions.
- More color matrices, transfer functions and color primaries.
- The echo-canceler is enabled now.
- Pro-Audio mode now uses 3 periods by default. This lowers the
latency on some drivers (Firewire). The latency of Firewire is
also reported correctly now.
- The ALSA DLL bandwidth is configurable now.
- The resampler now uses fixed point for the phases and is a little
faster when updating adaptive rates.
- The convolver is a little faster by swapping buffers instead of
copying samples.
- Latency and ProcessLatency support was added to filter-graph.
(#4678)
- Audio channel position support was added to filter-graph.
- A new ffmpeg avfilter plugin was added to filter-graph.
- A new ONNX filter was added to filter-graph.
- A debug, pipe, zeroramp and noisegate filter was added to the
filter-graph. (#4745)
- The filter-graph lv2 plugin now supports options and state.
- videoconvert was greatly improved.
- The v4l2 plugin can negotiate DMABUF with modifiers.
- Colorimetry information was added to v4l2 and libcamera.
- Audioconvert can handle empty buffers more efficiently.
- Improve the POD compare functions for Rectangle.
- There is now a SPA_POD_PROP_FLAG_DROP flag to drop the property when
the property is missing from one side.
- A new FEATURE choice was added that is basically a flags choice with
a FLAG_DROP property.
- Metadata features were added. This is a way to negotiate new features
for the metadata. (#4885)
- DSD playback with pw-cat has been improved.
- Compatibility and xrun prevention for the SOF driver has been
improved. (#4489)
- The filter-graph max plugin can now have 8 input channels.
- Buffer Negotiation between the mixer port and the node ports is much
improved. (#4918)
- An offline AEC benchmark was added.
- Channel positions are now read from HDMI ELD when possible.
- Audioconvert and filter-graph now also support properties of Long
and String types.
## ACP
- It's possible to disable the pro-audio profile.
- Support for Logitech Z407 PC Speakers was improved.
- Support for Razer BlackShark v3.
- Fix volume rounding down causing mute. (#4890)
## Tools
- pw-cat can now play and record MIDI 2.0 Clips, which is the
official format for storing MIDI 2.0 UMP data. pw-midi2play
and pw-midi2record were added as aliases.
- pw-cat can now upload sysex files. The pw-sysex alias was
added for this.
- The pw-link tool now has a -t option to list port latencies.
It also has better monitor support.
- pw-top can now clear the ERR column with the c key.
- pw-cli now keeps the types of the variables it stores and avoid
using wrongly typed variables that can crash things. It can now
also list the available variables.
- pw-dump can now output raw JSON and SPA JSON.
- pw-dump has configurable indentation level.
- pw-mididump can be forced to output MIDI 1.0 messages.
- pw-profiler now uses doubles for extra precision.
- pw-top now marks the async nodes with =.
## Bluetooth
- Telephony improvements.
- ASHA support was added.
- Add packet loss correction with spandsp for some codecs.
- Synchronisation between ISO streams in the same group.
## Pulse-server
- The SUSPEND event is now correctly generated. fail-on-suspend is
now implemented.
- PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND is now implemented. (#4255)
(#4726)
- RTP streams now have stream.properties for extra configuration.
- Timed out streams are now destroyed instead of lingering. (#4901)
- A new help and pipewire-pulse:list-modules core message was added.
## JACK
- Port rename callbacks are now emitted correctly.
- Use safe POD parsing for the control sequences.
## V4l2
- The wrapper now avoids a race while initializing PipeWire. (#4859)
## GStreamer
- Colorimetry support was added.
- Cursor metadata is now exposed as ROI metadata.
- Many more updates.
## Docs
- Document the client-node flow a bit more.
Older versions:
# PipeWire 1.4.0 (2025-03-06)
This is the 1.4 release that is API and ABI compatible with previous
@ -99,9 +297,6 @@ the 1.2 release last year, including:
## JACK
- Add an option to disable the MIDI2 port flags. (#4584)
Older versions:
# PipeWire 1.3.83 (2025-02-20)
This is the third and hopefully last 1.4 release candidate that

View file

@ -38,6 +38,7 @@ IGNORE_PREFIX = pw_ \
spa_ \
SPA_
GENERATE_TREEVIEW = YES
DISABLE_INDEX = NO
SEARCHENGINE = YES
GENERATE_LATEX = NO

View file

@ -41,6 +41,11 @@
<tab type="globals" visible="no" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
<tab type="usergroup" title="PipeWire Versions">
<tab type="user" url="https://docs.pipewire.org/1.2/" title="1.2.x"/>
<tab type="user" url="https://docs.pipewire.org/1.4/" title="1.4.x"/>
<tab type="user" url="https://docs.pipewire.org/devel/" title="Development"/>
</tab>
</navindex>
<!-- Layout definition for a class page -->

View file

@ -1,4 +1,4 @@
:root {
html {
/* --page-background-color: #729fcf; */
--primary-color: #729fcf;
--primary-dark-color: #729fcf;
@ -8,7 +8,7 @@
}
@media (prefers-color-scheme: light) {
:root {
html {
--code-background: #f5f5f5;
--code-foreground: #333333;
--fragment-background: #f5f5f5;

View file

@ -1019,8 +1019,9 @@ A choice contains an array of possible values.
child2 and child3, in steps of child4 in the value array.
- Enum (3) : child1 is a default value, options are any value from
the value array, preferred values come first.
- Flags (4) : child1 is a default value, options are any value from
the value array, preferred values come first.
- Flags (4) : only child1 is a flag value. When filtering, the flags
are AND-ed together.
- flags: must be 0
## Pod (20)

View file

@ -48,7 +48,7 @@ ALSA client match rules.
In addition, the PipeWire context configuration sections
may also be specified, see \ref page_man_pipewire_conf_5 "pipewire.conf(5)".
# STREAM PROPERTIES @IDX@ client.conf
# STREAM PROPERTIES @IDX@ client.conf stream.properties
The client configuration files contain a stream.properties section that configures the options for client streams:
```css
@ -93,7 +93,7 @@ A list of object properties that can be applied to streams can be found in
and
\ref props__audio_converter_properties "pipewire-props(7) Audio Adapter Properties"
# STREAM RULES @IDX@ client.conf
# STREAM RULES @IDX@ client.conf stream.rules
You can add \ref pipewire_conf__match_rules "match rules, see pipewire(1)"
to set properties for certain streams and filters.
@ -127,7 +127,7 @@ stream.rules = [
Will set the node.name of Firefox to "My Name".
# ALSA CLIENT PROPERTIES @IDX@ client.conf
# ALSA CLIENT PROPERTIES @IDX@ client.conf alsa.properties
An `alsa.properties` section can be added to configure client applications
that connect via the PipeWire ALSA plugin.
@ -169,7 +169,7 @@ The number of bytes in the alsa buffer. The default is 0, which is to allow any
This controls the volume curve used on the ALSA mixer. Possible values are `cubic` and
`linear`. The default is to use `cubic`.
# ALSA CLIENT RULES @IDX@ client.conf
# ALSA CLIENT RULES @IDX@ client.conf alsa.rules
It is possible to set ALSA client specific properties by using
\ref pipewire_conf__match_rules "Match rules, see pipewire(1)". You can

View file

@ -38,7 +38,7 @@ JACK client match rules.
In addition, the PipeWire context configuration sections
may also be specified, see \ref page_man_pipewire_conf_5 "pipewire.conf(5)".
# JACK PROPERTIES @IDX@ jack.conf
# JACK PROPERTIES @IDX@ jack.conf jack.properties
The configuration file can contain an extra JACK specific section called `jack.properties` like this:
```css
@ -206,7 +206,7 @@ JACK apps don't know about this flag yet and refuse to show the port.
Set this to true for applications that know how to handle MIDI2 ports.
\endparblock
# MATCH RULES @IDX@ jack.conf
# MATCH RULES @IDX@ jack.conf jack.rules
`jack.rules` provides an `update-props` action that takes an object with properties that are updated
on the client and node object of the jack client.

View file

@ -36,13 +36,96 @@ type. Other properties control settings of a specific kinds of device
or node (ALSA, Bluetooth, ...), and have meaning only for those
objects.
Usually, all the properties are configured in the session manager
configuration. For how to configure them, see the session manager
documentation. In minimal PipeWire setups without a session manager,
they can be configured via
\ref pipewire_conf__context_objects "context.objects in pipewire.conf(5)".
# CUSTOMIZING PROPERTIES @IDX@ props
\see [WirePlumber configuration](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration.html)
Usually, all device properties are configured in the session manager
configuration, see the session manager documentation.
Application properties are configured in
``client.conf`` (for native PipeWire and ALSA applications),
``pipewire-pulse.conf`` (for Pulseaudio applications), and
``jack.conf`` (for JACK applications).
In minimal PipeWire setups without a session manager,
the device properties can be configured via
\ref pipewire_conf__context_objects "context.objects in pipewire.conf(5)"
when creating the devices.
## Examples
Device configuration using WirePlumber (requires WirePlumber restart to apply).
See [WirePlumber configuration](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration.html)
```css
# ~/.config/wireplumber/wireplumber.conf.d/custom-props.conf
monitor.alsa.properties = {
alsa.udev.expose-busy = true
}
monitor.alsa.rules = [
{
matches = [ { device.name = "~alsa_card.pci-.*" } ],
actions = { update-props = { api.alsa.soft-mixer = true } }
},
{
matches = [ { node.name = "alsa_output.pci-0000_03_00.1.hdmi-stereo-extra3" } ]
actions = { update-props = { node.description = "Main Audio" } }
}
]
monitor.alsa-midi.properties = {
api.alsa.seq.ump = true
}
monitor.bluez.properties = {
bluez5.hfphsp-backend = ofono
}
monitor.bluez.rules = [
{
matches = [ { device.name = "~bluez_card.*" } ],
actions = { update-props = { bluez5.dummy-avrcp player = true } }
}
]
```
Native client configuration (requires client application restart to apply).
See \ref client_conf__stream_rules "pipewire-client.conf(5)"
```css
# ~/.config/pipewire/client.conf/custom-props.conf
stream.rules = [
{
matches = [ { application.name = "pw-play" } ]
actions = { update-props = { node.description = "Some pw-cat stream" } }
}
]
```
Pulseaudio client configuration (requires \ref page_man_pipewire-pulse_1 "pipewire-pulse(1)" restart to apply).
See \ref pipewire-pulse_conf__stream_rules "pipewire-pulse.conf(5)"
```css
# ~/.config/pipewire/pipewire-pulse.conf/custom-props.conf
stream.rules = [
{
matches = [ { application.name = "paplay" } ]
actions = { update-props = { node.description = "Some paplay stream" } }
}
]
```
JACK client configuration (requires client restart to apply).
See \ref jack_conf__match_rules "pipewire-jack.conf(5)"
```css
# ~/.config/pipewire/jack.conf/custom-props.conf
jack.rules = [
{
matches = [ { client.name = "jack_delay" } ]
actions = { update-props = { node.description = "Some JACK node" } }
}
]
```
# COMMON DEVICE PROPERTIES @IDX@ props
@ -91,12 +174,12 @@ ie. for example `device.Param.Props = { ... }` to set `Props`.
@PAR@ device-prop device.product.id # integer
\parblock
\copydoc PW_KEY_DEVICE_PRODUCT_NAME
\copydoc PW_KEY_DEVICE_PRODUCT_ID
\endparblock
@PAR@ device-prop device.product.name # string
\parblock
\copydoc PW_KEY_DEVICE_PRODUCT_ID
\copydoc PW_KEY_DEVICE_PRODUCT_NAME
\endparblock
@PAR@ device-prop device.class # string
@ -143,11 +226,14 @@ real or virtual devices.
These contain properties to identify the node or to display the node in a GUI application.
@PAR@ node-prop node.name
@PAR@ node-prop node.name # string
A (unique) name for the node. This is usually set on sink and sources to identify them
as targets for linking by the session manager.
@PAR@ node-prop node.description
@PAR@ node-prop node.nick # string
A short name for the node.
@PAR@ node-prop node.description # string
A human readable description of the node or stream.
@PAR@ node-prop media.name
@ -338,14 +424,14 @@ a sink or source.
@PAR@ node-prop node.exclusive = false
If this node wants to be linked exclusively to the sink/source.
@PAR@ node-prop target.object = <node.name|object.serial>
Where the node should link to, this can be a node.name or an object.serial.
@PAR@ node-prop node.target = <node.name|object.id>
Where this node should be linked to. This can be a node.name or an object.id of a node. This property is
deprecated, the target.object property should be used instead, which uses the more unique object.serial as
a possible target.
@PAR@ node-prop target.object = <node.name|object.serial>
Where the node should link to, this can be a node.name or an object.serial.
@PAR@ node-prop node.dont-reconnect = false
\parblock
When the node has a target configured and the target is destroyed, destroy the node as well.
@ -355,6 +441,13 @@ Note that if a stream should appear/disappear in sync with the target, a session
should be written instead.
\endparblock
@PAR@ node-prop node.dont-fallback = false
If linking this node to its specified target does not succeed, session
manager should not fall back to linking it to the default target.
@PAR@ node-prop node.dont-move = false
Whether the node target may be changed using metadata.
@PAR@ node-prop node.passive = false
\parblock
This is a passive node and so it should not keep sinks/sources busy. This property makes the session manager create passive links to the sink/sources. If the node is not otherwise linked (via a non-passive link), the node and the sink it is linked to are idle (and eventually suspended).
@ -371,6 +464,13 @@ Instruct the session manager to not remix the channels of a stream. Normally the
@PAR@ node-prop priority.session # integer
The priority for selecting this node as the default source or sink.
@PAR@ node-prop session.suspend-timeout-seconds = 3 # float
Timeout in seconds, after which an idle node is suspended.
Value ``0`` means the node will not be suspended.
@PAR@ node-prop state.restore-props = true
Whether session manager should save state for this node.
## Format Properties
Streams and also most device nodes can be configured in a certain format with properties.
@ -640,8 +740,12 @@ See \ref spa_param_port_config for the meaning.
## Monitor properties
@PAR@ monitor-prop alsa.use-acp # boolean
@PAR@ monitor-prop alsa.use-acp = true # boolean
Use \ref monitor-prop__alsa_card_profiles "ALSA Card Profiles" (ACP) for device configuration.
This autodetects available ALSA devices and configures port and hardware mixers.
@PAR@ monitor-prop alsa.use-ucm # boolean
Enable or disable UCM for all devices. Default: unset.
@PAR@ monitor-prop alsa.udev.expose-busy # boolean
Expose the ALSA card even if it is busy/in use. Default false. This can be useful when some
@ -658,7 +762,7 @@ When ACP is enabled and a UCM configuration is available for a device, by
default it is used instead of the ACP profiles. This option allows you to
disable this and use the ACP profiles instead.
This option does nothing if `api.alsa.use-acp` is set to `false`.
This option does nothing if `alsa.use-acp` is set to `false`.
\endparblock
@PAR@ device-prop api.alsa.soft-mixer = false # boolean
@ -718,6 +822,13 @@ some devices.
\copydoc SPA_KEY_API_ALSA_SPLIT_ENABLE
\endparblock
@PAR@ device-prop api.acp.disable-pro-audio = false # boolean
Disable the "Pro Audio" profile for this device.
@PAR@ device-prop api.acp.use-eld-channels = false # boolean
Use the channel count and mapping the connected HDMI device
provides via ELD information.
## Node properties
@PAR@ node-prop audio.channels # integer
@ -778,6 +889,12 @@ Setting this to 0 makes htimestamp never get disabled.
Disable timer-based scheduling, and use IRQ for scheduling instead.
The "Pro Audio" profile will usually enable this setting, if it is expected it works on the hardware.
@PAR@ node-prop api.alsa.dll-bandwidth-max # double
Sets the maximum bandwidth of the DLL (delay-locked loop) filter used to smooth out rate adjustments.
The default value may be too responsive in some scenarios.
For example, with UAC2 pitch control, the host reacts more slowly compared to local resampling,
so using a lower bandwidth helps avoid oscillations or instability.
@PAR@ node-prop api.alsa.auto-link = false # boolean
Link follower PCM devices to the driver PCM device when using IRQ-based scheduling.
The "Pro Audio" profile will usually enable this setting, if it is expected it works on the hardware.
@ -791,12 +908,18 @@ Static set the device systemic latency, in nanoseconds.
@PAR@ node-prop api.alsa.path # string
UNDOCUMENTED
@PAR@ node-prop api.alsa.pcm.card # integer
Card index to open. Usually determined from `api.alsa.path`.
@PAR@ node-prop api.alsa.open.ucm # boolean
Open device using UCM.
@PAR@ node-prop api.alsa.bind-ctls # boolean
UNDOCUMENTED
@PAR@ node-prop api.alsa.bind-ctl.NAME # boolean
UNDOCUMENTED
@PAR@ node-prop iec958.codecs # JSON array of string
Enable only specific IEC958 codecs. This can be used to disable some codecs the hardware supports.
Available values: PCM, AC3, DTS, MPEG, MPEG2-AAC, EAC3, TRUEHD, DTSHD
@ -818,6 +941,34 @@ Informative property.
Informative property.
\endparblock
@PAR@ node-prop api.alsa.dsd-lsb = false # boolean
Use LSB bit order for DSD audio output.
# ALSA MIDI PROPERTIES @IDX@ props
## Node properties
For ALSA MIDI in Wireplumber, MIDI bridge node properties are
configured in the monitor properties.
@PAR@ monitor-prop api.alsa.seq.ump = true # boolean
Use MIDI 2.0 if possible.
@PAR@ monitor-prop api.alsa.seq.min-pool = 500 # integer
UNDOCUMENTED
@PAR@ monitor-prop api.alsa.seq.max-pool = 2000 # integer
UNDOCUMENTED
@PAR@ monitor-prop clock.name = "clock.system.monotonic" # string
Clock to follow.
@PAR@ monitor-prop api.alsa.path = "default" # string
Sequencer device to use.
@PAR@ monitor-prop api.alsa.disable-longname = true # boolean
If card long name should not be passed to MIDI port.
# BLUETOOTH PROPERTIES @IDX@ props
@ -963,6 +1114,26 @@ Maximum number of octets supported per codec frame for the LC3 codec (default: 4
@PAR@ monitor-prop bluez5.bap-server-capabilities.max_frames # integer
Maximum number of codec frames supported per SDU for the LC3 codec (default: 2).
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.locations # JSON or integer
Sink audio locations of the server, as channel positions or PACS bitmask.
Example: `FL,FR`
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.contexts # integer
Available sink contexts PACS bitmask of the the server.
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.supported-contexts # integer
Supported sink contexts PACS bitmask of the the server.
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.locations # JSON or integer
Source audio locations of the server, as channel positions or PACS bitmask.
Example: `FL,FR`
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.contexts # integer
Available source contexts PACS bitmask of the the server.
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.supported-contexts # integer
Supported source contexts PACS bitmask of the the server.
## Device properties
@PAR@ device-prop bluez5.auto-connect # boolean
@ -997,6 +1168,31 @@ PipeWire Opus Pro Audio duplex encoding mode: audio, voip, lowdelay
@PAR@ device-prop bluez5.bap.cig = "auto" # integer, or 'auto'
Set CIG ID for BAP unicast streams of the device.
@PAR@ device-prop bluez5.bap.preset = "auto" # string
BAP QoS preset name that needed to be used with vendor config.
This property is experimental.
Available: "48_2_1", ... as in the BAP specification.
@PAR@ device-prop bluez5.bap.rtn # integer
BAP QoS preset name that needed to be used with vendor config.
This property is experimental.
Default: as per QoS preset.
@PAR@ device-prop bluez5.bap.latency # integer
BAP QoS latency that needs to be applied for vendor defined preset
This property is experimental.
Default: as QoS preset.
@PAR@ device-prop bluez5.bap.delay = 40000 # integer
BAP QoS delay that needs to be applied for vendor defined preset
This property is experimental.
Default: as per QoS preset.
@PAR@ device-prop bluez5.framing = false # boolean
BAP QoS framing that needs to be applied for vendor defined preset
This property is experimental.
Default: as per QoS preset.
## Node properties
@PAR@ node-prop bluez5.media-source-role # string
@ -1007,6 +1203,17 @@ this instance. Available values:
- input: appear as source node.
\endparblock
@PAR@ node-prop bluez5.decode-buffer.latency # integer
Applies on media source nodes and defines the target amount
of samples to be buffered on the output of the decoder.
Default: 0, which means it is automatically determined.
@PAR@ node-prop node.latency-offset-msec # string
Applies only for BLE MIDI nodes.
Latency adjustment to apply on the node. Larger values add a
constant latency, but reduces timing jitter caused by Bluetooth
transport.
# PORT PROPERTIES @IDX@ props
Port properties are usually not directly configurable via PipeWire

View file

@ -54,7 +54,7 @@ for the detailed description.
In addition, the PipeWire context configuration sections
may also be specified, see \ref page_man_pipewire_conf_5 "pipewire.conf(5)".
# STREAM PROPERTIES @IDX@ pipewire-pulse.conf
# STREAM PROPERTIES @IDX@ pipewire-pulse.conf stream.properties
The `stream.properties` section contains properties for streams created
by the pipewire-pulse server.
@ -100,18 +100,18 @@ stream.properties = {
}
```
# STREAM RULES @IDX@ pipewire-pulse.conf
# STREAM RULES @IDX@ pipewire-pulse.conf stream.rules
The `stream.rules` section works the same as
\ref client_conf__stream_rules "pipewire-client.conf(5) stream.rules".
# PULSEAUDIO PROPERTIES @IDX@ pipewire-pulse.conf
# PULSEAUDIO PROPERTIES @IDX@ pipewire-pulse.conf pulse.properties
For `pulse.properties` section,
see \ref page_module_protocol_pulse "libpipewire-module-protocol-pulse(7)"
for available options.
# PULSEAUDIO RULES @IDX@ pipewire-pulse.conf
# PULSEAUDIO RULES @IDX@ pipewire-pulse.conf pulse.rules
For each client, a set of rules can be written in `pulse.rules`
section to configure quirks of the client or to force some pulse

View file

@ -140,7 +140,7 @@ Array of dictionaries. Match rules for modifying device properties
on the server.
# CONTEXT PROPERTIES @IDX@ pipewire.conf
# CONTEXT PROPERTIES @IDX@ pipewire.conf context.properties
Available PipeWire properties in `context.properties` and possible
default values.
@ -275,6 +275,20 @@ Warn about failures to lock memory.
@PAR@ pipewire.conf mem.mlock-all = false
Try to mlock all current and future memory by the process.
@PAR@ pipewire.conf rlimit.nofile = 4096
Try to set the max file descriptor number resource limit of the process.
A value of -1 raises the limit to the system defined hard maximum value.
The file resource limit is usually 1024 and should only be raised if the
program does not use the select() system call. PipeWire does normally not
use select().
@PAR@ pipewire.conf rlimit.*resource* = *value*
Set resource limits. *resource* can be one of: as, core, cpu,
data, fsize, locks, memlock, msgqueue, nice, nofile, nproc, rss, rtprio,
rttime, sigpending or stack. See the documentation of setrlimit to get the
meaning of these resources. A value of -1 will set the maximum allowed
limit.
@PAR@ pipewire.conf settings.check-quantum = false
Check if the quantum in the settings metadata update is compatible
with the configured limits.
@ -302,7 +316,7 @@ the `context.modules` and `context.objects` sections can declare
additional conditions that control whether a module or object is loaded
depending on what properties are present.
# SPA LIBRARIES @IDX@ pipewire.conf
# SPA LIBRARIES @IDX@ pipewire.conf context.spa-libs
SPA plugins are loaded based on their factory-name. This is a well
known name that uniquely describes the features that the plugin should
@ -331,7 +345,7 @@ context.spa-libs = {
}
```
# MODULES @IDX@ pipewire.conf
# MODULES @IDX@ pipewire.conf context.modules
PipeWire modules to be loaded. See
\ref page_man_libpipewire-modules_7 "libpipewire-modules(7)".
@ -364,7 +378,7 @@ A \ref pipewire_conf__match_rules "match rule" `matches` condition.
The module is loaded only if one of the expressions in the array matches
to a context property.
# CONTEXT OBJECTS @IDX@ pipewire.conf
# CONTEXT OBJECTS @IDX@ pipewire.conf context.objects
The `context.objects` section allows you to make some objects from factories (usually created
by loading modules in `context.modules`).
@ -417,7 +431,7 @@ context.objects = [
]
```
# COMMAND EXECUTION @IDX@ pipewire.conf
# COMMAND EXECUTION @IDX@ pipewire.conf context.exec
The `context.exec` section can be used to start arbitrary commands as
part of the initialization of the PipeWire program.
@ -590,7 +604,7 @@ matches = [
```
# CONTEXT PROPERTIES RULES @IDX@ pipewire.conf
# CONTEXT PROPERTIES RULES @IDX@ pipewire.conf context.properties.rules
`context.properties.rules` can be used to dynamically update the properties
based on other properties.
@ -614,7 +628,7 @@ context.properties.rules = [
}
```
# NODE RULES @IDX@ pipewire.conf
# NODE RULES @IDX@ pipewire.conf node.rules
The node.rules are evaluated every time the properties on a node are set
or updated. This can be used on the server side to override client set
@ -647,7 +661,7 @@ node.rules = [
Will set the `node.force-quantum` property of `jack_simple_client` to 512.
# DEVICE RULES @IDX@ pipewire.conf
# DEVICE RULES @IDX@ pipewire.conf device.rules
The device.rules are evaluated every time the properties on a device are set
or updated. This can be used on the server side to override client set

View file

@ -48,5 +48,6 @@ See \ref page_api.
- [Bluetooth, PipeWire and Whatsapp calls](https://gjhenrique.com/pipewire.html)
- [Intoduction to PipeWire](https://bootlin.com/blog/an-introduction-to-pipewire/)
- [A custom PipeWire node](https://bootlin.com/blog/a-custom-pipewire-node/)
- [FOSDEM 2025 talk and slides](https://fosdem.org/2025/schedule/event/fosdem-2025-4749-pipewire-state-of-the-union/)
*/

View file

@ -44,6 +44,8 @@ The native protocol and object model is similar to
serialization/deserialization of messages. This is because the data structures
in the messages are more complicated and not easily expressible in XML.
See \ref page_module_protocol_native for details.
See also \ref page_native_protocol for the documentation of the protocol
messages.
# Extensibility

View file

@ -0,0 +1,115 @@
/** \page page_driver Driver architecture and workflow
This document explains how drivers are structured and how they operate.
This is useful to know both for debugging and for writing new drivers.
(For details about how the graph does scheduling, which is tied to the driver,
see \ref page_scheduling ).
# Clocks
A driver is a node that starts graph cycles. Typically, this is accomplished
by using a timer that periodically invokes a callback, or by an interrupt.
Drivers use the monotonic system clock as the reference for timestamping. Note
that "monotonic system clock" does not refer to the \c MONOTONIC_RAW clock in
Linux, but rather, to the regular monotonic clock.
Drivers may actually be run by a custom internal clock instead of the monotonic
system clock. One example would be a sound card DAC's clock. Another would be
a network adapter with a built in PHC. Or, the driver may be using a system
clock other than the monotonic system clock. The driver then needs to perform
some sort of timestamp translation and drift compensation from that internal
clock to the monotonic clock, since it still needs to generate monotonic clock
timestamps for the beginning cycle. (More on that below.)
# Updates and graph cycle start
Every time a driver starts a graph cycle, it must update the contents of the
\ref spa_io_clock instance that is assigned to them through the
\ref spa_node_methods::set_io callback. The fields of the struct must be
updated as follows:
- \ref spa_io_clock::nsec : Must be set to the time (according to the monotonic
system clock) when the cycle that the driver is about to trigger started. To
minimize jitter, it is usually a good idea to increment this by a fixed amount
except for when the driver starts and when discontinuities occur in its clock.
- \ref spa_io_clock::rate : Set to a value that can translate samples to nanoseconds.
- \ref spa_io_clock::position : Current cycle position, in samples. This is the
ideal position of the graph cycle (this is explained in greater detail further below).
It is incremented by the duration (in samples) at the beginning of each cycle. If
a discontinuity is experienced by the driver that results in a discontinuity in the
position of the old and the current cycle, consider setting the
\ref SPA_IO_CLOCK_FLAG_DISCONT flag to inform other nodes about this.
- \ref spa_io_clock::duration : Duration of this new cycle, in samples.
- \ref spa_io_clock::rate_diff : A decimal value that is set to whatever correction
factor the driver applied to for a drift between an internal driver clock and the
monotonic system clock. A value above 1.0 means that the internal driver clock
is faster than the monotonic system clock, and vice versa. Always set this to
1.0 if the driver is directly using the monotonic clock.
- \ref spa_io_clock::next_nsec : Must be set to the time (according to the monotonic
system clock) when the cycle that comes after the current one is to be started. In
some cases, this may actually be in the past relative to nsec, for example, when
some internal driver clock experienced a discontinuity. Consider setting the
\ref SPA_IO_CLOCK_FLAG_DISCONT flag in such a case. Just like with nsec, to
minimize jitter, it is usually a good idea to increment this by a fixed amount
except for when the driver starts and when discontinuities occur in its clock.
The driver node signals the start of the graph cycle by calling \ref spa_node_call_ready
with the \ref SPA_STATUS_HAVE_DATA and \ref SPA_STATUS_NEED_DATA flags passed
to that function call. That call must happen inside the thread that runs the
data loop assigned to the driver node.
As mentioned above, the \ref spa_io_clock::position field is the _ideal_ position
of the graph cycle, in samples. This contrasts with \ref spa_io_clock::nsec, which
is the moment in monotonic clock time when the cycle _actually_ happens. This is an
important distinction when driver is run by a clock that is different to the monotonic
clock. In that case, the \ref spa_io_clock::nsec timestamps are adjusted to match the
pace of that different clock (explained in the section below). In such a case,
\ref spa_io_clock::position still is incremented by the duration in samples. This
is important, since nodes and modules may use this field as an offset within their own
internal ring buffers or similar structures, using the position field as an offset within
said data structures. This requires the position field to advance in a continuous way.
By incrementing by the duration, this requirement is met.
# Using clocks other than the monotonic clock
As mentioned earlier, the driver may be run by an internal clock that is different
to the monotonic clock. If that other clock can be directly used for scheduling
graph cycle initiations, then it is sufficient to compute the offset between that
clock and the monotonic clock (that is, offset = monotonic_clock_time - other_clock_time)
at each cycle and use that offset to translate that other clock's time to the monotonic
clock time. This is accomplished by adding that offset to the \ref spa_io_clock::nsec
and \ref spa_io_clock::next_nsec fields. For example, when the driver uses the realtime
system clock instead of the monotonic system clock, then that realtime clock can still
be used with \c timerfd to schedule callback invocations within the data loop. Then,
computing the (monotonic_clock_time - realtime_clock_time) offset is sufficient, as
mentioned, to be able to translate clock's time to monotonic time for \ref spa_io_clock::nsec
and \ref spa_io_clock::next_nsec (which require monotonic clock timestamps).
If however that other clock cannot be used for scheduling graph cycle initiations directly
(for example, because the API of that clock has no functionality to trigger callbacks),
then, in addition to the aforementioned offset, the driver has to use the monotonic clock
for triggering callbacks (usually via \c timerfd) and adjust the time when callbacks are
invoked such that they match the pace of that other clock.
As an example (clock speed difference exaggerated for sake of clarity), suppose the other
clock is twice as fast as the monotonic clock. Then the monotonic clock timestamps have
to be calculated in a manner that halves the durations between said timestamps, and the
\ref spa_io_clock::rate_diff field is set to 2.0.
The dummy node driver uses a DLL for this purpose. It is fed the difference between the
expected position (in samples) and the actual position (derived from the current time
of the driver's internal clock), passes the delta between these two quantities into the
DLL, and the DLL computes a correction factor (2.0 in the above example) which is used
for scaling durations between \c timerfd timeouts. This forms a control loop, since the
correction factor causes the durations between the timeouts to be adjusted such that the
difference between the expected position and the actual position reaches zero. Keep in
mind the notes above about \ref spa_io_clock::position being the ideal position of the
graph cycle, meaning that even in this case, the duration it is incremented by is
_not_ scaled by the correction factor; the duration in samples remains unchanged.
(Other popular control loop mechanisms that are suitable alternatives to the DLL are
PID controllers and Kalman filters.)
*/

View file

@ -11,6 +11,9 @@
- \subpage page_library
- \subpage page_dma_buf
- \subpage page_scheduling
- \subpage page_driver
- \subpage page_latency
- \subpage page_tag
- \subpage page_native_protocol

View file

@ -0,0 +1,282 @@
/** \page page_latency Latency support
This document explains how the latency in the PipeWire graph is implemented.
# Use Cases
## A node port has a latency
Applications need to be able to query the latency of a port.
Linked Nodes need to be informed of the latency of a port.
## dynamically update port latencies
It needs to be possible to dynamically update the latency of a port and this
should inform all linked ports/nodes of the updated latency.
## Linked nodes add latency to the signal
When two nodes/ports have a latency, the signal is delayed by the sum of
the nodes latencies.
## Calculate the signal delay upstream and downstream
A node might need to know how much a signal was delayed since it arrived
in the node.
A node might need to know how much the signal will be delayed before it
exists the graph.
## Detect latency mismatch
When a signal travels through 2 different parts of the graph with different
latencies and then eventually join, there is a latency mismatch. It should
be possible to detect this mismatch.
# Concepts
## Port Latency
The fundamental object for implementing latency reporting in PipeWire is the
Latency object.
It consists of a direction (input/output) and min/max latency values. The latency
values can express a latency relative to the graph quantum, the samplerate or in
nanoseconds. There is a mininum and maximum latency value in the Latency object.
The direction of the latency object determines how the latency object propagates.
- SPA_DIRECTION_OUTPUT Latency objects move from output ports downstream and contain
the latency from all nodes upstream. An output latency received on an input port
should instruct the node to update the output latency on its output ports related
to this input port. This corresponds to the JackCaptureLatency.
- SPA_DIRECTION_INPUT Latency objects move from input ports upstream and contain
the latency from all nodes downstream. An input latency received on an output port
should instruct the node to update the input latency on its input ports related
to this output port. This corresponds to the JackPlaybackLatency.
PipeWire will automatically propagate Latency objects from ports to all linked ports
in the graph. Output Latency objects on output ports are propagated to linked input
ports and input Latency objects on input ports are propagated to linked output ports.
If a port has links with multiple other ports, the Latency objects are merged by
taking the min of the min values and the max of the max values of all latency objects
on the other ports.
This way, Output Latency always describes the aggragated total upstream latency of
signal up to the port and Input latency describes the aggregated downstream latency
of the signal from the port.
## Node ProcessLatency
This is a per node property and applies to the latency introduced by the node
logic itself.
This mostly works if (almost) all data processing ports (input/output) participate in
the same data processing with the same latency, which is a common use case.
ProcessLatency is mostly used to easily calculate Output and Input Latency on ports.
We can simply add the ProcessLatency to all latency values in the ports Latency objects
to obtain the corresponding Latency object for the other ports.
# Latency updates
Latency params on the ports can be updated as needed. This can happen because some upstream or
downstream latency changed or when the ProcessLatency of a node changes.
When the ProcessLatency changes, the procedure to notify of latency changes is:
- Take output latency on input port, add new ProcessLatency, set new latency on output
port. This propagates the new latency downstream.
- Take input latency on output port, add new ProcessLatency, set new latency on input
port. This propagates the new latency upstream.
PipeWire will automatically aggregate latency from links and propagate the new latencies
down and upstream.
# Async nodes
When a node has the node.async property set to true, it will be considered an async
node and will be scheduled differently, see scheduling.dox.
A link between a port of an async node and another port (async or not) is called an
async link and will have the link.async=true property.
An async link will add 1 quantum of latency between the nodes it links. A special
exception is made for the output ports of the driver node, which do not add latency.
The Latency param will be updated with 1 extra quantum when they travel over an async
link.
# Examples
## A source node with a given ProcessLatency
When we have a source with a ProcessLatency, for example, of 1024 samples:
```
+----------+ + Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
| FL ---+ Latency: [{ "direction": "input", "min-rate": 0, "max-rate": 0 } ]
| source +
| FR ---+ Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
+----------+ + Latency: [{ "direction": "input", "min-rate": 0, "max-rate": 0 } ]
^
|
ProcessLatency: [ { "quantum": 0, "rate": 1024, "ns": 0 } ]
```
Both output ports have an output latency of 1024 samples and no input latency.
## A sink node with a given ProcessLatency
When we have a sink with a ProcessLatency, for example, of 512 samples:
```
Latency: [{ "direction": "output", "min-rate": 0, "max-rate": 0 } ]
Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
^
| +----------+
+---- FL |
| sink | <- ProcessLatency: [ { "quantum": 0, "rate": 512, "ns": 0 } ]
+---- FR |
| +----------+
v
Latency: [{ "direction": "output", "min-rate": 0, "max-rate": 0 } ]
Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
```
Both input ports have an input latency of 512 samples and no output latency.
## A source and sink node linked together
With the source and sink from above, if we link the FL channels, the input latency
from the input port of the sink is propagated to the output port of the source
and the output latency of the output port is propagated to the input port of the
sink:
```
Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
^
| Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
| Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
| |
+----------+v v+--------+
| FL ------------ FL |
| source + | sink |
| FR --+ FR |
+----------+ | +--------+
v
Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
Latency: [{ "direction": "input", "min-rate": 0, "max-rate": 0 } ]
```
## Insert a latency node
If we place a node with a 256 sample latency in the above source-sink graph:
```
Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
Latency: [{ "direction": "input", "min-rate": 768, "max-rate": 768 } ]
^
| Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
| Latency: [{ "direction": "input", "min-rate": 768, "max-rate": 768 } ]
| ^
| | Latency: [{ "direction": "output", "min-rate": 1280, "max-rate": 1280 } ]
| | Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
| | ^
| | |
+----------+v v+--------+v +-------+
| FL ------------ FL FL --------- FL |
| source + | node | ^ | sink |
| . | . | . |
+----------+ +--------+ | +-------+
v
Latency: [{ "direction": "output", "min-rate": 1280, "max-rate": 1280 } ]
Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
```
See how the output latency propagates and is increased going downstream and the
input latency is increased and traveling upstream.
## Link a port to two port with different latencies
When we introduce a sink2 with different input latency and link this to
the node FL output port, it will aggregate the two input latencies by
taking the min of min and max of max.
```
Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
Latency: [{ "direction": "input", "min-rate": 768, "max-rate": 2304 } ]
^
| Latency: [{ "direction": "output", "min-rate": 1024, "max-rate": 1024 } ]
| Latency: [{ "direction": "input", "min-rate": 768, "max-rate": 2304 } ]
| ^
| | Latency: [{ "direction": "output", "min-rate": 1280, "max-rate": 1280 } ]
| | Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 2048 } ]
| | ^
| | | Latency: [{ "direction": "output", "min-rate": 1280, "max-rate": 1280 } ]
| | | Latency: [{ "direction": "input", "min-rate": 512, "max-rate": 512 } ]
| | | ^
| | | |
+----------+v v+--------+v v +-------+
| FL ------------ FL FL --------- FL |
| source + | node | \ | sink |
| . | . \ . |
+----------+ +--------+ \ +-------+
\
\ +-------+
+--- FL |
^ | sink2 |
| . .
| +-------+
v
Latency: [{ "direction": "output", "min-rate": 1280, "max-rate": 1280 } ]
Latency: [{ "direction": "input", "min-rate": 2048, "max-rate": 2048 } ]
```
The source node now knows that its output signal will be delayed between 768 amd 2304 samples
depending on the path in the graph.
We also see that node.FL has different min/max-rate input latencies. This information can be
used to insert a delay node to align the latencies again. For example, if we delay the signal
between node.FL and FL.sink with 1536 samples, the latencies will be aligned again.
## An async output stream and sink node linked together
The sink has 1 quantum of Input latency. The stream has no output latency. When the Input latency
travels over the async link 1 quantum of latency is added and the Input latency on the stream is
now 2 quanta. Similar for the stream Output latency that receives an additional 1 quantum of
latency when it arrives in the sink over the async link.
```
Latency: [{ "direction": "output", "min-quantum": 0, "max-quantum": 0 } ]
Latency: [{ "direction": "input", "min-quantum": 2, "max-quantum": 2 } ]
^
| Latency: [{ "direction": "output", "min-quantum": 1, "max-quantum": 1 } ]
| Latency: [{ "direction": "input", "min-quantum": 1, "max-quantum": 1 } ]
| |
+----------+v v+--------+
| async FL ------------ FL |
| stream + | sink |
| FR --+ FR |
+----------+ | +--------+
v
Latency: [{ "direction": "output", "min-quantum": 0, "max-quantum": 0 } ]
Latency: [{ "direction": "input", "min-quantum": 0, "max-quantum": 0 } ]
```
*/

View file

@ -92,6 +92,9 @@ The media session will check the permissions on `/dev/snd/seq` before
attempting to create this node. It will also use inotify to wait
until the sequencer device node is accessible.
Currently, the session manager does not try to link control messages
automatically.
## JACK
JACK assumes all `"application/control"` ports are MIDI ports.
@ -102,11 +105,12 @@ filtering out the \ref SPA_CONTROL_Midi, \ref SPA_CONTROL_OSC and
converted to control messages in a similar way.
Normally, all MIDI and UMP messages are converted to MIDI1 jack events unless
the JACK port was created with an explcit "32 bits raw UMP" format, in which
case the raw UMP is passed to the JACK application directly. For output ports,
the JACK port was created with an explcit "32 bit raw UMP" format or with
the JackPortIsMIDI2 flag, in which case the raw UMP is passed to the JACK
application directly. For output ports,
the JACK events are assumed to be MIDI1 and converted to UMP unless the port
has the "32 bit raw UMP" format, in which case the UMP messages are simply
passed on.
has the "32 bit raw UMP" format or the JackPortIsMIDI2 flag, in which case
the UMP messages are simply passed on.
There is a 1 to 1 mapping between the JACK events and control
messages so there is no information loss or need for complicated

View file

@ -179,7 +179,7 @@ A client requests to bind to the registry object and list the available objects
on the server.
Like with all bindings, first the client allocates a new proxy id and puts this
as the new_id field. Methods and Events can then be sent and received on the
as the new_id field. Methods and Events can then be sent and received on the
new_id (in the message Id field).
```
@ -237,7 +237,7 @@ Core::Done event.
Create a new object from a factory of a certain type.
The client allocates a new_id for the proxy. The server will allocate a new
resource with the same new_id and from then on, Methods and Events will be
resource with the same new_id and from then on, Methods and Events will be
exchanged between the new object of the given type.
```
@ -290,7 +290,7 @@ server.
String: version
String: name
Long: change_mask
Struct(
Struct(
Int: n_items
(String: key
String: value)*
@ -434,7 +434,7 @@ registry.
Struct(
Int: id
Int: global_id
Struct(
Struct(
Int: n_items
(String: key
String: value)*
@ -498,7 +498,7 @@ Notify a client about a new global object.
Int: permissions
String: type
Int: version
Struct(
Struct(
Int: n_items
(String: key
String: value)*
@ -556,7 +556,7 @@ Is used to update the properties of a client.
```
Struct(
Struct(
Struct(
Int: n_items
(String: key
String: value)*
@ -610,7 +610,7 @@ when the client info is updated later.
Struct(
Int: id
Long: change_mask
Struct(
Struct(
Int: n_items
(String: key
String: value)*
@ -628,7 +628,7 @@ Emitted as the reply of the GetPermissions method.
```
Struct(
Int: index
Struct(
Struct(
Int: n_permissions
(Int: id
Int: permission)*
@ -705,15 +705,15 @@ The info event is emitted when binding or when the device information changed.
Struct(
Int: id
Long: change_mask
Struct(
Struct(
Int: n_items
( String: key
String: value )*
): props
Struct(
Struct(
Int: n_params
( Int: id
Int: flags )*
( Id: id
Int: flags )*
): param_info
)
```
@ -741,7 +741,7 @@ Emitted as a result of EnumParams or SubscribeParams.
```
- seq: the sequence number send by the client EnumParams or server generated
in the SubscribeParams case.
- id: the param id that is reported, see enum spa_param_type
- id: the param id that is reported, see enum spa_param_type
- index: the index of the parameter
- next: the index of the next parameter
- param: the parameter. The object type depends on the id
@ -768,7 +768,7 @@ Info is emitted when binding to the factory global or when the information chang
String: type
Int: version
Long: change_mask
Struct(
Struct(
Int: n_items
( String: key
String: value )*
@ -808,7 +808,7 @@ Info is emitted when binding to the link global or when the information changed.
Int: state
String: error
Pod: format
Struct(
Struct(
Int: n_items
( String: key
String: value )*
@ -850,7 +850,7 @@ Info is emitted when binding to the module global or when the information change
String: filename
String: args
Long: change_mask
Struct(
Struct(
Int: n_items
( String: key
String: value )*
@ -926,7 +926,7 @@ Send a Command to the node.
Pod: command
)
```
- command: the command to send. See enum spa_node_command
- command: the command to send. See enum spa_node_command
## Node events
@ -944,15 +944,15 @@ The info event is emitted when binding or when the node information changed.
Int: n_output_ports
Id: state
String: error
Struct(
Struct(
Int: n_items
( String: key
String: value )*
): props
Struct(
Struct(
Int: n_params
( Int: id
Int: flags )*
Int: flags )*
): param_info
)
```
@ -987,7 +987,7 @@ Emitted as a result of EnumParams or SubscribeParams.
```
- seq: the sequence number send by the client EnumParams or server generated
in the SubscribeParams case.
- id: the param id that is reported, see enum spa_param_type
- id: the param id that is reported, see enum spa_param_type
- index: the index of the parameter
- next: the index of the next parameter
- param: the parameter. The object type depends on the id
@ -1040,15 +1040,15 @@ The info event is emitted when binding or when the port information changed.
Int: id
Int: direction
Long: change_mask
Struct(
Struct(
Int: n_items
( String: key
String: value )*
): props
Struct(
Struct(
Int: n_params
( Int: id
Int: flags )*
Int: flags )*
): param_info
)
```
@ -1077,7 +1077,7 @@ Emitted as a result of EnumParams or SubscribeParams.
```
- seq: the sequence number send by the client EnumParams or server generated
in the SubscribeParams case.
- id: the param id that is reported, see enum spa_param_type
- id: the param id that is reported, see enum spa_param_type
- index: the index of the parameter
- next: the index of the next parameter
@ -1091,6 +1091,77 @@ It creates a server Node that can be controlled from a client. Processing will h
in the client. It is used by pw-stream and pw-filter to implement the PipeWire media
processing nodes.
To create a client-node, one must first connect to the server and then make a
ClientNode proxy and do Core::CreateObject with the client-node factory.
This will create a server side ClientNode resource that can be controlled with the
proxy.
After the proxy is set up, the conversation between client and server goes as
follows:
```
client server
| |
|---------------------------------------->|
| ClientNode::Update | send initial node configuration
| |
|<----------------------------------------|
| Core::AddMem | memory for node activation
|<----------------------------------------|
| ClientNode::SetActivation | the node activation
|<----------------------------------------|
| ClientNode::Transport | the node transport
|<----------------------------------------|
| ClientNode::SetIO | clock IO
| |
|---------------------------------------->|
| ClientNode::SetActive(true) | set the node active
| |
|<----------------------------------------|
| ClientNode::SetParam | optional volume restore/settings
|<----------------------------------------|
| ClientNode::SetParam | optional PortConfig if needed
|---------------------------------------->|
| ClientNode::Update | Upload changed params
| |
|---------------------------------------->|
| ClientNode::PortUpdate | config for each port
. .
|<----------------------------------------|
| ClientNode::PortSetMixInfo | mixer inputs for each linked port
|<----------------------------------------|
| ClientNode::PortSetParam | Latency of the ports
|<----------------------------------------|
| ClientNode::SetActivation | activation of port peers
|---------------------------------------->|
| ClientNode::PortUpdate | Ack port updates
. .
|<----------------------------------------|
| ClientNode::PortSetParam | formats of the ports
|---------------------------------------->|
| ClientNode::PortUpdate | Ack port format update
. .
|<----------------------------------------|
| Core::AddMem | memory for the port buffers
|<----------------------------------------|
| ClientNode::PortUseBuffers | buffers for a port
. .
|<----------------------------------------|
| Core::AddMem | memory for driver activation
|<----------------------------------------|
| ClientNode::SetActivation | the driver activation
|<----------------------------------------|
| ClientNode::SetIO | driver Position IO
|<----------------------------------------|
| Core::AddMem | memory for port IO
|<----------------------------------------|
| ClientNode::PortSetIO | buffers/async-buffers port IO
. .
|<----------------------------------------|
| ClientNode::Command | Start command
. .
```
## ClientNode methods
### ClientNode::GetNode (Opcode 1)
@ -1333,7 +1404,7 @@ Add a new port to the node
Struct(
Int: direction
Int: port_id
Struct(
Struct(
Int: n_items
( String: key
String: value )*
@ -1486,7 +1557,7 @@ ports of a node.
Int: port_id
Int: mix_id
Int: peer_id
Struct(
Struct(
Int: n_items
( String: key
String: value )*
@ -1570,7 +1641,7 @@ The profiler has no methods
Pod: object
)
```
- object: a SPA_TYPE_OBJECT_Profiler object. See enum spa_profiler
- object: a SPA_TYPE_OBJECT_Profiler object. See enum spa_profiler
# Footer {#native-protocol-footer}

View file

@ -2,26 +2,26 @@
This document tries to explain how the PipeWire graph is scheduled.
Graph are constructed from linked nodes together with their ports. This
Graphs are constructed from linked nodes together with their ports. This
results in a dependency graph between nodes. Special care is taken for
loopback links so that the graph remains a directed graph.
# Processing threads
The server (and clients) have two processing threads:
The server (and clients) has two processing threads:
- A main thread that will do all IPC with clients and server and configures the
- A main thread that will do all IPC with clients and server and configure the
nodes in the graph for processing.
- A (or more) data processing thread that only does the data processing.
- One (or more) data processing threads that only do the data processing.
The data processing threads are given realtime priority and are designed to
run with as little overhead as possible. All of the node resources such as
buffers, io areas and metadata will be set up in shared memory before the
buffers, I/O areas and metadata will be set up in shared memory before the
node is scheduled to run.
This document describes the processing that happens in the data processing
thread after the main-thread has configured it.
thread after the main thread has configured it.
# Nodes
@ -41,7 +41,7 @@ Each node also has:
+-v---------+
activation {
status:OK, // bitmask of NEED_DATA, HAVE_DATA or OK
pending:0, // number of unsatisfied dependencies to be able to run
pending:0, // number of unsatisfied dependencies needed to be able to run
required:0 // number of dependencies with other nodes
}
```
@ -49,7 +49,7 @@ Each node also has:
The activation record has the following information:
- processing state and pending dependencies. As long as there are pending dependencies
the node can not be processed. This is the only relevant information for actually
the node cannot be processed. This is the only relevant information for actually
scheduling the graph and is shown in the above illustration.
- Current status of the node and profiling info (TRIGGERED, AWAKE, FINISHED, timestamps
when the node changed state).
@ -152,14 +152,15 @@ will then:
- Check the previous cycle. Did it complete? Mark xrun on unfinished nodes.
- Perform reposition requests if any, timebase changes, etc..
- The pending counter of each follower node is set to the required field.
- Update the cycle counter in the driver activation io.
- It then loops over all targets of the driver and atomically decrements the required
field of the activation record. When the required field is 0, the eventfd is signaled
and the node can be scheduled.
In our example above, Node A and B will have their pending state decremented. Node A
In our example above, nodes A and B will have their pending state decremented. Node A
will be 0 and will be triggered first (node B has 2 pending dependencies to start with and
will not be triggered yet). The driver itself also has 2 dependencies left and will not
be triggered (complete) yet.
be triggered (completed) yet.
## Scheduling node A
@ -171,12 +172,12 @@ After processing, node A goes through the list of targets and decrements each pe
field (node A has a reference to B and the driver).
In our above example, the driver is decremented (from 2 to 1) but is not yet triggered.
node B is decremented (from 1 to 0) and is triggered by writing to the eventfd.
Node B is decremented (from 1 to 0) and is triggered by writing to the eventfd.
## Scheduling node B
Node B is scheduled and processes the input from node A. It then goes through the list of
targets and decrements the pending fields. It decrements the pending field of the
targets and decrements the pending fields. It decrements the pending field of the
driver (from 1 to 0) and triggers the driver.
## Scheduling the driver
@ -184,11 +185,131 @@ driver (from 1 to 0) and triggers the driver.
The graph always completes after the driver is triggered and scheduled. All required
fields from all the nodes in the target list of the driver are now 0.
The driver calculates some stats about cpu time etc.
The driver calculates some stats about CPU time etc.
# Remote nodes.
# Async scheduling
For remote nodes, the eventfd and the activation is transferred from the server
When a node has the node.async property set to true, it will be considered an async
node and will be scheduled differently.
Async nodes don't increment the pending counter of their peers and the upstream peers
also don't increment the async node pending counters. Only the driver increments the
pending counter to the async node.
This means that the async nodes do not depend on any other node and also are not a
dependency for other nodes. This also means that the async nodes can be scheduled as
soon as the driver has started the graph.
The completion of the async node does not influence the completion of the graph in
any way and async nodes are therefore interesting when real-time performance can not
be guaranteed, for example when the processing threads are not running with a real-time
priority.
A link between a port of an async node and another port (async or not) is called an
async link and will have the link.async=true property.
Because async nodes then run concurrently with other nodes, a method must be in place
to avoid concurrent access to buffer data. This is done by sending a spa_io_async_buffers
I/O to the (mixer) ports of an async link. The spa_io_async_buffers has 2 spa_io_buffer
slots.
The driver will increment a cycle counter for each cycle that it starts. Output ports
will write to the spa_io_async_buffers (cycle+1)&1 slot and input ports will read from
(cycle&1) slots. This way the async node will always consume the output of the previous
cycle and will provide data for the next cycle. They will therefore always add 1 cycle
of latency in the graph.
A special exception is made for the output ports of the driver node. When the driver is
started, the output port buffers are copied to the previous cycle spa_io_buffer slot.
This way, the async nodes will immediately pick up the new data from the driver source.
Because there are 2 buffers in flight on the spa_io_async_buffers I/O area, the link needs
to negotiate at least 2 buffers for this to work.
## Example
A, B, C are async nodes and have async links between their ports. The async
link has the spa_io_async_buffers with 2 slots (named 0 and 1) below. All the
slots are empty.
```
+--------+ +-------+ +-------+
| A | | B | | C |
| 0 -( )-> 0 0 -( )-> 0 |
| 1 ( ) 1 1 ( ) 1 |
+--------+ +-------+ +-------+
```
cycle 0: A produces a buffer AB0 on the output port in the (cycle+1)&1 slot (1).
B consumes slot cycle&1 (0) with the empty buffer and produces BC0 in slot 1
C consumes slot cycle&1 (0) with the empty buffer
```
+--------+ +-------+ +-------+
| A | | B | | C |
| (AB0) 0 -( )-> 0 ( ) 0 -( )-> 0 ( ) |
| 1 (AB0) 1 1 (BC0) 1 |
+--------+ +-------+ +-------+
```
cycle 1: A produces a buffer AB1 on the output port in the (cycle+1)&1 slot (0).
B consumes slot cycle&1 (1) with buffer AB0 and produces BC1 in slot 0
C consumes slot cycle&1 (1) with buffer BC0
```
+--------+ +-------+ +-------+
| A | | B | | C |
| (AB1) 0 -(AB1)-> 0 (AB0) 0 -(BC1)-> 0 (BC0) |
| 1 (AB0) 1 1 (BC0) 1 |
+--------+ +-------+ +-------+
```
cycle 2: A produces a buffer AB2 on the output port in the (cycle+1)&1 slot (1).
B consumes slot cycle&1 (0) with buffer AB1 and produces BC2 in slot 1
C consumes slot cycle&1 (0) with buffer BC1
```
+--------+ +-------+ +-------+
| A | | B | | C |
| (AB2) 0 -(AB1)-> 0 (AB1) 0 -(BC1)-> 0 (BC1) |
| 1 (AB2) 1 1 (BC2) 1 |
+--------+ +-------+ +-------+
```
Each async link adds 1 cycle of latency to the chain. Notice how AB0 from cycle 0,
produces BC1 in cycle 1, which arrives in node C at cycle 2.
## Latency reporting
Because the latency is really introduced by the links, the additional cycle of
latency is added when the SPA_PARAM_Latency is copied between the output and
input ports of a link.
It is possible for a sync node A to be linked to another sync node D and an
async node B:
```
+--------+ +-------+
| A | | B |
| (AB1) 0 -(AB1)-> 0 (AB0) 0 ...
| 1 \(AB0) 1 1
+--------+ \ +-------+
\
\ +-------+
\ | D |
-(AB1)-> 0 (AB1) |
| |
+-------+
```
The output latency on A's output port is what A reports. When it is copied to the
input port of B, 1 cycle is added and when it is copied to D, nothing is added.
# Remote nodes
For remote nodes, the eventfd and the activation are transferred from the server
to the client.
This means that writing to the remote client eventfd will wake the client directly
@ -198,7 +319,7 @@ All remote clients also get the activation and eventfd of the peer and driver th
are linked to and can directly trigger peers and drivers without going to the
server first.
## Remote driver nodes.
## Remote driver nodes
Remote drivers start the graph cycle directly without going to the server first.
@ -206,7 +327,8 @@ After they complete (and only when the profiler is active), they will trigger an
extra eventfd to signal the server that the graph completed. This is used by the
server to generate the profiler info.
## Lazy scheduling
# Lazy scheduling
Normally, a driver will wake up the graph and all the followers need to process
the data in sync. There are cases where:
@ -228,7 +350,7 @@ When the graph is started or partially controlled by RequestProcess events and
commands we say we have lazy scheduling. The driver is not always scheduling according
to its own rhythm but also depending on the follower.
We can't just enable lazy scheduling when no follower will emit RequestProcess events
We cannot just enable lazy scheduling when no follower will emit RequestProcess events
or when no driver will listen for RequestProcess commands. Two new node properties are
defined:
@ -243,9 +365,9 @@ defined:
>1 means request events as a follower are supported with increasing preference
We can only enable lazy scheduling when both the driver and (at least one) follower
has the node.supports-lazy and node.supports-request property respectively.
have the node.supports-lazy and node.supports-request properties respectively.
Node can end up as a driver (is_driver()) and lazy scheduling can be enabled (is_lazy()),
Nodes can end up as a driver (is_driver()) and lazy scheduling can be enabled (is_lazy()),
which results in the following cases:
driver producer
@ -302,7 +424,7 @@ Some use cases:
consumer
- node.driver = false
-> producer selected as driver, consumer is simple follower.
-> producer selected as driver, consumer is a simple follower.
lazy scheduling inactive (no lazy driver or no request follower)

70
doc/dox/internals/tag.dox Normal file
View file

@ -0,0 +1,70 @@
/** \page page_tag Tag support
This document explains how stream specific metadata is transported in
the PipeWire graph.
The metadata is a dictionary of string key/value pairs with information
such as the author, track, copyright, album information etc.
# Use Cases
## A stream/node/port has some metadata
Applications need to be able to query the Tag of a port/node/stream.
Linked Nodes need to be informed of the upstream and downstream tags.
## dynamically update tags
It needs to be possible to dynamically update the tags of a port/node/stream
and this should inform all linked ports/nodes of the updated tags.
## Aggregate tags upstream and downstream
A node might need to know all the upstream and downstream tags. Each node can
add or remove metadata in the Tag param.
A mixer node might need to combine the Tags of the two input streams and
generate a combined tag.
# Concepts
## Port Tags
The fundamental object for implementing metadata reporting in PipeWire is the
Tag object.
It consists of a direction (input/output) and one or more generic dictionaries
with string key/value pairs.
The direction of the tag object determines how the object propagates in the graph.
- SPA_DIRECTION_OUTPUT Tag objects move from output ports downstream and contain
the metadata from all nodes upstream. An output tag received on an input port
should instruct the node to update the output tag on its output ports related
to this input port.
- SPA_DIRECTION_INPUT Tag objects move from input ports upstream and contain
the metadata from all nodes downstream. An input tag received on an output port
should instruct the node to update the input tag on its input ports related
to this output port.
PipeWire will automatically propagate Tag objects from ports to all linked ports
in the graph. Output Tag objects on output ports are propagated to linked input
ports and input Tag objects on input ports are propagated to linked output ports.
If a port has links with multiple other ports, the Tag objects are merged by
appending the dictionaties to the Tag param. Intermediate nodes or sinks are allowed
to take the multiple dictionaries in a Tag and combine them into one dictionary if
they would like to do so.
This way, Output Tag always describes the aggragated total upstream metadata of
signal up to the port and Input tag describes the aggregated downstream metadata
of the signal from the port.
# Tag updates
Tag params on the ports can be updated as needed. This can happen because some upstream or
downstream Tag changed or when the metadata of a node/port/stream changes.
*/

View file

@ -14,6 +14,10 @@ Play and record media with PipeWire
**pw-midirecord** \[*options*\] \[*FILE* \| -\]
**pw-midi2play** \[*options*\] \[*FILE* \| -\]
**pw-midi2record** \[*options*\] \[*FILE* \| -\]
**pw-dsdplay** \[*options*\] \[*FILE* \| -\]
# DESCRIPTION
@ -24,10 +28,10 @@ supported by `libsndfile` for PCM capture and playback. When capturing
PCM, the filename extension is used to guess the file format with the
WAV file format as the default.
It understands standard MIDI files for playback and recording. This tool
will not render MIDI files, it will simply make the MIDI events
available to the graph. You need a MIDI renderer such as qsynth,
timidity or a hardware MIDI rendered to hear the MIDI.
It understands standard MIDI files and MIDI 2.0 clip files for playback
and recording. This tool will not render MIDI files, it will simply make
the MIDI events available to the graph. You need a MIDI renderer such as
qsynth, timidity or a hardware MIDI renderer to hear the MIDI.
DSD playback is supported with the DSF file format. This tool will only
work with native DSD capable hardware and will produce an error when no
@ -53,13 +57,13 @@ connection is made to the default PipeWire instance.
\par -p | \--playback
Playback mode. Read data from the specified file, and play it back. If
the tool is called under the name **pw-play** or **pw-midiplay** this is
the default.
the tool is called under the name **pw-play**, **pw-midiplay** or
**pw-midi2play** this is the default.
\par -r | \--record
Recording mode. Capture data and write it to the specified file. If the
tool is called under the name **pw-record** or **pw-midirecord** this is
the default.
tool is called under the name **pw-record**, **pw-midirecord** or
**pw-midi2record** this is the default.
\par -m | \--midi
MIDI mode. *FILE* is a MIDI file. If the tool is called under the name
@ -69,6 +73,14 @@ simply provide the MIDI events in the graph. You need a separate MIDI
renderer such as qsynth, timidity or a hardware renderer to hear the
MIDI.
\par -c | \--midi-clip
MIDI 2.0 clip mode. *FILE* is a MIDI 2.0 clip file. If the tool is called
under the name **pw-midi2play** or **pw-midi2record** this is the default.
Note that this program will *not* render the MIDI events into audible
samples, it will simply provide the MIDI events in the graph. You need a
separate MIDI renderer such as qsynth, timidity or a hardware renderer to
hear the MIDI.
\par -d | \--dsd
DSD mode. *FILE* is a DSF file. If the tool is called under the name
**pw-dsdplay** this is the default. Note that this program will *not*

View file

@ -33,6 +33,10 @@ for many commands.
\par quit | q
Exit from **pw-cli**
\par list-vars
List all currently known variables and their type. Some commands create
objects that are identified with a variable.
# MODULE MANAGEMENT
Modules are loaded and unloaded in the local instance, thus the pw-cli
@ -48,12 +52,12 @@ For most modules it is OK to be loaded more than once.
This command returns a module variable that can be used to unload the
module.
The locally module is *not* visible in the remote instance. It is not
The local module is *not* visible in the remote instance. It is not
possible in PipeWire to load modules in a remote instance.
\endparblock
\par unload-module *module-var*
Unload a module, specified either by its variable.
Unload a module, specified by its variable.
# OBJECT INTROSPECTION

View file

@ -4,7 +4,7 @@ The PipeWire Link Command
# SYNOPSIS
**pw-link** \[*options*\] -o-l \[*out-pattern*\] \[*in-pattern*\]
**pw-link** \[*options*\] -o|-i|-l|-t \[*out-pattern*\] \[*in-pattern*\]
**pw-link** \[*options*\] *output* *input*
@ -37,11 +37,14 @@ output ports and their links.
List output ports
\par -i | \--input
List output ports
List input ports
\par -l | \--links
List links
\par -t | \--latency
List port latencies
\par -m | \--monitor
Monitor links and ports. **pw-link** will not exit but monitor and print
new and destroyed ports or links.

View file

@ -14,7 +14,7 @@ node and device statistics.
A hierarchical view is shown of Driver nodes and follower nodes. The
Driver nodes are actively using a timer to schedule dataflow in the
followers. The followers of a driver node as shown below their driver
with a + sign in a tree-like representation.
with a + sign (or = for async nodes) in a tree-like representation.
The columns presented are as follows:
@ -173,10 +173,20 @@ For Video formats, the layout is \<pixelformat\>
\parblock
Name assigned to the device/node, as found in *pw-dump* node.name
Names are prefixed by *+* when they are linked to a driver (entry
above with no +)
Names are prefixed by *+*/*=* when they are linked to a driver (entry
above with no +/=)
\endparblock
# COMMANDS
The following keys can be used in the interactive mode:
\par q
Quit
\par c
Clear the ERR counters. This does *not* clear the counters globally,
it will only reset the counters in this instance of *pw-top*.
# OPTIONS

View file

@ -9,12 +9,12 @@ PipeWire API step-by-step with simple short examples.
- \subpage page_tutorial4
- \subpage page_tutorial5
- \subpage page_tutorial6
- \subpage page_tutorial7
# More Example Programs
- \ref audio-src.c "": \snippet{doc} audio-src.c title
- \ref audio-dsp-filter.c "": \snippet{doc} audio-dsp-filter.c title
- \ref video-play.c "": \snippet{doc} video-play.c title
- \subpage page_examples

View file

@ -1,6 +1,6 @@
/** \page page_tutorial6 Tutorial - Part 6: Binding Objects
\ref page_tutorial5 | \ref page_tutorial "Index"
\ref page_tutorial5 | \ref page_tutorial "Index" | \ref page_tutorial7
In this tutorial we show how to bind to an object so that we can
receive events and call methods on the object.
@ -64,6 +64,6 @@ you created. Otherwise, they will be leaked:
}
\endcode
\ref page_tutorial5 | \ref page_tutorial "Index"
\ref page_tutorial5 | \ref page_tutorial "Index" | \ref page_tutorial7
*/

View file

@ -0,0 +1,242 @@
/** \page page_tutorial7 Tutorial - Part 7: Creating an Audio DSP Filter
\ref page_tutorial6 | \ref page_tutorial "Index"
In this tutorial we show how to use \ref pw_filter "pw_filter" to create
a real-time audio processing filter. This is useful for implementing audio
effects, equalizers, analyzers, and other DSP applications.
Let's take a look at the code before we break it down:
\snippet tutorial7.c code
Save as tutorial7.c and compile with:
gcc -Wall tutorial7.c -o tutorial7 -lm $(pkg-config --cflags --libs libpipewire-0.3)
## Overview
Unlike \ref pw_stream "pw_stream" which is designed for applications that
produce or consume audio data, \ref pw_filter "pw_filter" is designed for
applications that process existing audio streams. Filters have both input
and output ports and operate in the DSP domain using 32-bit floating point
samples.
## Setting up the Filter
We start with the usual boilerplate and define our data structure:
\code{.c}
struct data {
struct pw_main_loop *loop;
struct pw_filter *filter;
struct port *in_port;
struct port *out_port;
};
\endcode
The filter object manages both input and output ports. Each port represents
an audio channel that can be connected to other applications.
## Creating the Filter
\code{.c}
data.filter = pw_filter_new_simple(
pw_main_loop_get_loop(data.loop),
"audio-filter",
pw_properties_new(
PW_KEY_MEDIA_TYPE, "Audio",
PW_KEY_MEDIA_CATEGORY, "Filter",
PW_KEY_MEDIA_ROLE, "DSP",
NULL),
&filter_events,
&data);
\endcode
We use `pw_filter_new_simple()` which automatically manages the core connection
for us. The properties are important:
- `PW_KEY_MEDIA_TYPE`: "Audio" indicates this is an audio filter
- `PW_KEY_MEDIA_CATEGORY`: "Filter" tells the session manager this processes audio
- `PW_KEY_MEDIA_ROLE`: "DSP" indicates this is for audio processing
## Adding Ports
Next we add input and output ports:
\code{.c}
data.in_port = pw_filter_add_port(data.filter,
PW_DIRECTION_INPUT,
PW_FILTER_PORT_FLAG_MAP_BUFFERS,
sizeof(struct port),
pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_PORT_NAME, "input",
NULL),
NULL, 0);
data.out_port = pw_filter_add_port(data.filter,
PW_DIRECTION_OUTPUT,
PW_FILTER_PORT_FLAG_MAP_BUFFERS,
sizeof(struct port),
pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_PORT_NAME, "output",
NULL),
NULL, 0);
\endcode
Key points about filter ports:
- `PW_DIRECTION_INPUT` and `PW_DIRECTION_OUTPUT` specify the port direction
- `PW_FILTER_PORT_FLAG_MAP_BUFFERS` allows direct memory access to buffers
- `PW_KEY_FORMAT_DSP` indicates this uses 32-bit float DSP format
- DSP ports work with normalized floating-point samples (typically -1.0 to 1.0)
## Setting Process Latency
\code{.c}
params[n_params++] = spa_process_latency_build(&b,
SPA_PARAM_ProcessLatency,
&SPA_PROCESS_LATENCY_INFO_INIT(
.ns = 10 * SPA_NSEC_PER_MSEC
));
\endcode
This tells PipeWire that our filter adds 10 milliseconds of processing latency.
This information helps the audio system maintain proper timing and latency
compensation throughout the audio graph.
## Connecting the Filter
\code{.c}
if (pw_filter_connect(data.filter,
PW_FILTER_FLAG_RT_PROCESS,
params, n_params) < 0) {
fprintf(stderr, "can't connect\n");
return -1;
}
\endcode
The `PW_FILTER_FLAG_RT_PROCESS` flag ensures our process callback runs in the
real-time audio thread. This is crucial for low-latency audio processing but
means our process function must be real-time safe (no allocations, file I/O,
or blocking operations).
## The Process Callback
The heart of the filter is the process callback:
\snippet tutorial7.c on_process
The process function is called for each audio buffer and works as follows:
1. Get the number of samples to process from `position->clock.duration`
2. Get input and output buffer pointers using `pw_filter_get_dsp_buffer()`
3. Process the audio data (here we just copy input to output)
4. The framework handles queueing the processed buffers
### Key Points about DSP Processing:
- **Float Format**: DSP buffers use 32-bit float samples, typically normalized to [-1.0, 1.0]
- **Real-time Safe**: The process function runs in the audio thread and must be real-time safe
- **Buffer Management**: `pw_filter_get_dsp_buffer()` handles the buffer lifecycle automatically
- **Sample-accurate**: Processing happens at the audio sample rate with precise timing
## Advanced Usage
This example shows a simple passthrough, but you can implement any audio processing:
\code{.c}
/* Example: Simple volume control */
for (uint32_t i = 0; i < n_samples; i++) {
out[i] = in[i] * 0.5f; // Reduce volume by half
}
/* Example: Simple high-pass filter */
static float last_sample = 0.0f;
float alpha = 0.99f;
for (uint32_t i = 0; i < n_samples; i++) {
out[i] = alpha * (out[i] + in[i] - last_sample);
last_sample = in[i];
}
\endcode
## Comparison with pw_stream
| Feature | pw_stream | pw_filter |
|---------|-----------|-----------|
| **Use case** | Audio playback/recording | Audio processing/effects |
| **Data format** | Various (S16, S32, etc.) | 32-bit float DSP |
| **Ports** | Single direction | Input and output |
| **Buffer management** | Manual queue/dequeue | Automatic via get_dsp_buffer |
| **Typical apps** | Media players, recorders | Equalizers, effects, analyzers |
## Connecting and Linking the Filter
### Manual Linking Options
Filters require manual connection by design. You can connect them using:
#### Using pw-link command line:
\code{.sh}
# List output ports (sources)
pw-link -o
# List input ports (sinks)
pw-link -i
# List existing connections
pw-link -l
# Connect a source to filter input
pw-link "source_app:output_FL" "audio-filter:input"
# Connect filter output to sink
pw-link "audio-filter:output" "sink_app:input_FL"
\endcode
### Understanding Filter Auto-Connection Behavior
**Important**: Unlike audio sources and sinks, filters are **not automatically connected** by WirePlumber. This is by design because filters are meant to be explicitly inserted into audio chains where needed.
**Why filters don't auto-connect**:
- Filters process existing audio streams rather than generate/consume them
- Auto-connecting filters could create unwanted audio processing
- Filters typically require specific placement in the audio graph
- Manual connection gives users control over when/where effects are applied
### Testing the Filter
The filter requires manual connection to test. Here's the recommended workflow:
1. **Start an audio source** (e.g., `pw-play music.wav`)
2. **Run your filter** (`./tutorial7`)
3. **Check available ports**:
```sh
# List output ports
pw-link -o | grep -E "(pw-play|audio-filter)"
# List input ports
pw-link -i | grep -E "(audio-filter|playback)"
```
4. **Connect the audio chain manually**:
```sh
# Connect source -> filter -> sink
pw-link "pw-play:output_FL" "audio-filter:input"
pw-link "audio-filter:output" "alsa_output.pci-0000_00_1f.3.analog-stereo:playback_FL"
```
You should hear the audio pass through your filter. Modify the process function
to add effects like volume changes, filtering, or other audio processing.
**Alternative: Use a patchbay tool**
- **Helvum**: `flatpak install flathub org.pipewire.Helvum`
- **qpwgraph**: Available in most Linux distributions
- **Carla**: Full-featured audio plugin host
These tools provide graphical interfaces for connecting PipeWire nodes and are ideal for experimenting with filter placement.
\ref page_tutorial6 | \ref page_tutorial "Index"
*/

File diff suppressed because it is too large Load diff

152
doc/examples/tutorial7.c Normal file
View file

@ -0,0 +1,152 @@
/*
[title]
\ref page_tutorial7
[title]
*/
/* [code] */
#include <stdio.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
#include <spa/pod/builder.h>
#include <spa/param/latency-utils.h>
#include <pipewire/pipewire.h>
#include <pipewire/filter.h>
struct data;
struct port {
struct data *data;
};
struct data {
struct pw_main_loop *loop;
struct pw_filter *filter;
struct port *in_port;
struct port *out_port;
};
/* [on_process] */
static void on_process(void *userdata, struct spa_io_position *position)
{
struct data *data = userdata;
float *in, *out;
uint32_t n_samples = position->clock.duration;
pw_log_trace("do process %d", n_samples);
in = pw_filter_get_dsp_buffer(data->in_port, n_samples);
out = pw_filter_get_dsp_buffer(data->out_port, n_samples);
if (in == NULL || out == NULL)
return;
/* Simple passthrough - copy input to output.
* Here you could implement any audio processing:
* - Filters (lowpass, highpass, bandpass)
* - Effects (reverb, delay, distortion)
* - Dynamic processing (compressor, limiter)
* - Equalization
* - etc.
*/
memcpy(out, in, n_samples * sizeof(float));
}
/* [on_process] */
static const struct pw_filter_events filter_events = {
PW_VERSION_FILTER_EVENTS,
.process = on_process,
};
static void do_quit(void *userdata, int signal_number)
{
struct data *data = userdata;
pw_main_loop_quit(data->loop);
}
int main(int argc, char *argv[])
{
struct data data = { 0, };
const struct spa_pod *params[1];
uint32_t n_params = 0;
uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
pw_init(&argc, &argv);
/* make a main loop. If you already have another main loop, you can add
* the fd of this pipewire mainloop to it. */
data.loop = pw_main_loop_new(NULL);
pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGINT, do_quit, &data);
pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGTERM, do_quit, &data);
/* Create a simple filter, the simple filter manages the core and remote
* objects for you if you don't need to deal with them.
*
* Pass your events and a user_data pointer as the last arguments. This
* will inform you about the filter state. The most important event
* you need to listen to is the process event where you need to process
* the data.
*/
data.filter = pw_filter_new_simple(
pw_main_loop_get_loop(data.loop),
"audio-filter",
pw_properties_new(
PW_KEY_MEDIA_TYPE, "Audio",
PW_KEY_MEDIA_CATEGORY, "Filter",
PW_KEY_MEDIA_ROLE, "DSP",
NULL),
&filter_events,
&data);
/* make an audio DSP input port */
data.in_port = pw_filter_add_port(data.filter,
PW_DIRECTION_INPUT,
PW_FILTER_PORT_FLAG_MAP_BUFFERS,
sizeof(struct port),
pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_PORT_NAME, "input",
NULL),
NULL, 0);
/* make an audio DSP output port */
data.out_port = pw_filter_add_port(data.filter,
PW_DIRECTION_OUTPUT,
PW_FILTER_PORT_FLAG_MAP_BUFFERS,
sizeof(struct port),
pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_PORT_NAME, "output",
NULL),
NULL, 0);
/* Set processing latency information */
params[n_params++] = spa_process_latency_build(&b,
SPA_PARAM_ProcessLatency,
&SPA_PROCESS_LATENCY_INFO_INIT(
.ns = 10 * SPA_NSEC_PER_MSEC
));
/* Now connect this filter. We ask that our process function is
* called in a realtime thread. */
if (pw_filter_connect(data.filter,
PW_FILTER_FLAG_RT_PROCESS,
params, n_params) < 0) {
fprintf(stderr, "can't connect\n");
return -1;
}
/* and wait while we let things run */
pw_main_loop_run(data.loop);
pw_filter_destroy(data.filter);
pw_main_loop_destroy(data.loop);
pw_deinit();
return 0;
}
/* [code] */

View file

@ -25,7 +25,7 @@ Assumes BUILD_DIR environment variable is set.
containing all index items from the specified section.
# Section title @IDX@ <section>
# Section title @IDX@ <section> [<alternative index name>]
Adds the section title to the index, and expands to an anchor
@ -51,7 +51,7 @@ def index_key(section, name):
BUILD_DIR = os.environ["BUILD_DIR"]
PAR_RE = r"^@PAR@\s+([^\s]*)[ \t]+(\S+)(.*)$"
IDX_RE = r"^(#+)(.*)@IDX@[ \t]+(\S+)[ \t]*$"
IDX_RE = r"^(#+)(.*)@IDX@[ \t]+(\S+)([ \t]+\S+)?[ \t]*$"
SECREF_RE = r"^@SECREF@[ \t]+([^\n]*)[ \t]*$"
@ -71,10 +71,16 @@ def main(args):
level = m.group(1)
title = name = m.group(2).strip()
section = m.group(3)
alt = m.group(4)
if title == title.upper():
name = name.capitalize()
key = index_key(section, name)
return f"{level} {title} {{#{key}}}"
text = f"{level} {title} {{#{key}}}"
if alt and alt.strip():
alt_key = index_key(section, alt.strip())
if alt_key != key:
text += f"\n\\anchor {alt_key}"
return text
def secref(m):
import os
@ -148,9 +154,12 @@ def load_index(sections, text):
def idx(m):
name = m.group(2).strip()
section = m.group(3)
alt = m.group(4)
if name == name.upper():
name = name.capitalize()
sections.setdefault(section, []).append(name)
if alt and alt.strip():
sections.setdefault(section, []).append(alt.strip())
return ""
text = re.sub(PAR_RE, par, text, flags=re.M)

View file

@ -58,6 +58,8 @@ extra_docs = [
'dox/internals/index.dox',
'dox/internals/design.dox',
'dox/internals/access.dox',
'dox/internals/latency.dox',
'dox/internals/tag.dox',
'dox/internals/midi.dox',
'dox/internals/portal.dox',
'dox/internals/daemon.dox',
@ -66,6 +68,7 @@ extra_docs = [
'dox/internals/objects.dox',
'dox/internals/audio.dox',
'dox/internals/scheduling.dox',
'dox/internals/driver.dox',
'dox/internals/protocol.dox',
'dox/internals/pulseaudio.dox',
'dox/internals/dma-buf.dox',
@ -76,6 +79,7 @@ extra_docs = [
'dox/tutorial/tutorial4.dox',
'dox/tutorial/tutorial5.dox',
'dox/tutorial/tutorial6.dox',
'dox/tutorial/tutorial7.dox',
'dox/api/index.dox',
'dox/api/spa-index.dox',
'dox/api/spa-plugins.dox',
@ -170,6 +174,7 @@ example_files = [
'tutorial4.c',
'tutorial5.c',
'tutorial6.c',
'tutorial7.c',
]
example_dep_files = []
foreach h : example_files

View file

@ -43,6 +43,7 @@ This determines the ordering of items in Doxygen sidebar.
\addtogroup pw_protocol
\addtogroup pw_resource
\addtogroup pw_thread_loop
\addtogroup pw_timer_queue
\addtogroup pw_work_queue
\}

View file

@ -1,10 +1,10 @@
project('pipewire', ['c' ],
version : '1.4.0',
version : '1.5.81',
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
meson_version : '>= 0.61.1',
default_options : [ 'warning_level=3',
'c_std=gnu11',
'cpp_std=c++17',
'cpp_std=c++20',
'b_pie=true',
#'b_sanitize=address,undefined',
'buildtype=debugoptimized' ])
@ -81,6 +81,7 @@ pkgconfig = import('pkgconfig')
common_flags = [
'-fvisibility=hidden',
'-fno-strict-aliasing',
'-fno-strict-overflow',
'-Werror=suggest-attribute=format',
'-Wsign-compare',
'-Wpointer-arith',
@ -114,10 +115,11 @@ cc_flags = common_flags + [
'-Werror=old-style-definition',
'-Werror=missing-parameter-type',
'-Werror=strict-prototypes',
'-DSPA_AUDIO_MAX_CHANNELS=128u',
]
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
cc_flags_native = cc_native.get_supported_arguments(cc_flags)
add_project_arguments(cc_native.get_supported_arguments(cc_flags),
language: 'c', native: true)
have_cpp = add_languages('cpp', native: false, required : false)
@ -127,21 +129,30 @@ if have_cpp
add_project_arguments(cxx.get_supported_arguments(cxx_flags), language: 'cpp')
endif
sse_args = '-msse'
sse2_args = '-msse2'
ssse3_args = '-mssse3'
sse41_args = '-msse4.1'
fma_args = '-mfma'
avx_args = '-mavx'
avx2_args = '-mavx2'
have_sse = false
have_sse2 = false
have_ssse3 = false
have_sse41 = false
have_fma = false
have_avx = false
have_avx2 = false
if host_machine.cpu_family() in ['x86', 'x86_64']
sse_args = '-msse'
sse2_args = '-msse2'
ssse3_args = '-mssse3'
sse41_args = '-msse4.1'
fma_args = '-mfma'
avx_args = '-mavx'
avx2_args = '-mavx2'
have_sse = cc.has_argument(sse_args)
have_sse2 = cc.has_argument(sse2_args)
have_ssse3 = cc.has_argument(ssse3_args)
have_sse41 = cc.has_argument(sse41_args)
have_fma = cc.has_argument(fma_args)
have_avx = cc.has_argument(avx_args)
have_avx2 = cc.has_argument(avx2_args)
have_sse = cc.has_argument(sse_args)
have_sse2 = cc.has_argument(sse2_args)
have_ssse3 = cc.has_argument(ssse3_args)
have_sse41 = cc.has_argument(sse41_args)
have_fma = cc.has_argument(fma_args)
have_avx = cc.has_argument(avx_args)
have_avx2 = cc.has_argument(avx2_args)
endif
have_neon = false
if host_machine.cpu_family() == 'aarch64'
@ -268,11 +279,9 @@ endforeach
cdata.set('HAVE_PIDFD_OPEN',
cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '')
systemd = dependency('systemd', required: get_option('systemd'))
systemd_dep = dependency('libsystemd',required: get_option('systemd'))
summary({'systemd conf data': systemd.found()}, bool_yn: true)
systemd_dep = dependency('libsystemd', required: get_option('libsystemd'))
summary({'libsystemd': systemd_dep.found()}, bool_yn: true)
cdata.set('HAVE_SYSTEMD', systemd.found() and systemd_dep.found())
cdata.set('HAVE_SYSTEMD', systemd_dep.found())
logind_dep = dependency(get_option('logind-provider'), required: get_option('logind'))
summary({'logind': logind_dep.found()}, bool_yn: true)
@ -312,7 +321,7 @@ cdata.set('HAVE_DBUS', dbus_dep.found())
sdl_dep = dependency('sdl2', required : get_option('sdl2'))
summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
drm_dep = dependency('libdrm', required : false)
fftw_dep = dependency('fftw3f', required : false)
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
summary({'fftw3f (filter-chain convolver)': fftw_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_FFTW', fftw_dep.found())
@ -331,12 +340,23 @@ endif
pw_cat_ffmpeg = get_option('pw-cat-ffmpeg')
ffmpeg = get_option('ffmpeg')
if pw_cat_ffmpeg.allowed() or ffmpeg.allowed()
# libswscale is only used by videoconvert. FFmpeg might however be used for
# compressed audio (both for decoding said compressed audio and for parsing
# it in pw-cat). If users only care about audio, then libswscale would still
# become a requirement if its required flag is defined only by FFmpeg options.
# Make the videoconvert option a factor in swscale_dep as well to avoid this.
videoconvert = get_option('videoconvert')
avcodec_dep = dependency('libavcodec', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
avformat_dep = dependency('libavformat', required: pw_cat_ffmpeg.enabled())
avfilter_dep = dependency('libavfilter', required: ffmpeg.enabled())
avutil_dep = dependency('libavutil', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
swscale_dep = dependency('libswscale', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
swscale_dep = dependency('libswscale', required: (pw_cat_ffmpeg.enabled() or ffmpeg.enabled()) and videoconvert.enabled())
else
avcodec_dep = dependency('', required: false)
avformat_dep = dependency('', required: false)
avfilter_dep = dependency('', required: false)
avutil_dep = dependency('', required: false)
swscale_dep = dependency('', required: false)
endif
cdata.set('HAVE_PW_CAT_FFMPEG_INTEGRATION', pw_cat_ffmpeg.allowed())
@ -371,9 +391,6 @@ libusb_dep = dependency('libusb-1.0', required : get_option('libusb'))
summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_LIBUSB', libusb_dep.found())
cap_lib = dependency('libcap', required : false)
cdata.set('HAVE_LIBCAP', cap_lib.found())
glib2_dep = dependency('glib-2.0', required : get_option('flatpak'))
summary({'GLib-2.0 (Flatpak support)': glib2_dep.found()}, bool_yn: true, section: 'Misc dependencies')
flatpak_support = glib2_dep.found()
@ -401,6 +418,7 @@ gst_deps_def = {
gst_dep = []
gst_dma_drm_found = false
gst_shm_allocator_found = false
foreach depname, kwargs: gst_deps_def
dep = dependency(depname, required: gst_option, kwargs: kwargs)
summary({depname: dep.found()}, bool_yn: true, section: 'GStreamer modules')
@ -416,9 +434,13 @@ foreach depname, kwargs: gst_deps_def
if depname == 'gstreamer-allocators-1.0' and dep.version().version_compare('>= 1.23.1')
gst_dma_drm_found = true
gst_shm_allocator_found = true
endif
endforeach
summary({'gstreamer SHM allocator': gst_shm_allocator_found}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_GSTREAMER_SHM_ALLOCATOR', gst_shm_allocator_found)
# This code relies on the array being empty if any dependency was not found
gst_dp_found = gst_dep.length() > 0
summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Backend')
@ -481,7 +503,7 @@ endif
summary({'intl support': libintl_dep.found()}, bool_yn: true)
need_alsa = get_option('pipewire-alsa').enabled() or 'media-session' in get_option('session-managers')
alsa_dep = dependency('alsa', version : '>=1.2.10', required: need_alsa)
alsa_dep = dependency('alsa', version : '>=1.2.6', required: need_alsa)
summary({'pipewire-alsa': alsa_dep.found()}, bool_yn: true)
if host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
@ -612,6 +634,8 @@ devenv.prepend('GST_PLUGIN_PATH', builddir / 'src'/ 'gst')
devenv.prepend('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins')
devenv.prepend('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src')
devenv.set('PIPEWIRE_LOG_SYSTEMD', 'false')
devenv.set('PW_UNINSTALLED', '1')
devenv.set('PW_BUILDDIR', meson.project_build_root())
meson.add_devenv(devenv)

View file

@ -30,8 +30,8 @@ option('gstreamer-device-provider',
description: 'Build GStreamer device provider plugin',
type: 'feature',
value: 'auto')
option('systemd',
description: 'Enable systemd integration',
option('libsystemd',
description: 'Enable code that depends on libsystemd',
type: 'feature',
value: 'auto')
option('logind',
@ -48,9 +48,9 @@ option('systemd-system-service',
type: 'feature',
value: 'disabled')
option('systemd-user-service',
description: 'Install systemd user service file (ignored without systemd)',
description: 'Install systemd user service file',
type: 'feature',
value: 'enabled')
value: 'auto')
option('selinux',
description: 'Enable SELinux integration',
type: 'feature',
@ -129,6 +129,10 @@ option('bluez5-codec-ldac',
description: 'Enable LDAC Sony open source codec implementation',
type: 'feature',
value: 'auto')
option('bluez5-codec-ldac-dec',
description: 'Enable LDAC Sony open source codec decoding',
type: 'feature',
value: 'auto')
option('bluez5-codec-aac',
description: 'Enable Fraunhofer FDK AAC open source codec implementation',
type: 'feature',
@ -149,6 +153,10 @@ option('bluez5-codec-g722',
description: 'Enable G722 open source codec implementation',
type: 'feature',
value: 'auto')
option('bluez5-plc-spandsp',
description: 'Enable SpanDSP for packet loss concealment',
type: 'feature',
value: 'auto')
option('control',
description: 'Enable control spa plugin integration',
type: 'feature',
@ -379,3 +387,11 @@ option('ebur128',
description: 'Enable code that depends on ebur128',
type: 'feature',
value: 'auto')
option('fftw',
description: 'Enable code that depends on fftw',
type: 'feature',
value: 'auto')
option('onnxruntime',
description: 'Enable code that depends on onnxruntime',
type: 'feature',
value: 'auto')

View file

@ -22,9 +22,11 @@ PW_LOG_TOPIC_STATIC(alsa_log_topic, "alsa.ctl");
#define VOLUME_MIN ((uint32_t) 0U)
#define VOLUME_MAX ((uint32_t) 0x10000U)
#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS
struct volume {
uint32_t channels;
long values[SPA_AUDIO_MAX_CHANNELS];
long values[MAX_CHANNELS];
};
typedef struct {
@ -498,7 +500,7 @@ static struct spa_pod *build_volume_mute(struct spa_pod_builder *b, struct volum
spa_pod_builder_push_object(b, &f[0],
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
if (volume) {
float volumes[SPA_AUDIO_MAX_CHANNELS];
float volumes[MAX_CHANNELS];
uint32_t i, n_volumes = 0;
n_volumes = volume->channels;
@ -850,11 +852,11 @@ static void parse_props(struct global *g, const struct spa_pod *param, bool devi
break;
case SPA_PROP_channelVolumes:
{
float volumes[SPA_AUDIO_MAX_CHANNELS];
float volumes[MAX_CHANNELS];
uint32_t n_volumes, i;
n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
volumes, SPA_AUDIO_MAX_CHANNELS);
volumes, SPA_N_ELEMENTS(volumes));
g->node.channel_volume.channels = n_volumes;
for (i = 0; i < n_volumes; i++)

View file

@ -30,8 +30,8 @@ PW_LOG_TOPIC_STATIC(alsa_log_topic, "alsa.pcm");
#define MIN_BUFFERS 2u
#define MAX_BUFFERS 64u
#define MAX_CHANNELS 64
#define MAX_RATE (48000*8)
#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS
#define MIN_PERIOD 64
@ -617,6 +617,7 @@ static int snd_pcm_pipewire_stop(snd_pcm_ioplug_t *io)
if (pw->activated && pw->stream != NULL) {
pw_stream_set_active(pw->stream, false);
pw->activated = false;
pw_thread_loop_signal(pw->main_loop, false);
}
pw_thread_loop_unlock(pw->main_loop);
return 0;
@ -642,7 +643,7 @@ static int snd_pcm_pipewire_pause(snd_pcm_ioplug_t * io, int enable)
#define _FORMAT_BE(p, fmt) p ? SPA_AUDIO_FORMAT_UNKNOWN : SPA_AUDIO_FORMAT_ ## fmt ## _OE
#endif
static int set_default_channels(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
static int set_default_channels(uint32_t channels, uint32_t position[MAX_CHANNELS])
{
switch (channels) {
case 8:
@ -915,12 +916,16 @@ static int snd_pcm_pipewire_set_chmap(snd_pcm_ioplug_t * io,
default:
return -EINVAL;
}
if (map->channels > MAX_CHANNELS)
return -ENOTSUP;
for (i = 0; i < map->channels; i++) {
char buf[8];
position[i] = chmap_to_channel(map->pos[i]);
pw_log_debug("map %d: %s / %s", i,
snd_pcm_chmap_name(map->pos[i]),
spa_debug_type_find_short_name(spa_type_audio_channel,
position[i]));
spa_type_audio_channel_make_short_name(position[i],
buf, sizeof(buf), "UNK"));
}
return 1;
}

View file

@ -102,6 +102,7 @@ struct notify {
#define NOTIFY_TYPE_SHUTDOWN ((7<<4)|NOTIFY_ACTIVE_FLAG)
#define NOTIFY_TYPE_LATENCY ((8<<4)|NOTIFY_ACTIVE_FLAG)
#define NOTIFY_TYPE_TOTAL_LATENCY ((9<<4)|NOTIFY_ACTIVE_FLAG)
#define NOTIFY_TYPE_PORT_RENAME ((10<<4)|NOTIFY_ACTIVE_FLAG)
int type;
struct object *object;
int arg1;
@ -171,6 +172,7 @@ struct object {
} port_link;
struct {
unsigned long flags;
char old_name[REAL_JACK_PORT_NAME_SIZE+1];
char name[REAL_JACK_PORT_NAME_SIZE+1];
char alias1[REAL_JACK_PORT_NAME_SIZE+1];
char alias2[REAL_JACK_PORT_NAME_SIZE+1];
@ -231,6 +233,13 @@ struct buffer {
uint32_t n_mem;
};
struct mix_info {
struct spa_pod_parser parser;
struct spa_pod_frame frame;
struct spa_pod_control control;
const void *control_body;
};
struct mix {
struct spa_list link;
struct spa_list port_link;
@ -245,6 +254,8 @@ struct mix {
struct buffer buffers[MAX_BUFFERS];
uint32_t n_buffers;
struct mix_info mix_info;
unsigned int to_free:1;
};
@ -626,8 +637,8 @@ do_mix_set_io(struct spa_loop *loop, bool async, uint32_t seq,
static inline void mix_set_io(struct mix *mix, void *data, size_t size)
{
struct io_info info = { .mix = mix, .data = data, .size = size };
pw_data_loop_invoke(mix->port->client->loop,
do_mix_set_io, SPA_ID_INVALID, &info, sizeof(info), false, NULL);
pw_loop_locked(mix->port->client->loop->loop,
do_mix_set_io, SPA_ID_INVALID, &info, sizeof(info), NULL);
}
static void init_mix(struct mix *mix, uint32_t mix_id, struct port *port, uint32_t peer_id)
@ -1083,6 +1094,16 @@ static void on_notify_event(void *data, uint64_t count)
notify->arg1,
c->portregistration_arg);
break;
case NOTIFY_TYPE_PORT_RENAME:
if (o->registered != notify->arg1)
break;
pw_log_debug("%p: port rename %u %s->%s", c, o->serial,
o->port.old_name, o->port.name);
do_callback(c, rename_callback, c->active,
o->serial,
o->port.old_name, o->port.name,
c->rename_arg);
break;
case NOTIFY_TYPE_CONNECT:
if (o->registered == notify->arg1)
break;
@ -1183,6 +1204,9 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
emit = c->portregistration_callback != NULL && o != NULL;
o->visible = arg1;
break;
case NOTIFY_TYPE_PORT_RENAME:
emit = c->rename_callback != NULL && o != NULL;
break;
case NOTIFY_TYPE_CONNECT:
emit = c->connect_callback != NULL && o != NULL;
break;
@ -1477,7 +1501,8 @@ static inline int event_compare(uint8_t s1, uint8_t s2)
return priotab[(s2>>4) & 7] - priotab[(s1>>4) & 7];
}
static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
static inline int event_sort(struct spa_pod_control *a, const void *abody,
struct spa_pod_control *b, const void *bbody)
{
if (a->offset < b->offset)
return -1;
@ -1488,18 +1513,18 @@ static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *
switch(a->type) {
case SPA_CONTROL_Midi:
{
uint8_t *sa = SPA_POD_BODY(&a->value), *sb = SPA_POD_BODY(&b->value);
const uint8_t *sa = abody, *sb = bbody;
if (SPA_POD_BODY_SIZE(&a->value) < 1 || SPA_POD_BODY_SIZE(&b->value) < 1)
return 0;
return event_compare(sa[0], sb[0]);
}
case SPA_CONTROL_UMP:
{
uint32_t *sa = SPA_POD_BODY(&a->value), *sb = SPA_POD_BODY(&b->value);
const uint32_t *sa = abody, *sb = bbody;
if (SPA_POD_BODY_SIZE(&a->value) < 4 || SPA_POD_BODY_SIZE(&b->value) < 4)
return 0;
if ((sa[0] >> 28) != 2 || (sa[0] >> 28) != 4 ||
(sb[0] >> 28) != 2 || (sb[0] >> 28) != 4)
if (((sa[0] >> 28) != 2 && (sa[0] >> 28) != 4) ||
((sb[0] >> 28) != 2 && (sb[0] >> 28) != 4))
return 0;
return event_compare(sa[0] >> 16, sb[0] >> 16);
}
@ -1538,7 +1563,7 @@ static inline jack_midi_data_t* midi_event_reserve(void *port_buffer,
res = ev->inline_data;
} else {
mb->write_pos += data_size;
ev->byte_offset = mb->buffer_size - 1 - mb->write_pos;
ev->byte_offset = mb->buffer_size - mb->write_pos;
res = SPA_PTROFF(mb, ev->byte_offset, uint8_t);
}
mb->event_count += 1;
@ -1546,69 +1571,91 @@ static inline jack_midi_data_t* midi_event_reserve(void *port_buffer,
return res;
}
static inline int midi_event_append(void *port_buffer, const jack_midi_data_t *data, size_t data_size)
{
struct midi_buffer *mb = port_buffer;
struct midi_event *events = SPA_PTROFF(mb, sizeof(*mb), struct midi_event);
struct midi_event *ev;
size_t old_size;
uint8_t *old, *buf;
ev = &events[--mb->event_count];
mb->write_pos -= ev->size;
old_size = ev->size;
if (old_size <= MIDI_INLINE_MAX)
old = ev->inline_data;
else
old = SPA_PTROFF(mb, ev->byte_offset, uint8_t);
buf = midi_event_reserve(port_buffer, ev->time, old_size + data_size);
if (SPA_UNLIKELY(buf == NULL))
return -ENOBUFS;
memmove(buf, old, old_size);
memcpy(buf+old_size, data, data_size);
return 0;
}
static inline int midi_event_write(void *port_buffer,
jack_nframes_t time,
const jack_midi_data_t *data,
size_t data_size, bool fix)
{
jack_midi_data_t *retbuf = midi_event_reserve (port_buffer, time, data_size);
if (SPA_UNLIKELY(retbuf == NULL))
return -ENOBUFS;
if (SPA_UNLIKELY(retbuf == NULL))
return -ENOBUFS;
memcpy (retbuf, data, data_size);
if (fix)
fix_midi_event(retbuf, data_size);
return 0;
}
static void convert_to_event(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix, uint32_t type)
static void convert_to_event(struct mix_info **mix, uint32_t n_mix, void *midi, bool fix, uint32_t type)
{
struct spa_pod_control *c[n_seq];
uint64_t state = 0;
uint32_t i;
int res = 0;
for (i = 0; i < n_seq; i++)
c[i] = spa_pod_control_first(&seq[i]->body);
bool in_sysex = false;
while (true) {
struct spa_pod_control *next = NULL;
struct mix_info *next = NULL;
uint32_t next_index = 0;
struct spa_pod_control *control;
size_t size;
uint8_t *data;
uint64_t state = 0;
for (i = 0; i < n_seq; i++) {
if (!spa_pod_control_is_inside(&seq[i]->body,
SPA_POD_BODY_SIZE(seq[i]), c[i]))
continue;
if (next == NULL || event_sort(c[i], next) <= 0) {
next = c[i];
for (i = 0; i < n_mix; i++) {
struct mix_info *m = mix[i];
if (next == NULL || event_sort(&m->control, m->control_body,
&next->control, next->control_body) <= 0) {
next = m;
next_index = i;
}
}
if (SPA_UNLIKELY(next == NULL))
break;
switch(next->type) {
control = &next->control;
data = (uint8_t*)next->control_body;
size = SPA_POD_BODY_SIZE(&control->value);
switch(control->type) {
case SPA_CONTROL_OSC:
if (!TYPE_ID_CAN_OSC(type))
break;
SPA_FALLTHROUGH;
case SPA_CONTROL_Midi:
{
uint8_t *data = SPA_POD_BODY(&next->value);
size_t size = SPA_POD_BODY_SIZE(&next->value);
if (type == TYPE_ID_UMP) {
while (size > 0) {
uint32_t ump[4];
int ump_size = spa_ump_from_midi(&data, &size, ump, sizeof(ump), 0, &state);
if (ump_size <= 0)
break;
if ((res = midi_event_write(midi, next->offset,
if ((res = midi_event_write(midi, control->offset,
(uint8_t*)ump, ump_size, false)) < 0)
break;
}
} else {
res = midi_event_write(midi, next->offset, data, size, fix);
res = midi_event_write(midi, control->offset, data, size, fix);
}
if (res < 0)
pw_log_warn("midi %p: can't write event: %s", midi,
@ -1617,25 +1664,43 @@ static void convert_to_event(struct spa_pod_sequence **seq, uint32_t n_seq, void
}
case SPA_CONTROL_UMP:
{
void *data = SPA_POD_BODY(&next->value);
size_t size = SPA_POD_BODY_SIZE(&next->value);
uint8_t ev[32];
if (type == TYPE_ID_MIDI) {
int ev_size = spa_ump_to_midi(data, size, ev, sizeof(ev));
if (ev_size <= 0)
break;
size = ev_size;
data = ev;
} else if (type != TYPE_ID_UMP)
break;
uint8_t ev[32];
const uint32_t *d = (uint32_t*)data;
if ((res = midi_event_write(midi, next->offset, data, size, fix)) < 0)
while (size > 0) {
bool was_sysex = in_sysex;
int ev_size = spa_ump_to_midi(&d, &size, ev, sizeof(ev), &state);
if (ev_size <= 0)
break;
if (!in_sysex && ev[0] == 0xf0)
in_sysex = true;
if (in_sysex && ev[ev_size-1] == 0xf7)
in_sysex = false;
if (was_sysex)
res = midi_event_append(midi, ev, ev_size);
else
res = midi_event_write(midi, control->offset, ev, ev_size, fix);
if (res < 0)
break;
}
} else if (type == TYPE_ID_UMP) {
res = midi_event_write(midi, control->offset, data, size, fix);
}
if (res < 0)
pw_log_warn("midi %p: can't write event: %s", midi,
spa_strerror(res));
break;
}
}
c[next_index] = spa_pod_control_next(c[next_index]);
if (spa_pod_parser_get_control_body(&next->parser,
&next->control, &next->control_body) < 0) {
spa_pod_parser_pop(&next->parser, &next->frame);
mix[next_index] = mix[--n_mix];
}
}
}
@ -2459,16 +2524,16 @@ static int client_node_command(void *data, const struct spa_command *command)
case SPA_NODE_COMMAND_Suspend:
case SPA_NODE_COMMAND_Pause:
if (c->started) {
pw_data_loop_invoke(c->loop,
do_unprepare_client, SPA_ID_INVALID, NULL, 0, false, c);
pw_loop_locked(c->loop->loop,
do_unprepare_client, SPA_ID_INVALID, NULL, 0, c);
c->started = false;
}
break;
case SPA_NODE_COMMAND_Start:
if (!c->started) {
pw_data_loop_invoke(c->loop,
do_prepare_client, SPA_ID_INVALID, NULL, 0, false, c);
pw_loop_locked(c->loop->loop,
do_prepare_client, SPA_ID_INVALID, NULL, 0, c);
c->started = true;
}
break;
@ -3242,8 +3307,8 @@ static int client_node_set_activation(void *data,
link->trigger = link->activation->server_version < 1 ? trigger_link_v0 : trigger_link_v1;
spa_list_append(&c->links, &link->link);
pw_data_loop_invoke(c->loop,
do_add_link, SPA_ID_INVALID, NULL, 0, false, link);
pw_loop_locked(c->loop->loop,
do_add_link, SPA_ID_INVALID, NULL, 0, link);
}
else {
link = find_activation(&c->links, node_id);
@ -3253,8 +3318,8 @@ static int client_node_set_activation(void *data,
}
spa_list_remove(&link->link);
pw_data_loop_invoke(c->loop,
do_remove_link, SPA_ID_INVALID, NULL, 0, false, link);
pw_loop_locked(c->loop->loop,
do_remove_link, SPA_ID_INVALID, NULL, 0, link);
queue_free_link(c, link);
}
@ -3429,24 +3494,6 @@ static const char* type_to_string(jack_port_type_id_t type_id)
}
}
static const char* type_to_format_dsp(jack_port_type_id_t type_id)
{
switch(type_id) {
case TYPE_ID_AUDIO:
return JACK_DEFAULT_AUDIO_TYPE;
case TYPE_ID_VIDEO:
return JACK_DEFAULT_VIDEO_TYPE;
case TYPE_ID_OSC:
return JACK_DEFAULT_OSC_TYPE;
case TYPE_ID_MIDI:
return JACK_DEFAULT_MIDI_TYPE;
case TYPE_ID_UMP:
return JACK_DEFAULT_UMP_TYPE;
default:
return NULL;
}
}
static bool type_is_dsp(jack_port_type_id_t type_id)
{
switch(type_id) {
@ -3638,6 +3685,67 @@ static const struct pw_node_events node_events = {
.info = node_info,
};
#define FILTER_NAME " ()[].:*$"
#define FILTER_PORT " ()[].*$"
static void filter_name(char *str, const char *filter, char filter_char)
{
char *p;
for (p = str; *p; p++) {
if (strchr(filter, *p) != NULL)
*p = filter_char;
}
}
static int update_port_name(struct object *o, const char *name)
{
struct object *ot = o->port.node, *op;
struct client *c = o->client;
char tmp[REAL_JACK_PORT_NAME_SIZE+1];
char port_name[REAL_JACK_PORT_NAME_SIZE+1];
if (o->port.is_monitor && !c->merge_monitor)
snprintf(tmp, sizeof(tmp), "%.*s%s:%s",
(int)(JACK_CLIENT_NAME_SIZE-(sizeof(MONITOR_EXT)-1)),
ot->node.name, MONITOR_EXT, name);
else
snprintf(tmp, sizeof(tmp), "%s:%s", ot->node.name, name);
if (c->filter_name)
filter_name(tmp, FILTER_PORT, c->filter_char);
op = find_port_by_name(c, tmp);
if (op != NULL && op != o)
snprintf(port_name, sizeof(port_name), "%.*s-%u",
(int)(sizeof(tmp)-11), tmp, o->serial);
else
snprintf(port_name, sizeof(port_name), "%s", tmp);
if (spa_streq(port_name, o->port.name))
return 0;
strcpy(o->port.old_name, o->port.name);
strcpy(o->port.name, port_name);
return 1;
}
static void port_info(void *data, const struct pw_port_info *info)
{
struct object *o = data;
struct client *c = o->client;
if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
const char *str = spa_dict_lookup(info->props, PW_KEY_PORT_NAME);
if (str != NULL) {
if (update_port_name(o, str) > 0) {
pw_log_info("%p: port rename %u %s->%s", c, o->serial,
o->port.old_name, o->port.name);
queue_notify(c, NOTIFY_TYPE_PORT_RENAME, o, 1, NULL);
}
}
}
}
static void port_param(void *data, int seq,
uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
@ -3660,27 +3768,16 @@ static void port_param(void *data, int seq,
static const struct pw_port_events port_events = {
PW_VERSION_PORT_EVENTS,
.info = port_info,
.param = port_param,
};
#define FILTER_NAME " ()[].:*$"
#define FILTER_PORT " ()[].*$"
static void filter_name(char *str, const char *filter, char filter_char)
{
char *p;
for (p = str; *p; p++) {
if (strchr(filter, *p) != NULL)
*p = filter_char;
}
}
static void registry_event_global(void *data, uint32_t id,
uint32_t permissions, const char *type, uint32_t version,
const struct spa_dict *props)
{
struct client *c = (struct client *) data;
struct object *o, *ot, *op;
struct object *o, *ot;
const char *str;
bool do_emit = true, do_sync = false;
uint32_t serial;
@ -3746,6 +3843,8 @@ static void registry_event_global(void *data, uint32_t id,
}
if (str == NULL)
str = node_name;
if (str == NULL)
str = spa_dict_lookup(props, PW_KEY_OBJECT_PATH);
if (str == NULL)
str = "node";
@ -3801,6 +3900,7 @@ static void registry_event_global(void *data, uint32_t id,
uint32_t node_id;
bool is_monitor = false;
char tmp[REAL_JACK_PORT_NAME_SIZE+1];
const char *name;
if ((str = spa_dict_lookup(props, PW_KEY_FORMAT_DSP)) == NULL)
str = "other";
@ -3816,7 +3916,7 @@ static void registry_event_global(void *data, uint32_t id,
spa_strstartswith(str, "jack:flags:"))
flags = atoi(str+11);
if ((str = spa_dict_lookup(props, PW_KEY_PORT_NAME)) == NULL)
if ((name = spa_dict_lookup(props, PW_KEY_PORT_NAME)) == NULL)
goto exit;
if (type_id == TYPE_ID_UMP && c->flag_midi2)
@ -3852,7 +3952,7 @@ static void registry_event_global(void *data, uint32_t id,
o = NULL;
if (node_id == c->node_id) {
snprintf(tmp, sizeof(tmp), "%s:%s", c->name, str);
snprintf(tmp, sizeof(tmp), "%s:%s", c->name, name);
o = find_port_by_name(c, tmp);
if (o != NULL)
pw_log_info("%p: %s found our port %p", c, tmp, o);
@ -3870,6 +3970,7 @@ static void registry_event_global(void *data, uint32_t id,
o->port.node = ot;
o->port.latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
o->port.latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
o->port.type_id = type_id;
do_emit = node_is_active(c, ot);
@ -3891,27 +3992,12 @@ static void registry_event_global(void *data, uint32_t id,
pthread_mutex_lock(&c->context.lock);
spa_list_append(&c->context.objects, &o->link);
pthread_mutex_unlock(&c->context.lock);
if (is_monitor && !c->merge_monitor)
snprintf(tmp, sizeof(tmp), "%.*s%s:%s",
(int)(JACK_CLIENT_NAME_SIZE-(sizeof(MONITOR_EXT)-1)),
ot->node.name, MONITOR_EXT, str);
else
snprintf(tmp, sizeof(tmp), "%s:%s", ot->node.name, str);
if (c->filter_name)
filter_name(tmp, FILTER_PORT, c->filter_char);
op = find_port_by_name(c, tmp);
if (op != NULL)
snprintf(o->port.name, sizeof(o->port.name), "%.*s-%u",
(int)(sizeof(tmp)-11), tmp, serial);
else
snprintf(o->port.name, sizeof(o->port.name), "%s", tmp);
o->port.type_id = type_id;
}
o->port.flags = flags;
o->port.node_id = node_id;
o->port.is_monitor = is_monitor;
if (c->fill_aliases) {
if ((str = spa_dict_lookup(props, PW_KEY_OBJECT_PATH)) != NULL)
snprintf(o->port.alias1, sizeof(o->port.alias1), "%s", str);
@ -3919,7 +4005,6 @@ static void registry_event_global(void *data, uint32_t id,
if ((str = spa_dict_lookup(props, PW_KEY_PORT_ALIAS)) != NULL)
snprintf(o->port.alias2, sizeof(o->port.alias2), "%s", str);
}
if ((str = spa_dict_lookup(props, PW_KEY_PORT_ID)) != NULL) {
o->port.system_id = atoi(str);
snprintf(o->port.system, sizeof(o->port.system), "system:%s_%d",
@ -3928,9 +4013,8 @@ static void registry_event_global(void *data, uint32_t id,
o->port.system_id+1);
}
o->port.flags = flags;
o->port.node_id = node_id;
o->port.is_monitor = is_monitor;
if (node_id != c->node_id)
update_port_name(o, name);
pw_log_debug("%p: %p add port %d name:%s %d", c, o, id,
o->port.name, type_id);
@ -5507,7 +5591,7 @@ jack_port_t * jack_port_register (jack_client_t *client,
spa_list_init(&p->mix);
pw_properties_set(p->props, PW_KEY_FORMAT_DSP, type_to_format_dsp(type_id));
pw_properties_set(p->props, PW_KEY_FORMAT_DSP, type_to_string(type_id));
pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name);
if (flags > 0x1f) {
pw_properties_setf(p->props, PW_KEY_PORT_EXTRA,
@ -5719,13 +5803,15 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
struct mix *mix;
void *ptr = p->emptyptr;
struct midi_buffer *mb = (struct midi_buffer*)midi_scratch;
struct spa_pod_sequence *seq[MAX_MIX];
uint32_t n_seq = 0;
struct mix_info *mix_info[MAX_MIX];
uint32_t n_mix_info = 0;
spa_list_for_each(mix, &p->mix, port_link) {
struct spa_data *d;
struct buffer *b;
void *pod;
struct mix_info *mi = &mix->mix_info;
struct spa_pod_sequence seq;
const void *seq_body;
if (mix->id == SPA_ID_INVALID)
continue;
@ -5737,25 +5823,28 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
continue;
d = &b->datas[0];
spa_pod_parser_init_from_data(&mi->parser, d->data, d->maxsize,
d->chunk->offset, d->chunk->size);
if (spa_pod_parser_push_sequence_body(&mi->parser,
&mi->frame, &seq, &seq_body) < 0)
continue;
if (spa_pod_parser_get_control_body(&mi->parser,
&mi->control, &mi->control_body) < 0)
continue;
if ((pod = spa_pod_from_data(d->data, d->maxsize, d->chunk->offset, d->chunk->size)) == NULL)
continue;
if (!spa_pod_is_sequence(pod))
continue;
seq[n_seq++] = pod;
if (n_seq == MAX_MIX)
mix_info[n_mix_info++] = mi;
if (n_mix_info == MAX_MIX)
break;
}
midi_init_buffer(mb, MIDI_SCRATCH_FRAMES, frames);
/* first convert to a thread local scratch buffer, then memcpy into
* the per port buffer. This makes it possible to call this function concurrently
* but also have different pointers per port */
convert_to_event(seq, n_seq, mb, p->client->fix_midi_events, p->object->port.type_id);
convert_to_event(mix_info, n_mix_info, mb, p->client->fix_midi_events, p->object->port.type_id);
memcpy(ptr, mb, sizeof(struct midi_buffer) + (mb->event_count
* sizeof(struct midi_event)));
if (mb->write_pos) {
size_t offs = mb->buffer_size - 1 - mb->write_pos;
if (mb->write_pos > 0) {
size_t offs = mb->buffer_size - mb->write_pos;
memcpy(SPA_PTROFF(ptr, offs, void), SPA_PTROFF(mb, offs, void), mb->write_pos);
}
return ptr;
@ -5818,21 +5907,26 @@ void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
goto done;
if (TYPE_ID_IS_EVENT(o->port.type_id)) {
struct spa_pod_sequence *seq[1];
struct mix_info *mix_info[1], mi;
struct spa_data *d;
void *pod;
struct spa_pod_sequence seq;
const void *seq_body;
ptr = midi_scratch;
midi_init_buffer(ptr, MIDI_SCRATCH_FRAMES, frames);
d = &b->datas[0];
if ((pod = spa_pod_from_data(d->data, d->maxsize,
d->chunk->offset, d->chunk->size)) == NULL)
spa_pod_parser_init_from_data(&mi.parser, d->data, d->maxsize,
d->chunk->offset, d->chunk->size);
if (spa_pod_parser_push_sequence_body(&mi.parser,
&mi.frame, &seq, &seq_body) < 0)
goto done;
if (!spa_pod_is_sequence(pod))
if (spa_pod_parser_get_control_body(&mi.parser,
&mi.control, &mi.control_body) < 0)
goto done;
seq[0] = pod;
convert_to_event(seq, 1, ptr, c->fix_midi_events, o->port.type_id);
mix_info[0] = &mi;
convert_to_event(mix_info, 1, ptr, c->fix_midi_events, o->port.type_id);
} else {
ptr = get_buffer_data(b, frames);
}

View file

@ -772,6 +772,19 @@ static int v4l2_dup(int oldfd)
return do_dup(oldfd, FD_MAP_DUP);
}
/* Deferred PipeWire init (called on first device access) */
static void pipewire_init_func(void)
{
pw_init(NULL, NULL);
PW_LOG_TOPIC_INIT(v4l2_log_topic);
}
static void ensure_pipewire_init(void)
{
static pthread_once_t pipewire_once = PTHREAD_ONCE_INIT;
pthread_once(&pipewire_once, pipewire_init_func);
}
static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
{
int res, flags;
@ -795,6 +808,8 @@ static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
if (passthrough)
return globals.old_fops.openat(dirfd, path, oflag, mode);
ensure_pipewire_init();
pw_log_info("path:%s oflag:%d mode:%d", path, oflag, mode);
if ((file = find_file_by_dev(dev_id)) != NULL) {
@ -1385,7 +1400,6 @@ static int vidioc_enum_framesizes(struct file *file, struct v4l2_frmsizeenum *ar
spa_list_for_each(p, &g->param_list, link) {
const struct format_info *fi;
uint32_t media_type, media_subtype, format;
struct spa_rectangle size;
if (p->id != SPA_PARAM_EnumFormat || p->param == NULL)
continue;
@ -1409,22 +1423,96 @@ static int vidioc_enum_framesizes(struct file *file, struct v4l2_frmsizeenum *ar
if (fi->fourcc != arg->pixel_format)
continue;
if (spa_pod_parse_object(p->param,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&size)) < 0)
const struct spa_pod_prop *size_prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_size);
if (!size_prop)
continue;
arg->type = V4L2_FRMSIZE_TYPE_DISCRETE;
arg->discrete.width = size.width;
arg->discrete.height = size.height;
uint32_t n_sizes, choice;
const struct spa_pod *size_pods = spa_pod_get_values(&size_prop->value, &n_sizes, &choice);
if (!size_pods || n_sizes <= 0)
continue;
const struct spa_rectangle *sizes = SPA_POD_BODY_CONST(size_pods);
if (size_pods->type != SPA_TYPE_Rectangle || size_pods->size != sizeof(*sizes))
continue;
switch (choice) {
case SPA_CHOICE_Enum:
n_sizes -= 1;
sizes += 1;
SPA_FALLTHROUGH;
case SPA_CHOICE_None:
arg->type = V4L2_FRMSIZE_TYPE_DISCRETE;
for (size_t i = 0; i < n_sizes; i++, count++) {
arg->discrete.width = sizes[i].width;
arg->discrete.height = sizes[i].height;
pw_log_debug("count:%u %.4s %ux%u", count, (char*)&fi->fourcc,
arg->discrete.width, arg->discrete.height);
if (count == arg->index) {
found = true;
break;
}
}
pw_log_debug("count:%d %.4s %dx%d", count, (char*)&fi->fourcc,
size.width, size.height);
if (count == arg->index) {
found = true;
break;
case SPA_CHOICE_Range:
if (n_sizes < 3)
continue;
arg->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
arg->stepwise.min_width = sizes[1].width;
arg->stepwise.min_height = sizes[1].height;
arg->stepwise.max_width = sizes[2].width;
arg->stepwise.max_height = sizes[2].height;
arg->stepwise.step_width = arg->stepwise.step_height = 1;
pw_log_debug("count:%u %.4s (%ux%u)-(%ux%u)", count, (char*)&fi->fourcc,
arg->stepwise.min_width, arg->stepwise.min_height,
arg->stepwise.max_width, arg->stepwise.max_height);
if (count == arg->index) {
found = true;
break;
}
count++;
break;
case SPA_CHOICE_Step:
if (n_sizes < 4)
continue;
arg->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
arg->stepwise.min_width = sizes[1].width;
arg->stepwise.min_height = sizes[1].height;
arg->stepwise.max_width = sizes[2].width;
arg->stepwise.max_height = sizes[2].height;
arg->stepwise.step_width = sizes[3].width;
arg->stepwise.step_height = sizes[3].height;
pw_log_debug("count:%u %.4s (%ux%u)-(%ux%u)/(+%u,%u)", count, (char*)&fi->fourcc,
arg->stepwise.min_width, arg->stepwise.min_height,
arg->stepwise.min_width, arg->stepwise.min_height,
arg->stepwise.step_width, arg->stepwise.step_height);
if (count == arg->index) {
found = true;
break;
}
count++;
break;
default:
continue;
}
count++;
if (found)
break;
}
pw_thread_loop_unlock(file->loop);
@ -2100,7 +2188,7 @@ static struct {
{ V4L2_CID_SATURATION, SPA_PROP_saturation },
{ V4L2_CID_HUE, SPA_PROP_hue },
{ V4L2_CID_GAMMA, SPA_PROP_gamma },
{ V4L2_CID_EXPOSURE, SPA_PROP_exposure },
{ V4L2_CID_EXPOSURE_ABSOLUTE, SPA_PROP_exposure },
{ V4L2_CID_GAIN, SPA_PROP_gain },
{ V4L2_CID_SHARPNESS, SPA_PROP_sharpness },
};
@ -2311,6 +2399,8 @@ static int vidioc_s_ctrl(struct file *file, struct v4l2_control *arg)
struct spa_pod_frame f[1];
struct spa_pod *param;
pod = spa_pod_get_values(type, &n_vals, &choice);
if (n_vals < 1)
break;
spa_pod_builder_push_object(&b, &f[0],
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
@ -2563,10 +2653,14 @@ static void initialize(void)
globals.old_fops.ioctl = dlsym(RTLD_NEXT, "ioctl");
globals.old_fops.mmap = dlsym(RTLD_NEXT, "mmap64");
globals.old_fops.munmap = dlsym(RTLD_NEXT, "munmap");
pw_init(NULL, NULL);
PW_LOG_TOPIC_INIT(v4l2_log_topic);
/* NOTE:
* We avoid calling pw_init() here (constructor/early init path) because
* that can deadlock in certain host processes (e.g. Zoom >= 5.0) when
* the preload causes PipeWire initialisation to run too early.
*
* PipeWire initialisation (pw_init + PW_LOG_TOPIC_INIT) is deferred
* to ensure it runs on-demand in the first actual V4L2 open call.
*/
pthread_mutex_init(&globals.lock, NULL);
pw_array_init(&globals.file_maps, 1024);
pw_array_init(&globals.fd_maps, 256);

View file

@ -1,4 +1,5 @@
af
ar
as
be
bg

797
po/ar.po Normal file
View file

@ -0,0 +1,797 @@
# Arabic translation of PipeWire
# This file is distributed under the same license as the pipewire package.
#
# SPDX-FileCopyrightText: 2025 r <r>
msgid ""
msgstr ""
"Project-Id-Version: pipewire\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/issues/"
"new\n"
"POT-Creation-Date: 2024-02-25 03:43+0300\n"
"PO-Revision-Date: 2025-06-22 13:09+0200\n"
"Last-Translator: r <r>\n"
"Language-Team: Arabic <kde-i18n-doc@kde.org>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && "
"n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Lokalize 25.04.0\n"
#: src/daemon/pipewire.c:26
#, c-format
msgid ""
"%s [options]\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -c, --config Load config (Default %s)\n"
msgstr ""
"%s [خيارات]\n"
" -h, --help إظهار هذه المساعدة\n"
" --version إظهار الإصدار\n"
" -c, --config تحميل التضبيط (الافتراضي %s)\n"
#: src/daemon/pipewire.desktop.in:4
msgid "PipeWire Media System"
msgstr "نظام الوسائط بايب‌واير"
#: src/daemon/pipewire.desktop.in:5
msgid "Start the PipeWire Media System"
msgstr "ابدأ نظام الوسائط بايب‌واير"
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159
#, c-format
msgid "Tunnel to %s%s%s"
msgstr "نفّق إلى %s%s%s"
#: src/modules/module-fallback-sink.c:40
msgid "Dummy Output"
msgstr "إخراج وهمي"
#: src/modules/module-pulse-tunnel.c:774
#, c-format
msgid "Tunnel for %s@%s"
msgstr "نفّق ل %s@%s"
#: src/modules/module-zeroconf-discover.c:315
msgid "Unknown device"
msgstr "جهاز غير معروف"
#: src/modules/module-zeroconf-discover.c:327
#, c-format
msgid "%s on %s@%s"
msgstr "%s على %s@%s"
#: src/modules/module-zeroconf-discover.c:331
#, c-format
msgid "%s on %s"
msgstr "%s على %s"
#: src/tools/pw-cat.c:991
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -v, --verbose Enable verbose operations\n"
"\n"
msgstr ""
"%s [خيارات] [<file>|-]\n"
" -h, --help إظهار هذه المساعدة\n"
" --version إظهار الإصدار\n"
" -v, --verbose تمكين العمليات المطولة\n"
"\n"
#: src/tools/pw-cat.c:998
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
" --media-type Set media type (default %s)\n"
" --media-category Set media category (default %s)\n"
" --media-role Set media role (default %s)\n"
" --target Set node target serial or name "
"(default %s)\n"
" 0 means don't link\n"
" --latency Set node latency (default %s)\n"
" Xunit (unit = s, ms, us, ns)\n"
" or direct samples (256)\n"
" the rate is the one of the source "
"file\n"
" -P --properties Set node properties\n"
"\n"
msgstr ""
"-R, --remote اسم العملية الخفية البعيدة\n"
" --media-type تعيين نوع الوسائط (الافتراضي %s)\n"
" --media-category تعيين فئة الوسائط (الافتراضي %s)\n"
" --media-role تعيين دور الوسائط (الافتراضي %s)\n"
" --target تعيين المسلسل أو اسم هدف العُقدة "
"\n (الافتراضي %s)"
" 0 يعني عدم الربط\n"
" --latency تعيين زمن انتقال العُقدة (الافتراضي %s"
")\n"
" وحدة X (الوحدة = s, ms, us, ns)\n"
" أو عينات مباشرة (256)\n"
" المعدل هو معدل ملف المصدر\n"
" -P --properties تعيين خصائص العُقدة\n"
"\n"
#: src/tools/pw-cat.c:1016
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
"%u)\n"
" --channels Number of channels (req. for rec) "
"(default %u)\n"
" --channel-map Channel map\n"
" one of: \"stereo\", "
"\"surround-51\",... or\n"
" comma separated list of channel "
"names: eg. \"FL,FR\"\n"
" --format Sample format %s (req. for rec) "
"(default %s)\n"
" --volume Stream volume 0-1.0 (default %.3f)\n"
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
"\n"
msgstr ""
"--rate معدل العينة (مطلوب للتسجيل) (الافتراضي %u)\n"
" --channels عدد القنوات (مطلوب للتسجيل) (الافتراضي"
" %u)\n"
" --channel-map خريطة القنوات\n"
" أحد الخيارات: \"مِجساميّ\", \"محيط"
"ي-51\",... أو\n"
" قائمة بأسماء القنوات مفصولة بفاصلة"
": مثال \"FL,FR\"\n"
" --format تنسيق العينة %s (مطلوب للتسجيل) (الافت"
"راضي %s)\n"
" --volume حجم البث 0-1.0 (الافتراضي %.3f)\n"
" -q --quality جودة إعادة التشكيل (0 - 15) (الافتراضي"
" %d)\n"
"\n"
#: src/tools/pw-cat.c:1033
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
"\n"
msgstr ""
"-p, --playback وضع التشغيل\n"
" -r, --record وضع التسجيل\n"
" -m, --midi وضع Midi\n"
" -d, --dsd وضع DSD\n"
" -o, --encoded الوضع المرمّز\n"
"\n"
#: src/tools/pw-cli.c:2252
#, c-format
msgid ""
"%s [options] [command]\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -d, --daemon Start as daemon (Default false)\n"
" -r, --remote Remote daemon name\n"
" -m, --monitor Monitor activity\n"
"\n"
msgstr ""
"%s [خيارات] [أمر]\n"
" -h, --help إظهار هذه المساعدة\n"
" --version إظهار الإصدار\n"
" -d, --daemon بدء كخفي (افتراضي خطأ)\n"
" -r, --remote اسم الخفي البعيد\n"
" -m, --monitor مراقبة النشاط\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:327
msgid "Pro Audio"
msgstr "صوت احترافي"
#: spa/plugins/alsa/acp/acp.c:488 spa/plugins/alsa/acp/alsa-mixer.c:4633
#: spa/plugins/bluez5/bluez5-device.c:1701
msgid "Off"
msgstr "معطل"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "الإدخال"
#: spa/plugins/alsa/acp/alsa-mixer.c:2653
msgid "Docking Station Input"
msgstr "إدخال محطة الإرساء"
#: spa/plugins/alsa/acp/alsa-mixer.c:2654
msgid "Docking Station Microphone"
msgstr "ميكروفون محطة الإرساء"
#: spa/plugins/alsa/acp/alsa-mixer.c:2655
msgid "Docking Station Line In"
msgstr "مدخل خطي محط الارساء"
#: spa/plugins/alsa/acp/alsa-mixer.c:2656
#: spa/plugins/alsa/acp/alsa-mixer.c:2747
msgid "Line In"
msgstr "مدخل خطي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:1989
msgid "Microphone"
msgstr "ميكروفون"
#: spa/plugins/alsa/acp/alsa-mixer.c:2658
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
msgid "Front Microphone"
msgstr "ميكروفون أمامي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2659
#: spa/plugins/alsa/acp/alsa-mixer.c:2743
msgid "Rear Microphone"
msgstr "ميكروفون خلفي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2660
msgid "External Microphone"
msgstr "ميكروفون خارجي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2661
#: spa/plugins/alsa/acp/alsa-mixer.c:2745
msgid "Internal Microphone"
msgstr "ميكروفون داخلي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2662
#: spa/plugins/alsa/acp/alsa-mixer.c:2748
msgid "Radio"
msgstr "راديو"
#: spa/plugins/alsa/acp/alsa-mixer.c:2663
#: spa/plugins/alsa/acp/alsa-mixer.c:2749
msgid "Video"
msgstr "مرئيّ"
#: spa/plugins/alsa/acp/alsa-mixer.c:2664
msgid "Automatic Gain Control"
msgstr "التحكم التلقائي في الكسب"
#: spa/plugins/alsa/acp/alsa-mixer.c:2665
msgid "No Automatic Gain Control"
msgstr "دون التحكم التلقائي في الكسب"
#: spa/plugins/alsa/acp/alsa-mixer.c:2666
msgid "Boost"
msgstr "تعزيز"
#: spa/plugins/alsa/acp/alsa-mixer.c:2667
msgid "No Boost"
msgstr "دون تعزيز"
#: spa/plugins/alsa/acp/alsa-mixer.c:2668
msgid "Amplifier"
msgstr ""
""
"مُضَخِّم"
#: spa/plugins/alsa/acp/alsa-mixer.c:2669
msgid "No Amplifier"
msgstr "دون مُضَخِّم"
#: spa/plugins/alsa/acp/alsa-mixer.c:2670
msgid "Bass Boost"
msgstr "تعزيز القرار"
#: spa/plugins/alsa/acp/alsa-mixer.c:2671
msgid "No Bass Boost"
msgstr "دون تعزيز القرار"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:1995
msgid "Speaker"
msgstr "مكبر صوت"
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
msgid "Headphones"
msgstr "سماعات الأذن"
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
msgid "Analog Input"
msgstr "إدخال التناظري"
#: spa/plugins/alsa/acp/alsa-mixer.c:2744
msgid "Dock Microphone"
msgstr "ميكروفون محطة الارساء"
#: spa/plugins/alsa/acp/alsa-mixer.c:2746
msgid "Headset Microphone"
msgstr "ميكروفون سماعة الرأس"
#: spa/plugins/alsa/acp/alsa-mixer.c:2750
msgid "Analog Output"
msgstr "إخراج تناظري"
#: spa/plugins/alsa/acp/alsa-mixer.c:2752
msgid "Headphones 2"
msgstr "سماعات الأذن 2"
#: spa/plugins/alsa/acp/alsa-mixer.c:2753
msgid "Headphones Mono Output"
msgstr "سماعات الأذن أحادية الإخراج"
#: spa/plugins/alsa/acp/alsa-mixer.c:2754
msgid "Line Out"
msgstr "مخرج خطي"
#: spa/plugins/alsa/acp/alsa-mixer.c:2755
msgid "Analog Mono Output"
msgstr "إخراج أحادي تناظري"
#: spa/plugins/alsa/acp/alsa-mixer.c:2756
msgid "Speakers"
msgstr "مكبرات الصوت"
#: spa/plugins/alsa/acp/alsa-mixer.c:2757
msgid "HDMI / DisplayPort"
msgstr "HDMI / ديسبلاي بورت"
#: spa/plugins/alsa/acp/alsa-mixer.c:2758
msgid "Digital Output (S/PDIF)"
msgstr "إخراج الرقمي (S/PDIF)"
#: spa/plugins/alsa/acp/alsa-mixer.c:2759
msgid "Digital Input (S/PDIF)"
msgstr "إدخال الرقمي (S/PDIF)"
#: spa/plugins/alsa/acp/alsa-mixer.c:2760
msgid "Multichannel Input"
msgstr "إدخال متعدد القنوات"
#: spa/plugins/alsa/acp/alsa-mixer.c:2761
msgid "Multichannel Output"
msgstr "إخراج متعدد القنوات"
#: spa/plugins/alsa/acp/alsa-mixer.c:2762
msgid "Game Output"
msgstr "إخراج اللعبة"
#: spa/plugins/alsa/acp/alsa-mixer.c:2763
#: spa/plugins/alsa/acp/alsa-mixer.c:2764
msgid "Chat Output"
msgstr "إخراج المحادثة"
#: spa/plugins/alsa/acp/alsa-mixer.c:2765
msgid "Chat Input"
msgstr "إدخال المحادثة"
#: spa/plugins/alsa/acp/alsa-mixer.c:2766
msgid "Virtual Surround 7.1"
msgstr "محيطي تخيلي 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4456
msgid "Analog Mono"
msgstr "تناظري أحادي"
#: spa/plugins/alsa/acp/alsa-mixer.c:4457
msgid "Analog Mono (Left)"
msgstr "تناظري أحادي (يسار)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
msgid "Analog Mono (Right)"
msgstr "تناظري أحادي (يمين)"
#. Note: Not translated to "Analog Stereo Input", because the source
#. * name gets "Input" appended to it automatically, so adding "Input"
#. * here would lead to the source name to become "Analog Stereo Input
#. * Input". The same logic applies to analog-stereo-output,
#. * multichannel-input and multichannel-output.
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
#: spa/plugins/alsa/acp/alsa-mixer.c:4467
#: spa/plugins/alsa/acp/alsa-mixer.c:4468
msgid "Analog Stereo"
msgstr "مِجْساميّ تناظري"
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
msgid "Mono"
msgstr "أحادي"
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
msgid "Stereo"
msgstr "مِجْساميّ"
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
#: spa/plugins/bluez5/bluez5-device.c:1977
msgid "Headset"
msgstr "سماعة الرأس"
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
msgid "Speakerphone"
msgstr "مكبر صوت الجوّال"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
msgid "Multichannel"
msgstr "متعدد القنوات"
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
msgid "Analog Surround 2.1"
msgstr "تناظري محيطي 2.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
msgid "Analog Surround 3.0"
msgstr "تناظري محيطي 3.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
msgid "Analog Surround 3.1"
msgstr "تناظري محيطي 3.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
msgid "Analog Surround 4.0"
msgstr "تناظري محيطي 4.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
msgid "Analog Surround 4.1"
msgstr "تناظري محيطي 4.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
msgid "Analog Surround 5.0"
msgstr "تناظري محيطي 5.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
msgid "Analog Surround 5.1"
msgstr "تناظري محيطي 5.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
msgid "Analog Surround 6.0"
msgstr "تناظري محيطي 6.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
msgid "Analog Surround 6.1"
msgstr "تناظري محيطي 6.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
msgid "Analog Surround 7.0"
msgstr "تناظري محيطي 7.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
msgid "Analog Surround 7.1"
msgstr "تناظري محيطي 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
msgid "Digital Stereo (IEC958)"
msgstr "مِجْساميّ رقمي (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "محيطي رقمي 4.0 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "محيطي رقمي 5.1 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "محيطي رقمي 5.1 (IEC958/DTS)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
msgid "Digital Stereo (HDMI)"
msgstr "مِجْساميّ رقمي (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
msgid "Digital Surround 5.1 (HDMI)"
msgstr "محيطي رقمي 5.1 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
msgid "Chat"
msgstr "محادثة"
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
msgid "Game"
msgstr "لعبة"
#: spa/plugins/alsa/acp/alsa-mixer.c:4625
msgid "Analog Mono Duplex"
msgstr "تناظري أحادي مزدوج"
#: spa/plugins/alsa/acp/alsa-mixer.c:4626
msgid "Analog Stereo Duplex"
msgstr "مِجْساميّ تناظري مزدوج"
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
msgid "Digital Stereo Duplex (IEC958)"
msgstr "مِجْساميّ رقمي مزدوج (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
msgid "Multichannel Duplex"
msgstr "مزدوج متعدد القنوات"
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
msgid "Stereo Duplex"
msgstr "مِجساميّ مزدوج"
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
msgid "Mono Chat + 7.1 Surround"
msgstr "محادثة أحادية + محيطي 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4733
#, c-format
msgid "%s Output"
msgstr "إخراج %s"
#: spa/plugins/alsa/acp/alsa-mixer.c:4741
#, c-format
msgid "%s Input"
msgstr "إدخال %s"
#: spa/plugins/alsa/acp/alsa-util.c:1220 spa/plugins/alsa/acp/alsa-util.c:1314
#, c-format
msgid ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
"ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu "
"ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايت "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[1] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[2] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[3] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[4] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[5] ""
"أرجعت الدالة snd_pcm_avail() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1286
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايت "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[1] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايتات "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[2] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايتات "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[3] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايتات "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[4] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايتات "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[5] ""
"أرجعت الدالة snd_pcm_delay() قيمة كبيرة بشكل استثنائي: %li بايتات "
"(%s%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1333
#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
"%lu.\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr ""
"أرجعت الدالة snd_pcm_avail_delay() قيمًا غريبة: التأخير %lu أقل من avail "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1376
#, c-format
msgid ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
"(%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes "
"(%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايت "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[1] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[2] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[3] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[4] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
msgstr[5] ""
"أرجعت الدالة snd_pcm_mmap_begin() قيمة كبيرة بشكل استثنائي: %lu بايتات "
"(%lu مللي ثانية).\n"
"من المرجح أن يكون هذا خطأ في برنامج تشغيل ALSA '%s'. يُرجى الإبلاغ عن هذه المش"
"كلة "
"لمطوري ALSA."
#: spa/plugins/alsa/acp/channelmap.h:457
msgid "(invalid)"
msgstr "(غير صالح)"
#: spa/plugins/alsa/acp/compat.c:193
msgid "Built-in Audio"
msgstr "صوت مدمج"
#: spa/plugins/alsa/acp/compat.c:198
msgid "Modem"
msgstr "مودم"
#: spa/plugins/bluez5/bluez5-device.c:1712
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "بوابة الصوت (مصدر A2DP و HSP/HFP AG)"
#: spa/plugins/bluez5/bluez5-device.c:1760
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "تشغيل عالي الدقة (A2DP Sink, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1763
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "مزدوج عالي الدقة (مصدر A2DP/Sink, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1771
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "تشغيل عالي الدقة (A2DP Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1773
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "مزدوج عالي الدقة (مصدر A2DP/Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1823
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "تشغيل عالي الدقة (BAP Sink, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1828
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "إدخال عالي الدقة (مصدر BAP, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1832
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "مزدوج عالي الدقة (مصدر BAP/Sink, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1841
msgid "High Fidelity Playback (BAP Sink)"
msgstr "تشغيل عالي الدقة (BAP Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1845
msgid "High Fidelity Input (BAP Source)"
msgstr "إدخال عالي الدقة (مصدر BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1848
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "مزدوج عالي الدقة (مصدر BAP/Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1897
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "وحدة رأس سماعة الرأس (HSP/HFP, codec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1978
#: spa/plugins/bluez5/bluez5-device.c:1983
#: spa/plugins/bluez5/bluez5-device.c:1990
#: spa/plugins/bluez5/bluez5-device.c:1996
#: spa/plugins/bluez5/bluez5-device.c:2002
#: spa/plugins/bluez5/bluez5-device.c:2008
#: spa/plugins/bluez5/bluez5-device.c:2014
#: spa/plugins/bluez5/bluez5-device.c:2020
#: spa/plugins/bluez5/bluez5-device.c:2026
msgid "Handsfree"
msgstr "دون استخدام اليدين"
#: spa/plugins/bluez5/bluez5-device.c:1984
msgid "Handsfree (HFP)"
msgstr "دون استخدام اليدين (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2001
msgid "Headphone"
msgstr "سماعة الأذن"
#: spa/plugins/bluez5/bluez5-device.c:2007
msgid "Portable"
msgstr "محمول"
#: spa/plugins/bluez5/bluez5-device.c:2013
msgid "Car"
msgstr "سيارة"
#: spa/plugins/bluez5/bluez5-device.c:2019
msgid "HiFi"
msgstr "HiFi"
#: spa/plugins/bluez5/bluez5-device.c:2025
msgid "Phone"
msgstr "جوّال"
#: spa/plugins/bluez5/bluez5-device.c:2032
msgid "Bluetooth"
msgstr "بلوتوث"
#: spa/plugins/bluez5/bluez5-device.c:2033
msgid "Bluetooth (HFP)"
msgstr "بلوتوث (HFP)"

390
po/ca.po
View file

@ -5,7 +5,7 @@
# Xavier Conde Rueda <xavi.conde@gmail.com>, 2008.
# Agustí Grau <fletxa@gmail.com>, 2009.
# Judith Pintó Subirada <judithp@gmail.com>
# Jordi Mas i Herǹandez, <jmas@softcatala.org>, 2022-2023
# Jordi Mas i Herǹandez, <jmas@softcatala.org>, 2022-2025
#
# This file is translated according to the glossary and style guide of
# Softcatalà. If you plan to modify this file, please read first the page
@ -16,7 +16,7 @@
# Aquest fitxer s'ha de traduir d'acord amb el recull de termes i la guia
# d'estil de Softcatalà. Si voleu modificar aquest fitxer, llegiu si
# us plau la pàgina de catalanització del projecte Fedora a:
# http://www.softcatala.org/projectes/fedora/
# https://www.softcatala.org/projectes/fedora/
# i contacteu l'anterior traductor/a.
# Josep Torné Llavall <josep.torne@gmail.com>, 2009, 2012.
# Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>, 2016. #zanata
@ -27,10 +27,9 @@
msgid ""
msgstr ""
"Project-Id-Version: pipewire\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2023-06-06 15:28+0000\n"
"PO-Revision-Date: 2023-06-06 22:39+0200\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues\n"
"POT-Creation-Date: 2025-07-20 15:32+0000\n"
"PO-Revision-Date: 2025-06-20 21:46+0200\n"
"Last-Translator: Jordi Mas i Herǹandez, <jmas@softcatala.org>,\n"
"Language-Team: Catalan <fedora@softcatala.net>\n"
"Language: ca\n"
@ -38,60 +37,64 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.2\n"
"X-Generator: Poedit 3.2.2\n"
#: src/daemon/pipewire.c:26
#: src/daemon/pipewire.c:29
#, c-format
msgid ""
"%s [options]\n"
" -h, --help Show this help\n"
" -v, --verbose Increase verbosity by one level\n"
" --version Show version\n"
" -c, --config Load config (Default %s)\n"
" -P --properties Set context properties\n"
msgstr ""
"%s [opcions]\n"
" -h, --help Mostra aquesta ajuda\n"
" -v, --verbose Augmenta la verbositat en un nivell\n"
" --version Mostra la versió\n"
" -c, --config Carrega la configuració "
"(predeterminada %s)\n"
" -c, --config Carrega la configuració (predeterminada %s)\n"
" -P --properties Estableix les propietats del context\n"
"\n"
#: src/daemon/pipewire.desktop.in:4
#: src/daemon/pipewire.desktop.in:3
msgid "PipeWire Media System"
msgstr "Sistema multimèdia PipeWire"
#: src/daemon/pipewire.desktop.in:5
#: src/daemon/pipewire.desktop.in:4
msgid "Start the PipeWire Media System"
msgstr "Inicia el sistema multimèdia PipeWire"
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:141
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:141
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159
#, c-format
msgid "Tunnel to %s%s%s"
msgstr "Túnel cap a %s%s%s"
#: src/modules/module-fallback-sink.c:31
#: src/modules/module-fallback-sink.c:40
msgid "Dummy Output"
msgstr "Sortida fictícia"
#: src/modules/module-pulse-tunnel.c:844
#: src/modules/module-pulse-tunnel.c:760
#, c-format
msgid "Tunnel for %s@%s"
msgstr "Túnel per a %s@%s"
#: src/modules/module-zeroconf-discover.c:315
#: src/modules/module-zeroconf-discover.c:320
msgid "Unknown device"
msgstr "Dispositiu desconegut"
#: src/modules/module-zeroconf-discover.c:327
#: src/modules/module-zeroconf-discover.c:332
#, c-format
msgid "%s on %s@%s"
msgstr "%s en %s@%s"
#: src/modules/module-zeroconf-discover.c:331
#: src/modules/module-zeroconf-discover.c:336
#, c-format
msgid "%s on %s"
msgstr "%s en %s"
#: src/tools/pw-cat.c:974
#: src/tools/pw-cat.c:1044
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
@ -105,86 +108,68 @@ msgstr ""
" --version Mostra la versió\n"
" -v, --verbose Habilita les operacions detallades\n"
#: src/tools/pw-cat.c:981
#: src/tools/pw-cat.c:1051
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
" --media-type Set media type (default %s)\n"
" --media-category Set media category (default %s)\n"
" --media-role Set media role (default %s)\n"
" --target Set node target serial or name "
"(default %s)\n"
" --target Set node target serial or name (default %s)\n"
" 0 means don't link\n"
" --latency Set node latency (default %s)\n"
" Xunit (unit = s, ms, us, ns)\n"
" or direct samples (256)\n"
" the rate is the one of the source "
"file\n"
" the rate is the one of the source file\n"
" -P --properties Set node properties\n"
"\n"
msgstr ""
" -R, --remote Nom del dimoni remot\n"
" --media-type Estableix el tipus de mitjà (per "
"defecte %s)\n"
" --media-category Estableix la categoria del "
"mitjà (per defecte %s)\n"
" --media-role Estableix el rol del mitjà (per "
"defecte %s)\n"
" --target Estableix l'objectiu sèrie o el nom "
"del node (per defecte %s)\n"
" --media-type Estableix el tipus de mitjà (per defecte %s)\n"
" --media-category Estableix la categoria del mitjà (per defecte %s)\n"
" --media-role Estableix el rol del mitjà (per defecte %s)\n"
" --target Estableix l'objectiu sèrie o el nom del node (per defecte %s)\n"
" 0 vol dir que no enllaça\n"
" --latency Estableix latència del node (per "
"defecte %s)\n"
" --latency Estableix latència del node (per defecte %s)\n"
" Xunit (unitat = s, ms, us, ns)\n"
" o mostres directes (256)\n"
" la taxa és la del fitxer d'origen\n"
" -P --properties Estableix les propietats del "
"node\n"
" -P --properties Estableix les propietats del node\n"
"\n"
#: src/tools/pw-cat.c:999
#: src/tools/pw-cat.c:1069
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
"%u)\n"
" --channels Number of channels (req. for rec) "
"(default %u)\n"
" --rate Sample rate (req. for rec) (default %u)\n"
" --channels Number of channels (req. for rec) (default %u)\n"
" --channel-map Channel map\n"
" one of: \"stereo\", "
"\"surround-51\",... or\n"
" comma separated list of channel "
"names: eg. \"FL,FR\"\n"
" --format Sample format %s (req. for rec) "
"(default %s)\n"
" one of: \"stereo\", \"surround-51\",... or\n"
" comma separated list of channel names: eg. \"FL,FR\"\n"
" --format Sample format %s (req. for rec) (default %s)\n"
" --volume Stream volume 0-1.0 (default %.3f)\n"
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
" -q --quality Resampler quality (0 - 15) (default %d)\n"
" -a, --raw RAW mode\n"
"\n"
msgstr ""
" --rate Freqüència de mostreig (req. per a "
"rec) (predeterminat %u)\n"
" --channels Nombre de canals (req. per a rec) "
"(predeterminat %u)\n"
" --rate Freqüència de mostreig (req. per a rec) (predeterminat %u)\n"
" --channels Nombre de canals (req. per a rec) (predeterminat %u)\n"
" --channel-map Mapa de canals\n"
" un dels següents: \"stereo\", "
"\"surround-51\",... o\n"
" llista separada per comes dels "
"noms dels canals: per exemple. «FL,FR»\n"
" --format Format de mostra %s (req. per a rec) "
"(predeterminat %s)\n"
" --volume Volum del flux 0-1.0 (predeterminat "
"%.3f)\n"
" -q --quality Qualitat de remostrador (0 - 15) "
"(predeterminal %d)\n"
" un dels següents: \"stereo\", \"surround-51\",... o\n"
" llista separada per comes dels noms dels canals: per exemple. «FL,FR»\n"
" --format Format de mostra %s (req. per a rec) (predeterminat %s)\n"
" --volume Volum del flux 0-1.0 (predeterminat %.3f)\n"
" -q --quality Qualitat de remostrador (0 - 15) (predeterminat %d)\n"
" -a, --raw Mode RAW\n"
"\n"
#: src/tools/pw-cat.c:1016
#: src/tools/pw-cat.c:1087
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
" -s, --sysex SysEx mode\n"
"\n"
msgstr ""
" -p, --playback Mode de reproducció\n"
@ -192,9 +177,10 @@ msgstr ""
" -m, --midi Mode MIDI\n"
" -d, --dsd Mode DSD\n"
" -o, --encoded Mode codificat\n"
" -s, --sysex Mode SysEx\n"
"\n"
#: src/tools/pw-cli.c:2220
#: src/tools/pw-cli.c:2386
#, c-format
msgid ""
"%s [options] [command]\n"
@ -208,21 +194,25 @@ msgstr ""
"%s [opcions] [ordre]\n"
" -h, --help Mostra aquesta ajuda\n"
" --version Mostra la versió\n"
" -d, --daemon Inicia com a dimoni (fals per "
"defecte)\n"
" -d, --daemon Inicia com a dimoni (fals per defecte)\n"
" -r, --remote Nom del dimoni remot\n"
" -m, --monitor Monitor d'activitat\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:303
#: spa/plugins/alsa/acp/acp.c:351
msgid "Pro Audio"
msgstr "Pro Audio"
#: spa/plugins/alsa/acp/acp.c:427 spa/plugins/alsa/acp/alsa-mixer.c:4648
#: spa/plugins/bluez5/bluez5-device.c:1586
#: spa/plugins/alsa/acp/acp.c:520 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1974
msgid "Off"
msgstr "Inactiu"
#: spa/plugins/alsa/acp/acp.c:603
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [Error d'ALSA UCM]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "Entrada"
@ -246,7 +236,7 @@ msgstr "Entrada de línia"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:1831
#: spa/plugins/bluez5/bluez5-device.c:2372
msgid "Microphone"
msgstr "Micròfon"
@ -312,12 +302,15 @@ msgid "No Bass Boost"
msgstr "Sense accentuació dels baixos"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:1837
#: spa/plugins/bluez5/bluez5-device.c:2378
msgid "Speaker"
msgstr "Altaveu"
#. Don't call it "headset", the HF one has the mic
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
#: spa/plugins/bluez5/bluez5-device.c:2384
#: spa/plugins/bluez5/bluez5-device.c:2451
msgid "Headphones"
msgstr "Auriculars"
@ -394,15 +387,15 @@ msgstr "Entrada del xat"
msgid "Virtual Surround 7.1"
msgstr "Envoltant virtual 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
msgid "Analog Mono"
msgstr "Mono analògic"
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
msgid "Analog Mono (Left)"
msgstr "Mono analògic (esquerra)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
msgid "Analog Mono (Right)"
msgstr "Mono analògic (dreta)"
@ -411,338 +404,307 @@ msgstr "Mono analògic (dreta)"
#. * here would lead to the source name to become "Analog Stereo Input
#. * Input". The same logic applies to analog-stereo-output,
#. * multichannel-input and multichannel-output.
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
msgid "Analog Stereo"
msgstr "Estèreo analògic"
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
#: spa/plugins/alsa/acp/alsa-mixer.c:4462
msgid "Mono"
msgstr "Mono"
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
#: spa/plugins/alsa/acp/alsa-mixer.c:4463
msgid "Stereo"
msgstr "Estèreo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
#: spa/plugins/alsa/acp/alsa-mixer.c:4642
#: spa/plugins/bluez5/bluez5-device.c:1819
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/bluez5/bluez5-device.c:2360
msgid "Headset"
msgstr "Auriculars"
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
#: spa/plugins/alsa/acp/alsa-mixer.c:4643
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
msgid "Speakerphone"
msgstr "Altaveu del telèfon"
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
msgid "Multichannel"
msgstr "Multicanal"
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
msgid "Analog Surround 2.1"
msgstr "Envoltant analògic 2.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
msgid "Analog Surround 3.0"
msgstr "Envoltant analògic 3.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
msgid "Analog Surround 3.1"
msgstr "Envoltant analògic 3.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
msgid "Analog Surround 4.0"
msgstr "Envoltant analògic 4.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
msgid "Analog Surround 4.1"
msgstr "Envoltant analògic 4.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
msgid "Analog Surround 5.0"
msgstr "Envoltant analògic 5.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4494
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
msgid "Analog Surround 5.1"
msgstr "Envoltant analògic 5.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4495
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
msgid "Analog Surround 6.0"
msgstr "Envoltant analògic 6.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4496
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
msgid "Analog Surround 6.1"
msgstr "Envoltant analògic 6.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4497
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
msgid "Analog Surround 7.0"
msgstr "Envoltant analògic 7.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4498
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
msgid "Analog Surround 7.1"
msgstr "Envoltant analògic 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4499
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
msgid "Digital Stereo (IEC958)"
msgstr "Estèreo digital (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4500
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "Envoltant digital 4.0 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4501
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "Envoltant digital 5.1 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4502
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "Envoltant digital 5.1 (IEC958/DTS)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4503
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
msgid "Digital Stereo (HDMI)"
msgstr "Estèreo digital (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4504
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
msgid "Digital Surround 5.1 (HDMI)"
msgstr "Envoltant digital 5.1 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4505
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
msgid "Chat"
msgstr "Xat"
#: spa/plugins/alsa/acp/alsa-mixer.c:4506
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
msgid "Game"
msgstr "Joc"
#: spa/plugins/alsa/acp/alsa-mixer.c:4640
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
msgid "Analog Mono Duplex"
msgstr "Dúplex mono analògic"
#: spa/plugins/alsa/acp/alsa-mixer.c:4641
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
msgid "Analog Stereo Duplex"
msgstr "Dúplex estèreo analògic"
#: spa/plugins/alsa/acp/alsa-mixer.c:4644
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
msgid "Digital Stereo Duplex (IEC958)"
msgstr "Dúplex estèreo digital (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4645
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
msgid "Multichannel Duplex"
msgstr "Dúplex Multicanal"
#: spa/plugins/alsa/acp/alsa-mixer.c:4646
#: spa/plugins/alsa/acp/alsa-mixer.c:4633
msgid "Stereo Duplex"
msgstr "Dúplex estèreo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4647
#: spa/plugins/alsa/acp/alsa-mixer.c:4634
msgid "Mono Chat + 7.1 Surround"
msgstr "Xat mono + 7.1 envoltant"
#: spa/plugins/alsa/acp/alsa-mixer.c:4748
#: spa/plugins/alsa/acp/alsa-mixer.c:4735
#, c-format
msgid "%s Output"
msgstr "Sortida %s"
#: spa/plugins/alsa/acp/alsa-mixer.c:4756
#: spa/plugins/alsa/acp/alsa-mixer.c:4743
#, c-format
msgid "%s Input"
msgstr "Entrada %s"
#: spa/plugins/alsa/acp/alsa-util.c:1187 spa/plugins/alsa/acp/alsa-util.c:1281
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
#, c-format
msgid ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
"ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgid_plural ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu "
"ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgstr[0] ""
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu byte (%lu "
"ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu byte (%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
msgstr[1] ""
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu bytes (%lu "
"ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu bytes (%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1253
#: spa/plugins/alsa/acp/alsa-util.c:1299
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgid_plural ""
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgstr[0] ""
"snd_pcm_delay() ha retornat un valor excepcionalment gran: %li byte (%s%lu "
"ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_delay() ha retornat un valor excepcionalment gran: %li byte (%s%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
msgstr[1] ""
"snd_pcm_delay() ha retornat un valor excepcionalment gran: %li bytes (%s%lu "
"ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_delay() ha retornat un valor excepcionalment gran: %li bytes (%s%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1300
#: spa/plugins/alsa/acp/alsa-util.c:1346
#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
"%lu.\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgstr ""
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu bytes (%lu "
"ms).\n"
"Probablement es tracta d'un error del controlador d'ALSA «%s». Informeu "
"d'aquest problema als desenvolupadors d'ALSA."
"snd_pcm_avail() ha retornat un valor excepcionalment gran: %lu bytes (%lu ms).\n"
"Probablement es tracta d'un error del controlador d'ALSA «%s». Informeu d'aquest problema als desenvolupadors d'ALSA."
#: spa/plugins/alsa/acp/alsa-util.c:1343
#: spa/plugins/alsa/acp/alsa-util.c:1389
#, c-format
msgid ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
"(%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgid_plural ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes "
"(%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
msgstr[0] ""
"snd_pcm_mmap_begin() ha retornat un valor excepcionalment gran: %lu byte "
"(%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_mmap_begin() ha retornat un valor excepcionalment gran: %lu byte (%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
msgstr[1] ""
"snd_pcm_mmap_begin() ha retornat un valor excepcionalment gran: %lu bytes "
"(%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu "
"d'aquest incident als desenvolupadors de l'ALSA."
"snd_pcm_mmap_begin() ha retornat un valor excepcionalment gran: %lu bytes (%lu ms).\n"
"Probablement es tracta d'un error del controlador de l'ALSA «%s». Informeu d'aquest incident als desenvolupadors de l'ALSA."
#: spa/plugins/alsa/acp/channelmap.h:457
msgid "(invalid)"
msgstr "(incorrecte)"
#: spa/plugins/alsa/acp/compat.c:189
#: spa/plugins/alsa/acp/compat.c:194
msgid "Built-in Audio"
msgstr "Àudio intern"
#: spa/plugins/alsa/acp/compat.c:194
#: spa/plugins/alsa/acp/compat.c:199
msgid "Modem"
msgstr "Mòdem"
#: spa/plugins/bluez5/bluez5-device.c:1597
#: spa/plugins/bluez5/bluez5-device.c:1985
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "Passarel·la d'àudio (A2DP Source & HSP/HFP AG)"
#: spa/plugins/bluez5/bluez5-device.c:1622
#: spa/plugins/bluez5/bluez5-device.c:2014
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "Retransmissió d'àudio per als audiòfons (ASHA Sink)"
#: spa/plugins/bluez5/bluez5-device.c:2057
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "Reproducció d'alta fidelitat (Sink A2DP, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1625
#: spa/plugins/bluez5/bluez5-device.c:2060
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "Dúplex d'alta fidelitat (A2DP Source/Sink, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1633
#: spa/plugins/bluez5/bluez5-device.c:2068
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "Reproducció d'alta fidelitat (A2DP Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1635
#: spa/plugins/bluez5/bluez5-device.c:2070
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "Dúplex d'alta fidelitat (A2DP Source/Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1677
#: spa/plugins/bluez5/bluez5-device.c:2144
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "Reproducció d'alta fidelitat (sortida BAP, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1681
#: spa/plugins/bluez5/bluez5-device.c:2149
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "Entrada d'alta fidelitat (font A2DP, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1685
#: spa/plugins/bluez5/bluez5-device.c:2153
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "Dúplex d'alta fidelitat (BAP Source/Sink, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1693
#: spa/plugins/bluez5/bluez5-device.c:2162
msgid "High Fidelity Playback (BAP Sink)"
msgstr "Reproducció d'alta fidelitat (Sortida BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1696
#: spa/plugins/bluez5/bluez5-device.c:2166
msgid "High Fidelity Input (BAP Source)"
msgstr "Entrada d'alta fidelitat (Font BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1699
#: spa/plugins/bluez5/bluez5-device.c:2169
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "Dúplex d'alta fidelitat (BAP Source/Sink)"
#: spa/plugins/bluez5/bluez5-device.c:1735
#: spa/plugins/bluez5/bluez5-device.c:2209
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "Unitat d'ariculars pel cap (HSP/HFP, còdec %s)"
msgstr "Unitat d'auriculars pel cap (HSP/HFP, còdec %s)"
#: spa/plugins/bluez5/bluez5-device.c:1740
msgid "Headset Head Unit (HSP/HFP)"
msgstr "Unitat d'ariculars pel cap (HSP/HFP)"
#: spa/plugins/bluez5/bluez5-device.c:1820
#: spa/plugins/bluez5/bluez5-device.c:1825
#: spa/plugins/bluez5/bluez5-device.c:1832
#: spa/plugins/bluez5/bluez5-device.c:1838
#: spa/plugins/bluez5/bluez5-device.c:1844
#: spa/plugins/bluez5/bluez5-device.c:1850
#: spa/plugins/bluez5/bluez5-device.c:1856
#: spa/plugins/bluez5/bluez5-device.c:1862
#: spa/plugins/bluez5/bluez5-device.c:1868
#: spa/plugins/bluez5/bluez5-device.c:2361
#: spa/plugins/bluez5/bluez5-device.c:2366
#: spa/plugins/bluez5/bluez5-device.c:2373
#: spa/plugins/bluez5/bluez5-device.c:2379
#: spa/plugins/bluez5/bluez5-device.c:2385
#: spa/plugins/bluez5/bluez5-device.c:2391
#: spa/plugins/bluez5/bluez5-device.c:2397
#: spa/plugins/bluez5/bluez5-device.c:2403
#: spa/plugins/bluez5/bluez5-device.c:2409
msgid "Handsfree"
msgstr "Mans lliures"
#: spa/plugins/bluez5/bluez5-device.c:1826
#: spa/plugins/bluez5/bluez5-device.c:2367
msgid "Handsfree (HFP)"
msgstr "Mans lliures (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:1843
msgid "Headphone"
msgstr "Auricular"
#: spa/plugins/bluez5/bluez5-device.c:1849
#: spa/plugins/bluez5/bluez5-device.c:2390
msgid "Portable"
msgstr "Portable"
#: spa/plugins/bluez5/bluez5-device.c:1855
#: spa/plugins/bluez5/bluez5-device.c:2396
msgid "Car"
msgstr "Cotxe"
#: spa/plugins/bluez5/bluez5-device.c:1861
#: spa/plugins/bluez5/bluez5-device.c:2402
msgid "HiFi"
msgstr "HiFi"
#: spa/plugins/bluez5/bluez5-device.c:1867
#: spa/plugins/bluez5/bluez5-device.c:2408
msgid "Phone"
msgstr "Telèfon"
#: spa/plugins/bluez5/bluez5-device.c:1874
#: spa/plugins/bluez5/bluez5-device.c:2415
msgid "Bluetooth"
msgstr "Bluetooth"
#: spa/plugins/bluez5/bluez5-device.c:1875
#: spa/plugins/bluez5/bluez5-device.c:2416
msgid "Bluetooth (HFP)"
msgstr "Bluetooth (HFP)"

View file

@ -9,15 +9,15 @@ msgstr ""
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2021-08-26 03:31+0000\n"
"PO-Revision-Date: 2021-08-26 21:52+0630\n"
"PO-Revision-Date: 2025-10-02 11:36+0630\n"
"Last-Translator: zayar lwin <lw1nzayar@yandex.com>\n"
"Language-Team: lw1nzayar@yandex.com\n"
"Language: my\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.4.2\n"
"Last-Translator: zayar lwin <lw1nzayar@yandex.com>\n"
"Language: my\n"
"X-Generator: Poedit 3.7\n"
#: src/daemon/pipewire.c:45
#, c-format
@ -27,23 +27,24 @@ msgid ""
" --version Show version\n"
" -c, --config Load config (Default %s)\n"
msgstr ""
"%s [options]\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -c, --config Load config (Default %s)\n"
"%s [options]\r\n"
" -h, --help Show this help\r\n"
" --version Show version\r\n"
" -c, --config Load config (Default %s)\r\n"
"\n"
#: src/daemon/pipewire.desktop.in:4
msgid "PipeWire Media System"
msgstr "ပိုက်ဝိုင်ယာ မီဒီယာစစ်စတမ်"
msgstr "ပိုက်ဝိုင်ယာ မီဒီယာစစ်"
#: src/daemon/pipewire.desktop.in:5
msgid "Start the PipeWire Media System"
msgstr "ပိုက်ဝိုင်ယာ မီဒီယာစစ်စတမ် စတင်ရန်"
msgstr "ပိုက်ဝိုင်ယာ မီဒီယာစစ် စတင်ရန်"
#: src/examples/media-session/alsa-monitor.c:588
#: spa/plugins/alsa/acp/compat.c:189
msgid "Built-in Audio"
msgstr "နဂိုတည်းကထည့်သွင်းထားသည်ံ့ အသံကရိယာ"
msgstr "မူလပါရှိပြီးအသံကိရိယာ"
#: src/examples/media-session/alsa-monitor.c:592
#: spa/plugins/alsa/acp/compat.c:194
@ -53,7 +54,7 @@ msgstr "ဆ.သ.ရ-စက်"
#: src/examples/media-session/alsa-monitor.c:601
#: src/modules/module-zeroconf-discover.c:296
msgid "Unknown device"
msgstr "မသိသောစက်"
msgstr "မသိ"
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:173
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:173
@ -69,12 +70,12 @@ msgstr "%s@%sအတွက် လုံခြုံစွာဒေတာပို
#: src/modules/module-zeroconf-discover.c:308
#, c-format
msgid "%s on %s@%s"
msgstr ""
msgstr "%s on %s@%s"
#: src/modules/module-zeroconf-discover.c:312
#, c-format
msgid "%s on %s"
msgstr ""
msgstr "%s on %s"
#: src/tools/pw-cat.c:1016
#, c-format
@ -85,6 +86,11 @@ msgid ""
" -v, --verbose Enable verbose operations\n"
"\n"
msgstr ""
"%s [options] <file>\r\n"
" -h, --help Show this help\r\n"
" --version Show version\r\n"
" -v, --verbose Enable verbose operations\r\n"
"\r\n"
#: src/tools/pw-cat.c:1023
#, c-format
@ -103,6 +109,20 @@ msgid ""
" --list-targets List available targets for --target\n"
"\n"
msgstr ""
" -R, --remote Remote daemon name\r\n"
" --media-type Set media type (default %s)\r\n"
" --media-category Set media category (default %s)\r\n"
" --media-role Set media role (default %s)\r\n"
" --target Set node target (default %s)\r\n"
" 0 means don't link\r\n"
" --latency Set node latency (default %s)\r\n"
" Xunit (unit = s, ms, us, ns)\r\n"
" or direct samples (256)\r\n"
" the rate is the one of the source "
"file\r\n"
" --list-targets List available targets for --"
"target\r\n"
"\r\n"
#: src/tools/pw-cat.c:1041
#, c-format
@ -123,6 +143,22 @@ msgid ""
"%d)\n"
"\n"
msgstr ""
" --rate Sample rate (req. for rec) (default "
"%u)\r\n"
" --channels Number of channels (req. for rec) "
"(default %u)\r\n"
" --channel-map Channel map\r\n"
" one of: \"stereo\", "
"\"surround-51\",... or\r\n"
" comma separated list of channel "
"names: eg. \"FL,FR\"\r\n"
" --format Sample format %s (req. for rec) "
"(default %s)\r\n"
" --volume Stream volume 0-1.0 (default %.3f)"
"\r\n"
" -q --quality Resampler quality (0 - 15) (default "
"%d)\r\n"
"\r\n"
#: src/tools/pw-cat.c:1058
msgid ""
@ -131,6 +167,10 @@ msgid ""
" -m, --midi Midi mode\n"
"\n"
msgstr ""
" -p, --playback Playback mode\r\n"
" -r, --record Recording mode\r\n"
" -m, --midi Midi mode\r\n"
"\r\n"
#: src/tools/pw-cli.c:2954
#, c-format
@ -142,6 +182,12 @@ msgid ""
" -r, --remote Remote daemon name\n"
"\n"
msgstr ""
"%s [options] [command]\r\n"
" -h, --help Show this help\r\n"
" --version Show version\r\n"
" -d, --daemon Start as daemon (Default false)\r\n"
" -r, --remote Remote daemon name\r\n"
"\r\n"
#: spa/plugins/alsa/acp/acp.c:306
msgid "Pro Audio"
@ -473,12 +519,12 @@ msgstr "မိုနို စကားပြောဆိုသံ + ၇.၁ ပ
#: spa/plugins/alsa/acp/alsa-mixer.c:4750
#, c-format
msgid "%s Output"
msgstr "%s ထုတ်ပို့ကရိယာ"
msgstr "%s အသံထုတ်"
#: spa/plugins/alsa/acp/alsa-mixer.c:4757
#, c-format
msgid "%s Input"
msgstr "%s လက်ခံကရိယာ"
msgstr "%s အသံသွင်း"
#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
#, c-format
@ -493,20 +539,26 @@ msgid_plural ""
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"snd_pcm_avail() မှ ပြန်ပေးသည့်တန်ဖိုးသည် အလွန်ကြီးမားနေသည်- %lu ဘိုက် (%lu ms)။\n"
"ဖြစ်နိုင်ခြေအများဆုံးမှာ ALSA ဒရိုက်ဗာ %s တွင် ပရိုဂရမ်အမှားတစ်ခုရှိနေခြင်းဖြစ်သည်။ ဤပြဿနာအား "
"ALSA ရေးသားသူများထံသို့ သတင်းပို့ပေးပါ။"
#: spa/plugins/alsa/acp/alsa-util.c:1239
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"snd_pcm_delay() မှ ပြန်ပေးသည့်တန်ဖိုးသည် အလွန်ကြီးမားနေသည်- %li ဘိုက် (%s%lu ms)။\n"
"ဖြစ်နိုင်ခြေအများဆုံးမှာ ALSA ဒရိုက်ဗာ %s တွင် ပရိုဂရမ်အမှားတစ်ခုရှိနေခြင်းဖြစ်သည်။ ဤပြဿနာအား "
"ALSA ရေးသားသူများထံသို့ သတင်းပို့ပေးပါ။"
#: spa/plugins/alsa/acp/alsa-util.c:1286
#, c-format
@ -516,6 +568,10 @@ msgid ""
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr ""
"snd_pcm_avail_delay() မှ ထူးဆန်းသောတန်ဖိုးများ ပြန်ပေးခဲ့သည်- နှောင့်နှေးမှု %lu သည် ရနိုင်မှု %lu "
"ထက် နည်းနေပါသည်။\n"
"ဖြစ်နိုင်ခြေအများဆုံးမှာ ALSA ဒရိုက်ဘာ '%s တွင် ပရိုဂရမ်အမှားတစ်ခုရှိနေခြင်းဖြစ်သည်။ ဤပြဿနာအား "
"ALSA ရေးသားသူများထံသို့ သတင်းပို့ပေးပါ။"
#: spa/plugins/alsa/acp/alsa-util.c:1329
#, c-format
@ -530,6 +586,9 @@ msgid_plural ""
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
"snd_pcm_mmap_begin() မှ ပြန်ပေးသည့်တန်ဖိုးသည် အလွန်ကြီးမားနေသည်- %lu ဘိုက် (%lu ms)။\n"
"ဖြစ်နိုင်ခြေအများဆုံးမှာ ALSA ဒရိုက်ဗာ %s တွင် ပရိုဂရမ်အမှားတစ်ခုရှိနေခြင်းဖြစ်သည်။ ဤပြဿနာအား "
"ALSA ရေးသားသူများထံသို့ သတင်းပို့ပေးပါ။"
#: spa/plugins/alsa/acp/channelmap.h:466
msgid "(invalid)"

View file

@ -272,7 +272,7 @@ msgstr "Contraròtle automatic del ganh"
#: spa/plugins/alsa/acp/alsa-mixer.c:2665
msgid "No Automatic Gain Control"
msgstr "Pas de contraròtle automatic del ganh"
msgstr "Cap de contraròtle automatic del ganh"
#: spa/plugins/alsa/acp/alsa-mixer.c:2666
msgid "Boost"
@ -288,7 +288,7 @@ msgstr "Amplificador"
#: spa/plugins/alsa/acp/alsa-mixer.c:2669
msgid "No Amplifier"
msgstr "Pas d'amplificador"
msgstr "Cap d'amplificador"
#: spa/plugins/alsa/acp/alsa-mixer.c:2670
msgid "Bass Boost"
@ -296,7 +296,7 @@ msgstr "Amplificacion bassas"
#: spa/plugins/alsa/acp/alsa-mixer.c:2671
msgid "No Bass Boost"
msgstr "Pas d'amplificacion de las bassas"
msgstr "Cap d'amplificacion de las bassas"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:1995
@ -531,12 +531,12 @@ msgstr "Messatjariá mono + Surround 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4733
#, c-format
msgid "%s Output"
msgstr "%s Sortida"
msgstr "Sortida %s"
#: spa/plugins/alsa/acp/alsa-mixer.c:4741
#, c-format
msgid "%s Input"
msgstr "%s Entrada"
msgstr "Entrada %s"
#: spa/plugins/alsa/acp/alsa-util.c:1220 spa/plugins/alsa/acp/alsa-util.c:1314
#, c-format

115
po/pl.po
View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: pipewire\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2025-01-09 15:25+0000\n"
"PO-Revision-Date: 2025-02-09 14:55+0100\n"
"POT-Creation-Date: 2025-09-13 03:33+0000\n"
"PO-Revision-Date: 2025-09-13 11:47+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n"
@ -38,11 +38,11 @@ msgstr ""
"%s)\n"
" -P --properties Ustawia właściwości kontekstu\n"
#: src/daemon/pipewire.desktop.in:4
#: src/daemon/pipewire.desktop.in:3
msgid "PipeWire Media System"
msgstr "System multimediów PipeWire"
#: src/daemon/pipewire.desktop.in:5
#: src/daemon/pipewire.desktop.in:4
msgid "Start the PipeWire Media System"
msgstr "Uruchomienie systemu multimediów PipeWire"
@ -75,7 +75,7 @@ msgstr "%s na %s@%s"
msgid "%s on %s"
msgstr "%s na %s"
#: src/tools/pw-cat.c:973
#: src/tools/pw-cat.c:1084
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
@ -90,7 +90,7 @@ msgstr ""
" -v, --verbose Wyświetla więcej komunikatów\n"
"\n"
#: src/tools/pw-cat.c:980
#: src/tools/pw-cat.c:1091
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
@ -128,7 +128,7 @@ msgstr ""
" -P --properties Ustawia właściwości węzła\n"
"\n"
#: src/tools/pw-cat.c:998
#: src/tools/pw-cat.c:1109
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
@ -146,6 +146,9 @@ msgid ""
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
" -a, --raw RAW mode\n"
" -M, --force-midi Force midi format, one of \"midi\" "
"or \"ump\", (default ump)\n"
" -n, --sample-count COUNT Stop after COUNT samples\n"
"\n"
msgstr ""
" --rate Częstotliwość próbki (wymagane do "
@ -164,15 +167,21 @@ msgstr ""
" -q --quality Jakość resamplera od 0 do 15 "
"(domyślnie %d)\n"
" -a, --raw Tryb RAW\n"
" -M, --force-midi Wymusza format MIDI, można użyć "
"„midi”\n"
" albo „ump” (domyślnie ump)\n"
" -n, --sample-count LICZBA Zatrzymuje po LICZBIE próbek\n"
"\n"
#: src/tools/pw-cat.c:1016
#: src/tools/pw-cat.c:1129
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
" -s, --sysex SysEx mode\n"
" -c, --midi-clip MIDI clip mode\n"
"\n"
msgstr ""
" -p, --playback Tryb odtwarzania\n"
@ -180,9 +189,11 @@ msgstr ""
" -m, --midi Tryb MIDI\n"
" -d, --dsd Tryb DSD\n"
" -o, --encoded Tryb zakodowany\n"
" -s, --sysex Tryb SysEx\n"
" -c, --midi-clip Tryb klipu MIDI\n"
"\n"
#: src/tools/pw-cli.c:2306
#: src/tools/pw-cli.c:2386
#, c-format
msgid ""
"%s [options] [command]\n"
@ -202,15 +213,20 @@ msgstr ""
" -m, --monitor Monitoruje aktywność\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:347
#: spa/plugins/alsa/acp/acp.c:351
msgid "Pro Audio"
msgstr "Dźwięk w zastosowaniach profesjonalnych"
#: spa/plugins/alsa/acp/acp.c:507 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1795
#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1974
msgid "Off"
msgstr "Wyłączone"
#: spa/plugins/alsa/acp/acp.c:610
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [błąd UCM biblioteki ALSA]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "Wejście"
@ -234,7 +250,7 @@ msgstr "Wejście liniowe"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:2139
#: spa/plugins/bluez5/bluez5-device.c:2372
msgid "Microphone"
msgstr "Mikrofon"
@ -300,12 +316,15 @@ msgid "No Bass Boost"
msgstr "Brak podbicia basów"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:2145
#: spa/plugins/bluez5/bluez5-device.c:2378
msgid "Speaker"
msgstr "Głośnik"
#. Don't call it "headset", the HF one has the mic
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
#: spa/plugins/bluez5/bluez5-device.c:2384
#: spa/plugins/bluez5/bluez5-device.c:2451
msgid "Headphones"
msgstr "Słuchawki"
@ -415,7 +434,7 @@ msgstr "Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/bluez5/bluez5-device.c:2127
#: spa/plugins/bluez5/bluez5-device.c:2360
msgid "Headset"
msgstr "Słuchawki z mikrofonem"
@ -631,112 +650,108 @@ msgstr[2] ""
msgid "(invalid)"
msgstr "(nieprawidłowe)"
#: spa/plugins/alsa/acp/compat.c:193
#: spa/plugins/alsa/acp/compat.c:194
msgid "Built-in Audio"
msgstr "Wbudowany dźwięk"
#: spa/plugins/alsa/acp/compat.c:198
#: spa/plugins/alsa/acp/compat.c:199
msgid "Modem"
msgstr "Modem"
#: spa/plugins/bluez5/bluez5-device.c:1806
#: spa/plugins/bluez5/bluez5-device.c:1985
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "Bramka dźwięku (źródło A2DP i AG HSP/HFP)"
#: spa/plugins/bluez5/bluez5-device.c:1834
#: spa/plugins/bluez5/bluez5-device.c:2014
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "Przesyłanie dźwięku do aparatów słuchowych (odpływ ASHA)"
#: spa/plugins/bluez5/bluez5-device.c:1874
#: spa/plugins/bluez5/bluez5-device.c:2057
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1877
#: spa/plugins/bluez5/bluez5-device.c:2060
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1885
#: spa/plugins/bluez5/bluez5-device.c:2068
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP)"
#: spa/plugins/bluez5/bluez5-device.c:1887
#: spa/plugins/bluez5/bluez5-device.c:2070
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP)"
#: spa/plugins/bluez5/bluez5-device.c:1937
#: spa/plugins/bluez5/bluez5-device.c:2144
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "Odtwarzanie o wysokiej dokładności (odpływ BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1942
#: spa/plugins/bluez5/bluez5-device.c:2149
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "Wejście o wysokiej dokładności (źródło BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1946
#: spa/plugins/bluez5/bluez5-device.c:2153
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "Dupleks o wysokiej dokładności (źródło/odpływ BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1955
#: spa/plugins/bluez5/bluez5-device.c:2162
msgid "High Fidelity Playback (BAP Sink)"
msgstr "Odtwarzanie o wysokiej dokładności (odpływ BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1959
#: spa/plugins/bluez5/bluez5-device.c:2166
msgid "High Fidelity Input (BAP Source)"
msgstr "Wejście o wysokiej dokładności (źródło BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1962
#: spa/plugins/bluez5/bluez5-device.c:2169
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "Dupleks o wysokiej dokładności (źródło/odpływ BAP)"
#: spa/plugins/bluez5/bluez5-device.c:2008
#: spa/plugins/bluez5/bluez5-device.c:2209
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "Jednostka główna słuchawek z mikrofonem (HSP/HFP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:2128
#: spa/plugins/bluez5/bluez5-device.c:2133
#: spa/plugins/bluez5/bluez5-device.c:2140
#: spa/plugins/bluez5/bluez5-device.c:2146
#: spa/plugins/bluez5/bluez5-device.c:2152
#: spa/plugins/bluez5/bluez5-device.c:2158
#: spa/plugins/bluez5/bluez5-device.c:2164
#: spa/plugins/bluez5/bluez5-device.c:2170
#: spa/plugins/bluez5/bluez5-device.c:2176
#: spa/plugins/bluez5/bluez5-device.c:2361
#: spa/plugins/bluez5/bluez5-device.c:2366
#: spa/plugins/bluez5/bluez5-device.c:2373
#: spa/plugins/bluez5/bluez5-device.c:2379
#: spa/plugins/bluez5/bluez5-device.c:2385
#: spa/plugins/bluez5/bluez5-device.c:2391
#: spa/plugins/bluez5/bluez5-device.c:2397
#: spa/plugins/bluez5/bluez5-device.c:2403
#: spa/plugins/bluez5/bluez5-device.c:2409
msgid "Handsfree"
msgstr "Zestaw głośnomówiący"
#: spa/plugins/bluez5/bluez5-device.c:2134
#: spa/plugins/bluez5/bluez5-device.c:2367
msgid "Handsfree (HFP)"
msgstr "Zestaw głośnomówiący (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2151
msgid "Headphone"
msgstr "Słuchawki"
#: spa/plugins/bluez5/bluez5-device.c:2157
#: spa/plugins/bluez5/bluez5-device.c:2390
msgid "Portable"
msgstr "Przenośne"
#: spa/plugins/bluez5/bluez5-device.c:2163
#: spa/plugins/bluez5/bluez5-device.c:2396
msgid "Car"
msgstr "Samochód"
#: spa/plugins/bluez5/bluez5-device.c:2169
#: spa/plugins/bluez5/bluez5-device.c:2402
msgid "HiFi"
msgstr "HiFi"
#: spa/plugins/bluez5/bluez5-device.c:2175
#: spa/plugins/bluez5/bluez5-device.c:2408
msgid "Phone"
msgstr "Telefon"
#: spa/plugins/bluez5/bluez5-device.c:2182
#: spa/plugins/bluez5/bluez5-device.c:2415
msgid "Bluetooth"
msgstr "Bluetooth"
#: spa/plugins/bluez5/bluez5-device.c:2183
#: spa/plugins/bluez5/bluez5-device.c:2416
msgid "Bluetooth (HFP)"
msgstr "Bluetooth (HFP)"

137
po/sl.po
View file

@ -9,16 +9,16 @@ msgstr ""
"Project-Id-Version: PipeWire master\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2025-01-09 15:25+0000\n"
"PO-Revision-Date: 2025-01-23 09:23+0100\n"
"POT-Creation-Date: 2025-09-11 03:34+0000\n"
"PO-Revision-Date: 2025-09-11 11:47+0200\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"Language-Team: Slovenian <gnome-si@googlegroups.com>\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && n"
"%100<=4 ? 2 : 3);\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && "
"n%100<=4 ? 2 : 3);\n"
"X-Generator: Poedit 2.2.1\n"
#: src/daemon/pipewire.c:29
@ -37,13 +37,13 @@ msgstr ""
" --version Pokaži različico\n"
" -c, --config Naloži prilagoditev config (privzeto "
"%s)\n"
" -P properties Določi lastnosti konteksta\n"
" -P --properties Določi lastnosti konteksta\n"
#: src/daemon/pipewire.desktop.in:4
#: src/daemon/pipewire.desktop.in:3
msgid "PipeWire Media System"
msgstr "Medijski sistem PipeWire"
#: src/daemon/pipewire.desktop.in:5
#: src/daemon/pipewire.desktop.in:4
msgid "Start the PipeWire Media System"
msgstr "Zaženite medijski sistem PipeWire"
@ -76,7 +76,7 @@ msgstr "%s na %s@%s"
msgid "%s on %s"
msgstr "%s na %s"
#: src/tools/pw-cat.c:973
#: src/tools/pw-cat.c:1084
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
@ -92,7 +92,7 @@ msgstr ""
"\n"
"</file>\n"
#: src/tools/pw-cat.c:980
#: src/tools/pw-cat.c:1091
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
@ -129,7 +129,7 @@ msgstr ""
" -P --properties Nastavi lastnosti vozlišča\n"
"\n"
#: src/tools/pw-cat.c:998
#: src/tools/pw-cat.c:1109
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
@ -147,14 +147,17 @@ msgid ""
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
" -a, --raw RAW mode\n"
" -M, --force-midi Force midi format, one of \"midi\" "
"or \"ump\", (default ump)\n"
" -n, --sample-count COUNT Stop after COUNT samples\n"
"\n"
msgstr ""
" --rate Mera vzorčenja (zahtevano za rec) "
" --rate Mera vzorčenja (zaht. za rec) "
"(privzeto %u)\n"
" --channels Število kanalov (zaht. za snemanje) "
"(privzeto %u)\n"
" --channels Število kanalov (zahteva za "
"snemanje) (privzeto %u)\n"
" --channel-map Preslikava kanalov\n"
" Ena izmed: \"Stereo\", "
" Ena izmed: \"stereo\", "
"\"surround-51\",... ali\n"
" seznam imen kanalov, ločen z "
"vejico: npr. \"FL,FR\"\n"
@ -164,16 +167,20 @@ msgstr ""
" -q --quality Kakovost prevzorčenja (0 - 15) "
"(privzeto %d)\n"
" -a, --raw neobdelan način (RAW)\n"
"\n"
" -M, --force-midi Vsili zapis midi, eden izmed "
"\"midi\" ali \"ump\" (privzeto ump)\n"
" -n, --sample-count ŠTEVEC Ustavi po ŠTEVEC vzorcih\n"
"\n"
#: src/tools/pw-cat.c:1016
#: src/tools/pw-cat.c:1129
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
" -s, --sysex SysEx mode\n"
" -c, --midi-clip MIDI clip mode\n"
"\n"
msgstr ""
" -p, --playback Način predvajanja\n"
@ -181,9 +188,11 @@ msgstr ""
" -m, --midi Midi način\n"
" -d, --dsd Način DSD\n"
" -o, --encoded Kodiran način\n"
" -s, --sysex Način SysEx\n"
" -c, --midi-clip Način posnetka MIDI\n"
"\n"
#: src/tools/pw-cli.c:2306
#: src/tools/pw-cli.c:2386
#, c-format
msgid ""
"%s [options] [command]\n"
@ -203,15 +212,20 @@ msgstr ""
" -m, --monitor Spremljaj dejavnosti\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:347
#: spa/plugins/alsa/acp/acp.c:351
msgid "Pro Audio"
msgstr "Profesionalni zvok"
#: spa/plugins/alsa/acp/acp.c:507 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1795
#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1974
msgid "Off"
msgstr "Izklopljeno"
#: spa/plugins/alsa/acp/acp.c:610
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [napaka ALSA UCM]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "Vhod"
@ -235,7 +249,7 @@ msgstr "Linijski vhod"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:2139
#: spa/plugins/bluez5/bluez5-device.c:2372
msgid "Microphone"
msgstr "Mikrofon"
@ -301,12 +315,15 @@ msgid "No Bass Boost"
msgstr "Brez ojačitve nizkih tonov"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:2145
#: spa/plugins/bluez5/bluez5-device.c:2378
msgid "Speaker"
msgstr "Zvočnik"
#. Don't call it "headset", the HF one has the mic
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
#: spa/plugins/bluez5/bluez5-device.c:2384
#: spa/plugins/bluez5/bluez5-device.c:2451
msgid "Headphones"
msgstr "Slušalke"
@ -416,7 +433,7 @@ msgstr "Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/bluez5/bluez5-device.c:2127
#: spa/plugins/bluez5/bluez5-device.c:2360
msgid "Headset"
msgstr "Slušalka"
@ -575,13 +592,13 @@ msgstr[3] ""
#: spa/plugins/alsa/acp/alsa-util.c:1299
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
@ -655,112 +672,108 @@ msgstr[3] ""
msgid "(invalid)"
msgstr "(neveljavno)"
#: spa/plugins/alsa/acp/compat.c:193
#: spa/plugins/alsa/acp/compat.c:194
msgid "Built-in Audio"
msgstr "Vgrajen zvok"
#: spa/plugins/alsa/acp/compat.c:198
#: spa/plugins/alsa/acp/compat.c:199
msgid "Modem"
msgstr "Modem"
#: spa/plugins/bluez5/bluez5-device.c:1806
#: spa/plugins/bluez5/bluez5-device.c:1985
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "Zvožni prehod (vir A2DP in HSP/HFP AG)"
#: spa/plugins/bluez5/bluez5-device.c:1834
#: spa/plugins/bluez5/bluez5-device.c:2014
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "Pretakanje zvoka za slušne aparate (ponor ASHA)"
#: spa/plugins/bluez5/bluez5-device.c:1874
#: spa/plugins/bluez5/bluez5-device.c:2057
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "Predvajanje visoke ločljivosti (ponor A2DP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1877
#: spa/plugins/bluez5/bluez5-device.c:2060
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1885
#: spa/plugins/bluez5/bluez5-device.c:2068
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "Predvajanje visoke ločljivosti (ponor A2DP)"
#: spa/plugins/bluez5/bluez5-device.c:1887
#: spa/plugins/bluez5/bluez5-device.c:2070
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP)"
#: spa/plugins/bluez5/bluez5-device.c:1937
#: spa/plugins/bluez5/bluez5-device.c:2144
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "Predvajanje visoke ločljivosti (ponor BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1942
#: spa/plugins/bluez5/bluez5-device.c:2149
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "Vhod visoke ločljivosti (vir BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1946
#: spa/plugins/bluez5/bluez5-device.c:2153
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1955
#: spa/plugins/bluez5/bluez5-device.c:2162
msgid "High Fidelity Playback (BAP Sink)"
msgstr "Predvajanje visoke ločljivosti (ponor BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1959
#: spa/plugins/bluez5/bluez5-device.c:2166
msgid "High Fidelity Input (BAP Source)"
msgstr "Vhod visoke ločljivosti (vir BAP)"
#: spa/plugins/bluez5/bluez5-device.c:1962
#: spa/plugins/bluez5/bluez5-device.c:2169
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP)"
#: spa/plugins/bluez5/bluez5-device.c:2008
#: spa/plugins/bluez5/bluez5-device.c:2209
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "Naglavna enota slušalk (HSP/HFP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:2128
#: spa/plugins/bluez5/bluez5-device.c:2133
#: spa/plugins/bluez5/bluez5-device.c:2140
#: spa/plugins/bluez5/bluez5-device.c:2146
#: spa/plugins/bluez5/bluez5-device.c:2152
#: spa/plugins/bluez5/bluez5-device.c:2158
#: spa/plugins/bluez5/bluez5-device.c:2164
#: spa/plugins/bluez5/bluez5-device.c:2170
#: spa/plugins/bluez5/bluez5-device.c:2176
#: spa/plugins/bluez5/bluez5-device.c:2361
#: spa/plugins/bluez5/bluez5-device.c:2366
#: spa/plugins/bluez5/bluez5-device.c:2373
#: spa/plugins/bluez5/bluez5-device.c:2379
#: spa/plugins/bluez5/bluez5-device.c:2385
#: spa/plugins/bluez5/bluez5-device.c:2391
#: spa/plugins/bluez5/bluez5-device.c:2397
#: spa/plugins/bluez5/bluez5-device.c:2403
#: spa/plugins/bluez5/bluez5-device.c:2409
msgid "Handsfree"
msgstr "Prostoročno telefoniranje"
#: spa/plugins/bluez5/bluez5-device.c:2134
#: spa/plugins/bluez5/bluez5-device.c:2367
msgid "Handsfree (HFP)"
msgstr "Prostoročno telefoniranje (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2151
msgid "Headphone"
msgstr "Slušalke"
#: spa/plugins/bluez5/bluez5-device.c:2157
#: spa/plugins/bluez5/bluez5-device.c:2390
msgid "Portable"
msgstr "Prenosna naprava"
#: spa/plugins/bluez5/bluez5-device.c:2163
#: spa/plugins/bluez5/bluez5-device.c:2396
msgid "Car"
msgstr "Avtomobil"
#: spa/plugins/bluez5/bluez5-device.c:2169
#: spa/plugins/bluez5/bluez5-device.c:2402
msgid "HiFi"
msgstr "HiFi"
#: spa/plugins/bluez5/bluez5-device.c:2175
#: spa/plugins/bluez5/bluez5-device.c:2408
msgid "Phone"
msgstr "Telefon"
#: spa/plugins/bluez5/bluez5-device.c:2182
#: spa/plugins/bluez5/bluez5-device.c:2415
msgid "Bluetooth"
msgstr "Bluetooth"
#: spa/plugins/bluez5/bluez5-device.c:2183
#: spa/plugins/bluez5/bluez5-device.c:2416
msgid "Bluetooth (HFP)"
msgstr "Bluetooth (HFP)"

183
po/sv.po
View file

@ -1,9 +1,9 @@
# Swedish translation for pipewire.
# Copyright © 2008-2024 Free Software Foundation, Inc.
# Copyright © 2008-2025 Free Software Foundation, Inc.
# This file is distributed under the same license as the pipewire package.
# Daniel Nylander <po@danielnylander.se>, 2008, 2012.
# Josef Andersson <josef.andersson@fripost.org>, 2014, 2017.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022, 2023, 2024.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022, 2023, 2024, 2025.
#
# Termer:
# input/output: ingång/utgång (det handlar om ljud)
@ -19,8 +19,8 @@ msgstr ""
"Project-Id-Version: pipewire\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2024-11-05 03:27+0000\n"
"PO-Revision-Date: 2024-11-07 21:52+0100\n"
"POT-Creation-Date: 2025-04-16 15:31+0000\n"
"PO-Revision-Date: 2025-04-22 10:43+0200\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@ -65,7 +65,7 @@ msgstr "Tunnel till %s%s%s"
msgid "Dummy Output"
msgstr "Attrapputgång"
#: src/modules/module-pulse-tunnel.c:777
#: src/modules/module-pulse-tunnel.c:760
#, c-format
msgid "Tunnel for %s@%s"
msgstr "Tunnel för %s@%s"
@ -184,7 +184,7 @@ msgstr ""
" -o, --encoded Kodat läge\n"
"\n"
#: src/tools/pw-cli.c:2318
#: src/tools/pw-cli.c:2306
#, c-format
msgid ""
"%s [options] [command]\n"
@ -198,20 +198,25 @@ msgstr ""
"%s [flaggor] [kommando]\n"
" -h, --help Visa denna hjälp\n"
" --version Show version\n"
" -d, --daemon Starta som demon (Standard false)\n"
" -d, --daemon Starta som demon (standard false)\n"
" -r, --remote Fjärrdemonnamn\n"
" -m, --monitor Övervaka aktivitet\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:327
#: spa/plugins/alsa/acp/acp.c:350
msgid "Pro Audio"
msgstr "Professionellt ljud"
#: spa/plugins/alsa/acp/acp.c:487 spa/plugins/alsa/acp/alsa-mixer.c:4633
#: spa/plugins/bluez5/bluez5-device.c:1705
#: spa/plugins/alsa/acp/acp.c:511 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1802
msgid "Off"
msgstr "Av"
#: spa/plugins/alsa/acp/acp.c:593
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [ALSA UCM-fel]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "Ingång"
@ -235,7 +240,7 @@ msgstr "Linje in"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:2026
#: spa/plugins/bluez5/bluez5-device.c:2146
msgid "Microphone"
msgstr "Mikrofon"
@ -301,7 +306,7 @@ msgid "No Bass Boost"
msgstr "Ingen basökning"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:2032
#: spa/plugins/bluez5/bluez5-device.c:2152
msgid "Speaker"
msgstr "Högtalare"
@ -383,15 +388,15 @@ msgstr "Chatt-ingång"
msgid "Virtual Surround 7.1"
msgstr "Virtual surround 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4456
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
msgid "Analog Mono"
msgstr "Analog mono"
#: spa/plugins/alsa/acp/alsa-mixer.c:4457
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
msgid "Analog Mono (Left)"
msgstr "Analog mono (vänster)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
msgid "Analog Mono (Right)"
msgstr "Analog mono (höger)"
@ -400,147 +405,147 @@ msgstr "Analog mono (höger)"
#. * here would lead to the source name to become "Analog Stereo Input
#. * Input". The same logic applies to analog-stereo-output,
#. * multichannel-input and multichannel-output.
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
#: spa/plugins/alsa/acp/alsa-mixer.c:4467
#: spa/plugins/alsa/acp/alsa-mixer.c:4468
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
msgid "Analog Stereo"
msgstr "Analog stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
#: spa/plugins/alsa/acp/alsa-mixer.c:4462
msgid "Mono"
msgstr "Mono"
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4463
msgid "Stereo"
msgstr "Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
#: spa/plugins/bluez5/bluez5-device.c:2014
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/bluez5/bluez5-device.c:2134
msgid "Headset"
msgstr "Headset"
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
msgid "Speakerphone"
msgstr "Högtalartelefon"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
msgid "Multichannel"
msgstr "Multikanal"
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
msgid "Analog Surround 2.1"
msgstr "Analog surround 2.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
msgid "Analog Surround 3.0"
msgstr "Analog surround 3.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
msgid "Analog Surround 3.1"
msgstr "Analog surround 3.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
msgid "Analog Surround 4.0"
msgstr "Analog surround 4.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
msgid "Analog Surround 4.1"
msgstr "Analog surround 4.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
msgid "Analog Surround 5.0"
msgstr "Analog surround 5.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
msgid "Analog Surround 5.1"
msgstr "Analog surround 5.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
msgid "Analog Surround 6.0"
msgstr "Analog surround 6.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
msgid "Analog Surround 6.1"
msgstr "Analog surround 6.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
msgid "Analog Surround 7.0"
msgstr "Analog surround 7.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
msgid "Analog Surround 7.1"
msgstr "Analog surround 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
msgid "Digital Stereo (IEC958)"
msgstr "Digital stereo (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "Digital surround 4.0 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "Digital surround 5.1 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "Digital surround 5.1 (IEC958/DTS)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
msgid "Digital Stereo (HDMI)"
msgstr "Digital stereo (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
msgid "Digital Surround 5.1 (HDMI)"
msgstr "Digital surround 5.1 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
msgid "Chat"
msgstr "Chatt"
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
msgid "Game"
msgstr "Spel"
#: spa/plugins/alsa/acp/alsa-mixer.c:4625
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
msgid "Analog Mono Duplex"
msgstr "Analog mono duplex"
#: spa/plugins/alsa/acp/alsa-mixer.c:4626
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
msgid "Analog Stereo Duplex"
msgstr "Analog stereo duplex"
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
msgid "Digital Stereo Duplex (IEC958)"
msgstr "Digital stereo duplex (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
msgid "Multichannel Duplex"
msgstr "Multikanalduplex"
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
#: spa/plugins/alsa/acp/alsa-mixer.c:4633
msgid "Stereo Duplex"
msgstr "Stereo duplex"
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
#: spa/plugins/alsa/acp/alsa-mixer.c:4634
msgid "Mono Chat + 7.1 Surround"
msgstr "Mono Chatt + 7.1 Surround"
#: spa/plugins/alsa/acp/alsa-mixer.c:4733
#: spa/plugins/alsa/acp/alsa-mixer.c:4735
#, c-format
msgid "%s Output"
msgstr "%s-utgång"
#: spa/plugins/alsa/acp/alsa-mixer.c:4741
#: spa/plugins/alsa/acp/alsa-mixer.c:4743
#, c-format
msgid "%s Input"
msgstr "%s-ingång"
#: spa/plugins/alsa/acp/alsa-util.c:1231 spa/plugins/alsa/acp/alsa-util.c:1325
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
#, c-format
msgid ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
@ -563,7 +568,7 @@ msgstr[1] ""
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
"problemet till ALSA-utvecklarna."
#: spa/plugins/alsa/acp/alsa-util.c:1297
#: spa/plugins/alsa/acp/alsa-util.c:1299
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
@ -586,7 +591,7 @@ msgstr[1] ""
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
"problemet till ALSA-utvecklarna."
#: spa/plugins/alsa/acp/alsa-util.c:1344
#: spa/plugins/alsa/acp/alsa-util.c:1346
#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
@ -599,7 +604,7 @@ msgstr ""
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
"problemet till ALSA-utvecklarna."
#: spa/plugins/alsa/acp/alsa-util.c:1387
#: spa/plugins/alsa/acp/alsa-util.c:1389
#, c-format
msgid ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
@ -634,100 +639,104 @@ msgstr "Inbyggt ljud"
msgid "Modem"
msgstr "Modem"
#: spa/plugins/bluez5/bluez5-device.c:1716
#: spa/plugins/bluez5/bluez5-device.c:1813
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
#: spa/plugins/bluez5/bluez5-device.c:1764
#: spa/plugins/bluez5/bluez5-device.c:1841
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "Ljudströmning för hörhjälpmedel (ASHA-utgång)"
#: spa/plugins/bluez5/bluez5-device.c:1881
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1767
#: spa/plugins/bluez5/bluez5-device.c:1884
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1775
#: spa/plugins/bluez5/bluez5-device.c:1892
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "High fidelity-uppspelning (A2DP-utgång)"
#: spa/plugins/bluez5/bluez5-device.c:1777
#: spa/plugins/bluez5/bluez5-device.c:1894
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "High fidelity duplex (A2DP-källa/utgång)"
#: spa/plugins/bluez5/bluez5-device.c:1827
#: spa/plugins/bluez5/bluez5-device.c:1944
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1832
#: spa/plugins/bluez5/bluez5-device.c:1949
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "High fidelity-ingång (BAP-källa, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1836
#: spa/plugins/bluez5/bluez5-device.c:1953
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "High fidelity duplex (BAP-källa/utgång, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:1845
#: spa/plugins/bluez5/bluez5-device.c:1962
msgid "High Fidelity Playback (BAP Sink)"
msgstr "High fidelity-uppspelning (BAP-utgång)"
#: spa/plugins/bluez5/bluez5-device.c:1849
#: spa/plugins/bluez5/bluez5-device.c:1966
msgid "High Fidelity Input (BAP Source)"
msgstr "High fidelity-ingång (BAP-källa)"
#: spa/plugins/bluez5/bluez5-device.c:1852
#: spa/plugins/bluez5/bluez5-device.c:1969
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "High fidelity duplex (BAP-källa/utgång)"
#: spa/plugins/bluez5/bluez5-device.c:1901
#: spa/plugins/bluez5/bluez5-device.c:2015
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
#: spa/plugins/bluez5/bluez5-device.c:2015
#: spa/plugins/bluez5/bluez5-device.c:2020
#: spa/plugins/bluez5/bluez5-device.c:2027
#: spa/plugins/bluez5/bluez5-device.c:2033
#: spa/plugins/bluez5/bluez5-device.c:2039
#: spa/plugins/bluez5/bluez5-device.c:2045
#: spa/plugins/bluez5/bluez5-device.c:2051
#: spa/plugins/bluez5/bluez5-device.c:2057
#: spa/plugins/bluez5/bluez5-device.c:2063
#: spa/plugins/bluez5/bluez5-device.c:2135
#: spa/plugins/bluez5/bluez5-device.c:2140
#: spa/plugins/bluez5/bluez5-device.c:2147
#: spa/plugins/bluez5/bluez5-device.c:2153
#: spa/plugins/bluez5/bluez5-device.c:2159
#: spa/plugins/bluez5/bluez5-device.c:2165
#: spa/plugins/bluez5/bluez5-device.c:2171
#: spa/plugins/bluez5/bluez5-device.c:2177
#: spa/plugins/bluez5/bluez5-device.c:2183
msgid "Handsfree"
msgstr "Handsfree"
#: spa/plugins/bluez5/bluez5-device.c:2021
#: spa/plugins/bluez5/bluez5-device.c:2141
msgid "Handsfree (HFP)"
msgstr "Handsfree (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2038
#: spa/plugins/bluez5/bluez5-device.c:2158
msgid "Headphone"
msgstr "Hörlurar"
#: spa/plugins/bluez5/bluez5-device.c:2044
#: spa/plugins/bluez5/bluez5-device.c:2164
msgid "Portable"
msgstr "Bärbar"
#: spa/plugins/bluez5/bluez5-device.c:2050
#: spa/plugins/bluez5/bluez5-device.c:2170
msgid "Car"
msgstr "Bil"
#: spa/plugins/bluez5/bluez5-device.c:2056
#: spa/plugins/bluez5/bluez5-device.c:2176
msgid "HiFi"
msgstr "HiFi"
#: spa/plugins/bluez5/bluez5-device.c:2062
#: spa/plugins/bluez5/bluez5-device.c:2182
msgid "Phone"
msgstr "Telefon"
#: spa/plugins/bluez5/bluez5-device.c:2069
#: spa/plugins/bluez5/bluez5-device.c:2189
msgid "Bluetooth"
msgstr "Bluetooth"
#: spa/plugins/bluez5/bluez5-device.c:2070
#: spa/plugins/bluez5/bluez5-device.c:2190
msgid "Bluetooth (HFP)"
msgstr "Bluetooth (HFP)"

341
po/tr.po
View file

@ -1,46 +1,51 @@
# Turkish translation for PipeWire.
# Copyright (C) 2014-2024 PipeWire's COPYRIGHT HOLDER
# Copyright (C) 2014-2025 PipeWire's COPYRIGHT HOLDER
# This file is distributed under the same license as the PipeWire package.
#
# Necdet Yücel <necdetyucel@gmail.com>, 2014.
# Kaan Özdinçer <kaanozdincer@gmail.com>, 2014.
# Muhammet Kara <muhammetk@gmail.com>, 2015, 2016, 2017.
# Oğuz Ersen <oguz@ersen.moe>, 2021-2022.
# Sabri Ünal <libreajans@gmail.com>, 2024.
# Sabri Ünal <yakushabb@gmail.com>, 2024, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: PipeWire master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-25 03:43+0300\n"
"PO-Revision-Date: 2024-02-25 03:49+0300\n"
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2025-10-24 15:37+0000\n"
"PO-Revision-Date: 2025-10-24 20:15+0300\n"
"Last-Translator: Sabri Ünal <yakushabb@gmail.com>\n"
"Language-Team: Türkçe <takim@gnome.org.tr>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4.2\n"
"X-Generator: Poedit 3.8\n"
#: src/daemon/pipewire.c:26
#: src/daemon/pipewire.c:29
#, c-format
msgid ""
"%s [options]\n"
" -h, --help Show this help\n"
" -v, --verbose Increase verbosity by one level\n"
" --version Show version\n"
" -c, --config Load config (Default %s)\n"
" -P --properties Set context properties\n"
msgstr ""
"%s [seçenekler]\n"
" -h, --help Bu yardımı göster\n"
" -v, --verbose Ayrıntı düzeyini bir düzey artır\n"
" --version Sürümü göster\n"
" -c, --config Yapılandırmayı yükle (Öntanımlı %s)\n"
" -P --properties Bağlam özelliklerini ayarla\n"
#: src/daemon/pipewire.desktop.in:4
#: src/daemon/pipewire.desktop.in:3
msgid "PipeWire Media System"
msgstr "PipeWire Ortam Sistemi"
#: src/daemon/pipewire.desktop.in:5
#: src/daemon/pipewire.desktop.in:4
msgid "Start the PipeWire Media System"
msgstr "PipeWire Ortam Sistemini Başlat"
@ -54,26 +59,26 @@ msgstr "%s%s%s tüneli"
msgid "Dummy Output"
msgstr "Temsili Çıkış"
#: src/modules/module-pulse-tunnel.c:774
#: src/modules/module-pulse-tunnel.c:760
#, c-format
msgid "Tunnel for %s@%s"
msgstr "%s@%s için tünel"
#: src/modules/module-zeroconf-discover.c:315
#: src/modules/module-zeroconf-discover.c:320
msgid "Unknown device"
msgstr "Bilinmeyen aygıt"
#: src/modules/module-zeroconf-discover.c:327
#: src/modules/module-zeroconf-discover.c:332
#, c-format
msgid "%s on %s@%s"
msgstr "%s, %s@%s"
#: src/modules/module-zeroconf-discover.c:331
#: src/modules/module-zeroconf-discover.c:336
#, c-format
msgid "%s on %s"
msgstr "%s, %s"
#: src/tools/pw-cat.c:991
#: src/tools/pw-cat.c:1096
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
@ -88,7 +93,7 @@ msgstr ""
" -v, --verbose Ayrıntılı işlemleri etkinleştir\n"
"\n"
#: src/tools/pw-cat.c:998
#: src/tools/pw-cat.c:1103
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
@ -122,7 +127,7 @@ msgstr ""
" -P --properties Düğüm özelliklerini ayarla\n"
"\n"
#: src/tools/pw-cat.c:1016
#: src/tools/pw-cat.c:1121
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
@ -139,6 +144,10 @@ msgid ""
" --volume Stream volume 0-1.0 (default %.3f)\n"
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
" -a, --raw RAW mode\n"
" -M, --force-midi Force midi format, one of \"midi\" "
"or \"ump\", (default ump)\n"
" -n, --sample-count COUNT Stop after COUNT samples\n"
"\n"
msgstr ""
" --rate Örnekleme oranı (kayıt için gerekli) "
@ -156,15 +165,21 @@ msgstr ""
"%.3f)\n"
" -q --quality Yeniden örnekleyici kalitesi (0 - "
"15) (öntanımlı %d)\n"
" -a, --raw HAM kipi\n"
" -M, --force-midi Midi biçimini zorla, ikisinden "
"birisi \"midi\" ya da\"ump\", (öntanımlı ump)\n"
" -n, --sample-count COUNT COUNT örnekleme sonrası dur\n"
"\n"
#: src/tools/pw-cat.c:1033
#: src/tools/pw-cat.c:1141
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
" -s, --sysex SysEx mode\n"
" -c, --midi-clip MIDI clip mode\n"
"\n"
msgstr ""
" -p, --playback Çalma kipi\n"
@ -172,9 +187,11 @@ msgstr ""
" -m, --midi Midi kipi\n"
" -d, --dsd DSD kipi\n"
" -o, --encoded Kodlanmış kip\n"
" -s, --sysex SysEx kipi\n"
" -c, --midi-clip MIDI klip kipi\n"
"\n"
#: src/tools/pw-cli.c:2252
#: src/tools/pw-cli.c:2386
#, c-format
msgid ""
"%s [options] [command]\n"
@ -193,195 +210,203 @@ msgstr ""
" -r, --remote Uzak arka plan programı adı\n"
" -m, --monitor Etkinliği izle\n"
#: spa/plugins/alsa/acp/acp.c:327
#: spa/plugins/alsa/acp/acp.c:361
msgid "Pro Audio"
msgstr "Profesyonel Ses"
#: spa/plugins/alsa/acp/acp.c:488 spa/plugins/alsa/acp/alsa-mixer.c:4633
#: spa/plugins/bluez5/bluez5-device.c:1701
#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699
#: spa/plugins/bluez5/bluez5-device.c:1976
msgid "Off"
msgstr "Kapalı"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
#: spa/plugins/alsa/acp/acp.c:620
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [ALSA UCM hatası]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
msgid "Input"
msgstr "Giriş"
#: spa/plugins/alsa/acp/alsa-mixer.c:2653
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
msgid "Docking Station Input"
msgstr "Yerleştirme İstasyonu Girişi"
#: spa/plugins/alsa/acp/alsa-mixer.c:2654
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
msgid "Docking Station Microphone"
msgstr "Yerleştirme İstasyonu Mikrofonu"
#: spa/plugins/alsa/acp/alsa-mixer.c:2655
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
msgid "Docking Station Line In"
msgstr "Yerleştirme İstasyonu Hat Girişi"
#: spa/plugins/alsa/acp/alsa-mixer.c:2656
#: spa/plugins/alsa/acp/alsa-mixer.c:2747
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
msgid "Line In"
msgstr "Hat Girişi"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:1989
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
#: spa/plugins/bluez5/bluez5-device.c:2374
msgid "Microphone"
msgstr "Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2658
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
msgid "Front Microphone"
msgstr "Ön Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2659
#: spa/plugins/alsa/acp/alsa-mixer.c:2743
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
msgid "Rear Microphone"
msgstr "Arka Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2660
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
msgid "External Microphone"
msgstr "Harici Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2661
#: spa/plugins/alsa/acp/alsa-mixer.c:2745
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
msgid "Internal Microphone"
msgstr "Dahili Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2662
#: spa/plugins/alsa/acp/alsa-mixer.c:2748
#: spa/plugins/alsa/acp/alsa-mixer.c:2731
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
msgid "Radio"
msgstr "Radyo"
#: spa/plugins/alsa/acp/alsa-mixer.c:2663
#: spa/plugins/alsa/acp/alsa-mixer.c:2749
#: spa/plugins/alsa/acp/alsa-mixer.c:2732
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
msgid "Video"
msgstr "Video"
#: spa/plugins/alsa/acp/alsa-mixer.c:2664
#: spa/plugins/alsa/acp/alsa-mixer.c:2733
msgid "Automatic Gain Control"
msgstr "Otomatik Kazanç Denetimi"
#: spa/plugins/alsa/acp/alsa-mixer.c:2665
#: spa/plugins/alsa/acp/alsa-mixer.c:2734
msgid "No Automatic Gain Control"
msgstr "Otomatik Kazanç Denetimi Yok"
#: spa/plugins/alsa/acp/alsa-mixer.c:2666
#: spa/plugins/alsa/acp/alsa-mixer.c:2735
msgid "Boost"
msgstr "Artır"
#: spa/plugins/alsa/acp/alsa-mixer.c:2667
#: spa/plugins/alsa/acp/alsa-mixer.c:2736
msgid "No Boost"
msgstr "Artırma Yok"
#: spa/plugins/alsa/acp/alsa-mixer.c:2668
#: spa/plugins/alsa/acp/alsa-mixer.c:2737
msgid "Amplifier"
msgstr "Yükseltici"
#: spa/plugins/alsa/acp/alsa-mixer.c:2669
#: spa/plugins/alsa/acp/alsa-mixer.c:2738
msgid "No Amplifier"
msgstr "Yükseltici Yok"
#: spa/plugins/alsa/acp/alsa-mixer.c:2670
#: spa/plugins/alsa/acp/alsa-mixer.c:2739
msgid "Bass Boost"
msgstr "Bas Artır"
#: spa/plugins/alsa/acp/alsa-mixer.c:2671
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
msgid "No Bass Boost"
msgstr "Bas Artırma Yok"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:1995
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:2380
msgid "Speaker"
msgstr "Hoparlör"
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
#. Don't call it "headset", the HF one has the mic
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
#: spa/plugins/bluez5/bluez5-device.c:2386
#: spa/plugins/bluez5/bluez5-device.c:2453
msgid "Headphones"
msgstr "Kulaklık"
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
msgid "Analog Input"
msgstr "Analog Giriş"
#: spa/plugins/alsa/acp/alsa-mixer.c:2744
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
msgid "Dock Microphone"
msgstr "Yapışık Mikrofon"
#: spa/plugins/alsa/acp/alsa-mixer.c:2746
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
msgid "Headset Microphone"
msgstr "Mikrofonlu Kulaklık"
#: spa/plugins/alsa/acp/alsa-mixer.c:2750
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
msgid "Analog Output"
msgstr "Analog Çıkış"
#: spa/plugins/alsa/acp/alsa-mixer.c:2752
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
msgid "Headphones 2"
msgstr "Kulaklık 2"
#: spa/plugins/alsa/acp/alsa-mixer.c:2753
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
msgid "Headphones Mono Output"
msgstr "Kulaklık Tek Kanallı Çıkış"
#: spa/plugins/alsa/acp/alsa-mixer.c:2754
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
msgid "Line Out"
msgstr "Hat Çıkışı"
#: spa/plugins/alsa/acp/alsa-mixer.c:2755
#: spa/plugins/alsa/acp/alsa-mixer.c:2824
msgid "Analog Mono Output"
msgstr "Analog Tek Kanallı Çıkış"
#: spa/plugins/alsa/acp/alsa-mixer.c:2756
#: spa/plugins/alsa/acp/alsa-mixer.c:2825
msgid "Speakers"
msgstr "Hoparlörler"
#: spa/plugins/alsa/acp/alsa-mixer.c:2757
#: spa/plugins/alsa/acp/alsa-mixer.c:2826
msgid "HDMI / DisplayPort"
msgstr "HDMI / DisplayPort"
#: spa/plugins/alsa/acp/alsa-mixer.c:2758
#: spa/plugins/alsa/acp/alsa-mixer.c:2827
msgid "Digital Output (S/PDIF)"
msgstr "Sayısal Çıkış (S/PDIF)"
#: spa/plugins/alsa/acp/alsa-mixer.c:2759
#: spa/plugins/alsa/acp/alsa-mixer.c:2828
msgid "Digital Input (S/PDIF)"
msgstr "Sayısal Giriş (S/PDIF)"
#: spa/plugins/alsa/acp/alsa-mixer.c:2760
#: spa/plugins/alsa/acp/alsa-mixer.c:2829
msgid "Multichannel Input"
msgstr "Çok Kanallı Giriş"
#: spa/plugins/alsa/acp/alsa-mixer.c:2761
#: spa/plugins/alsa/acp/alsa-mixer.c:2830
msgid "Multichannel Output"
msgstr "Çok Kanallı Çıkış"
#: spa/plugins/alsa/acp/alsa-mixer.c:2762
#: spa/plugins/alsa/acp/alsa-mixer.c:2831
msgid "Game Output"
msgstr "Oyun Çıkışı"
#: spa/plugins/alsa/acp/alsa-mixer.c:2763
#: spa/plugins/alsa/acp/alsa-mixer.c:2764
#: spa/plugins/alsa/acp/alsa-mixer.c:2832
#: spa/plugins/alsa/acp/alsa-mixer.c:2833
msgid "Chat Output"
msgstr "Sohbet Çıkışı"
#: spa/plugins/alsa/acp/alsa-mixer.c:2765
#: spa/plugins/alsa/acp/alsa-mixer.c:2834
msgid "Chat Input"
msgstr "Sohbet Girişi"
#: spa/plugins/alsa/acp/alsa-mixer.c:2766
#: spa/plugins/alsa/acp/alsa-mixer.c:2835
msgid "Virtual Surround 7.1"
msgstr "Sanal Çevresel Ses 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4456
#: spa/plugins/alsa/acp/alsa-mixer.c:4522
msgid "Analog Mono"
msgstr "Analog Tek Kanallı"
#: spa/plugins/alsa/acp/alsa-mixer.c:4457
#: spa/plugins/alsa/acp/alsa-mixer.c:4523
msgid "Analog Mono (Left)"
msgstr "Analog Tek Kanallı (Sol)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
#: spa/plugins/alsa/acp/alsa-mixer.c:4524
msgid "Analog Mono (Right)"
msgstr "Analog Tek Kanallı (Sağ)"
@ -390,147 +415,147 @@ msgstr "Analog Tek Kanallı (Sağ)"
#. * here would lead to the source name to become "Analog Stereo Input
#. * Input". The same logic applies to analog-stereo-output,
#. * multichannel-input and multichannel-output.
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
#: spa/plugins/alsa/acp/alsa-mixer.c:4467
#: spa/plugins/alsa/acp/alsa-mixer.c:4468
#: spa/plugins/alsa/acp/alsa-mixer.c:4525
#: spa/plugins/alsa/acp/alsa-mixer.c:4533
#: spa/plugins/alsa/acp/alsa-mixer.c:4534
msgid "Analog Stereo"
msgstr "Analog Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
#: spa/plugins/alsa/acp/alsa-mixer.c:4526
msgid "Mono"
msgstr "Tek Kanallı"
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
msgid "Stereo"
msgstr "Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
#: spa/plugins/bluez5/bluez5-device.c:1977
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
#: spa/plugins/bluez5/bluez5-device.c:2362
msgid "Headset"
msgstr "Kulaklık"
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
#: spa/plugins/alsa/acp/alsa-mixer.c:4536
#: spa/plugins/alsa/acp/alsa-mixer.c:4694
msgid "Speakerphone"
msgstr "Hoparlör"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4537
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
msgid "Multichannel"
msgstr "Çok kanallı"
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
msgid "Analog Surround 2.1"
msgstr "Analog Çevresel Ses 2.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
msgid "Analog Surround 3.0"
msgstr "Analog Çevresel Ses 3.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
msgid "Analog Surround 3.1"
msgstr "Analog Çevresel Ses 3.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
msgid "Analog Surround 4.0"
msgstr "Analog Çevresel Ses 4.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
msgid "Analog Surround 4.1"
msgstr "Analog Çevresel Ses 4.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
msgid "Analog Surround 5.0"
msgstr "Analog Çevresel Ses 5.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
msgid "Analog Surround 5.1"
msgstr "Analog Çevresel Ses 5.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
msgid "Analog Surround 6.0"
msgstr "Analog Çevresel Ses 6.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
msgid "Analog Surround 6.1"
msgstr "Analog Çevresel Ses 6.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
msgid "Analog Surround 7.0"
msgstr "Analog Çevresel Ses 7.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
msgid "Analog Surround 7.1"
msgstr "Analog Çevresel Ses 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
msgid "Digital Stereo (IEC958)"
msgstr "Sayısal Stereo (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "Sayısal Çevresel Ses 4.0 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "Sayısal Çevresel Ses 5.1 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "Sayısal Çevresel Ses 5.1 (IEC958/DTS)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
msgid "Digital Stereo (HDMI)"
msgstr "Sayısal Stereo (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
msgid "Digital Surround 5.1 (HDMI)"
msgstr "Sayısal Çevresel Ses 5.1 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
msgid "Chat"
msgstr "Sohbet"
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
msgid "Game"
msgstr "Oyun"
#: spa/plugins/alsa/acp/alsa-mixer.c:4625
#: spa/plugins/alsa/acp/alsa-mixer.c:4691
msgid "Analog Mono Duplex"
msgstr "Analog Tek Kanallı İkili"
#: spa/plugins/alsa/acp/alsa-mixer.c:4626
#: spa/plugins/alsa/acp/alsa-mixer.c:4692
msgid "Analog Stereo Duplex"
msgstr "Analog İkili Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/alsa/acp/alsa-mixer.c:4695
msgid "Digital Stereo Duplex (IEC958)"
msgstr "Sayısal İkili Stereo (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
msgid "Multichannel Duplex"
msgstr "Çok Kanallı İkili"
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
msgid "Stereo Duplex"
msgstr "İkili Stereo"
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
msgid "Mono Chat + 7.1 Surround"
msgstr "Tek Kanallı Sohbet + 7.1 Çevresel Ses"
#: spa/plugins/alsa/acp/alsa-mixer.c:4733
#: spa/plugins/alsa/acp/alsa-mixer.c:4799
#, c-format
msgid "%s Output"
msgstr "%s Çıkışı"
#: spa/plugins/alsa/acp/alsa-mixer.c:4741
#: spa/plugins/alsa/acp/alsa-mixer.c:4807
#, c-format
msgid "%s Input"
msgstr "%s Girişi"
#: spa/plugins/alsa/acp/alsa-util.c:1220 spa/plugins/alsa/acp/alsa-util.c:1314
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
#, c-format
msgid ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
@ -547,16 +572,16 @@ msgstr[0] ""
"Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
"geliştiricilerine bildirin."
#: spa/plugins/alsa/acp/alsa-util.c:1286
#: spa/plugins/alsa/acp/alsa-util.c:1299
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgid_plural ""
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
"%lu ms).\n"
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
"(%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr[0] ""
@ -564,7 +589,7 @@ msgstr[0] ""
"Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
"geliştiricilerine bildirin."
#: spa/plugins/alsa/acp/alsa-util.c:1333
#: spa/plugins/alsa/acp/alsa-util.c:1346
#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
@ -577,7 +602,7 @@ msgstr ""
"Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
"geliştiricilerine bildirin."
#: spa/plugins/alsa/acp/alsa-util.c:1376
#: spa/plugins/alsa/acp/alsa-util.c:1389
#, c-format
msgid ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
@ -595,112 +620,112 @@ msgstr[0] ""
"Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
"geliştiricilerine bildirin."
#: spa/plugins/alsa/acp/channelmap.h:457
#: spa/plugins/alsa/acp/channelmap.h:460
msgid "(invalid)"
msgstr "(geçersiz)"
#: spa/plugins/alsa/acp/compat.c:193
#: spa/plugins/alsa/acp/compat.c:194
msgid "Built-in Audio"
msgstr "Dahili Ses"
#: spa/plugins/alsa/acp/compat.c:198
#: spa/plugins/alsa/acp/compat.c:199
msgid "Modem"
msgstr "Modem"
#: spa/plugins/bluez5/bluez5-device.c:1712
#: spa/plugins/bluez5/bluez5-device.c:1987
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "Ses Geçidi (A2DP Kaynak & HSP/HFP AG)"
#: spa/plugins/bluez5/bluez5-device.c:1760
#: spa/plugins/bluez5/bluez5-device.c:2016
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "İşitme Aygıtları İçin Ses Akışı (ASHA Alıcı)"
#: spa/plugins/bluez5/bluez5-device.c:2059
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "Yüksek Kaliteli Çalma (A2DP Alıcı, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1763
#: spa/plugins/bluez5/bluez5-device.c:2062
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "Yüksek Kaliteli İkili (A2DP Kaynak/Alıcı, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1771
#: spa/plugins/bluez5/bluez5-device.c:2070
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "Yüksek Kaliteli Çalma (A2DP Alıcı)"
#: spa/plugins/bluez5/bluez5-device.c:1773
#: spa/plugins/bluez5/bluez5-device.c:2072
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "Yüksek Kaliteli İkili (A2DP Kaynak/Alıcı)"
#: spa/plugins/bluez5/bluez5-device.c:1823
#: spa/plugins/bluez5/bluez5-device.c:2146
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "Yüksek Kaliteli Çalma (BAP Alıcı, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1828
#: spa/plugins/bluez5/bluez5-device.c:2151
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "Yüksek Kaliteli Giriş (BAP Kaynak, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1832
#: spa/plugins/bluez5/bluez5-device.c:2155
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "Yüksek Kaliteli İkili (BAP Kaynak/Alıcı, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1841
#: spa/plugins/bluez5/bluez5-device.c:2164
msgid "High Fidelity Playback (BAP Sink)"
msgstr "Yüksek Kaliteli Çalma (BAP Alıcı)"
#: spa/plugins/bluez5/bluez5-device.c:1845
#: spa/plugins/bluez5/bluez5-device.c:2168
msgid "High Fidelity Input (BAP Source)"
msgstr "Yüksek Kaliteli Giriş (BAP Kaynak)"
#: spa/plugins/bluez5/bluez5-device.c:1848
#: spa/plugins/bluez5/bluez5-device.c:2171
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "Yüksek Kaliteli İkili (BAP Kaynak/Alıcı)"
#: spa/plugins/bluez5/bluez5-device.c:1897
#: spa/plugins/bluez5/bluez5-device.c:2211
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "Kulaklık Ana Birimi (HSP/HFP, çözücü %s)"
#: spa/plugins/bluez5/bluez5-device.c:1978
#: spa/plugins/bluez5/bluez5-device.c:1983
#: spa/plugins/bluez5/bluez5-device.c:1990
#: spa/plugins/bluez5/bluez5-device.c:1996
#: spa/plugins/bluez5/bluez5-device.c:2002
#: spa/plugins/bluez5/bluez5-device.c:2008
#: spa/plugins/bluez5/bluez5-device.c:2014
#: spa/plugins/bluez5/bluez5-device.c:2020
#: spa/plugins/bluez5/bluez5-device.c:2026
#: spa/plugins/bluez5/bluez5-device.c:2363
#: spa/plugins/bluez5/bluez5-device.c:2368
#: spa/plugins/bluez5/bluez5-device.c:2375
#: spa/plugins/bluez5/bluez5-device.c:2381
#: spa/plugins/bluez5/bluez5-device.c:2387
#: spa/plugins/bluez5/bluez5-device.c:2393
#: spa/plugins/bluez5/bluez5-device.c:2399
#: spa/plugins/bluez5/bluez5-device.c:2405
#: spa/plugins/bluez5/bluez5-device.c:2411
msgid "Handsfree"
msgstr "Ahizesiz"
#: spa/plugins/bluez5/bluez5-device.c:1984
#: spa/plugins/bluez5/bluez5-device.c:2369
msgid "Handsfree (HFP)"
msgstr "Ahizesiz (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2001
msgid "Headphone"
msgstr "Kulaklık"
#: spa/plugins/bluez5/bluez5-device.c:2007
#: spa/plugins/bluez5/bluez5-device.c:2392
msgid "Portable"
msgstr "Taşınabilir"
#: spa/plugins/bluez5/bluez5-device.c:2013
#: spa/plugins/bluez5/bluez5-device.c:2398
msgid "Car"
msgstr "Araba"
#: spa/plugins/bluez5/bluez5-device.c:2019
#: spa/plugins/bluez5/bluez5-device.c:2404
msgid "HiFi"
msgstr "Yüksek Kalite"
#: spa/plugins/bluez5/bluez5-device.c:2025
#: spa/plugins/bluez5/bluez5-device.c:2410
msgid "Phone"
msgstr "Telefon"
#: spa/plugins/bluez5/bluez5-device.c:2032
#: spa/plugins/bluez5/bluez5-device.c:2417
msgid "Bluetooth"
msgstr "Bluetooth"
#: spa/plugins/bluez5/bluez5-device.c:2033
#: spa/plugins/bluez5/bluez5-device.c:2418
msgid "Bluetooth (HFP)"
msgstr "Bluetooth (HFP)"

View file

@ -6,15 +6,15 @@
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012.
# Frank Hill <hxf.prc@gmail.com>, 2015.
# Mingye Wang (Arthur2e5) <arthur200126@gmail.com>, 2015.
# lumingzh <lumingzh@qq.com>, 2024.
# lumingzh <lumingzh@qq.com>, 2024-2025.
#
msgid ""
msgstr ""
"Project-Id-Version: pipewire.master-tx\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
"issues\n"
"POT-Creation-Date: 2024-09-09 16:36+0000\n"
"PO-Revision-Date: 2024-10-08 09:41+0800\n"
"POT-Creation-Date: 2025-09-21 15:33+0000\n"
"PO-Revision-Date: 2025-09-22 08:53+0800\n"
"Last-Translator: lumingzh <lumingzh@qq.com>\n"
"Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
@ -22,7 +22,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2016-03-22 13:23+0000\n"
"X-Generator: Gtranslator 47.0\n"
"X-Generator: Gtranslator 49.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: src/daemon/pipewire.c:29
@ -42,11 +42,11 @@ msgstr ""
" -c, --config 加载配置 (默认 %s)\n"
" -P --properties 设置上下文属性\n"
#: src/daemon/pipewire.desktop.in:4
#: src/daemon/pipewire.desktop.in:3
msgid "PipeWire Media System"
msgstr "PipeWire 多媒体系统"
#: src/daemon/pipewire.desktop.in:5
#: src/daemon/pipewire.desktop.in:4
msgid "Start the PipeWire Media System"
msgstr "启动 PipeWire 多媒体系统"
@ -60,26 +60,26 @@ msgstr "至 %s%s%s 的隧道"
msgid "Dummy Output"
msgstr "虚拟输出"
#: src/modules/module-pulse-tunnel.c:774
#: src/modules/module-pulse-tunnel.c:760
#, c-format
msgid "Tunnel for %s@%s"
msgstr "用于 %s@%s 的隧道"
#: src/modules/module-zeroconf-discover.c:318
#: src/modules/module-zeroconf-discover.c:320
msgid "Unknown device"
msgstr "未知设备"
#: src/modules/module-zeroconf-discover.c:330
#: src/modules/module-zeroconf-discover.c:332
#, c-format
msgid "%s on %s@%s"
msgstr "%2$s@%3$s 上的 %1$s"
#: src/modules/module-zeroconf-discover.c:334
#: src/modules/module-zeroconf-discover.c:336
#, c-format
msgid "%s on %s"
msgstr "%2$s 上的 %1$s"
#: src/tools/pw-cat.c:996
#: src/tools/pw-cat.c:1084
#, c-format
msgid ""
"%s [options] [<file>|-]\n"
@ -94,7 +94,7 @@ msgstr ""
" -v, --verbose 输出详细操作\n"
"\n"
#: src/tools/pw-cat.c:1003
#: src/tools/pw-cat.c:1091
#, c-format
msgid ""
" -R, --remote Remote daemon name\n"
@ -126,7 +126,7 @@ msgstr ""
" -P --properties 设置节点属性\n"
"\n"
#: src/tools/pw-cat.c:1021
#: src/tools/pw-cat.c:1109
#, c-format
msgid ""
" --rate Sample rate (req. for rec) (default "
@ -144,6 +144,9 @@ msgid ""
" -q --quality Resampler quality (0 - 15) (default "
"%d)\n"
" -a, --raw RAW mode\n"
" -M, --force-midi Force midi format, one of \"midi\" "
"or \"ump\", (default ump)\n"
" -n, --sample-count COUNT Stop after COUNT samples\n"
"\n"
msgstr ""
" --rate 采样率 (录制模式需要) (默认 %u)\n"
@ -151,22 +154,27 @@ msgstr ""
" --channel-map 通道映射\n"
" \"stereo\", \"surround-51\",... "
"中的其一或\n"
" 以\",\"分隔的通道名列表: 如 \"FL,"
"FR\"\n"
" 以\",\"分隔的通道名列表: 如 "
"\"FL,FR\"\n"
" --format 采样格式 %s (录制模式需要) (默认 "
"%s)\n"
" --volume 媒体流音量 0-1.0 (默认 %.3f)\n"
" -q --quality 重采样质量 (0 - 15) (默认 %d)\n"
" -a, --raw 原生模式\n"
" -M, --force-midi 强制 midi 格式,\"midi\" 或 \"ump\" "
"其一 (默认 ump)\n"
" -n, --sample-count COUNT 计数采样后停止\n"
"\n"
#: src/tools/pw-cat.c:1039
#: src/tools/pw-cat.c:1129
msgid ""
" -p, --playback Playback mode\n"
" -r, --record Recording mode\n"
" -m, --midi Midi mode\n"
" -d, --dsd DSD mode\n"
" -o, --encoded Encoded mode\n"
" -s, --sysex SysEx mode\n"
" -c, --midi-clip MIDI clip mode\n"
"\n"
msgstr ""
" -p, --playback 回放模式\n"
@ -174,9 +182,11 @@ msgstr ""
" -m, --midi Midi 模式\n"
" -d, --dsd DSD 模式\n"
" -o, --encoded 编码模式\n"
" -s, --sysex SysEx 模式\n"
" -c, --midi-clip MIDI 剪辑模式\n"
"\n"
#: src/tools/pw-cli.c:2285
#: src/tools/pw-cli.c:2386
#, c-format
msgid ""
"%s [options] [command]\n"
@ -194,15 +204,20 @@ msgstr ""
" -m, --monitor 监视器活动\n"
"\n"
#: spa/plugins/alsa/acp/acp.c:327
#: spa/plugins/alsa/acp/acp.c:351
msgid "Pro Audio"
msgstr "专业音频"
#: spa/plugins/alsa/acp/acp.c:488 spa/plugins/alsa/acp/alsa-mixer.c:4633
#: spa/plugins/bluez5/bluez5-device.c:1701
#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635
#: spa/plugins/bluez5/bluez5-device.c:1974
msgid "Off"
msgstr "关"
#: spa/plugins/alsa/acp/acp.c:610
#, c-format
msgid "%s [ALSA UCM error]"
msgstr "%s [ALSA UCM 错误]"
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
msgid "Input"
msgstr "输入"
@ -226,7 +241,7 @@ msgstr "输入插孔"
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
#: spa/plugins/bluez5/bluez5-device.c:1989
#: spa/plugins/bluez5/bluez5-device.c:2372
msgid "Microphone"
msgstr "话筒"
@ -292,12 +307,15 @@ msgid "No Bass Boost"
msgstr "无重低音增强"
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
#: spa/plugins/bluez5/bluez5-device.c:1995
#: spa/plugins/bluez5/bluez5-device.c:2378
msgid "Speaker"
msgstr "扬声器"
#. Don't call it "headset", the HF one has the mic
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
#: spa/plugins/bluez5/bluez5-device.c:2384
#: spa/plugins/bluez5/bluez5-device.c:2451
msgid "Headphones"
msgstr "模拟耳机"
@ -374,15 +392,15 @@ msgstr "语音输入"
msgid "Virtual Surround 7.1"
msgstr "虚拟环绕 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4456
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
msgid "Analog Mono"
msgstr "模拟单声道"
#: spa/plugins/alsa/acp/alsa-mixer.c:4457
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
msgid "Analog Mono (Left)"
msgstr "模拟单声道 (左声道)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
msgid "Analog Mono (Right)"
msgstr "模拟单声道 (右声道)"
@ -391,147 +409,147 @@ msgstr "模拟单声道 (右声道)"
#. * here would lead to the source name to become "Analog Stereo Input
#. * Input". The same logic applies to analog-stereo-output,
#. * multichannel-input and multichannel-output.
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
#: spa/plugins/alsa/acp/alsa-mixer.c:4467
#: spa/plugins/alsa/acp/alsa-mixer.c:4468
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
msgid "Analog Stereo"
msgstr "模拟立体声"
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
#: spa/plugins/alsa/acp/alsa-mixer.c:4462
msgid "Mono"
msgstr "单声道"
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
#: spa/plugins/alsa/acp/alsa-mixer.c:4463
msgid "Stereo"
msgstr "立体声"
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
#: spa/plugins/bluez5/bluez5-device.c:1977
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/bluez5/bluez5-device.c:2360
msgid "Headset"
msgstr "耳机"
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
msgid "Speakerphone"
msgstr "扬声麦克风"
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
msgid "Multichannel"
msgstr "多声道"
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
msgid "Analog Surround 2.1"
msgstr "模拟环绕 2.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
msgid "Analog Surround 3.0"
msgstr "模拟环绕 3.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
msgid "Analog Surround 3.1"
msgstr "模拟环绕 3.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
msgid "Analog Surround 4.0"
msgstr "模拟环绕 4.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
msgid "Analog Surround 4.1"
msgstr "模拟环绕 4.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
msgid "Analog Surround 5.0"
msgstr "模拟环绕 5.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
msgid "Analog Surround 5.1"
msgstr "模拟环绕 5.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
msgid "Analog Surround 6.0"
msgstr "模拟环绕 6.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
msgid "Analog Surround 6.1"
msgstr "模拟环绕 6.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
msgid "Analog Surround 7.0"
msgstr "模拟环绕 7.0"
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
msgid "Analog Surround 7.1"
msgstr "模拟环绕 7.1"
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
msgid "Digital Stereo (IEC958)"
msgstr "数字立体声 (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "数字环绕 4.0 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "数字环绕 5.1 (IEC958/AC3)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "数字环绕 5.1 (IEC958/DTS)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
msgid "Digital Stereo (HDMI)"
msgstr "数字立体声 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
msgid "Digital Surround 5.1 (HDMI)"
msgstr "数字环绕 5.1 (HDMI)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
msgid "Chat"
msgstr "语音"
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
msgid "Game"
msgstr "游戏"
#: spa/plugins/alsa/acp/alsa-mixer.c:4625
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
msgid "Analog Mono Duplex"
msgstr "模拟单声道双工"
#: spa/plugins/alsa/acp/alsa-mixer.c:4626
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
msgid "Analog Stereo Duplex"
msgstr "模拟立体声双工"
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
msgid "Digital Stereo Duplex (IEC958)"
msgstr "数字立体声双工 (IEC958)"
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
msgid "Multichannel Duplex"
msgstr "多声道双工"
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
#: spa/plugins/alsa/acp/alsa-mixer.c:4633
msgid "Stereo Duplex"
msgstr "模拟立体声双工"
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
#: spa/plugins/alsa/acp/alsa-mixer.c:4634
msgid "Mono Chat + 7.1 Surround"
msgstr "单声道语音 + 7.1 环绕声"
#: spa/plugins/alsa/acp/alsa-mixer.c:4733
#: spa/plugins/alsa/acp/alsa-mixer.c:4735
#, c-format
msgid "%s Output"
msgstr "%s 输出"
#: spa/plugins/alsa/acp/alsa-mixer.c:4741
#: spa/plugins/alsa/acp/alsa-mixer.c:4743
#, c-format
msgid "%s Input"
msgstr "%s 输入"
#: spa/plugins/alsa/acp/alsa-util.c:1231 spa/plugins/alsa/acp/alsa-util.c:1325
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
#, c-format
msgid ""
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
@ -547,7 +565,7 @@ msgstr[0] ""
"snd_pcm_avail() 返回的值非常大:%lu 字节(%lu 毫秒)。\n"
"这很可能是由 ALSA 驱动程序 %s 的缺陷导致的。请向 ALSA 开发者报告这个问题。"
#: spa/plugins/alsa/acp/alsa-util.c:1297
#: spa/plugins/alsa/acp/alsa-util.c:1299
#, c-format
msgid ""
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
@ -563,7 +581,7 @@ msgstr[0] ""
"snd_pcm_delay() 返回的值非常大:%li 字节(%s%lu 毫秒)。\n"
"这很可能是由 ALSA 驱动程序 %s 的缺陷导致的。请向 ALSA 开发者报告这个问题。"
#: spa/plugins/alsa/acp/alsa-util.c:1344
#: spa/plugins/alsa/acp/alsa-util.c:1346
#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
@ -574,7 +592,7 @@ msgstr ""
"snd_pcm_avail_delay() 返回的值非常很奇怪:延迟 %lu 小于可用 (avail) %lu。\n"
"这很可能是由 ALSA 驱动程序 %s 的缺陷导致的。请向 ALSA 开发者报告这个问题。"
#: spa/plugins/alsa/acp/alsa-util.c:1387
#: spa/plugins/alsa/acp/alsa-util.c:1389
#, c-format
msgid ""
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
@ -594,111 +612,114 @@ msgstr[0] ""
msgid "(invalid)"
msgstr "(无效)"
#: spa/plugins/alsa/acp/compat.c:193
#: spa/plugins/alsa/acp/compat.c:194
msgid "Built-in Audio"
msgstr "内置音频"
#: spa/plugins/alsa/acp/compat.c:198
#: spa/plugins/alsa/acp/compat.c:199
msgid "Modem"
msgstr "调制解调器"
#: spa/plugins/bluez5/bluez5-device.c:1712
#: spa/plugins/bluez5/bluez5-device.c:1985
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
msgstr "音频网关 (A2DP 信源 或 HSP/HFP 网关)"
#: spa/plugins/bluez5/bluez5-device.c:1760
#: spa/plugins/bluez5/bluez5-device.c:2014
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
msgstr "助听器音频流 (ASHA 信宿)"
#: spa/plugins/bluez5/bluez5-device.c:2057
#, c-format
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
msgstr "高保真回放 (A2DP 信宿, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1763
#: spa/plugins/bluez5/bluez5-device.c:2060
#, c-format
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
msgstr "高保真双工 (A2DP 信源/信宿, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1771
#: spa/plugins/bluez5/bluez5-device.c:2068
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "高保真回放 (A2DP 信宿)"
#: spa/plugins/bluez5/bluez5-device.c:1773
#: spa/plugins/bluez5/bluez5-device.c:2070
msgid "High Fidelity Duplex (A2DP Source/Sink)"
msgstr "高保真双工 (A2DP 信源/信宿)"
#: spa/plugins/bluez5/bluez5-device.c:1823
#: spa/plugins/bluez5/bluez5-device.c:2144
#, c-format
msgid "High Fidelity Playback (BAP Sink, codec %s)"
msgstr "高保真回放 (BAP 信宿, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1828
#: spa/plugins/bluez5/bluez5-device.c:2149
#, c-format
msgid "High Fidelity Input (BAP Source, codec %s)"
msgstr "高保真输入 (BAP 信源, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1832
#: spa/plugins/bluez5/bluez5-device.c:2153
#, c-format
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
msgstr "高保真双工 (BAP 信源/信宿, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1841
#: spa/plugins/bluez5/bluez5-device.c:2162
msgid "High Fidelity Playback (BAP Sink)"
msgstr "高保真回放 (BAP 信宿)"
#: spa/plugins/bluez5/bluez5-device.c:1845
#: spa/plugins/bluez5/bluez5-device.c:2166
msgid "High Fidelity Input (BAP Source)"
msgstr "高保真输入 (BAP 信源)"
#: spa/plugins/bluez5/bluez5-device.c:1848
#: spa/plugins/bluez5/bluez5-device.c:2169
msgid "High Fidelity Duplex (BAP Source/Sink)"
msgstr "高保真双工 (BAP 信源/信宿)"
#: spa/plugins/bluez5/bluez5-device.c:1897
#: spa/plugins/bluez5/bluez5-device.c:2209
#, c-format
msgid "Headset Head Unit (HSP/HFP, codec %s)"
msgstr "头戴式耳机单元 (HSP/HFP, 编码 %s)"
#: spa/plugins/bluez5/bluez5-device.c:1978
#: spa/plugins/bluez5/bluez5-device.c:1983
#: spa/plugins/bluez5/bluez5-device.c:1990
#: spa/plugins/bluez5/bluez5-device.c:1996
#: spa/plugins/bluez5/bluez5-device.c:2002
#: spa/plugins/bluez5/bluez5-device.c:2008
#: spa/plugins/bluez5/bluez5-device.c:2014
#: spa/plugins/bluez5/bluez5-device.c:2020
#: spa/plugins/bluez5/bluez5-device.c:2026
#: spa/plugins/bluez5/bluez5-device.c:2361
#: spa/plugins/bluez5/bluez5-device.c:2366
#: spa/plugins/bluez5/bluez5-device.c:2373
#: spa/plugins/bluez5/bluez5-device.c:2379
#: spa/plugins/bluez5/bluez5-device.c:2385
#: spa/plugins/bluez5/bluez5-device.c:2391
#: spa/plugins/bluez5/bluez5-device.c:2397
#: spa/plugins/bluez5/bluez5-device.c:2403
#: spa/plugins/bluez5/bluez5-device.c:2409
msgid "Handsfree"
msgstr "免手操作"
#: spa/plugins/bluez5/bluez5-device.c:1984
#: spa/plugins/bluez5/bluez5-device.c:2367
msgid "Handsfree (HFP)"
msgstr "免手操作 (HFP)"
#: spa/plugins/bluez5/bluez5-device.c:2001
msgid "Headphone"
msgstr "头戴耳机"
#: spa/plugins/bluez5/bluez5-device.c:2007
#: spa/plugins/bluez5/bluez5-device.c:2390
msgid "Portable"
msgstr "便携式"
#: spa/plugins/bluez5/bluez5-device.c:2013
#: spa/plugins/bluez5/bluez5-device.c:2396
msgid "Car"
msgstr "车内"
#: spa/plugins/bluez5/bluez5-device.c:2019
#: spa/plugins/bluez5/bluez5-device.c:2402
msgid "HiFi"
msgstr "高保真"
#: spa/plugins/bluez5/bluez5-device.c:2025
#: spa/plugins/bluez5/bluez5-device.c:2408
msgid "Phone"
msgstr "电话"
#: spa/plugins/bluez5/bluez5-device.c:2032
#: spa/plugins/bluez5/bluez5-device.c:2415
msgid "Bluetooth"
msgstr "蓝牙"
#: spa/plugins/bluez5/bluez5-device.c:2033
#: spa/plugins/bluez5/bluez5-device.c:2416
msgid "Bluetooth (HFP)"
msgstr "蓝牙 (HFP)"
#~ msgid "Headphone"
#~ msgstr "头戴耳机"
#~ msgid "Headset Head Unit (HSP/HFP)"
#~ msgstr "头戴式耳机单元 (HSP/HFP)"

View file

@ -53,6 +53,7 @@ export ALSA_PLUGIN_DIR="${BUILDDIR}/pipewire-alsa/alsa-plugins"
export PW_BUILDDIR=$BUILDDIR
export PW_UNINSTALLED=1
export PKG_CONFIG_PATH="${BUILDDIR}/meson-uninstalled/:${PKG_CONFIG_PATH}"
export PIPEWIRE_LOG_SYSTEMD=false
if [ -d "${BUILDDIR}/subprojects/wireplumber" ]; then
# FIXME: find a nice, shell-neutral way to specify a prompt

View file

@ -578,7 +578,7 @@ static int make_nodes(struct data *data)
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_OUTPUT),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
if ((res = spa_node_set_param(data->source_node, SPA_PARAM_PortConfig, 0, param) < 0)) {
if ((res = spa_node_set_param(data->source_node, SPA_PARAM_PortConfig, 0, param)) < 0) {
printf("can't setup source node %d\n", res);
return res;
}
@ -647,7 +647,7 @@ static int make_nodes(struct data *data)
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param) < 0)) {
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param)) < 0) {
printf("can't setup sink node %d\n", res);
return res;
}
@ -987,7 +987,7 @@ int main(int argc, char *argv[])
setlocale(LC_ALL, "");
while ((c = getopt_long(argc, argv, "hdmstiac:", long_options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "hd:m:s:t:i:a:c:", long_options, NULL)) != -1) {
switch (c) {
case 'h':
show_help(&data, argv[0], false);

View file

@ -24,6 +24,7 @@
#include <SDL2/SDL.h>
#include <spa/support/plugin.h>
#include <spa/utils/keys.h>
#include <spa/utils/names.h>
#include <spa/utils/result.h>
#include <spa/utils/string.h>
@ -83,7 +84,8 @@ struct data {
unsigned int n_buffers;
};
static int load_handle(struct data *data, struct spa_handle **handle, const char *lib, const char *name)
static int load_handle(struct data *data, struct spa_handle **handle, const char *lib, const char *name,
const struct spa_dict *params)
{
int res;
void *hnd;
@ -117,9 +119,9 @@ static int load_handle(struct data *data, struct spa_handle **handle, const char
if (!spa_streq(factory->name, name))
continue;
*handle = calloc(1, spa_handle_factory_get_size(factory, NULL));
*handle = calloc(1, spa_handle_factory_get_size(factory, params));
if ((res = spa_handle_factory_init(factory, *handle,
NULL, data->support,
params, data->support,
data->n_support)) < 0) {
printf("can't make factory instance: %d\n", res);
return res;
@ -129,13 +131,14 @@ static int load_handle(struct data *data, struct spa_handle **handle, const char
return -EBADF;
}
static int make_node(struct data *data, struct spa_node **node, const char *lib, const char *name)
static int make_node(struct data *data, struct spa_node **node, const char *lib, const char *name,
const struct spa_dict *params)
{
struct spa_handle *handle = NULL;
void *iface;
int res;
if ((res = load_handle(data, &handle, lib, name)) < 0)
if ((res = load_handle(data, &handle, lib, name, params)) < 0)
return res;
if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Node, &iface)) < 0) {
@ -237,10 +240,13 @@ static int make_nodes(struct data *data, const char *device)
uint8_t buffer[256];
uint32_t index;
if ((res =
make_node(data, &data->source,
"libcamera/libspa-libcamera.so",
SPA_NAME_API_LIBCAMERA_SOURCE)) < 0) {
const struct spa_dict_item items[] = {
{ SPA_KEY_API_LIBCAMERA_PATH, device },
};
if ((res = make_node(data, &data->source,
"libcamera/libspa-libcamera.so", SPA_NAME_API_LIBCAMERA_SOURCE,
&SPA_DICT_INIT_ARRAY(items))) < 0) {
printf("can't create libcamera-source: %d\n", res);
return res;
}
@ -254,14 +260,6 @@ static int make_nodes(struct data *data, const char *device)
spa_debug_pod(0, NULL, props);
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_device, SPA_POD_String(device ? device : "/dev/media0"));
if ((res = spa_node_set_param(data->source, SPA_PARAM_Props, 0, props)) < 0)
printf("got set_props error %d\n", res);
return res;
}
@ -442,13 +440,18 @@ int main(int argc, char *argv[])
struct spa_handle *handle = NULL;
void *iface;
if (argc < 2) {
printf("usage: %s <camera-id>\n", argv[0]);
return EXIT_FAILURE;
}
if ((str = getenv("SPA_PLUGIN_DIR")) == NULL)
str = PLUGINDIR;
data.plugin_dir = str;
if ((res = load_handle(&data, &handle,
"support/libspa-support.so",
SPA_NAME_SUPPORT_SYSTEM)) < 0)
SPA_NAME_SUPPORT_SYSTEM, NULL)) < 0)
return res;
if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_System, &iface)) < 0) {
@ -460,7 +463,7 @@ int main(int argc, char *argv[])
if ((res = load_handle(&data, &handle,
"support/libspa-support.so",
SPA_NAME_SUPPORT_LOOP)) < 0)
SPA_NAME_SUPPORT_LOOP, NULL)) < 0)
return res;
if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Loop, &iface)) < 0) {

View file

@ -5,12 +5,12 @@
#ifndef SPA_BUFFER_ALLOC_H
#define SPA_BUFFER_ALLOC_H
#include <spa/buffer/buffer.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/buffer/buffer.h>
#ifndef SPA_API_BUFFER_ALLOC
#ifdef SPA_API_IMPL
#define SPA_API_BUFFER_ALLOC SPA_API_IMPL
@ -122,7 +122,7 @@ SPA_API_BUFFER_ALLOC int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info
* | | uint32_t offset |
* | | uint32_t size |
* | | int32_t stride |
* | | int32_t dummy |
* | | int32_t flags |
* | | ... <n_datas> chunks |
* | +------------------------------+
* +>| data | memory for n_datas data, aligned

View file

@ -5,13 +5,13 @@
#ifndef SPA_BUFFER_H
#define SPA_BUFFER_H
#include <spa/utils/defs.h>
#include <spa/buffer/meta.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/defs.h>
#include <spa/buffer/meta.h>
#ifndef SPA_API_BUFFER
#ifdef SPA_API_IMPL
#define SPA_API_BUFFER SPA_API_IMPL
@ -118,6 +118,17 @@ SPA_API_BUFFER void *spa_buffer_find_meta_data(const struct spa_buffer *b, uint3
return NULL;
}
SPA_API_BUFFER bool spa_buffer_has_meta_features(const struct spa_buffer *b, uint32_t type, uint32_t features)
{
uint32_t i;
for (i = 0; i < b->n_metas; i++) {
uint32_t t = b->metas[i].type;
if ((t >> 16) == type && (t & features) == features)
return true;
}
return false;
}
/**
* \}
*/

View file

@ -5,13 +5,13 @@
#ifndef SPA_META_H
#define SPA_META_H
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
#ifndef SPA_API_META
#ifdef SPA_API_IMPL
#define SPA_API_META SPA_API_IMPL
@ -37,10 +37,17 @@ enum spa_meta_type {
SPA_META_Busy, /**< don't write to buffer when count > 0 */
SPA_META_VideoTransform, /**< struct spa_meta_transform */
SPA_META_SyncTimeline, /**< struct spa_meta_sync_timeline */
_SPA_META_LAST, /**< not part of ABI/API */
SPA_META_START_custom = 0x200,
SPA_META_START_features = 0x10000, /* features start, these have 0 size, the
* type in the upper 16 bits and a bitmask in
* the lower 16 bits with type specific features. */
};
#define SPA_META_TYPE_FEATURES(type,features) (((type)<<16)|(features))
/**
* A metadata element.
*
@ -183,7 +190,12 @@ struct spa_meta_videotransform {
* this metadata as SPA_PARAM_BUFFERS_metaType when negotiating a buffer
* layout with 2 extra fds.
*/
#define SPA_META_FEATURE_SYNC_TIMELINE_RELEASE (1<<0) /**< metadata supports RELEASE */
struct spa_meta_sync_timeline {
#define SPA_META_SYNC_TIMELINE_UNSCHEDULED_RELEASE (1<<0) /**< this flag is set by the producer and cleared
* by the consumer when it promises to signal
* the release point */
uint32_t flags;
uint32_t padding;
uint64_t acquire_point; /**< the timeline acquire point, this is when the data

View file

@ -5,6 +5,10 @@
#ifndef SPA_BUFFER_TYPES_H
#define SPA_BUFFER_TYPES_H
#include <spa/buffer/buffer.h>
#include <spa/buffer/meta.h>
#include <spa/utils/type.h>
/**
* \addtogroup spa_buffer
* \{
@ -14,10 +18,6 @@
extern "C" {
#endif
#include <spa/buffer/buffer.h>
#include <spa/buffer/meta.h>
#include <spa/utils/type.h>
#define SPA_TYPE_INFO_Buffer SPA_TYPE_INFO_POINTER_BASE "Buffer"
#define SPA_TYPE_INFO_BUFFER_BASE SPA_TYPE_INFO_Buffer ":"

View file

@ -5,13 +5,13 @@
#ifndef SPA_CONTROL_H
#define SPA_CONTROL_H
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
/** \defgroup spa_control Control
* Control type declarations
*/

View file

@ -5,6 +5,10 @@
#ifndef SPA_CONTROL_TYPES_H
#define SPA_CONTROL_TYPES_H
#include <spa/utils/defs.h>
#include <spa/utils/type.h>
#include <spa/control/control.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,10 +18,6 @@ extern "C" {
* \{
*/
#include <spa/utils/defs.h>
#include <spa/utils/type.h>
#include <spa/control/control.h>
/* base for parameter object enumerations */
#define SPA_TYPE_INFO_Control SPA_TYPE_INFO_ENUM_BASE "Control"
#define SPA_TYPE_INFO_CONTROL_BASE SPA_TYPE_INFO_Control ":"

View file

@ -6,13 +6,13 @@
#ifndef SPA_CONTROL_UMP_UTILS_H
#define SPA_CONTROL_UMP_UTILS_H
#include <errno.h>
#include <spa/utils/defs.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <spa/utils/defs.h>
#ifndef SPA_API_CONTROL_UMP_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_CONTROL_UMP_UTILS SPA_API_IMPL
@ -48,64 +48,98 @@ SPA_API_CONTROL_UMP_UTILS size_t spa_ump_message_size(uint8_t message_type)
return ump_sizes[message_type & 0xf];
}
SPA_API_CONTROL_UMP_UTILS int spa_ump_to_midi(uint32_t *ump, size_t ump_size,
uint8_t *midi, size_t midi_maxsize)
SPA_API_CONTROL_UMP_UTILS int spa_ump_to_midi(const uint32_t **ump, size_t *ump_size,
uint8_t *midi, size_t midi_maxsize, uint64_t *state)
{
int size = 0;
uint32_t to_consume = 0;
const uint32_t *u = *ump;
if (ump_size < 4)
return 0;
if (*ump_size < 4 ||
(to_consume = (spa_ump_message_size(u[0]>>28) * 4)) > *ump_size) {
to_consume = *ump_size;
goto done;
}
if (midi_maxsize < 8)
return -ENOSPC;
switch (ump[0] >> 28) {
switch (u[0] >> 28) {
case 0x1: /* System Real Time and System Common Messages (except System Exclusive) */
midi[size++] = (ump[0] >> 16) & 0xff;
midi[size++] = (u[0] >> 16) & 0xff;
if (midi[0] >= 0xf1 && midi[0] <= 0xf3) {
midi[size++] = (ump[0] >> 8) & 0x7f;
midi[size++] = (u[0] >> 8) & 0x7f;
if (midi[0] == 0xf2)
midi[size++] = ump[0] & 0x7f;
midi[size++] = u[0] & 0x7f;
}
break;
case 0x2: /* MIDI 1.0 Channel Voice Messages */
midi[size++] = (ump[0] >> 16);
midi[size++] = (ump[0] >> 8);
midi[size++] = (u[0] >> 16);
midi[size++] = (u[0] >> 8);
if (midi[0] < 0xc0 || midi[0] > 0xdf)
midi[size++] = (ump[0]);
midi[size++] = (u[0]);
break;
case 0x3: /* Data Messages (including System Exclusive) */
{
uint8_t status, i, bytes;
if (ump_size < 8)
return 0;
status = (ump[0] >> 20) & 0xf;
bytes = SPA_CLAMP((ump[0] >> 16) & 0xf, 0u, 6u);
status = (u[0] >> 20) & 0xf;
bytes = SPA_CLAMP((u[0] >> 16) & 0xf, 0u, 6u);
if (status == 0 || status == 1)
midi[size++] = 0xf0;
for (i = 0 ; i < bytes; i++)
/* ump[0] >> 8 | ump[0] | ump[1] >> 24 | ump[1] >>16 ... */
midi[size++] = ump[(i+2)/4] >> ((5-i)%4 * 8);
/* u[0] >> 8 | u[0] | u[1] >> 24 | u[1] >>16 ... */
midi[size++] = u[(i+2)/4] >> ((5-i)%4 * 8);
if (status == 0 || status == 3)
midi[size++] = 0xf7;
break;
}
case 0x4: /* MIDI 2.0 Channel Voice Messages */
if (ump_size < 8)
return 0;
midi[size++] = (ump[0] >> 16) | 0x80;
if (midi[0] < 0xc0 || midi[0] > 0xdf)
midi[size++] = (ump[0] >> 8) & 0x7f;
midi[size++] = (ump[1] >> 25);
{
uint8_t status = (u[0] >> 16) | 0x80;
switch (status & 0xf0) {
case 0xc0:
/* program/bank change */
if (!(u[0] & 1))
*state = 2;
if (*state == 0) {
midi[size++] = (status & 0xf) | 0xb0;
midi[size++] = 0;
midi[size++] = (u[1] >> 8);
to_consume = 0;
*state = 1;
}
else if (*state == 1) {
midi[size++] = (status & 0xf) | 0xb0;
midi[size++] = 32;
midi[size++] = u[1];
to_consume = 0;
*state = 2;
}
else if (*state == 2) {
midi[size++] = status;
midi[size++] = (u[1] >> 24);
*state = 0;
}
break;
default:
midi[size++] = status;
midi[size++] = (u[0] >> 8) & 0x7f;
SPA_FALLTHROUGH;
case 0xd0:
midi[size++] = (u[1] >> 25);
break;
}
break;
}
case 0x0: /* Utility Messages */
case 0x5: /* Data Messages */
default:
return 0;
break;
}
done:
(*ump_size) -= to_consume;
(*ump) = SPA_PTROFF(*ump, to_consume, uint32_t);
return size;
}
@ -189,15 +223,15 @@ SPA_API_CONTROL_UMP_UTILS int spa_ump_from_midi(uint8_t **midi, size_t *midi_siz
break;
case 0xf2:
to_consume = 3;
prefix = 0x10000000;
prefix |= 0x10000000;
break;
case 0xf1: case 0xf3:
to_consume = 2;
prefix = 0x10000000;
prefix |= 0x10000000;
break;
case 0xf4 ... 0xff:
to_consume = 1;
prefix = 0x10000000;
prefix |= 0x10000000;
break;
default:
return -EIO;

View file

@ -5,6 +5,11 @@
#ifndef SPA_DEBUG_BUFFER_H
#define SPA_DEBUG_BUFFER_H
#include <spa/debug/context.h>
#include <spa/debug/mem.h>
#include <spa/debug/types.h>
#include <spa/buffer/type-info.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -18,11 +23,6 @@ extern "C" {
* \{
*/
#include <spa/debug/context.h>
#include <spa/debug/mem.h>
#include <spa/debug/types.h>
#include <spa/buffer/type-info.h>
#ifndef SPA_API_DEBUG_BUFFER
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_BUFFER SPA_API_IMPL

View file

@ -5,15 +5,16 @@
#ifndef SPA_DEBUG_CONTEXT_H
#define SPA_DEBUG_CONTEXT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <spa/utils/defs.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_debug
* \{

View file

@ -5,6 +5,9 @@
#ifndef SPA_DEBUG_DICT_H
#define SPA_DEBUG_DICT_H
#include <spa/debug/context.h>
#include <spa/utils/dict.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,9 +17,6 @@ extern "C" {
* \{
*/
#include <spa/debug/context.h>
#include <spa/utils/dict.h>
#ifndef SPA_API_DEBUG_DICT
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_DICT SPA_API_IMPL

View file

@ -5,10 +5,6 @@
#ifndef SPA_DEBUG_FILE_H
#define SPA_DEBUG_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
@ -21,6 +17,10 @@ extern "C" {
#include <spa/debug/mem.h>
#include <spa/debug/pod.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_debug
* \{

View file

@ -5,6 +5,15 @@
#ifndef SPA_DEBUG_FORMAT_H
#define SPA_DEBUG_FORMAT_H
#include <inttypes.h>
#include <spa/pod/iter.h>
#include <spa/utils/string.h>
#include <spa/debug/context.h>
#include <spa/debug/types.h>
#include <spa/param/type-info.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,13 +23,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/utils/string.h>
#include <spa/debug/context.h>
#include <spa/debug/types.h>
#include <spa/param/type-info.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_DEBUG_FORMAT
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_FORMAT SPA_API_IMPL
@ -41,10 +43,11 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
break;
case SPA_TYPE_Id:
{
const char *str = spa_debug_type_find_short_name(info, *(int32_t *) body);
uint32_t value = *(uint32_t *) body;
const char *str = spa_debug_type_find_short_name(info, value);
char tmp[64];
if (str == NULL) {
snprintf(tmp, sizeof(tmp), "%d", *(int32_t*)body);
snprintf(tmp, sizeof(tmp), "%" PRIu32, value);
str = tmp;
}
spa_strbuf_append(buffer, "%s", str);
@ -63,7 +66,7 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
spa_strbuf_append(buffer, "%f", *(double *) body);
break;
case SPA_TYPE_String:
spa_strbuf_append(buffer, "%s", (char *) body);
spa_strbuf_append(buffer, "%-*s", size, (char *) body);
break;
case SPA_TYPE_Rectangle:
{
@ -90,10 +93,12 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
int i = 0;
info = info && info->values ? info->values : info;
spa_strbuf_append(buffer, "< ");
SPA_POD_ARRAY_BODY_FOREACH(b, size, p) {
if (i++ > 0)
spa_strbuf_append(buffer, ", ");
spa_debug_strbuf_format_value(buffer, info, b->child.type, p, b->child.size);
if (b->child.size >= spa_pod_type_size(b->child.type)) {
SPA_POD_ARRAY_BODY_FOREACH(b, size, p) {
if (i++ > 0)
spa_strbuf_append(buffer, ", ");
spa_debug_strbuf_format_value(buffer, info, b->child.type, p, b->child.size);
}
}
spa_strbuf_append(buffer, " >");
break;
@ -128,7 +133,7 @@ SPA_API_DEBUG_FORMAT int spa_debugc_format(struct spa_debug_context *ctx, int in
if (info == NULL)
info = spa_type_format;
if (format == NULL || SPA_POD_TYPE(format) != SPA_TYPE_Object)
if (format == NULL || format->type != SPA_TYPE_Object)
return -EINVAL;
if (spa_format_parse(format, &mtype, &mstype) < 0)
@ -158,11 +163,12 @@ SPA_API_DEBUG_FORMAT int spa_debugc_format(struct spa_debug_context *ctx, int in
type = val->type;
size = val->size;
vals = SPA_POD_BODY(val);
if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST)
if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1 ||
size < spa_pod_type_size(type))
continue;
vals = SPA_POD_BODY(val);
ti = spa_debug_type_find(info, prop->key);
key = ti ? ti->name : NULL;

View file

@ -5,10 +5,6 @@
#ifndef SPA_DEBUG_LOG_H
#define SPA_DEBUG_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdarg.h>
@ -20,6 +16,10 @@ extern "C" {
#include <spa/debug/mem.h>
#include <spa/debug/pod.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SPA_API_DEBUG_LOG
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_LOG SPA_API_IMPL

View file

@ -5,19 +5,19 @@
#ifndef SPA_DEBUG_MEM_H
#define SPA_DEBUG_MEM_H
#include <inttypes.h>
#include <spa/debug/context.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
/**
* \addtogroup spa_debug
* \{
*/
#include <spa/debug/context.h>
#ifndef SPA_API_DEBUG_MEM
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_MEM SPA_API_IMPL

View file

@ -5,6 +5,10 @@
#ifndef SPA_DEBUG_NODE_H
#define SPA_DEBUG_NODE_H
#include <spa/node/node.h>
#include <spa/debug/context.h>
#include <spa/debug/dict.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,10 +18,6 @@ extern "C" {
* \{
*/
#include <spa/node/node.h>
#include <spa/debug/context.h>
#include <spa/debug/dict.h>
#ifndef SPA_API_DEBUG_NODE
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_NODE SPA_API_IMPL

View file

@ -5,6 +5,14 @@
#ifndef SPA_DEBUG_POD_H
#define SPA_DEBUG_POD_H
#include <inttypes.h>
#include <spa/debug/context.h>
#include <spa/debug/mem.h>
#include <spa/debug/types.h>
#include <spa/pod/pod.h>
#include <spa/pod/iter.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,12 +22,6 @@ extern "C" {
* \{
*/
#include <spa/debug/context.h>
#include <spa/debug/mem.h>
#include <spa/debug/types.h>
#include <spa/pod/pod.h>
#include <spa/pod/iter.h>
#ifndef SPA_API_DEBUG_POD
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_POD SPA_API_IMPL
@ -37,11 +39,11 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
spa_debugc(ctx, "%*s" "Bool %s", indent, "", (*(int32_t *) body) ? "true" : "false");
break;
case SPA_TYPE_Id:
spa_debugc(ctx, "%*s" "Id %-8d (%s)", indent, "", *(int32_t *) body,
spa_debug_type_find_name(info, *(int32_t *) body));
spa_debugc(ctx, "%*s" "Id %-8" PRIu32 " (%s)", indent, "", *(uint32_t *) body,
spa_debug_type_find_name(info, *(uint32_t *) body));
break;
case SPA_TYPE_Int:
spa_debugc(ctx, "%*s" "Int %d", indent, "", *(int32_t *) body);
spa_debugc(ctx, "%*s" "Int %" PRId32, indent, "", *(int32_t *) body);
break;
case SPA_TYPE_Long:
spa_debugc(ctx, "%*s" "Long %" PRIi64 "", indent, "", *(int64_t *) body);
@ -85,13 +87,18 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
struct spa_pod_array_body *b = (struct spa_pod_array_body *)body;
void *p;
const struct spa_type_info *ti = spa_debug_type_find(SPA_TYPE_ROOT, b->child.type);
uint32_t min_size = spa_pod_type_size(b->child.type);
spa_debugc(ctx, "%*s" "Array: child.size %d, child.type %s", indent, "",
spa_debugc(ctx, "%*s" "Array: child.size %" PRIu32 ", child.type %s", indent, "",
b->child.size, ti ? ti->name : "unknown");
info = info && info->values ? info->values : info;
SPA_POD_ARRAY_BODY_FOREACH(b, size, p)
spa_debugc_pod_value(ctx, indent + 2, info, b->child.type, p, b->child.size);
if (b->child.size < min_size) {
spa_debugc(ctx, "%*s" " INVALID child.size < %" PRIu32, indent, "", min_size);
} else {
info = info && info->values ? info->values : info;
SPA_POD_ARRAY_BODY_FOREACH(b, size, p)
spa_debugc_pod_value(ctx, indent + 2, info, b->child.type, p, b->child.size);
}
break;
}
case SPA_TYPE_Choice:
@ -99,20 +106,31 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
struct spa_pod_choice_body *b = (struct spa_pod_choice_body *)body;
void *p;
const struct spa_type_info *ti = spa_debug_type_find(spa_type_choice, b->type);
uint32_t min_size = spa_pod_type_size(b->child.type);
spa_debugc(ctx, "%*s" "Choice: type %s, flags %08x %d %d", indent, "",
spa_debugc(ctx, "%*s" "Choice: type %s, flags %08" PRIx32 " %" PRIu32 " %" PRIu32, indent, "",
ti ? ti->name : "unknown", b->flags, size, b->child.size);
SPA_POD_CHOICE_BODY_FOREACH(b, size, p)
spa_debugc_pod_value(ctx, indent + 2, info, b->child.type, p, b->child.size);
if (b->child.size < min_size) {
spa_debugc(ctx, "%*s" "INVALID child.size < %" PRIu32, indent, "", min_size);
} else {
SPA_POD_CHOICE_BODY_FOREACH(b, size, p)
spa_debugc_pod_value(ctx, indent + 2, info, b->child.type, p, b->child.size);
}
break;
}
case SPA_TYPE_Struct:
{
struct spa_pod *b = (struct spa_pod *)body, *p;
spa_debugc(ctx, "%*s" "Struct: size %d", indent, "", size);
SPA_POD_FOREACH(b, size, p)
spa_debugc_pod_value(ctx, indent + 2, info, p->type, SPA_POD_BODY(p), p->size);
spa_debugc(ctx, "%*s" "Struct: size %" PRIu32, indent, "", size);
SPA_POD_FOREACH(b, size, p) {
uint32_t min_size = spa_pod_type_size(p->type);
if (p->size < min_size) {
spa_debugc(ctx, "%*s" "INVALID child.size < %" PRIu32, indent, "", min_size);
} else {
spa_debugc_pod_value(ctx, indent + 2, info, p->type, SPA_POD_BODY(p), p->size);
}
}
break;
}
case SPA_TYPE_Object:
@ -125,21 +143,37 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
ii = ti ? spa_debug_type_find(ti->values, 0) : NULL;
ii = ii ? spa_debug_type_find(ii->values, b->id) : NULL;
spa_debugc(ctx, "%*s" "Object: size %d, type %s (%d), id %s (%d)", indent, "", size,
ti ? ti->name : "unknown", b->type, ii ? ii->name : "unknown", b->id);
spa_debugc(ctx, "%*s" "Object: size %" PRIu32 ", type %s (%" PRIu32 "), id %s (%" PRIu32 ")",
indent, "", size, ti ? ti->name : "unknown", b->type, ii ? ii->name : "unknown", b->id);
info = ti ? ti->values : info;
SPA_POD_OBJECT_BODY_FOREACH(b, size, p) {
static const char custom_prefix[] = SPA_TYPE_INFO_PROPS_BASE "Custom:";
char custom_name[sizeof(custom_prefix) + 16];
const char *name = "unknown";
uint32_t min_size = spa_pod_type_size(p->value.type);
ii = spa_debug_type_find(info, p->key);
if (ii) {
name = ii->name;
} else if (p->key >= SPA_PROP_START_CUSTOM) {
snprintf(custom_name, sizeof(custom_name),
"%s%" PRIu32, custom_prefix, p->key - SPA_PROP_START_CUSTOM);
name = custom_name;
}
spa_debugc(ctx, "%*s" "Prop: key %s (%d), flags %08x", indent+2, "",
ii ? ii->name : "unknown", p->key, p->flags);
spa_debugc(ctx, "%*s" "Prop: key %s (%" PRIu32 "), flags %08" PRIx32,
indent+2, "", name, p->key, p->flags);
spa_debugc_pod_value(ctx, indent + 4, ii ? ii->values : NULL,
p->value.type,
SPA_POD_CONTENTS(struct spa_pod_prop, p),
p->value.size);
if (p->value.size < min_size) {
spa_debugc(ctx, "%*s" "INVALID value.size < %" PRIu32, indent, "", min_size);
} else {
spa_debugc_pod_value(ctx, indent + 4, ii ? ii->values : NULL,
p->value.type,
SPA_POD_CONTENTS(struct spa_pod_prop, p),
p->value.size);
}
}
break;
}
@ -151,19 +185,25 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
ti = spa_debug_type_find(info, b->unit);
spa_debugc(ctx, "%*s" "Sequence: size %d, unit %s", indent, "", size,
spa_debugc(ctx, "%*s" "Sequence: size %" PRIu32 ", unit %s", indent, "", size,
ti ? ti->name : "unknown");
SPA_POD_SEQUENCE_BODY_FOREACH(b, size, c) {
uint32_t min_size = spa_pod_type_size(c->value.type);
ii = spa_debug_type_find(spa_type_control, c->type);
spa_debugc(ctx, "%*s" "Control: offset %d, type %s", indent+2, "",
spa_debugc(ctx, "%*s" "Control: offset %" PRIu32 ", type %s", indent+2, "",
c->offset, ii ? ii->name : "unknown");
spa_debugc_pod_value(ctx, indent + 4, ii ? ii->values : NULL,
c->value.type,
SPA_POD_CONTENTS(struct spa_pod_control, c),
c->value.size);
if (c->value.size < min_size) {
spa_debugc(ctx, "%*s" "INVALID value.size < %" PRIu32, indent, "", min_size);
} else {
spa_debugc_pod_value(ctx, indent + 4, ii ? ii->values : NULL,
c->value.type,
SPA_POD_CONTENTS(struct spa_pod_control, c),
c->value.size);
}
}
break;
}
@ -176,7 +216,7 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
spa_debugc_mem(ctx, indent + 2, body, size);
break;
default:
spa_debugc(ctx, "%*s" "unhandled POD type %d", indent, "", type);
spa_debugc(ctx, "%*s" "unhandled POD type %" PRIu32, indent, "", type);
break;
}
return 0;
@ -185,10 +225,10 @@ spa_debugc_pod_value(struct spa_debug_context *ctx, int indent, const struct spa
SPA_API_DEBUG_POD int spa_debugc_pod(struct spa_debug_context *ctx, int indent,
const struct spa_type_info *info, const struct spa_pod *pod)
{
if (pod->size < spa_pod_type_size(pod->type))
return -EINVAL;
return spa_debugc_pod_value(ctx, indent, info ? info : SPA_TYPE_ROOT,
SPA_POD_TYPE(pod),
SPA_POD_BODY(pod),
SPA_POD_BODY_SIZE(pod));
pod->type, SPA_POD_BODY(pod), pod->size);
}
SPA_API_DEBUG_POD int

View file

@ -5,6 +5,10 @@
#ifndef SPA_DEBUG_TYPES_H
#define SPA_DEBUG_TYPES_H
#include <spa/utils/type-info.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,10 +18,6 @@ extern "C" {
* \{
*/
#include <spa/utils/type-info.h>
#include <string.h>
#ifndef SPA_API_DEBUG_TYPES
#ifdef SPA_API_IMPL
#define SPA_API_DEBUG_TYPES SPA_API_IMPL

View file

@ -5,16 +5,16 @@
#ifndef SPA_FILTER_GRAPH_H
#define SPA_FILTER_GRAPH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <spa/utils/defs.h>
#include <spa/utils/hook.h>
#include <spa/pod/builder.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SPA_API_FILTER_GRAPH
#ifdef SPA_API_IMPL
#define SPA_API_FILTER_GRAPH SPA_API_IMPL

View file

@ -5,6 +5,13 @@
#ifndef SPA_GRAPH_H
#define SPA_GRAPH_H
#include <spa/utils/atomic.h>
#include <spa/utils/defs.h>
#include <spa/utils/list.h>
#include <spa/utils/hook.h>
#include <spa/node/node.h>
#include <spa/node/io.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -18,13 +25,6 @@ extern "C" {
* \{
*/
#include <spa/utils/atomic.h>
#include <spa/utils/defs.h>
#include <spa/utils/list.h>
#include <spa/utils/hook.h>
#include <spa/node/node.h>
#include <spa/node/io.h>
#ifndef SPA_API_GRAPH
#ifdef SPA_API_IMPL
#define SPA_API_GRAPH SPA_API_IMPL

View file

@ -5,15 +5,15 @@
#ifndef SPA_DEVICE_H
#define SPA_DEVICE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/defs.h>
#include <spa/utils/hook.h>
#include <spa/utils/dict.h>
#include <spa/pod/event.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SPA_API_DEVICE
#ifdef SPA_API_IMPL
#define SPA_API_DEVICE SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_EVENT_DEVICE_H
#define SPA_EVENT_DEVICE_H
#include <spa/pod/event.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/pod/event.h>
/**
* \addtogroup spa_device
* \{

View file

@ -5,14 +5,14 @@
#ifndef SPA_DEVICE_TYPE_INFO_H
#define SPA_DEVICE_TYPE_INFO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/type-info.h>
#include <spa/monitor/event.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_device
* \{

View file

@ -5,13 +5,13 @@
#ifndef SPA_DEVICE_UTILS_H
#define SPA_DEVICE_UTILS_H
#include <spa/pod/builder.h>
#include <spa/monitor/device.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/pod/builder.h>
#include <spa/monitor/device.h>
#ifndef SPA_API_DEVICE_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_DEVICE_UTILS SPA_API_IMPL

View file

@ -5,6 +5,8 @@
#ifndef SPA_COMMAND_NODE_H
#define SPA_COMMAND_NODE_H
#include <spa/pod/command.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,8 +16,6 @@ extern "C" {
* \{
*/
#include <spa/pod/command.h>
/* object id of SPA_TYPE_COMMAND_Node */
enum spa_node_command {
SPA_NODE_COMMAND_Suspend, /**< suspend a node, this removes all configured
@ -36,12 +36,24 @@ enum spa_node_command {
SPA_NODE_COMMAND_ParamEnd, /**< end a transaction */
SPA_NODE_COMMAND_RequestProcess,/**< Sent to a driver when some other node emitted
* the RequestProcess event. */
SPA_NODE_COMMAND_User, /**< User defined command */
};
#define SPA_NODE_COMMAND_ID(cmd) SPA_COMMAND_ID(cmd, SPA_TYPE_COMMAND_Node)
#define SPA_NODE_COMMAND_INIT(id) SPA_COMMAND_INIT(SPA_TYPE_COMMAND_Node, id)
/* properties for SPA_TYPE_COMMAND_Node */
enum spa_command_node {
SPA_COMMAND_NODE_START,
SPA_COMMAND_NODE_START_User = 0x1000,
SPA_COMMAND_NODE_extra, /** extra info (String) */
SPA_COMMAND_NODE_START_CUSTOM = 0x1000000,
};
/**
* \}
*/

View file

@ -5,6 +5,8 @@
#ifndef SPA_EVENT_NODE_H
#define SPA_EVENT_NODE_H
#include <spa/pod/event.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,8 +16,6 @@ extern "C" {
* \{
*/
#include <spa/pod/event.h>
/* object id of SPA_TYPE_EVENT_Node */
enum spa_node_event {
SPA_NODE_EVENT_Error,
@ -23,6 +23,7 @@ enum spa_node_event {
SPA_NODE_EVENT_RequestRefresh,
SPA_NODE_EVENT_RequestProcess, /*< Ask the driver to start processing
* the graph */
SPA_NODE_EVENT_User, /* User defined event */
};
#define SPA_NODE_EVENT_ID(ev) SPA_EVENT_ID(ev, SPA_TYPE_EVENT_Node)
@ -31,6 +32,11 @@ enum spa_node_event {
/* properties for SPA_TYPE_EVENT_Node */
enum spa_event_node {
SPA_EVENT_NODE_START,
SPA_EVENT_NODE_START_User = 0x1000,
SPA_EVENT_NODE_extra, /** extra info (String) */
SPA_EVENT_NODE_START_CUSTOM = 0x1000000,
};
/**

View file

@ -5,6 +5,9 @@
#ifndef SPA_IO_H
#define SPA_IO_H
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,9 +17,6 @@ extern "C" {
* \{
*/
#include <spa/utils/defs.h>
#include <spa/pod/pod.h>
/** IO areas
*
* IO information for a port on a node. This is allocated
@ -114,23 +114,54 @@ struct spa_io_range {
* Driver nodes are supposed to update the contents of \ref SPA_IO_Clock before
* signaling the start of a graph cycle. These updated clock values become
* visible to other nodes in \ref SPA_IO_Position. Non-driver nodes do
* not need to update the contents of their \ref SPA_IO_Clock.
* not need to update the contents of their \ref SPA_IO_Clock. Also
* see \ref page_driver for further details.
*
* The host generally gives each node a separate \ref spa_io_clock in \ref
* SPA_IO_Clock, so that updates made by the driver are not visible in the
* contents of \ref SPA_IO_Clock of other nodes. Instead, \ref SPA_IO_Position
* is used to look up the current graph time.
*
* A node is a driver when \ref spa_io_clock.id in \ref SPA_IO_Clock and
* \ref spa_io_position.clock.id in \ref SPA_IO_Position are the same.
* A node is a driver when \ref spa_io_clock::id and the ID in
* \ref spa_io_position.clock in \ref SPA_IO_Position are the same.
*
* The flags are set by the graph driver at the start of each cycle.
*/
struct spa_io_clock {
#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0) /* graph is freewheeling */
#define SPA_IO_CLOCK_FLAG_XRUN_RECOVER (1u<<1) /* recovering from xrun */
#define SPA_IO_CLOCK_FLAG_LAZY (1u<<2) /* lazy scheduling */
#define SPA_IO_CLOCK_FLAG_NO_RATE (1u<<3) /* the rate of the clock is only approximately.
* it is recommended to use the nsec as a clock source.
* The rate_diff contains the measured inaccuracy. */
#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0) /**< Graph is freewheeling. It runs at the maximum
* possible rate, only constrained by the processing
* power of the machine it runs on. This can be useful
* for offline processing, where processing in real
* time is not desired. */
#define SPA_IO_CLOCK_FLAG_XRUN_RECOVER (1u<<1) /**< A node's process callback did not complete within
* the last cycle's deadline, resulting in an xrun.
* This flag is not set for the entire graph. Instead,
* it is set at the start of the current cycle before
* a node that experienced an xrun has its process
* callback invoked. After said callback finished, the
* flag is cleared again. That way, the node knows that
* during the last cycle it experienced an xrun. They
* can use this information for example to resynchronize
* or clear custom stale states. */
#define SPA_IO_CLOCK_FLAG_LAZY (1u<<2) /**< The driver uses lazy scheduling. For details, see
* \ref PW_KEY_NODE_SUPPORTS_LAZY . */
#define SPA_IO_CLOCK_FLAG_NO_RATE (1u<<3) /**< The rate of the clock is only approximately.
* It is recommended to use the nsec as a clock source.
* The rate_diff contains the measured inaccuracy. */
#define SPA_IO_CLOCK_FLAG_DISCONT (1u<<4) /**< The clock experienced a discontinuity in its
* timestamps since the last cycle. If this is set,
* nodes know that timestamps between the last and
* the current cycle cannot be assumed to be
* continuous. Nodes that synchronize playback against
* clock timestamps should resynchronize (for example
* by flushing buffers to avoid incorrect delays).
* This differs from an xrun in that it is not necessariy
* an error and that it is not caused by missed process
* deadlines. If for example a custom network time
* based driver starts to follow a different time
* server, and the offset between that server and its
* local clock consequently suddenly changes, then that
* driver should set this flag. */
uint32_t flags; /**< Clock flags */
uint32_t id; /**< Unique clock id, set by host application */
char name[64]; /**< Clock name prefixed with API, set by node when it receives
@ -138,13 +169,16 @@ struct spa_io_clock {
* can be used to check if nodes share the same clock. */
uint64_t nsec; /**< Time in nanoseconds against monotonic clock
* (CLOCK_MONOTONIC). This fields reflects a real time instant
* in the past. The value may have jitter. */
* in the past, when the current cycle started. The value may
* have jitter. */
struct spa_fraction rate; /**< Rate for position/duration/delay/xrun */
uint64_t position; /**< Current position, in samples @ \ref rate */
uint64_t duration; /**< Duration of current cycle, in samples @ \ref rate */
int64_t delay; /**< Delay between position and hardware, in samples @ \ref rate */
double rate_diff; /**< Rate difference between clock and monotonic time, as a ratio of
* clock speeds. */
* clock speeds. A value higher than 1.0 means that the driver's
* internal clock is faster than the monotonic clock (by that
* factor), and vice versa. */
uint64_t next_nsec; /**< Estimated next wakeup time in nanoseconds.
* This time is a logical start time of the next cycle, and
* is not necessarily in the future.
@ -278,8 +312,8 @@ enum spa_io_position_state {
*
* It is set on all nodes in \ref SPA_IO_Position, and the contents of \ref
* spa_io_position.clock contain the clock updates made by the driving node in
* the graph in its \ref SPA_IO_Clock. Also, \ref spa_io_position.clock.id
* will contain the clock id of the driving node in the graph.
* the graph in its \ref SPA_IO_Clock. Also, the ID in \ref spa_io_position.clock
* will be the clock id of the driving node in the graph.
*
* The position clock indicates the logical start time of the current graph
* cycle.
@ -313,7 +347,7 @@ struct spa_io_position {
* and node rates. The \a flags and \a rate fields may be modified by the node.
*
* The node can request a correction to the resampling rate in its process(), by setting
* \ref SPA_IO_RATE_MATCH_ACTIVE on \a flags, and setting \a rate to the desired rate
* \ref SPA_IO_RATE_MATCH_FLAG_ACTIVE on \a flags, and setting \a rate to the desired rate
* correction. Usually the rate is obtained from DLL or other adaptive mechanism that
* e.g. drives the node buffer fill level toward a specific value.
*

View file

@ -5,6 +5,14 @@
#ifndef SPA_NODE_H
#define SPA_NODE_H
#include <errno.h>
#include <spa/utils/defs.h>
#include <spa/utils/type.h>
#include <spa/utils/hook.h>
#include <spa/buffer/buffer.h>
#include <spa/node/event.h>
#include <spa/node/command.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -19,14 +27,6 @@ extern "C" {
* \{
*/
#include <errno.h>
#include <spa/utils/defs.h>
#include <spa/utils/type.h>
#include <spa/utils/hook.h>
#include <spa/buffer/buffer.h>
#include <spa/node/event.h>
#include <spa/node/command.h>
#ifndef SPA_API_NODE
#ifdef SPA_API_IMPL
#define SPA_API_NODE SPA_API_IMPL

View file

@ -5,6 +5,12 @@
#ifndef SPA_NODE_TYPES_H
#define SPA_NODE_TYPES_H
#include <spa/utils/type.h>
#include <spa/node/command.h>
#include <spa/node/event.h>
#include <spa/node/io.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,12 +20,6 @@ extern "C" {
* \{
*/
#include <spa/utils/type.h>
#include <spa/node/command.h>
#include <spa/node/event.h>
#include <spa/node/io.h>
#define SPA_TYPE_INFO_IO SPA_TYPE_INFO_ENUM_BASE "IO"
#define SPA_TYPE_INFO_IO_BASE SPA_TYPE_INFO_IO ":"
@ -46,16 +46,20 @@ static const struct spa_type_info spa_type_node_event_id[] = {
{ SPA_NODE_EVENT_Buffering, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL },
{ SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL },
{ SPA_NODE_EVENT_RequestProcess, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestProcess", NULL },
{ SPA_NODE_EVENT_User, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "User", NULL },
{ 0, 0, NULL, NULL },
};
static const struct spa_type_info spa_type_node_event[] = {
{ SPA_EVENT_NODE_START, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_EVENT_BASE, spa_type_node_event_id },
{ SPA_EVENT_NODE_extra, SPA_TYPE_String, SPA_TYPE_INFO_NODE_EVENT_BASE "extra", NULL },
{ 0, 0, NULL, NULL },
};
#define SPA_TYPE_INFO_NodeCommand SPA_TYPE_INFO_COMMAND_BASE "Node"
#define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":"
#define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":"
static const struct spa_type_info spa_type_node_command_id[] = {
{ SPA_NODE_COMMAND_Suspend, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL },
@ -69,11 +73,15 @@ static const struct spa_type_info spa_type_node_command_id[] = {
{ SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL },
{ SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL },
{ SPA_NODE_COMMAND_RequestProcess, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "RequestProcess", NULL },
{ SPA_NODE_COMMAND_User, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "User", NULL },
{ 0, 0, NULL, NULL },
};
static const struct spa_type_info spa_type_node_command[] = {
{ 0, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_COMMAND_BASE, spa_type_node_command_id },
{ SPA_COMMAND_NODE_START, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_COMMAND_BASE, spa_type_node_command_id },
{ SPA_COMMAND_NODE_extra, SPA_TYPE_String, SPA_TYPE_INFO_NODE_COMMAND_BASE "extra", NULL },
{ 0, 0, NULL, NULL },
};

View file

@ -5,6 +5,10 @@
#ifndef SPA_NODE_UTILS_H
#define SPA_NODE_UTILS_H
#include <spa/pod/builder.h>
#include <spa/node/node.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,10 +18,6 @@ extern "C" {
* \{
*/
#include <spa/pod/builder.h>
#include <spa/node/node.h>
#ifndef SPA_API_NODE_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_NODE_UTILS SPA_API_IMPL

View file

@ -5,13 +5,13 @@
#ifndef SPA_AUDIO_AAC_TYPES_H
#define SPA_AUDIO_AAC_TYPES_H
#include <spa/utils/type.h>
#include <spa/param/audio/aac.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/type.h>
#include <spa/param/audio/aac.h>
/**
* \addtogroup spa_param
* \{

View file

@ -5,6 +5,11 @@
#ifndef SPA_AUDIO_AAC_UTILS_H
#define SPA_AUDIO_AAC_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +19,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_AUDIO_AAC_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_AAC_UTILS SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_AUDIO_AAC_H
#define SPA_AUDIO_AAC_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{
@ -18,19 +18,19 @@ extern "C" {
enum spa_audio_aac_stream_format {
SPA_AUDIO_AAC_STREAM_FORMAT_UNKNOWN,
/* Raw AAC frames */
/** Raw AAC frames */
SPA_AUDIO_AAC_STREAM_FORMAT_RAW,
/* ISO/IEC 13818-7 MPEG-2 Audio Data Transport Stream (ADTS) */
/** ISO/IEC 13818-7 MPEG-2 Audio Data Transport Stream (ADTS) */
SPA_AUDIO_AAC_STREAM_FORMAT_MP2ADTS,
/* ISO/IEC 14496-3 MPEG-4 Audio Data Transport Stream (ADTS) */
/** ISO/IEC 14496-3 MPEG-4 Audio Data Transport Stream (ADTS) */
SPA_AUDIO_AAC_STREAM_FORMAT_MP4ADTS,
/* ISO/IEC 14496-3 Low Overhead Audio Stream (LOAS) */
/** ISO/IEC 14496-3 Low Overhead Audio Stream (LOAS) */
SPA_AUDIO_AAC_STREAM_FORMAT_MP4LOAS,
/* ISO/IEC 14496-3 Low Overhead Audio Transport Multiplex (LATM) */
/** ISO/IEC 14496-3 Low Overhead Audio Transport Multiplex (LATM) */
SPA_AUDIO_AAC_STREAM_FORMAT_MP4LATM,
/* ISO/IEC 14496-3 Audio Data Interchange Format (ADIF) */
/** ISO/IEC 14496-3 Audio Data Interchange Format (ADIF) */
SPA_AUDIO_AAC_STREAM_FORMAT_ADIF,
/* ISO/IEC 14496-12 MPEG-4 file format */
/** ISO/IEC 14496-12 MPEG-4 file format */
SPA_AUDIO_AAC_STREAM_FORMAT_MP4FF,
SPA_AUDIO_AAC_STREAM_FORMAT_CUSTOM = 0x10000,

View file

@ -0,0 +1,69 @@
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2025 Carlos Rafael Giani */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_AUDIO_AC3_UTILS_H
#define SPA_AUDIO_AC3_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_param
* \{
*/
#ifndef SPA_API_AUDIO_AC3_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_AC3_UTILS SPA_API_IMPL
#else
#define SPA_API_AUDIO_AC3_UTILS static inline
#endif
#endif
SPA_API_AUDIO_AC3_UTILS int
spa_format_audio_ac3_parse(const struct spa_pod *format, struct spa_audio_info_ac3 *info)
{
int res;
res = spa_pod_parse_object(format,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate),
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels));
return res;
}
SPA_API_AUDIO_AC3_UTILS struct spa_pod *
spa_format_audio_ac3_build(struct spa_pod_builder *builder, uint32_t id,
const struct spa_audio_info_ac3 *info)
{
struct spa_pod_frame f;
spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_ac3),
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_ENCODED),
0);
if (info->rate != 0)
spa_pod_builder_add(builder,
SPA_FORMAT_AUDIO_rate, SPA_POD_Int(info->rate), 0);
if (info->channels != 0)
spa_pod_builder_add(builder,
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(info->channels), 0);
return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
}
/**
* \}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_AUDIO_AC3_UTILS_H */

View file

@ -0,0 +1,35 @@
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2025 Carlos Rafael Giani */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_AUDIO_AC3_H
#define SPA_AUDIO_AC3_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_param
* \{
*/
/** Dolby AC-3 audio info. */
struct spa_audio_info_ac3 {
uint32_t rate; /*< sample rate */
uint32_t channels; /*< number of channels */
};
#define SPA_AUDIO_INFO_AC3_INIT(...) ((struct spa_audio_info_ac3) { __VA_ARGS__ })
/**
* \}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_AUDIO_AC3_H */

View file

@ -5,6 +5,11 @@
#ifndef SPA_AUDIO_ALAC_UTILS_H
#define SPA_AUDIO_ALAC_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +19,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_AUDIO_ALAC_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_ALAC_UTILS SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_AUDIO_ALAC_H
#define SPA_AUDIO_ALAC_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{

View file

@ -5,13 +5,13 @@
#ifndef SPA_AUDIO_AMR_TYPES_H
#define SPA_AUDIO_AMR_TYPES_H
#include <spa/utils/type.h>
#include <spa/param/audio/amr.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/utils/type.h>
#include <spa/param/audio/amr.h>
/**
* \addtogroup spa_param
* \{

View file

@ -5,6 +5,11 @@
#ifndef SPA_AUDIO_AMR_UTILS_H
#define SPA_AUDIO_AMR_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +19,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_AUDIO_AMR_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_AMR_UTILS SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_AUDIO_AMR_H
#define SPA_AUDIO_AMR_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{

View file

@ -5,6 +5,11 @@
#ifndef SPA_AUDIO_APE_UTILS_H
#define SPA_AUDIO_APE_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +19,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_AUDIO_APE_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_APE_UTILS SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_AUDIO_APE_H
#define SPA_AUDIO_APE_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{

View file

@ -7,12 +7,17 @@
#define SPA_AUDIO_COMPRESSED_H
#include <spa/param/audio/aac.h>
#include <spa/param/audio/ac3.h>
#include <spa/param/audio/alac.h>
#include <spa/param/audio/amr.h>
#include <spa/param/audio/ape.h>
#include <spa/param/audio/dts.h>
#include <spa/param/audio/flac.h>
#include <spa/param/audio/mp3.h>
#include <spa/param/audio/mpegh.h>
#include <spa/param/audio/opus.h>
#include <spa/param/audio/ra.h>
#include <spa/param/audio/truehd.h>
#include <spa/param/audio/vorbis.h>
#include <spa/param/audio/wma.h>

View file

@ -5,6 +5,12 @@
#ifndef SPA_AUDIO_DSD_UTILS_H
#define SPA_AUDIO_DSD_UTILS_H
#include <spa/pod/iter.h>
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/format-utils.h>
#include <spa/param/audio/format.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +20,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/format-utils.h>
#include <spa/param/audio/format.h>
#ifndef SPA_API_AUDIO_DSD_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_DSD_UTILS SPA_API_IMPL
@ -41,7 +42,7 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
if (position == NULL ||
!spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
!spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position)))
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
return res;

View file

@ -7,13 +7,13 @@
#include <stdint.h>
#include <spa/param/param.h>
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/param.h>
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{

View file

@ -5,6 +5,11 @@
#ifndef SPA_AUDIO_DSP_UTILS_H
#define SPA_AUDIO_DSP_UTILS_H
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -14,11 +19,6 @@ extern "C" {
* \{
*/
#include <spa/pod/parser.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/format.h>
#include <spa/param/format-utils.h>
#ifndef SPA_API_AUDIO_DSP_UTILS
#ifdef SPA_API_IMPL
#define SPA_API_AUDIO_DSP_UTILS SPA_API_IMPL

View file

@ -5,12 +5,12 @@
#ifndef SPA_AUDIO_DSP_H
#define SPA_AUDIO_DSP_H
#include <spa/param/audio/raw.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/param/audio/raw.h>
/**
* \addtogroup spa_param
* \{

View file

@ -0,0 +1,39 @@
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2025 Carlos Rafael Giani */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_AUDIO_DTS_TYPES_H
#define SPA_AUDIO_DTS_TYPES_H
#include <spa/utils/type.h>
#include <spa/param/audio/dts.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_param
* \{
*/
#define SPA_TYPE_INFO_AudioDTSExtType SPA_TYPE_INFO_ENUM_BASE "AudioDTSExtType"
#define SPA_TYPE_INFO_AUDIO_DTS_EXT_TYPE_BASE SPA_TYPE_INFO_AudioDTSExtType ":"
static const struct spa_type_info spa_type_audio_dts_ext_type[] = {
{ SPA_AUDIO_DTS_EXT_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_DTS_EXT_TYPE_BASE "UNKNOWN", NULL },
{ SPA_AUDIO_DTS_EXT_NONE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_DTS_EXT_TYPE_BASE "NONE", NULL },
{ SPA_AUDIO_DTS_EXT_HD_HRA, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_DTS_EXT_TYPE_BASE "HRA", NULL },
{ SPA_AUDIO_DTS_EXT_HD_MA, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_DTS_EXT_TYPE_BASE "MA", NULL },
{ 0, 0, NULL, NULL },
};
/**
* \}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_AUDIO_DTS_TYPES_H */

Some files were not shown because too many files have changed in this diff Show more