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.
non-systemd systems also have logind, in the form of elogind, which works to
resolve the v4l2 video source race just as well. permit finding elogind, by
using a separate dep object.
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: #3539Closes: #3960
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
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>
Wireplumber creates SPA objects of the "api.v4l2.enum.udev" type without
ever creating any "api.v4l2.source" objects.
This was causing the v4l2_log_topic variable to never get initialized,
causing spa_log_xxx() calls in v4l2-udev.c to not work.
Call v4l2_log_topic_init() from v4l2-udev's impl_init() to fix this.
v4l2-device's impl_init() is also missing a call to v4l2_log_topic_init(),
add this as well.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
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>
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>
Previously both `impl_on_notify_events()` and `process_{device,card}()`
called `check_access()`. Avoid that by merging `ACTION_ADD` and
`ACTION_DISABLE` into a single `ACTION_CHANGE` and let `process_{device,card}()`
call `check_access()` and decide what to do.
Split up `process_{device,card}()` to have a separate function that does
the lookup based on the udev device, and only use that when there is
no available reference to the actual device/card object.
Instead of watching /dev, use a separate watch for each device.
This is supposed to achieve the same result as the now reverted
88f0dbd6fc ("v4l2: don't set inotify on /dev"):
Doing inotify on /dev is not a good idea because we will be woken up by
a lot of unrelated events.
There is a report of a performance regression on some IO benchmark
because of lock contention within the fsnotify subsystem due to this.
Instead, just watch for attribute changes on the /dev/videoX files
directly. We are only interested in attribute changes, udev should
notify us when the file is added or removed.
Fixes#3439
Doing inotify on /dev is not a good idea because we will be woken up by
a lot of unrelated events.
There is a report of a performance regression on some IO benchmark
because of lock contention within the fsnotify subsystem due to this.
Instead, just watch for attribute changes on the /dev/videoX files
directly. We are only interested in attribute changes, udev should
notify us when the file is added or removed.
udev/kernel sometimes give "Video Capture N" as ID_V4L_PRODUCT, which is
bogus as a device product name. The ID_MODEL* field seem to always have
a sensible product name.
Get device.product.name always from ID_MODEL*, and use ID_V4L_PRODUCT
only as the last fallback.
The inotify_event field has a variable sized type, so it's recommended to store
it at the end of the storage unit. Fixes gnu-variable-sized-type-not-at-end warning.
When we add a new listener to an object, it will emit the full state
of the object. For this it temporarily sets the change_mask to all
changes. Restore the previous state after this or else we might not
emit the right change_mask for the next listener.
Consider the case where one there are two listeners on an object.
The object emits a change and the first listener wants to enumerate the
changed params. For this is adds a new listener and then triggers the
enumeration. If we set the change_mask to 0 after adding the listener,
the second listener would get a 0 change_mask and fail to update
its state.
udev's ID_MODEL_ID and ID_VENDOR_ID are inconsistent: always 4-digit hex but
sound devices are prefixed with 0x, v4l devices are not. Depending on the
actual ID, the value will look like decimal (1234) or hex (a234).
pw-dump will then print those as either decimal integers (i.e. 0x1234 becomes
decimal 1234) or double (i.e. a234 becomes 41524.00).
Make this consistent by converting the string from hex do decimal where we
get it.
SPA_MEMBER is misleading, all we're doing here is pointer+offset and a
type-casting the result. Rename to SPA_PTROFF which is more expressive (and
has the same number of characters so we don't need to re-indent).
This is more in line with wayland and it allows us to create new
interfaces in modules without having to add anything to the type
enum. It also removes some lookups to map type_id to readable
name in debug.
Remove the monitor API, we can use the device API for it. Make sure
we support creating devices (like alsa) from another device (udev).
Use new object.id to store the object id in the object properties. Use
the port.id/node.id etc to make relations to other objects.
2019-09-20 13:04:14 +02:00
Renamed from spa/plugins/v4l2/v4l2-monitor.c (Browse further)