diff --git a/src/main.zig b/src/main.zig index 1489993..369d6ca 100644 --- a/src/main.zig +++ b/src/main.zig @@ -9,7 +9,7 @@ const weatherWidget = @import("widgets/weather/weather.zig"); const timeWidget = @import("widgets/time/time.zig"); const batteryWidget = @import("widgets/battery/battery.zig"); const memoryWidget = @import("widgets/memory/memory.zig"); -const cpuWidget = @import("widgets/memory/memory.zig"); +const cpuWidget = @import("widgets/cpu/cpu.zig"); const DebugAllocator = @import("debug_allocator.zig"); const Info = @import("types/info.zig"); @@ -32,11 +32,11 @@ pub fn main() !void { const widgets = [_]*Widget{ //&Widget.init(&textWidget.New("owo", "potato")), // 4KiB //&Widget.init(&textWidget.New("uwu", "tomato")), // 4KiB - &Widget.init(&cpuWidget.New(&br)), // Unknown - &Widget.init(&memoryWidget.New(&br)), // 4.08KiB - &Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB - &Widget.init(&batteryWidget.New(allocator, &br)), // 12.11KiB - &Widget.init(&timeWidget.New(allocator, &br)), // 32.46KiB + &Widget.init(&cpuWidget.New(&br)), // 4.08KiB + //&Widget.init(&memoryWidget.New(&br)), // 4.08KiB + //&Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB + //&Widget.init(&batteryWidget.New(allocator, &br)), // 12.11KiB + //&Widget.init(&timeWidget.New(allocator, &br)), // 32.46KiB }; bar.widgets = widgets[0..]; try br.start(); diff --git a/src/widgets/cpu/cpu.zig b/src/widgets/cpu/cpu.zig index b2af4fd..85f8d6e 100644 --- a/src/widgets/cpu/cpu.zig +++ b/src/widgets/cpu/cpu.zig @@ -4,8 +4,63 @@ const Bar = @import("../../types/bar.zig").Bar; const colour = @import("../../formatting/colour.zig").colour; const comptimeColour = @import("../../formatting/colour.zig").comptimeColour; const MouseEvent = @import("../../types/mouseevent.zig"); -const LoopingCounter = @import("../../types/loopingcounter.zig").LoopingCounter; +fn formatCPUPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8 { + var percentColour: []const u8 = ""; + if (percent > 80) { + percentColour = "red"; + } else if (percent > 60) { + percentColour = "orange"; + } else if (percent > 30) { + percentColour = "yellow"; + } else { + percentColour = "green"; + } + const percentString = try std.fmt.allocPrint(allocator, "{d:.2}" ++ comptimeColour("accentdark", "%"), .{ percent }); + + return colour(allocator, percentColour, percentString); +} + +fn parseFloat(buf: []const u8) !f64 { + return try std.fmt.parseFloat(f64, buf); +} + +fn fetchCPU() ![2]f64 { + var stat_file = try std.fs.cwd().openFile("/proc/stat", .{ .read = true, .write = false }); + defer stat_file.close(); + // data[0] = idle usage + // data[1] = non-idle usage + var data: [2]f64 = [2]f64{0.0,0.0}; + + var line_buffer: [128]u8 = undefined; + const line_opt = try stat_file.inStream().readUntilDelimiterOrEof(&line_buffer, '\n'); + if (line_opt) |line| { + var it = std.mem.tokenize(line, " "); + const stat_type = it.next().?; + if (!std.mem.eql(u8, stat_type, "cpu")) { + std.debug.print("First stat line wasn't CPU, Add while loop to find it.\n", .{}); + unreachable; + } + // Here are the fields. + // Ones marked with (i) are idle. + // The order for these is: + // user nice system idle(i) iowait(i) irq softirq steal guest guest_nice + data[1] += try parseFloat(it.next().?); // user + data[1] += try parseFloat(it.next().?); // nice + data[1] += try parseFloat(it.next().?); // system + data[0] += try parseFloat(it.next().?); // idle + data[0] += try parseFloat(it.next().?); // iowait + data[1] += try parseFloat(it.next().?); // irq + data[1] += try parseFloat(it.next().?); // softirq + data[1] += try parseFloat(it.next().?); // steal + data[1] += try parseFloat(it.next().?); // guest + data[1] += try parseFloat(it.next().?); // guest_nice + } else { + unreachable; + } + + return data; +} pub const CPUWidget = struct { bar: *Bar, @@ -23,12 +78,41 @@ pub const CPUWidget = struct { pub fn mouse_event(self: *CPUWidget, event: MouseEvent) void {} fn update_bar(self: *CPUWidget) !void { + // We need to calculate the difference between readings to get a more accurate reading. + // In order to do this we need a time difference. + const previous_stats = try fetchCPU(); + std.time.sleep(1000 * std.time.ns_per_ms); + const next_stats = try fetchCPU(); + // Reminder that for data: + // data[0] = idle usage + // data[1] = non-idle usage + const previous_total = previous_stats[0] + previous_stats[1]; + const next_total = next_stats[0] + next_stats[1]; + // Get the differences. + const total_difference = next_total - previous_total; + const idle_difference = next_stats[0] - previous_stats[0]; + // Work out CPU Percentage. + const percentage = ((total_difference - idle_difference)/total_difference)*100; + + + var buffer: [256]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buffer); + var allocator = &fba.allocator; + try self.bar.add(Info{ + .name = "cpu", + .full_text = try std.fmt.allocPrint(allocator, "{} {}", .{ + comptimeColour("accentlight", "cpu"), + formatCPUPercent(allocator, percentage), + }), + .markup = "pango", + }); } pub fn start(self: *CPUWidget) anyerror!void { - //while (self.bar.keep_running()) { - // self.update_bar() catch {}; - //} + //try self.update_bar(); + while (self.bar.keep_running()) { + try self.update_bar(); + } } }; diff --git a/src/widgets/memory/memory.zig b/src/widgets/memory/memory.zig index f31f67d..b18124c 100644 --- a/src/widgets/memory/memory.zig +++ b/src/widgets/memory/memory.zig @@ -35,8 +35,7 @@ fn formatMemoryPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8 } else { percentColour = "green"; } - const percentString = try std.fmt.allocPrint(allocator, "{d:.3}{}", .{ percent, comptimeColour("accentdark", "%") }); - + const percentString = try std.fmt.allocPrint(allocator, "{d:.2}" ++ comptimeColour("accentdark", "%"), .{ percent }); return colour(allocator, percentColour, percentString); }