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());
});
}
}
}
|