Commit graph

492 commits

Author SHA1 Message Date
Wim Taymans
b1c0662a00 pipewire-pulse: improve parsing of defaults
When we fail to parse a fraction from the config, give a warning and
continue with the default settings.
Print the final parsed value as debug.
2022-11-20 16:19:24 +01:00
Wim Taymans
fc159be9c6 pulse-server: make method to pause/resume stream
Make a method to pause and resume a stream and keep track of the paused
state of the stream. Use this function instead of setting the stream
inactive/active so that we get nice logging for each state change.
2022-11-20 16:19:24 +01:00
Wim Taymans
a11612bdad pulse-server: add event to the implementation
Add events when a server is started and stopped
2022-11-17 18:31:23 +01:00
Wim Taymans
b720da771e pulse-server: also advance read pointer in underrun
So that we ask for more data from the client.

Also retested with #2799 that caused this regression.

Fixes #2821
2022-11-10 16:13:33 +01:00
Wim Taymans
f801dc0886 pulse-server: keep read index in sync
Keep the ringbuffer and read_index variable in sync or else we might ask
for more data than maxlength and cause an overflow.

Fixes #2799
2022-11-02 11:43:30 +01:00
Wim Taymans
323ec0b51b pulse-server: improve maxlength calculations
When no maxlength is given, we use the MAXLENGTH value but we need to
round it DOWN (instead of up) because our buffer is only MAXLENGTH big.
Use CLAMP where we can.
When in capture mode, the maxlength exceeds MAXLENGTH, scale down the
fragsize instead.

Fixes noise in audacious when playing 6 channels sounds. float32 * 6
channels with the maximum buffer size would result in the ringbuffer
being overwritten.
2022-09-26 17:29:17 +02:00
Wim Taymans
e0d1be32fd pulse-server: don't read more than requested size
When we underrun, don't try to read more than what was requested
even if there is more in the ringbuffer.
2022-09-26 13:30:39 +02:00
Wim Taymans
e0614246f5 pulse-server: set fragsize as latency
Reducing the latency is just papering over the issue in #2702. The
real fix is to limit the blocksize to the fragsize like what is done
in 00a234daf2

Reducing the latency then also causes regressions like #2715 so don't
do that anymore.

Fixes #2715
2022-09-22 11:58:14 +02:00
Wim Taymans
47f2b72088 pulse-server: don't overwrite previous towrite value
And actually take the MAX_BLOCK into account when writing samples to a
client.
2022-09-21 12:00:36 +02:00
Wim Taymans
00a234daf2 pulse-server: limit capture blocks to fragsize
Don't send larger chunks than the fragsize. Some clients don't like
this. Also checked with #2418.

Fixes #2711
2022-09-21 11:34:13 +02:00
Wim Taymans
bd584ca8c0 pulse-server: ignore adjust-latency for capture
Don't update the fragsize, it breaks #2418 again.
2022-09-21 11:34:13 +02:00
Wim Taymans
0ce95e69fd pulse-server: adjust_latency should update the fragsize
Rename MAX_FRAGSIZE to MAX_BLOCK because it does not really limit the
fragsize, just the amount of data we can send in one block.

See #2711
2022-09-20 13:24:30 +02:00
Wim Taymans
d1cd199f16 pulse-server: set record latency as fragsize / 2
The record latency is set to fragsize / 2 by pulseaudio, so do the
same in pipewire.

Fixes #2702
2022-09-19 14:45:11 +02:00
Wim Taymans
50f76c8730 pulse-server: implement TRIGGER and PREBUF methods
Start and stop prebuf.
2022-09-07 13:02:55 +02:00
Wim Taymans
305f2104ee pulse-server: rework buffer attributes
Move the latency fraction calculation to fix_ functions so that the
new latency rate can be used when creating the streams.
Actually set the requested record attributes on the stream instead
of modifying the defaults.

See #2671
2022-09-06 11:53:51 +02:00
Wim Taymans
1a915c2ced pulse-server: set record attributes more like PulseAudio
PulseAudio assigns half of the fragsize to the source latency.
PulseAudio sends in chunks up to a fixed limit.

Checked against #2418
2022-09-05 18:13:12 +02:00
Wim Taymans
ad06db91ee Revert "pulse-server: send chunks with half the fragsize"
This reverts commit e10305851d.

If causes some regressions: see #2671
2022-09-05 16:19:42 +02:00
Wim Taymans
83e83608c8 Revert "pulse-server: tweak the fragsize/minreq handling"
This reverts commit ad214dde2e.
2022-09-05 16:18:54 +02:00
Wim Taymans
009ab9681d Revert "pulse-server: simplify latency handling"
This reverts commit 9c34a923db.
2022-09-05 16:18:45 +02:00
Wim Taymans
72ce2f815b Revert "pulse-server: enforce minfrag after latency adjust"
This reverts commit b70f32a259.
2022-09-05 16:18:34 +02:00
Wim Taymans
b70f32a259 pulse-server: enforce minfrag after latency adjust 2022-09-03 13:07:09 +02:00
Wim Taymans
9c34a923db pulse-server: simplify latency handling
We don't need to use the minreq field. The fragsize is only updated when
adjust_latency is used.
2022-09-01 16:46:18 +02:00
Wim Taymans
ad214dde2e pulse-server: tweak the fragsize/minreq handling
Only send 2/3 of the fragsize
2022-09-01 16:23:56 +02:00
Wim Taymans
e10305851d pulse-server: send chunks with half the fragsize
PulseAudio configures half of the fragsize as the source latency. It
also sends chunks as soon as they become available.

This means that we also need to configure the source with half of
the fragsize latency and send in chunks of fragsize/2. Keep this in
the unused (for record) minreq field.
2022-09-01 15:46:17 +02:00
Wim Taymans
35082e4f4b pulse-server: add the delay
Actually add the delay to the buffered amount of time instead of
overwriting.
2022-07-13 10:49:26 +02:00
Wim Taymans
855d17ac1b pulse-server: add some debugging 2022-07-13 10:42:00 +02:00
Pauli Virtanen
167537dffc pulse-server: fix warning
The rest of the fields are zeroed later in reply_create_record_stream,
but static analysis doesn't know that.
2022-07-06 14:36:22 +00:00
Pauli Virtanen
a46d4aedd7 pulse-server: work around race condition in SET_DEFAULT/MOVE_*
The default metadata update may be delayed for some time after
SET_DEFAULT, since the session manager has to work on it.

MOVE_* commands need to know what the client thinks is the current
default sink, so that they can decide between "move to default" and
"move to specific device".

To avoid race condition here, stash the default value set by the client
and use it in the MOVE_* commands, until the metadata update arrives.
2022-07-04 15:57:31 +00:00
Adolfo Rodrigues
6188e4d074 pulse-server: tweak maxlength some more
Make the buffer size at least 4 times as large as the fragment size to avoid
xruns.
2022-07-04 15:56:16 +00:00
Wim Taymans
8b649c4510 pulse-server: optimize property allocations
Only allocate a new properties object when we actually need to
change something.
2022-07-02 11:27:54 +02:00
Davide Beatrici
a31989b46d pulse-server: add card properties to sinks and sources
To match the original PulseAudio server's behavior.
2022-07-01 19:54:44 +00:00
Barnabás Pőcze
97a275e71e pulse-server: update quirks before querying the name
`client_update_quirks()` may modify `client::props` depending
on the "pulse.rules" section defined in the configuration file,
which means that it can change the value corresponding to the
"application.name" key. Therefore, `client::name` needs to
be queried after that.
2022-06-20 17:30:05 +00:00
Barnabás Pőcze
0f45d784d8 pulse-server: update client::name on UPDATE_CLIENT_PROPLIST command
`client::name` points to a string that is owned by `client::props`,
so when the property list is updated, it needs to be refreshed as well.
Otherwise, various use-after-frees can be triggered, for example:

==1471586==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200007e7d0 at pc 0x7f14390755d0 bp 0x7ffe23edee30 sp 0x7ffe23ede5a8
READ of size 3 at 0x60200007e7d0 thread T0
    #0 0x7f14390755cf in printf_common /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553
    #1 0x7f1439077215 in __interceptor_vsnprintf /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1665
    #2 0x7f1434ead47d in spa_vscnprintf ../spa/include/spa/utils/string.h:239
    #3 0x7f1434eae2ae in impl_log_logtv ../spa/plugins/support/logger.c:138
    #4 0x7f14385cacc7 in pw_log_logt ../src/pipewire/log.c:135
    #5 0x7f1433aef8e9 in do_set_profile ../src/modules/module-protocol-pulse/pulse-server.c:4656
    #6 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109
    #7 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276
    #8 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306
    #9 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442
    #10 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430
    #11 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148
    #12 0x55b065d73722 in main ../src/daemon/pipewire.c:131
    #13 0x7f143742928f  (/usr/lib/libc.so.6+0x2928f)
    #14 0x7f1437429349 in __libc_start_main (/usr/lib/libc.so.6+0x29349)
    #15 0x55b065d722a4 in _start (./src/daemon/pipewire-pulse+0x42a4)

0x60200007e7d0 is located 0 bytes inside of 16-byte region [0x60200007e7d0,0x60200007e7e0)
freed by thread T0 here:
    #0 0x7f14390be672 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f14386a775a in do_replace ../src/pipewire/properties.c:414
    #2 0x7f14386a785e in pw_properties_set ../src/pipewire/properties.c:441
    #3 0x7f14386a658b in pw_properties_update ../src/pipewire/properties.c:309
    #4 0x7f1433adb055 in do_update_proplist ../src/modules/module-protocol-pulse/pulse-server.c:3246
    #5 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109
    #6 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276
    #7 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306
    #8 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442
    #9 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430
    #10 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148
    #11 0x55b065d73722 in main ../src/daemon/pipewire.c:131
    #12 0x7f143742928f  (/usr/lib/libc.so.6+0x2928f)

previously allocated by thread T0 here:
    #0 0x7f1439072faa in __interceptor_strdup /usr/src/debug/gcc/libsanitizer/asan/asan_interceptors.cpp:439
    #1 0x7f14386a6fe2 in do_replace ../src/pipewire/properties.c:394
    #2 0x7f14386a785e in pw_properties_set ../src/pipewire/properties.c:441
    #3 0x7f1433a6c52d in read_props ../src/modules/module-protocol-pulse/message.c:147
    #4 0x7f1433a6f467 in message_get ../src/modules/module-protocol-pulse/message.c:359
    #5 0x7f1433ab3191 in do_set_client_name ../src/modules/module-protocol-pulse/pulse-server.c:1030
    #6 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109
    #7 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276
    #8 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306
    #9 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442
    #10 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430
    #11 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148
    #12 0x55b065d73722 in main ../src/daemon/pipewire.c:131
    #13 0x7f143742928f  (/usr/lib/libc.so.6+0x2928f)
2022-06-20 17:30:05 +00:00
Wim Taymans
ff05ebada6 pulse-server: tweak record attributes
Add some 'before' debug info of the attributes.
First clamp the fragsize to the maxlength and then clamp to the
minfrag or else we could bypass the configured minfrag by setting a
lower maxlength.
Scale the maxlength to at least twice the fragsize so that we can
buffer enough data in the ringbuffer to serve fragsize bytes.

See #2447
2022-06-20 11:42:59 +02:00
Barnabás Pőcze
080a97c0bb pulse-server: message: store pointer to impl directly
Store a pointer to the owner `impl` object instead of
the (embedded) `stat` object. This way `message_free()`
can be simplified since the owner `impl` does not need
to be passed explicitly.
2022-06-16 18:38:30 +00:00
Wim Taymans
68bafcf166 pulse-server: Don't send more than fragsize chunks
Send exactly fragsize chunks when capturing.

See #2418 and #2434
2022-06-14 11:20:18 +02:00
Wim Taymans
c1a61a7941 pulse-server: only append .monitor for capture streams 2022-06-13 20:12:10 +02:00
Wim Taymans
f88134232d pulse-server: fix name when moved to monitor
When a stream is moved to a monitor, make sure we append the .monitor
suffix to the node name.

Fixes #2440
2022-06-13 19:54:35 +02:00
Barnabás Pőcze
c8c2526f87 pulse-server: destroy modules first
The `impl::servers` list contains all servers, and they are all
destroyed in `impl_clear()`. However, by that time, modules were
not freed previously, so if there were any instances of
*module-protocol-native-tcp* loaded, then the unload() method
of those would call `server_free()` on already freed servers,
resulting in use-after-frees. Fix that by unloading modules
before destroying the servers.

==451490==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000006050 ...
READ of size 8 at 0x612000006050 thread T0
    #0 0x7f45edb19a0c in server_free ../src/modules/module-protocol-pulse/server.c:1022
    #1 0x7f45edb46c7d in module_native_protocol_tcp_unload ../src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c:66
    #2 0x7f45eda893c7 in module_unload ../src/modules/module-protocol-pulse/module.c:128
    #3 0x7f45edaf7269 in impl_unload_module ../src/modules/module-protocol-pulse/pulse-server.c:5336
    #4 0x7f45edaa1583 in pw_map_for_each ../src/pipewire/map.h:238
    #5 0x7f45edaf79c5 in impl_clear ../src/modules/module-protocol-pulse/pulse-server.c:5358
    ...

0x612000006050 is located 16 bytes inside of 264-byte region [0x612000006040,0x612000006148)
freed by thread T0 here:
    #0 0x7f45f30be672 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f45edb1a48a in server_free ../src/modules/module-protocol-pulse/server.c:1040
    #2 0x7f45edaf730b in impl_clear ../src/modules/module-protocol-pulse/pulse-server.c:5347
    ...

Fixes: f181210b29 ("pulse-server: properly unload modules")
2022-06-09 03:02:06 +02:00
Wim Taymans
0f839c7b61 modules: clamp input offset and size
So that we don't cause memory errors with invalid input.
2022-06-04 11:47:48 +02:00
Wim Taymans
efe30d5075 pulse-server: send STREAM_MOVED messages
Keep track of the last known peer of a stream and send a moved message
when it changes.

Fixes #2407
2022-06-03 16:59:08 +02:00
Wim Taymans
be9c738661 pulse-server: keep stream latency around 2022-06-03 16:58:37 +02:00
Wim Taymans
1252927d73 pulse-server: check all pending streams
Check all pending streams to see if the new link completes their
creation.

It is possible that the link linked 2 pending streams and then we
want to complete them both.
2022-06-03 15:50:54 +02:00
Wim Taymans
258a203d74 pulse-server: optimize link finding
When we get a new link object, only check if a pending stream is linked
according to the new link instead of iterating all links.
2022-06-03 15:48:08 +02:00
Barnabás Pőcze
c9f632da9f pulse-server: serve module properties from static list
None of the modules really need a dynamic property list,
so serve the properties from a static list.
2022-06-02 15:17:45 +02:00
Wim Taymans
2c4d36e4d0 pulse-server: always send frame_size multiples of samples.
See #2421
2022-06-02 09:05:23 +02:00
Wim Taymans
0d51f3b74e pulse-server: always send at least fragsize data
Make sure to never send less than the negotiated fragsize to a client.
Also make sure we don't send too much data in one go. This is more in
line with what pulseaudio does.

Fixes capture from multiple tabs in chrome.

Fixes #2418
2022-06-01 15:43:07 +02:00
Pauli Virtanen
98aa7ccff0 pulse-server: emulate synchronous MOVE_* commands
Make MOVE_SINK_INPUT/MOVE_SOURCE_OUTPUT change the linked peer
immediately in subsequent GET_SINK_INPUT_INFO/GET_SOURCE_OUTPUT_INFO
commands.  Do this by keeping track of the sink/source where the client
moved the stream to, and temporarily replying so in future GET_INFO (but
only in messages for that client).

We discard the temporary override when we either get an update event for
the stream (i.e. SM moved the stream), or a 1sec timer runs out. If the
timer runs out, we emit a sink-input/source-output change event, as in
that case what we claimed in the earlier GET_INFO messages might not be
true, so clients need to update their information.

This gets rid of race conditions where an application moves a stream,
and expects the move to be visible in future GET_INFO replies, which may
fail to happen because it takes some time for the session manager to
re-link the streams.

Fixes pasystray behavior.
2022-05-15 17:14:52 +00:00
Marcin Radomski
aa33c2841c pulse-server: avoid skipping more ringbuffer data than available
This prevents the ringbuffer from advancing the read pointer more than
the size of data actually available. It prevents the "avail" value from
keeping to drop when no audio is being played by the client.

Applying this patch seems to prevent the "randomly playing music after
a couple hours of silence" issue

Fixes #2366
2022-05-11 15:34:21 +02:00
Wim Taymans
d506781619 pulse-server: do a guess for the latency when starting
Guess the expected latency with the stream info we have and use that as
the node.latency. This way, the graph can attempt to start with some
sort of latency setting.

After we know the exact format, we can calculate the real latency and we
will update the node latency accordingly.
2022-05-06 16:54:22 +02:00