summaryrefslogtreecommitdiff
path: root/src/services/gpu.ts
blob: 916a2bc524e13b1756f50c93f4ef891424ccf910 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { execAsync, Gio, GObject, interval, property, register } from "astal";
import { gpu as config } from "config";

@register({ GTypeName: "Gpu" })
export default class Gpu extends GObject.Object {
    static instance: Gpu;
    static get_default() {
        if (!this.instance) this.instance = new Gpu();

        return this.instance;
    }

    readonly available: boolean = false;
    #usage: number = 0;

    @property(Number)
    get usage() {
        return this.#usage;
    }

    async calculateUsage() {
        const percs = (await execAsync("fish -c 'cat /sys/class/drm/card*/device/gpu_busy_percent'")).split("\n");
        return percs.reduce((a, b) => a + parseFloat(b), 0) / percs.length;
    }

    update() {
        this.calculateUsage().then(usage => {
            this.#usage = usage;
            this.notify("usage");
        });
    }

    constructor() {
        super();

        let enumerator = null;
        try {
            enumerator = Gio.File.new_for_path("/sys/class/drm").enumerate_children(
                Gio.FILE_ATTRIBUTE_STANDARD_NAME,
                Gio.FileQueryInfoFlags.NONE,
                null
            );
        } catch {}

        let info: Gio.FileInfo | undefined | null;
        while ((info = enumerator?.next_file(null))) {
            if (/card[0-9]+/.test(info.get_name())) {
                this.available = true;
                break;
            }
        }

        if (this.available) interval(config.interval, () => this.update());
    }
}