summaryrefslogtreecommitdiff
path: root/src/services/gpu.ts
blob: 5ac2d8dc4668c4c5841958919b4dcfa34f26727e (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
56
57
58
59
60
61
62
63
import { execAsync, Gio, GLib, 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");
            })
            .catch(console.error);
    }

    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 (GLib.file_test(`/sys/class/drm/${info.get_name()}/device/gpu_busy_percent`, GLib.FileTest.EXISTS)) {
                this.available = true;
                break;
            }
        }

        if (this.available) {
            let source = interval(config.interval.get(), () => this.update());
            config.interval.subscribe(i => {
                source.cancel();
                source = interval(i, () => this.update());
            });
        }
    }
}