M src/Loop.zig => src/Loop.zig +1 -1
@@ 50,7 50,7 @@ pub fn run(self: *Loop) !void {
.callbackOut = Event.noop,
});
try events.append(gpa, try self.state.wayland.getEvent());
- for (self.state.modules.items) |*module| {
+ for (self.state.modules.modules.items) |*module| {
try events.append(gpa, try module.getEvent());
}
A src/Modules.zig => src/Modules.zig +53 -0
@@ 0,0 1,53 @@
+const std = @import("std");
+const ArrayList = std.ArrayList;
+
+const Event = @import("Loop.zig").Event;
+const State = @import("main.zig").State;
+const Modules = @This();
+
+state: *State,
+modules: ArrayList(Module),
+
+pub const Alsa = @import("modules/Alsa.zig");
+pub const Backlight = @import("modules/Backlight.zig");
+pub const Battery = @import("modules/Battery.zig");
+
+pub const Module = struct {
+ impl: *anyopaque,
+ funcs: struct {
+ getEvent: fn (*anyopaque) anyerror!Event,
+ print: fn (*anyopaque, StringWriter) anyerror!void,
+ destroy: fn (*anyopaque) void,
+ },
+
+ pub const StringWriter = std.ArrayList(u8).Writer;
+
+ pub fn getEvent(self: *Module) !Event {
+ return self.funcs.getEvent(self.impl);
+ }
+
+ pub fn print(self: *Module, writer: StringWriter) !void {
+ return self.funcs.print(self.impl, writer);
+ }
+
+ pub fn destroyInstance(self: *Module) void {
+ return self.funcs.destroy(self.impl);
+ }
+};
+
+pub fn init(state: *State) Modules {
+ return Modules{
+ .state = state,
+ .modules = ArrayList(Module).init(state.gpa),
+ };
+}
+
+pub fn deinit(self: *Modules) void {
+ for (self.modules.items) |*module| module.destroyInstance();
+ self.modules.deinit();
+}
+
+pub fn register(self: *Modules, comptime ModuleType: type) !void {
+ const instance = try ModuleType.create(self.state);
+ try self.modules.append(try instance.module());
+}
M src/main.zig => src/main.zig +7 -20
@@ 6,19 6,15 @@ const fcft = @import("fcft");
const Config = @import("Config.zig");
const Loop = @import("Loop.zig");
-const modules = @import("modules.zig");
+const Modules = @import("Modules.zig");
const Wayland = @import("wayland.zig").Wayland;
pub const State = struct {
gpa: mem.Allocator,
config: Config,
wayland: Wayland,
+ modules: Modules,
loop: Loop,
-
- alsa: modules.Alsa,
- backlight: modules.Backlight,
- battery: modules.Battery,
- modules: std.ArrayList(modules.Module),
};
pub fn main() anyerror!void {
@@ 33,23 29,14 @@ pub fn main() anyerror!void {
state.config = try Config.init();
state.wayland = try Wayland.init(&state);
defer state.wayland.deinit();
+ state.modules = Modules.init(&state);
+ defer state.modules.deinit();
state.loop = try Loop.init(&state);
// modules
- state.modules = std.ArrayList(modules.Module).init(state.gpa);
- defer state.modules.deinit();
-
- state.alsa = try modules.Alsa.init(&state);
- state.backlight = try modules.Backlight.init(&state);
- defer state.backlight.deinit();
- state.battery = try modules.Battery.init(&state);
- defer state.battery.deinit();
-
- try state.modules.appendSlice(&.{
- try state.backlight.module(),
- state.battery.module(),
- state.alsa.module(),
- });
+ try state.modules.register(Modules.Alsa);
+ try state.modules.register(Modules.Backlight);
+ try state.modules.register(Modules.Battery);
// event loop
try state.wayland.registerGlobals();
D src/modules.zig => src/modules.zig +0 -23
@@ 1,23 0,0 @@
-const std = @import("std");
-
-const Event = @import("Loop.zig").Event;
-
-pub const Alsa = @import("modules/Alsa.zig");
-pub const Backlight = @import("modules/Backlight.zig");
-pub const Battery = @import("modules/Battery.zig");
-
-pub const Module = struct {
- impl: *anyopaque,
- eventFn: fn (*anyopaque) anyerror!Event,
- printFn: fn (*anyopaque, StringWriter) anyerror!void,
-
- pub const StringWriter = std.ArrayList(u8).Writer;
-
- pub fn getEvent(self: *Module) !Event {
- return self.eventFn(self.impl);
- }
-
- pub fn print(self: *Module, writer: StringWriter) !void {
- return self.printFn(self.impl, writer);
- }
-};
M src/modules/Alsa.zig => src/modules/Alsa.zig +45 -22
@@ 6,7 6,7 @@ const os = std.os;
const alsa = @cImport(@cInclude("alsa/asoundlib.h"));
-const Module = @import("../modules.zig").Module;
+const Module = @import("../Modules.zig").Module;
const Event = @import("../Loop.zig").Event;
const render = @import("../render.zig");
const State = @import("../main.zig").State;
@@ 14,20 14,44 @@ const utils = @import("../utils.zig");
const Alsa = @This();
state: *State,
-context: *alsa.snd_ctl_t,
+devices: DeviceList,
-pub fn init(state: *State) !Alsa {
- return Alsa{
+const Device = struct {
+ ctl: *alsa.snd_ctl_t,
+ name: []const u8,
+};
+
+const DeviceList = std.ArrayList(Device);
+
+pub fn create(state: *State) !*Alsa {
+ const self = try state.gpa.create(Alsa);
+ self.* = .{
.state = state,
- .context = try getAlsaCtl(state.gpa),
+ .devices = DeviceList.init(state.gpa),
};
+
+ var card: i32 = -1;
+ while(alsa.snd_card_next(&card) >= 0 and card >= 0) {
+ const name = try fmt.allocPrintZ(state.gpa, "hw:{d}", .{ card });
+
+ var ctl: ?*alsa.snd_ctl_t = null;
+ _ = alsa.snd_ctl_open(&ctl, name.ptr, alsa.SND_CTL_READONLY);
+ _ = alsa.snd_ctl_subscribe_events(ctl, 1);
+
+ try self.devices.append(.{ .ctl = ctl.?, .name = name });
+ }
+
+ return self;
}
-pub fn module(self: *Alsa) Module {
- return .{
+pub fn module(self: *Alsa) !Module {
+ return Module{
.impl = @ptrCast(*anyopaque, self),
- .eventFn = getEvent,
- .printFn = print,
+ .funcs = .{
+ .getEvent = getEvent,
+ .print = print,
+ .destroy = destroy,
+ },
};
}
@@ 35,7 59,8 @@ fn getEvent(self_opaque: *anyopaque) !Event {
const self = utils.cast(Alsa)(self_opaque);
var fd = mem.zeroes(alsa.pollfd);
- _ = alsa.snd_ctl_poll_descriptors(self.context, &fd, 1);
+ const device = &self.devices.items[0];
+ _ = alsa.snd_ctl_poll_descriptors(device.ctl, &fd, 1);
return Event{
.fd = @bitCast(os.pollfd, fd),
@@ 61,7 86,6 @@ fn print(self_opaque: *anyopaque, writer: Module.StringWriter) !void {
alsa.snd_mixer_selem_id_set_index(sid, 0);
alsa.snd_mixer_selem_id_set_name(sid, "Master");
const elem = alsa.snd_mixer_find_selem(handle, sid);
- _ = elem;
var unmuted: i32 = 0;
_ = alsa.snd_mixer_selem_get_playback_switch(
@@ 98,7 122,9 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void {
var event: ?*alsa.snd_ctl_event_t = null;
_ = alsa.snd_ctl_event_malloc(&event);
defer alsa.snd_ctl_event_free(event);
- _ = alsa.snd_ctl_read(self.context, event);
+
+ const device = &self.devices.items[0];
+ _ = alsa.snd_ctl_read(device.ctl, event);
for (self.state.wayland.monitors.items) |monitor| {
if (monitor.bar) |bar| {
@@ 113,15 139,12 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void {
}
}
-fn getAlsaCtl(gpa: mem.Allocator) !*alsa.snd_ctl_t {
- var card: i32 = -1;
- _ = alsa.snd_card_next(&card);
- const name = try fmt.allocPrintZ(gpa, "hw:{d}", .{ card });
- defer gpa.free(name);
-
- var ctl: ?*alsa.snd_ctl_t = null;
- _ = alsa.snd_ctl_open(&ctl, name.ptr, alsa.SND_CTL_READONLY);
- _ = alsa.snd_ctl_subscribe_events(ctl, 1);
+fn destroy(self_opaque: *anyopaque) void {
+ const self = utils.cast(Alsa)(self_opaque);
- return ctl.?;
+ for (self.devices.items) |*device| {
+ self.state.gpa.free(device.name);
+ }
+ self.devices.deinit();
+ self.state.gpa.destroy(self);
}
M src/modules/Backlight.zig => src/modules/Backlight.zig +31 -32
@@ 5,7 5,7 @@ const os = std.os;
const udev = @import("udev");
-const Module = @import("../modules.zig").Module;
+const Module = @import("../Modules.zig").Module;
const Event = @import("../Loop.zig").Event;
const render = @import("../render.zig");
const State = @import("../main.zig").State;
@@ 21,51 21,39 @@ const Device = struct {
name: []const u8,
value: u64,
max: u64,
-
- pub fn deinit(self: *Device, gpa: mem.Allocator) void {
- gpa.free(self.name);
- }
};
const DeviceList = std.ArrayList(Device);
-pub fn init(state: *State) !Backlight {
- 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();
+pub fn create(state: *State) !*Backlight {
+ const self = try state.gpa.create(Backlight);
+ self.state = state;
+ self.context = try udev.Udev.new();
- var devices = DeviceList.init(state.gpa);
- try updateDevices(state.gpa, context, &devices);
- if (devices.items.len == 0) return error.NoDevicesFound;
+ self.monitor = try udev.Monitor.newFromNetlink(self.context, "udev");
+ try self.monitor.filterAddMatchSubsystemDevType("backlight", null);
+ try self.monitor.filterAddMatchSubsystemDevType("power_supply", null);
+ try self.monitor.enableReceiving();
- return Backlight{
- .state = state,
- .context = context,
- .monitor = monitor,
- .devices = devices,
- };
-}
+ self.devices = DeviceList.init(state.gpa);
+ try updateDevices(state.gpa, self.context, &self.devices);
+ if (self.devices.items.len == 0) return error.NoDevicesFound;
-pub fn deinit(self: *Backlight) void {
- _ = self.context.unref();
- for (self.devices.items) |*device| {
- device.deinit(self.state.gpa);
- }
- self.devices.deinit();
+ return self;
}
pub fn module(self: *Backlight) !Module {
return Module{
.impl = @ptrCast(*anyopaque, self),
- .eventFn = getEvent,
- .printFn = print,
+ .funcs = .{
+ .getEvent = getEvent,
+ .print = print,
+ .destroy = destroy,
+ },
};
}
-pub fn getEvent(self_opaque: *anyopaque) !Event {
+fn getEvent(self_opaque: *anyopaque) !Event {
const self = utils.cast(Backlight)(self_opaque);
return Event{
@@ 95,7 83,7 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void {
}
}
-pub fn print(self_opaque: *anyopaque, writer: Module.StringWriter) !void {
+fn print(self_opaque: *anyopaque, writer: Module.StringWriter) !void {
const self = utils.cast(Backlight)(self_opaque);
try updateDevices(self.state.gpa, self.context, &self.devices);
@@ 148,3 136,14 @@ fn updateOrAppend(
device.value = try fmt.parseInt(u64, value, 10);
device.max = try fmt.parseInt(u64, max, 10);
}
+
+fn destroy(self_opaque: *anyopaque) void {
+ const self = utils.cast(Backlight)(self_opaque);
+
+ _ = self.context.unref();
+ for (self.devices.items) |*device| {
+ self.state.gpa.free(device.name);
+ }
+ self.devices.deinit();
+ self.state.gpa.destroy(self);
+}
M src/modules/Battery.zig => src/modules/Battery.zig +58 -55
@@ 5,7 5,7 @@ const os = std.os;
const udev = @import("udev");
-const Module = @import("../modules.zig").Module;
+const Module = @import("../Modules.zig").Module;
const Event = @import("../Loop.zig").Event;
const render = @import("../render.zig");
const State = @import("../main.zig").State;
@@ 21,53 21,44 @@ const Device = struct {
name: []const u8,
status: []const u8,
capacity: u8,
-
- pub fn deinit(self: *Device, gpa: mem.Allocator) void {
- gpa.free(self.name);
- gpa.free(self.status);
- }
};
const DeviceList = std.ArrayList(Device);
-pub fn init(state: *State) !Battery {
- const tfd = os.linux.timerfd_create(
- os.CLOCK.MONOTONIC,
- os.linux.TFD.CLOEXEC,
- );
- const interval: os.linux.itimerspec = .{
- .it_interval = .{ .tv_sec = 10, .tv_nsec = 0 },
- .it_value = .{ .tv_sec = 10, .tv_nsec = 0 },
+pub fn create(state: *State) !*Battery {
+ const self = try state.gpa.create(Battery);
+ self.state = state;
+
+ self.timerFd = tfd: {
+ const fd = os.linux.timerfd_create(
+ os.CLOCK.MONOTONIC,
+ os.linux.TFD.CLOEXEC,
+ );
+ const interval: os.linux.itimerspec = .{
+ .it_interval = .{ .tv_sec = 10, .tv_nsec = 0 },
+ .it_value = .{ .tv_sec = 10, .tv_nsec = 0 },
+ };
+ _ = os.linux.timerfd_settime(@intCast(i32, fd), 0, &interval, null);
+ break :tfd @intCast(os.fd_t, fd);
};
- _ = os.linux.timerfd_settime(@intCast(i32, tfd), 0, &interval, null);
- const context = try udev.Udev.new();
+ self.context = try udev.Udev.new();
- var devices = DeviceList.init(state.gpa);
- try updateDevices(state.gpa, context, &devices);
- if (devices.items.len == 0) return error.NoDevicesFound;
+ self.devices = DeviceList.init(state.gpa);
+ try updateDevices(state.gpa, self.context, &self.devices);
+ if (self.devices.items.len == 0) return error.NoDevicesFound;
- return Battery{
- .state = state,
- .context = context,
- .timerFd = @intCast(os.fd_t, tfd),
- .devices = devices,
- };
-}
-
-pub fn deinit(self: *Battery) void {
- _ = self.context.unref();
- for (self.devices.items) |*device| {
- device.deinit(self.state.gpa);
- }
- self.devices.deinit();
+ return self;
}
-pub fn module(self: *Battery) Module {
- return .{
+pub fn module(self: *Battery) !Module {
+ return Module{
.impl = @ptrCast(*anyopaque, self),
- .eventFn = getEvent,
- .printFn = print,
+ .funcs = .{
+ .getEvent = getEvent,
+ .print = print,
+ .destroy = destroy,
+ },
};
}
@@ 86,6 77,36 @@ pub fn getEvent(self_opaque: *anyopaque) !Event {
};
}
+pub fn print(self_opaque: *anyopaque, writer: Module.StringWriter) !void {
+ const self = utils.cast(Battery)(self_opaque);
+
+ try updateDevices(self.state.gpa, self.context, &self.devices);
+ const device = self.devices.items[0];
+
+ var icon: []const u8 = "❓";
+ if (mem.eql(u8, device.status, "Discharging")) {
+ icon = "🔋";
+ } else if (mem.eql(u8, device.status, "Charging")) {
+ icon = "🔌";
+ } else if (mem.eql(u8, device.status, "Full")) {
+ icon = "⚡";
+ }
+
+ try fmt.format(writer, "{s} {d}%", .{ icon, device.capacity });
+}
+
+pub fn destroy(self_opaque: *anyopaque) void {
+ const self = utils.cast(Battery)(self_opaque);
+
+ _ = self.context.unref();
+ for (self.devices.items) |*device| {
+ self.state.gpa.free(device.name);
+ self.state.gpa.free(device.status);
+ }
+ self.devices.deinit();
+ self.state.gpa.destroy(self);
+}
+
fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void {
const self = utils.cast(Battery)(self_opaque);
@@ 105,24 126,6 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void {
}
}
-pub fn print(self_opaque: *anyopaque, writer: Module.StringWriter) !void {
- const self = utils.cast(Battery)(self_opaque);
-
- try updateDevices(self.state.gpa, self.context, &self.devices);
- const device = self.devices.items[0];
-
- var icon: []const u8 = "❓";
- if (mem.eql(u8, device.status, "Discharging")) {
- icon = "🔋";
- } else if (mem.eql(u8, device.status, "Charging")) {
- icon = "🔌";
- } else if (mem.eql(u8, device.status, "Full")) {
- icon = "⚡";
- }
-
- try fmt.format(writer, "{s} {d}%", .{ icon, device.capacity });
-}
-
fn updateDevices(
gpa: mem.Allocator,
context: *udev.Udev,
M src/render.zig => src/render.zig +1 -1
@@ 121,7 121,7 @@ pub fn renderModules(bar: *Bar) !void {
defer string.deinit();
const writer = string.writer();
- for (state.modules.items) |*module| {
+ for (state.modules.modules.items) |*module| {
try std.fmt.format(writer, " | ", .{});
try module.print(writer);
}