oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
4,065 bytes raw
1
const std = @import("std");
2
const format_util = @import("format.zig");
3
4
pub const Cpu_Temp = struct {
5
    format: []const u8,
6
    device: []const u8,
7
    interval_secs: u64,
8
    color: c_ulong,
9
    cached_path: [128]u8,
10
    cached_path_len: usize,
11
12
    pub fn init(
13
        format: []const u8,
14
        device: []const u8,
15
        interval_secs: u64,
16
        color: c_ulong,
17
    ) Cpu_Temp {
18
        var self = Cpu_Temp{
19
            .format = format,
20
            .device = device,
21
            .interval_secs = interval_secs,
22
            .color = color,
23
            .cached_path = undefined,
24
            .cached_path_len = 0,
25
        };
26
        self.detect_path();
27
        return self;
28
    }
29
30
    fn detect_path(self: *Cpu_Temp) void {
31
        if (self.device.len > 0 and self.device[0] == '/') {
32
            if (self.device.len <= self.cached_path.len) {
33
                @memcpy(self.cached_path[0..self.device.len], self.device);
34
                self.cached_path_len = self.device.len;
35
            }
36
            return;
37
        }
38
39
        if (self.device.len > 0) {
40
            if (self.try_path("/sys/class/thermal/{s}/temp", self.device)) return;
41
            if (self.try_path("/sys/class/hwmon/{s}/temp1_input", self.device)) return;
42
        }
43
44
        if (self.find_hwmon_cpu()) return;
45
46
        if (self.try_path("/sys/class/thermal/{s}/temp", "thermal_zone0")) return;
47
    }
48
49
    fn try_path(self: *Cpu_Temp, comptime fmt: []const u8, device: []const u8) bool {
50
        const path = std.fmt.bufPrint(&self.cached_path, fmt, .{device}) catch return false;
51
        const file = std.fs.openFileAbsolute(path, .{}) catch return false;
52
        file.close();
53
        self.cached_path_len = path.len;
54
        return true;
55
    }
56
57
    fn find_hwmon_cpu(self: *Cpu_Temp) bool {
58
        var dir = std.fs.openDirAbsolute("/sys/class/hwmon", .{ .iterate = true }) catch return false;
59
        defer dir.close();
60
61
        var iter = dir.iterate();
62
        while (iter.next() catch null) |entry| {
63
            if (entry.kind != .directory and entry.kind != .sym_link) continue;
64
65
            var name_path: [128]u8 = undefined;
66
            const name_path_str = std.fmt.bufPrint(&name_path, "/sys/class/hwmon/{s}/name", .{entry.name}) catch continue;
67
68
            const name_file = std.fs.openFileAbsolute(name_path_str, .{}) catch continue;
69
            defer name_file.close();
70
71
            var name_buf: [32]u8 = undefined;
72
            const name_len = name_file.read(&name_buf) catch continue;
73
            const name = std.mem.trim(u8, name_buf[0..name_len], " \n\r\t");
74
75
            if (std.mem.eql(u8, name, "coretemp") or std.mem.eql(u8, name, "k10temp")) {
76
                const temp_path = std.fmt.bufPrint(&self.cached_path, "/sys/class/hwmon/{s}/temp1_input", .{entry.name}) catch continue;
77
                const temp_file = std.fs.openFileAbsolute(temp_path, .{}) catch continue;
78
                temp_file.close();
79
                self.cached_path_len = temp_path.len;
80
                return true;
81
            }
82
        }
83
        return false;
84
    }
85
86
    pub fn content(self: *Cpu_Temp, buffer: []u8) []const u8 {
87
        if (self.cached_path_len == 0) return buffer[0..0];
88
89
        const path = self.cached_path[0..self.cached_path_len];
90
        const file = std.fs.openFileAbsolute(path, .{}) catch return buffer[0..0];
91
        defer file.close();
92
93
        var temp_buf: [16]u8 = undefined;
94
        const len = file.read(&temp_buf) catch return buffer[0..0];
95
        const temp_str = std.mem.trim(u8, temp_buf[0..len], " \n\r\t");
96
97
        const millidegrees = std.fmt.parseInt(i32, temp_str, 10) catch return buffer[0..0];
98
        const degrees = @divTrunc(millidegrees, 1000);
99
100
        var deg_buf: [8]u8 = undefined;
101
        const deg_str = std.fmt.bufPrint(&deg_buf, "{d}", .{degrees}) catch return buffer[0..0];
102
103
        return format_util.substitute(self.format, deg_str, buffer);
104
    }
105
106
    pub fn interval(self: *Cpu_Temp) u64 {
107
        return self.interval_secs;
108
    }
109
110
    pub fn get_color(self: *Cpu_Temp) c_ulong {
111
        return self.color;
112
    }
113
};