Commit graph

4430 commits

Author SHA1 Message Date
Wim Taymans
feccb882b6 spa: add spa_json_begin
That combines spa_json_init() and spa_json_next, a common thing to do.
2024-09-16 09:50:31 +02:00
Hans de Goede
2a6ba61264 spa: v4l2: Use systemd-logind to listen for access changes
There is a race between logind applying ACLs to allow the active session
of a locally present user access to devices with a udev uaccess tag
(like /dev/video# nodes) getting applied vs wireplumber/pipewire starting.

Wireplumber/pipewire are part of the (user) default.target, which gets
started as soon as a user logs in and systemd --user is started for that
user, where as logind only starts applying the ACLs after the gnome-shell
associated logind session has been created.

This race may cause pipewire to not see v4l2 video sources at login,
this can be reproduced with these steps:

1. sudo setfacl --remove-all /dev/video*
2. systemctl --user restart pipewire
3. Now wp-ctl status will not show any video devices
   (like if pipewire was started before the udev uaccess ACLs got applied)
4. Do a switch to another (test) user without logging out, e.g. in GNOME
   go to the top right system menu press the power on/off icon and select
   "Switch User..."
5. Switch back to your normal user. Run getfacl /dev/video0 this will show
   your user has access now.
6. wp-ctl status should show the camera now, but it does not.

Fix pipewire not seeing v4l2 sources in this case by making v4l2-udev
monitor systemd-logind session changes and redoing the access() checks
on /dev/video# nodes when the session changes.

Closes: #3539
Closes: #3960
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-09-11 07:26:41 +00:00
Hans de Goede
ab245947e5 spa: v4l2: Remove start_inotify() call from impl_on_fd_events()
The spa_loop_add_source() call for udev event monitoring which uses
impl_on_fd_events() is done from start_monitor() which also unconditionally
calls start_inotify().

Since start_monitor() already always calls start_inotify() there is no
scenario where start_inotify() has not been called yet when
impl_on_fd_events() gets called. So the start_inotify() call in
impl_on_fd_events() is redundant, remove it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-09-11 07:26:41 +00:00
Wim Taymans
e15244b1e1 params: add function to compare process_latency_info 2024-09-10 17:28:37 +02:00
Wim Taymans
5c2b5fa552 audioadapter: clear the handle as well to avoid leaks 2024-09-09 13:42:44 +02:00
Wim Taymans
ffed9763fd audioadapter: improve convert plugin loader
Use the converter in the current plugin when no plugin loader was given
to make the unit tests work.
2024-09-09 13:26:45 +02:00
Wim Taymans
2762b8d98f videoadapter: sync with audioadapter 2024-09-06 17:35:34 +02:00
Wim Taymans
4d2cdd6da3 audioadapter: dynamically load the audio converter
So that we can plug in other implementations. Also handle the cases
where we can't load a converter.
2024-09-06 17:30:58 +02:00
Wim Taymans
b4c8627a62 audioadapter: improve format negiotiation
First try to pass the format of the converter directly into the
follower. This allows us to avoid conversion when it can be avoided.

Iterate all follower formats (not just the first one) to find something
that intersects with the converter formats.
2024-09-06 15:08:31 +02:00
Wim Taymans
9fb14be4e3 adapter: improve format parsing some more 2024-09-06 15:06:31 +02:00
Wim Taymans
c5a7f30a68 audioadapter: use generic audio format parsing
We don't need to use the raw audio format parsing functions, we can use
the more generic audio ones. This avoids some extra parsing for the
media type and subtype and will support compressed audio formats
as well when the converter handles this.
2024-09-06 14:46:34 +02:00
Wim Taymans
2cbcdbc579 videoconvert: add an ffmpeg based video converter
To activate:

PIPEWIRE_PROPS='{ video.adapt.converter = video.convert.ffmpeg }' build/src/examples/video-play

This makes it possible to start firefox with mjpg capture and then
video-play and it will decode the mjpeg transparently. Works for other
incompatible video formats as well, as long as they can be mmapped.

Ideally this should use something GPU accelerated and this is what the
vulkan converter will do.
2024-09-06 12:27:02 +02:00
Wim Taymans
7b30e515be videoadapter: sync with audio adapter
Try to passthrough the converter format to the follower when we can
before negotiating a conversion.

Try to convert between all follower formats instead of just the first
one.

When enumerating the port params, first enum the follower formats and
then the conversion formats.
2024-09-06 12:17:36 +02:00
Wim Taymans
f6803d4c03 audioadapter: pass the config mode around
When we are working in convert mode, configure the converter to convert
mode as well instead of DSP.
2024-09-06 11:20:25 +02:00
Stefan Ursella
189f2ec95b alsa-pcm: unlink pcm when driver is changed to a different pcm
We have to unlink pcms when they are linked to a driver from
a different pcm.

When a playback and a capture pcm is linked and we start
the playback pcm and the capture pcm later this can leads
to a 'EPIPE' error on the capture device.

...
spa.alsa: hw:3,0c: snd_pcm_start: Broken pipe
...
2024-09-06 08:42:20 +00:00
Wim Taymans
7036fc76e0 audioadapter: handle port flags better
Save the convert and follower port flags and use them in buffer
allocation.
2024-09-05 12:26:30 +02:00
Wim Taymans
37eef2cf23 v4l2: queue dropped first buffer again
When we drop the first buffer to avoid timestamp problems, queue it
again in the driver or else we will not be able to dequeue is again
later and we will be running with a buffer less.
2024-09-04 16:57:07 +02:00
Wim Taymans
f22206165a format: SPA_POD_Fraction takes a pointer to a fraction 2024-09-03 18:07:12 +02:00
Wim Taymans
cbbf37c3b8 audioadapter: move some checks around
Move the check for the follower==target to the negotiate functions.

Refer to the target when doing operations. The converter reference
is just some internal element that may or may not be active at the
moment. If we have multiple converter elements, the current active
one will be in target.
2024-09-02 15:18:29 +02:00
Wim Taymans
82e4b9a213 audioadapter: remove redundant statement
The same check is done a little later.
2024-09-02 11:51:40 +02:00
Robert Mader
d59158529b libcamera: reset ringbuffer when clearing buffers
Keeping the ringbuffer state around resulted in a high chance of
using wrong buffer IDs for consequent streams, causing various issues.
2024-08-30 06:49:17 +02:00
columbarius
4d33ccf89a videoconvert: Start dummy plugin in passthrough mode
Since the dummy plugin can't process buffers, we should configure the
adapter to use passthrough mode  for now, instead of requiering the user
to do it manually.
2024-08-29 14:00:51 +00:00
columbarius
17207038ea videoconvert: Add dummy plugin 2024-08-29 14:00:51 +00:00
Wim Taymans
01558bb9e9 alsa: improve midi port.name
The port.name should be something fairly unique and stable per node that
is also human readable.

Make sure we include the ALSA client name and port name in the
port.name but try to avoid double client names when the client name
is already in the port name.

There is also a api.alsa.disable-longname that is now set to true by
default. Setting this to false will include the unique client and port
id to the port.name.

This should make the midi port names much more presentable and more in
line with JACK1.
2024-08-26 13:42:09 +02:00
Wim Taymans
f160c86f6f doc: expand on the syncobj negotiation for sync_timeline
PipeWire doesn't impose how the syncobj fds are negotiated but provides
a way to add them to the buffer data when negotiating the Buffers.
2024-08-21 16:11:30 +02:00
Wim Taymans
fff52bb7a2 Revert "spa: support: loop: do not call control hooks on blocking invoke"
This reverts commit 9ae89b4247.

All invokes should be paired with a lock/unlock if the loop requires
this. For internal calls of invoke, this will also be true because all
pipewire functions should be called with the lock.

Fixes #4215
2024-08-21 14:48:54 +02:00
Wim Taymans
8edb6fc8b2 doc: add some small docs updates
Note that the sync_timeline metadata might add 2 fds, which are then not
part of the dma-buf planes.
2024-08-21 11:01:54 +02:00
Severin von Wnuck-Lipinski
cd2c80b089 bluez5: backend-native: Handle AT+CCWA command
Claim that call waiting notifications are supported.
Required for some devices (e.g. Soundcore Motion 300),
as they stop sending commands if the reply to CCWA is not OK.
2024-08-13 09:10:44 +00:00
Arun Raghavan
70a7bae5d7 resampler: Precompute some common filter coefficients
While this is quite fast on x86 (order of a few microseconds), the
computation can take a few milliseconds on ARM (measured at 1.9ms (32000
-> 48000) and 3.3ms (32000 -> 44100) on a Cortex A53).

Let's precompute some common rates so that we can avoid this overhead on
each stream (or any other audioconvert) instantiation. The approach
taken here is to write a little program to create the resampler
instance, and run that on the host at compile-time to generate some
common rate conversions.
2024-08-08 00:30:24 -04:00
Hans de Goede
46f89d8009 spa: v4l2: Remove start_watching_device() loop from start_inotify()
Now that start_monitor() (which calls start_inotify()) is called before
enum_devices() it no longer is necessary to call start_watching_device()
for devices which have been enumerated before start_inotify() gets
called (since there will not be any such devices anymore).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-07 22:38:16 +00:00
Hans de Goede
584168caab spa: v4l2: call start_monitor() before enum_devices()
This fixes 2 races wrt probing v4l2 devices:

1. Before this change there was a window where a new udev device can get
added between the udev_enumerate_scan_devices() call in enum_devices() and
the udev_monitor_enable_receiving(this->umonitor); call. If this window was
hit then enum_devices() would not see the device and no udev-event for it
would be received either causing the device to not be seen.

Enabling udev event monitoring before calling udev_enumerate_scan_devices()
fixes this. Note that the code is already prepared to deal with getting
multiple add/change events for the same udev device, so hitting the new
race window where PipeWire may receive both an add- or change-event and
also sees + probes the device from enum_devices() is not a problem.

2. Before this change devices added by enum_devices() would not have
inotify monitoring activated right away because notify.fd = -1 at this
time turning start_watching_device() into a no-op.

These devices without inotify monitoring would then have their access
checked by process_device() calling check_access().

Then after all devices have been enumerated start_monitor() would call
start_inotify() which calls start_watching_device() for all devices added
by enum_devices(). This leaves a window where the ACL can change without
there being an inotify watch for it.

Calling start_monitor() before enum_devices() puts start_inotify()
notify before enum_devices() so that the add_device() calls done
by enum_devices() will now successfully call start_watching_device()
closing this window.

PipeWire is somewhat likely to not notify ACL changes because of this
because PipeWire is part of the systemd user default.target, where as
logind only starts applying the ACLs after GNOME has created the seat
for the GNOME session. So on first login we have PipeWire starting
and logind applying the ACLs at the same time, which allows for the ACL
change to hit the small race window where PipeWire is not monitoring
for ACL changes. Fixing this second race should hopefully resolve
issue #3960.

Closes: #3960
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-07 22:38:16 +00:00
Hans de Goede
00a8ce8db6 spa: libcamera: Increase devices_str[] buffer size
Some complex camera pipelines, like the IPU6 can involve many /dev/video#
nodes (32 in the IPU6 case) and the current size of 128 chars is not enough
to hold all /dev/video# nodes in this cases causing SPA_KEY_DEVICE_DEVIDS
to get truncated, which in turn breaks the filtering of V4L2 devices which
are used by a libcamera driven camera in wireplumber.

Fix this by increasing the size of devices_str[] to 256.

This fixes wireplumber adding a bunch of non-function V4L2 video sources,
e.g. before this "wpctl status" outputs the following video sources:

Video
 ├─ Devices:
...
 ├─ Sources:
 │      90. ov2740
 │  *  115. ipu6 (V4L2)
...
 │     135. ipu6 (V4L2)
 │
 ├─ Filters:

After this fix the output is:

Video
 ├─ Devices:
...
 ├─ Sources:
 │  *   92. ov2740
 │
 ├─ Filters:

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-08-06 15:14:27 +02:00
Wim Taymans
8c1a69f1b5 loop: don't usleep when queue is full
When the queue is full, before this patch we used to go into usleep in
the hope that the other thread will run and empty the queue and that we
can retry after the usleep.

This however does not always work because the other thread might be waiting
for the thread that does the invoke call and we lock forever.

Therefore we should always try to make progress in some way. Instead of
waiting, allocate an (or use the previously allocated) overflow queue and
write to that one. We can chain multiple overflow queues together as many
as we need (but we might want to bound that as well).

The loop.retry-timeout property is now deprecated.

See #4114
2024-08-06 12:05:11 +02:00
Barnabás Pőcze
9ae89b4247 spa: support: loop: do not call control hooks on blocking invoke
The control hooks of a loop are called before the loop starts polling
and after it has finished polling. Currently, this is used to implement
the locking in pw_thread_loop. This is used to guarantee that the thread
loop's lock is taken while the thread loop is dispatching, and that
the lock can be taken while the loop is polling, when it is running
no user-space code.

However, calling the thread control hooks of thread A when doing an
blocking invoke from thread B serves little purpose, and in fact
can cause issues: for example, issuing a blocking invoke on a
pw_thread_loop does not work unless the lock thereof is taken.

This behaviour, of calling the control hooks from other threads,
is also not documented, and goes contrary to what is currently
stated in the loop.h header file:

  /** Executed right before waiting for events. It is typically used to
   * release locks. */
  ...
  /** Executed right after waiting for events. It is typically used to
   * reacquire locks. */

At the moment the implementation allows any thread to queue invoke
items on any other thread without restrictions; calling the control
hooks only places extra restrictions on the usability of this mechanism
(in case of pw_thread_loop, having to take the loop's lock).
So do not call the control hooks when doing a blocking invoke.
2024-08-05 18:14:39 +00:00
Vlad Pruteanu
786c2445e9 bluez5: Parse 'broadcasting' state
A new 'broadcasting' state is to be added in BlueZ. It is
functionally similar to 'pending', but for the Broadcast scenario.

Until now, on Broadcast sink side, the transports associated with a
scanned source would automatically be switched to pending. PipeWire
then acquired any transport that was pending.

This is to be changed, transports will now remain in 'idle' state
until the user calls transport.select on them from bluetoothctl.
This changes the state to 'broadcasting'. PipeWire will then acquire
these selected transports.

This way, the user can select to which sink he wishes to sync.
2024-08-01 10:36:58 +00:00
Arun Raghavan
9cd2bbc585 alsa-pcm: Lower the frequency of USB gadget rate updates
While the spec allows for 1ppm changes, our rate matching logic applies
these changes quite often, which can be spammy on USB. I haven't seen
hosts mind this, but it seems like it might be a problem at some point.

Additionally, if we also have bind ctls enabled, every pitch update is
also a wakeup for ourselves (whether or not we're listening for the
pitch ctls, since the mixer fd does not distinguish between ctls, those
are filtered after we wake up).

The 10ppm threshold is empirically tested as being not "too noisy" (i.e.
when updates happen, I can see them scroll by with `amixer events`).

If necessary, we can make this configurable in the future.
2024-07-31 12:00:07 -04:00
Wim Taymans
494600d46a loop: release queue lock before calling invoke function
We don't actually need to hold the lock while calling the invoke
function, we only need the lock to protect the list of queues.
2024-07-30 12:04:42 +02:00
Wim Taymans
65f067347d require newer alsa 1.2.10 for UMP support 2024-07-30 10:06:41 +02:00
Wim Taymans
ce89ce304d alsa: fix compilation wirh -UFASTPATH 2024-07-30 09:53:14 +02:00
Wim Taymans
802972f1ae ump: handle f0 .. f0 f7 .. f0 f7 .. f7 packets
Support the RFC 4695 sysex segmentation rules where a sysex packet can
be split into multiple chunks using the f0 and f7 patterns like:

begin      f0 ... f0
continue   f7 ... f0
end        f7 ... f7

Add a unit test for the sysex UMP conversion.
2024-07-30 09:38:40 +02:00
Wim Taymans
d9e7a10b0d modules: accept and produce UMP only 2024-07-30 09:38:40 +02:00
Wim Taymans
40cd8535eb audioconvert: only accept UMP on the control port 2024-07-30 09:38:40 +02:00
Wim Taymans
94bb5a2dd2 alsa: add UMP support
Use the new UMP alsa sequencer API to make it produce UMP packets.

Set the alsa sequencer to MIDI2.0, which will make it convert all
messages to MIDI-2.0 UMP automatically. We can copy this straight into
the control buffers.

This also solves some problems with large sysex messages that are now
nicely split into chunks with UMP.
2024-07-30 09:38:40 +02:00
Wim Taymans
0c4ea83b89 control: add support for mixing to UMP
Check the negotiated control output format and convert to it when
necessary.
2024-07-29 18:15:58 +02:00
Wim Taymans
7b03a41e3d spa: add some helpers to convert MIDI to and from UMP 2024-07-29 18:15:57 +02:00
Wim Taymans
3e87aca7a9 spa: Add UMP control type
UMP (universal Midi Packet) is an improved version of transmitting MIDI
messages. It also has support for MIDI 2.0 and is backwards compatible
with MIDI 1.0.
2024-07-29 18:15:57 +02:00
Wim Taymans
61dcd8dede audioconvert: set IO_Buffers only when buffers are negotiated
The IO_Buffers is used in the data thread to check if the port should be
scheduled or not. Make sure it is only set after we set buffers on the
port and cleared before the buffers are cleared.

Make sure we sync the port->io with the data thread.

See #4094
2024-07-29 18:15:06 +02:00
Vlad
308a93bd14 bluez5: Update default sync_factor
Due to the how the kernel part of BlueZ computes the extended
advertising interval for a Broadcast Source, a sync_factor smaller
than 2 will result in an invalid interval value (too small).
2024-07-28 13:45:45 +00:00
Wim Taymans
2a8a08f303 loop: signal when queue is full
When our queue is full, signal the wakeup event to make sure the thread
will wake up and try to clear the queue before we go to sleep.
2024-07-20 14:05:09 +02:00
Arun Raghavan
0dc17d8d88 spa: alsa: Fix stale function name in comment 2024-07-17 20:07:57 -04:00