diff --git a/README.md b/README.md
index d98ef27..2fd7359 100644
--- a/README.md
+++ b/README.md
@@ -89,7 +89,7 @@ Last line will smoothly change current backlight on every internal/external scre
Please note that for internal laptop screen, serialNumber must be your backlight kernel interface (eg: intel_backlight) or an empty string (to forcefully use first udev backlight subsystem matching device).
-A "version" bus property is exported too. It will return a "s" of clightd version.
+### Methods
*Smooth struct* here means:
* b -> isSmooth (true for smooth change)
@@ -112,6 +112,19 @@ A "version" bus property is exported too. It will return a "s" of clightd versio
| setdpms_timeouts | ssiii |
- env DISPLAY
- env XAUTHORITY
- New dpms timeouts
| iii | New dpms timeouts | ✔ | ✔ |
| getidletime | ss | - env DISPLAY
- env XAUTHORITY
| i | Current idle time in ms | | ✔ |
+### Properties
+
+| Prop | OUT | OUT values |
+|-|:-:|-|
+| version | s | Clightd version |
+
+### Signals
+
+| Sig | OUT | OUT values |
+|-|:-:|-|
+| WebcamChanged | ss | - Webcam's devpath
- Action string, as received from udev. Eg: "add", "remove".
|
+
+
## Ddcutil support
Clightd uses [ddcutil](https://github.com/rockowitz/ddcutil) C api to set external monitor brightness and thus supporting desktop PCs too.
diff --git a/TODO.md b/TODO.md
index 82c0333..2d66bca 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,4 +1,7 @@
## 2.4
+- [x] Add WebcamChanged signal that will be sent when a new webcam is connected/a webcam is disconnected
+
+## 2.5
- [ ] Add gamma (and dpms + idle) support on wayland (wlroots)
https://github.com/swaywm/wlroots/blob/master/examples/gamma-control.c
https://github.com/swaywm/wlroots/blob/master/examples/idle.c
diff --git a/inc/udev.h b/inc/udev.h
index b40d0e6..0cd1de8 100644
--- a/inc/udev.h
+++ b/inc/udev.h
@@ -2,5 +2,9 @@
extern struct udev *udev;
+#ifndef DISABLE_FRAME_CAPTURES
+int init_udev_monitor(const char *subsystem);
+void receive_udev_device(struct udev_device **dev);
+#endif
void get_udev_device(const char *interface, const char *subsystem,
sd_bus_error **ret_error, struct udev_device **dev);
diff --git a/src/clightd.c b/src/clightd.c
index 5ff7fb1..ccac6f2 100644
--- a/src/clightd.c
+++ b/src/clightd.c
@@ -45,6 +45,9 @@ enum poll_idx {
BRIGHT_SMOOTH,
#ifdef GAMMA_PRESENT
GAMMA_SMOOTH,
+#endif
+#ifndef DISABLE_FRAME_CAPTURES
+ UDEV_MON,
#endif
POLL_SIZE };
enum quit_codes { LEAVE_W_ERR = -1, SIGNAL_RCV = 1 };
@@ -74,6 +77,7 @@ static const sd_bus_vtable clightd_vtable[] = {
#ifndef DISABLE_FRAME_CAPTURES
SD_BUS_METHOD("captureframes", "si", "ad", method_captureframes, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("iswebcamavailable", "", "b", method_iswebcamavailable, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_SIGNAL("WebcamChanged", "ss", 0),
#endif
#ifdef DPMS_PRESENT
SD_BUS_METHOD("getdpms", "ss", "i", method_getdpms, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -151,6 +155,12 @@ static void set_pollfd(void) {
};
set_gamma_smooth_fd(gamma_smooth_fd);
#endif
+#ifndef DISABLE_FRAME_CAPTURES
+ main_p[UDEV_MON] = (struct pollfd) {
+ .fd = init_udev_monitor("video4linux"),
+ .events = POLLIN,
+ };
+#endif
}
/*
@@ -181,6 +191,17 @@ static void main_poll(void) {
case GAMMA_SMOOTH:
gamma_smooth_cb();
break;
+#endif
+#ifndef DISABLE_FRAME_CAPTURES
+ case UDEV_MON: {
+ struct udev_device *dev = NULL;
+ receive_udev_device(&dev);
+ if (dev) {
+ sd_bus_emit_signal(bus, object_path, bus_interface, "WebcamChanged", "ss", udev_device_get_devnode(dev), udev_device_get_action(dev));
+ udev_device_unref(dev);
+ }
+ break;
+ }
#endif
}
r--;
diff --git a/src/udev.c b/src/udev.c
index 0aee83a..689c5fc 100644
--- a/src/udev.c
+++ b/src/udev.c
@@ -2,6 +2,21 @@
static void get_first_matching_device(struct udev_device **dev, const char *subsystem);
+#ifndef DISABLE_FRAME_CAPTURES
+static struct udev_monitor *mon;
+
+int init_udev_monitor(const char *subsystem) {
+ mon = udev_monitor_new_from_netlink(udev, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype(mon, subsystem, NULL);
+ udev_monitor_enable_receiving(mon);
+ return udev_monitor_get_fd(mon);
+}
+
+void receive_udev_device(struct udev_device **dev) {
+ *dev = udev_monitor_receive_device(mon);
+}
+#endif
+
/**
* Set dev to first device in subsystem
*/