From: Cyril Levis <cyril@levis.name>
we can use several `-i`, eg: `-i "line power" -i mouse`.
---
main.c | 41 +++++++++++++++++++++++++++++++++++++++++
upower.c | 11 ++++++++++-
upower.h | 4 +++-
3 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/main.c b/main.c
index 6676933..3e11d83 100644
--- a/main.c
+++ b/main.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
@@ -107,6 +108,7 @@ static int send_warning_update(sd_bus *bus, struct upower_device *device) {
break;
case UPOWER_DEVICE_LEVEL_CRITICAL:
msg = "Warning: power level critical\n";
+ urgency = URGENCY_CRITICAL;
break;
case UPOWER_DEVICE_LEVEL_ACTION:
msg = "Warning: power level at action threshold\n";
@@ -126,6 +128,31 @@ static int send_warning_update(sd_bus *bus, struct upower_device *device) {
}
int main(int argc, char *argv[]) {
+ int opt = 0;
+ int device_type = 0;
+ int ignore_types_mask = 0;
+ bool ignore_initial = false;
+
+ while ((opt = getopt(argc, argv, "si:")) != -1) {
+ switch (opt) {
+ case 'i':
+ device_type = upower_device_type_int(optarg);
+ if (device_type > -1) {
+ ignore_types_mask |= 1 << device_type;
+ }
+ else {
+ printf("Unrecognized device type: %s\n", optarg);
+ }
+ break;
+ case 's':
+ ignore_initial = true;
+ break;
+ case '?':
+ fprintf(stderr, "Usage: %s [-i type] [-s]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
struct upower state = { 0 };
sd_bus *user_bus = NULL;
sd_bus *system_bus = NULL;
@@ -155,6 +182,14 @@ int main(int argc, char *argv[]) {
for (int idx = 0; idx < state.devices->length; idx++) {
struct upower_device *device = state.devices->items[idx];
+ if ((ignore_types_mask & (1 << device->type))) {
+ continue;
+ }
+
+ if (device->current.serial == 0 && ignore_initial) {
+ continue;
+ }
+
if (upower_device_has_battery(device)) {
ret = send_state_update(user_bus, device);
if (ret < 0) {
@@ -203,6 +238,12 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "could not wait for system bus messages: %s\n", strerror(-ret));
goto finish;
}
+
+ for (int idx = 0; idx < state.devices->length; idx++) {
+ struct upower_device *device = state.devices->items[idx];
+ device->current.serial = device->last.serial + 1;
+ }
+
}
finish:
diff --git a/upower.c b/upower.c
index 5ffa922..62678f2 100644
--- a/upower.c
+++ b/upower.c
@@ -120,6 +120,15 @@ char* upower_device_type_string(struct upower_device *device) {
return "unknown";
}
+int upower_device_type_int(char *device) {
+ for (int i=0; i < UPOWER_DEVICE_TYPE_LAST; i++) {
+ if (!strcmp(upower_type_string[i], device)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
static int upower_device_update_state(sd_bus *bus, struct upower_device *device) {
sd_bus_error error = SD_BUS_ERROR_NULL;
int ret;
@@ -515,4 +524,4 @@ void destroy_upower(sd_bus *bus, struct upower *state) {
list_free(state->devices);
state->devices = NULL;
}
-}
\ No newline at end of file
+}
diff --git a/upower.h b/upower.h
index 81d3d41..a397c40 100644
--- a/upower.h
+++ b/upower.h
@@ -62,6 +62,7 @@ enum change_slot {
struct upower_device_props {
int generation;
int online;
+ int serial;
double percentage;
enum upower_device_state state;
enum upower_device_level warning_level;
@@ -98,9 +99,10 @@ char* upower_device_state_string(struct upower_device *device);
char* upower_device_warning_level_string(struct upower_device *device);
char* upower_device_battery_level_string(struct upower_device *device);
char* upower_device_type_string(struct upower_device *device);
+int upower_device_type_int(char *device);
void upower_device_destroy(struct upower_device *device);
int init_upower(sd_bus *bus, struct upower *state);
void destroy_upower(sd_bus *bus, struct upower *state);
-#endif
\ No newline at end of file
+#endif
--
2.32.0
> + while ((opt = getopt(argc, argv, "si:")) != -1) {
> + switch (opt) {
> + case 'i':
> + device_type = upower_device_type_int(optarg);
> + if (device_type > -1) {
> + ignore_types_mask |= 1 << device_type;
> + }
> + else {
> + printf("Unrecognized device type: %s\n", optarg);
> + }
> + break;
> + case 's':
> + ignore_initial = true;
> + break;
> + case '?':
> + fprintf(stderr, "Usage: %s [-i type] [-s]\n", argv[0]);
> + exit(EXIT_FAILURE);
Could you add a -h, similar to e.g. wlsunset?
> + if ((ignore_types_mask & (1 << device->type))) {
> + continue;
> + }
> +
> + if (device->current.serial == 0 && ignore_initial) {
> + continue;
> + }
You still need to update device->last, otherwise you'll get all the
initial events next time. A goto instead of continue would solve that.
If I start poweralertd with ignore_initial right now it indeed silences
everything on startup, but if I toggle the power of my mouse then I get
all the events that had been silenced.
> + for (int idx = 0; idx < state.devices->length; idx++) {
> + struct upower_device *device = state.devices->items[idx];
> + device->current.serial = device->last.serial + 1;
Once the previous comment is addressed, you could just do this after
device->last = device->current.
It can alternatively be done whenever device->current is changed in
upower.c (such as in upower_device_update_state), which has the
side-effect of `device->last.serial != device->current.serial` meaning
that a change has occurred. This was a bit more in line with my
original idea, but either way works.