stevee

My wayland statusbar
git clone git://gtms.dev/stevee
Log | Files | Refs | Submodules | README | LICENSE

commit 756aba6844b16a86053ae33537b65fdc9e787405
parent f05bc63288d5d15c3f055e573314a78f02fdb096
Author: Andrea Feletto <andrea@andreafeletto.com>
Date:   Sun, 30 Jan 2022 20:17:32 +0100

use udev for battery

Diffstat:
Msrc/event.zig | 33++++-----------------------------
Msrc/modules.zig | 127++++++++++++++++++++++++++++++++++++++++++-------------------------------------
2 files changed, 71 insertions(+), 89 deletions(-)

diff --git a/src/event.zig b/src/event.zig @@ -6,13 +6,12 @@ const ArrayList = std.ArrayList; const wl = @import("wayland").client.wl; const udev = @import("udev"); -const c = @import("c.zig"); const render = @import("render.zig"); const State = @import("main.zig").State; pub const Loop = struct { state: *State, - fds: [5]os.pollfd, + fds: [4]os.pollfd, monitor: *udev.Monitor, pub fn init(state: *State) !Loop { @@ -35,13 +34,11 @@ pub const Loop = struct { }; _ = os.linux.timerfd_settime(@intCast(i32, tfd), 0, &interval, null); - // inotify - const ifd = os.linux.inotify_init1(os.linux.IN.CLOEXEC); - // udev const context = try udev.Udev.new(); const monitor = try udev.Monitor.newFromNetlink(context, "udev"); try monitor.filterAddMatchSubsystemDevType("backlight", null); + try monitor.filterAddMatchSubsystemDevType("power_supply", null); try monitor.enableReceiving(); const ufd = try monitor.getFd(); @@ -64,11 +61,6 @@ pub const Loop = struct { .revents = 0, }, .{ - .fd = @intCast(os.fd_t, ifd), - .events = os.POLL.IN, - .revents = 0, - }, - .{ .fd = @intCast(os.fd_t, ufd), .events = os.POLL.IN, .revents = 0, @@ -80,7 +72,6 @@ pub const Loop = struct { pub fn run(self: *Loop) !void { const display = self.state.wayland.display; - const tfd = self.fds[2].fd; while (true) { while (true) { @@ -114,6 +105,7 @@ pub const Loop = struct { // timer if (self.fds[2].revents & os.POLL.IN != 0) { + const tfd = self.fds[2].fd; var expirations = mem.zeroes([8]u8); _ = try os.read(tfd, &expirations); @@ -128,25 +120,8 @@ pub const Loop = struct { } } - // inotify - if (self.fds[3].revents & os.POLL.IN != 0) { - const ifd = self.fds[3].fd; - var event = mem.zeroes(os.linux.inotify_event); - _ = try os.read(ifd, mem.asBytes(&event)); - - for (self.state.wayland.outputs.items) |output| { - if (output.surface) |surface| { - if (surface.configured) { - render.renderModules(surface) catch continue; - surface.modulesSurface.commit(); - surface.backgroundSurface.commit(); - } - } - } - } - // udev - if (self.fds[4].revents & os.POLL.IN != 0) { + if (self.fds[3].revents & os.POLL.IN != 0) { _ = try self.monitor.receiveDevice(); for (self.state.wayland.outputs.items) |output| { diff --git a/src/modules.zig b/src/modules.zig @@ -31,36 +31,29 @@ pub const Module = struct { pub const Battery = struct { state: *State, - path: []const u8, - watch: i32, + context: *udev.Udev, + devices: DeviceList, - pub const Data = struct { - value: u8, - icon: []const u8, + const Device = struct { + name: []const u8, + voltage: u64, + charge: u64, + charge_full: u64, + status: []const u8, }; + const DeviceList = std.ArrayList(Device); pub fn init(state: *State) !Battery { - const path = try fs.path.join( - state.allocator, - &.{ "/sys/class/power_supply", state.config.batteryDev }, - ); - - const uevent_path = try fs.path.joinZ( - state.allocator, - &.{ path, "uevent" }, - ); - defer state.allocator.free(uevent_path); - - const watch = os.linux.inotify_add_watch( - state.loop.fds[3].fd, - uevent_path, - os.linux.IN.ACCESS, - ); + const context = try udev.Udev.new(); + + var devices = DeviceList.init(state.allocator); + try updateDevices(state.allocator, context, &devices); + if (devices.items.len == 0) return error.NoDevicesFound; return Battery{ .state = state, - .path = path, - .watch = @intCast(i32, watch), + .context= context, + .devices = devices, }; } @@ -71,59 +64,73 @@ pub const Battery = struct { pub fn print(self_opaque: *anyopaque, writer: StringWriter) !void { const self = Module.cast(Battery)(self_opaque); - const data = try self.readData(); - try fmt.format(writer, "{s} {d}%", .{ data.icon, data.value }); - } - - fn readData(self: *const Battery) !Data { - const voltage = try self.readInt("voltage_now"); - const charge = try self.readInt("charge_now"); - const charge_full = try self.readInt("charge_full"); - - const energy = @as(u64, charge) * @as(u64, voltage) / 1000000; - const energy_full = @as(u64, charge_full) * @as(u64, voltage) / 1000000; + try updateDevices(self.state.allocator, self.context, &self.devices); + const device = self.devices.items[0]; + const energy = device.charge * device.voltage / 1000000; + const energy_full = device.charge_full * device.voltage / 1000000; var capacity = @intToFloat(f64, energy) * 100.0; capacity /= @intToFloat(f64, energy_full); - const status = try self.readValue("status"); - var icon: []const u8 = "❓"; - if (mem.eql(u8, status, "Discharging")) { + if (mem.eql(u8, device.status, "Discharging")) { icon = "🔋"; - } else if (mem.eql(u8, status, "Charging")) { + } else if (mem.eql(u8, device.status, "Charging")) { icon = "🔌"; - } else if (mem.eql(u8, status, "Full")) { + } else if (mem.eql(u8, device.status, "Full")) { icon = "⚡"; } - return Data{ - .value = @floatToInt(u8, @round(capacity)), - .icon = icon, - }; + const value = @floatToInt(u8, @round(capacity)); + try fmt.format(writer, "{s} {d}%", .{ icon, value }); } - fn readInt(self: *const Battery, filename: []const u8) !u32 { - const value = try self.readValue(filename); - defer self.state.allocator.free(value); + fn updateDevices( + allocator: mem.Allocator, + context: *udev.Udev, + devices: *DeviceList, + ) !void { + const enumerate = try udev.Enumerate.new(context); + try enumerate.addMatchSubsystem("power_supply"); + try enumerate.addMatchSysattr("type", "Battery"); + try enumerate.scanDevices(); + const entries = enumerate.getListEntry(); - return fmt.parseInt(u32, value, 10); + var maybe_entry = entries; + while (maybe_entry) |entry| { + const path = entry.getName(); + const device = try udev.Device.newFromSyspath(context, path); + try updateOrAppend(allocator, devices, device); + maybe_entry = entry.getNext(); + } } - fn readValue(self: *const Battery, filename: []const u8) ![]u8 { - const state = self.state; - - const path = try fs.path.join( - state.allocator, - &.{ self.path, filename }, - ); - defer state.allocator.free(path); - - const file = try fs.openFileAbsolute(path, .{}); - defer file.close(); + fn updateOrAppend( + allocator: mem.Allocator, + devices: *DeviceList, + dev: *udev.Device, + ) !void { + const voltage = try dev.getSysattrValue("voltage_now"); + const charge = try dev.getSysattrValue("charge_now"); + const charge_full = try dev.getSysattrValue("charge_full"); + const status = try dev.getSysattrValue("status"); + const name = try dev.getSysname(); - var str = try file.readToEndAlloc(state.allocator, 128); - return state.allocator.resize(str, str.len - 1).?; + const device = blk: { + for (devices.items) |*device| { + if (mem.eql(u8, device.name, name)) { + break :blk device; + } + } else { + const device = try devices.addOne(); + device.name = try allocator.dupe(u8, name); + break :blk device; + } + }; + device.voltage = try fmt.parseInt(u64, voltage, 10); + device.charge = try fmt.parseInt(u64, charge, 10); + device.charge_full = try fmt.parseInt(u64, charge_full, 10); + device.status = try allocator.dupe(u8, status); } };