ags: add brightness class, media widget on center-window and more

This commit is contained in:
retrozinndev
2025-02-15 08:24:00 -03:00
parent 2eb2f15db9
commit 6e9f2d4a7d
23 changed files with 441 additions and 268 deletions
+36 -2
View File
@@ -71,14 +71,47 @@ function handleVolumeArgs(args: Array<string>) {
if(!args[1])
return `Please specify what you want to do!\n\n${volumeHelp()}`
if(!/(sink|source)\-mute/.test(args[1]) && !args[2])
if(/^(sink|source)(\-increase|\-decrease|\-set)$/.test(args[1]) && !args[2])
return `You forgot to add a value to be set!`;
if(Number.isNaN(Number.parseFloat(args[2])) && Number.isSafeInteger(Number.parseFloat(args[2])))
return `Argument "${args[2]} is not a valid number! Please use integers"`;
const command: Array<string> = args[1].split('-');
if(/help/.test(args[1]))
return volumeHelp();
switch(command[1]) {
case "set":
command[0] === "sink" ?
Wireplumber.getDefault().setSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().setSourceVolume(Number.parseInt(args[2]))
return `Done! Set ${command[0]} volume to ${args[2]}`;
case "mute":
command[0] === "sink" ?
Wireplumber.getDefault().toggleMuteSink()
:
Wireplumber.getDefault().toggleMuteSource()
return `Done toggling mute!`;
case "increase":
command[0] === "sink" ?
Wireplumber.getDefault().increaseSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().increaseSourceVolume(Number.parseInt(args[2]))
return `Done increasing volume by ${args[2]}`;
case "decrease":
command[0] === "sink" ?
Wireplumber.getDefault().decreaseSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().decreaseSourceVolume(Number.parseInt(args[2]))
return `Done decreasing volume to ${args[2]}`;
}
return `Couldn't resolve arguments! "${args.join(' ').replace(new RegExp(`^${args[0]}`), "")}"`;
@@ -109,9 +142,10 @@ Options:
close [window_name]: sets specified window's visibility to false.
toggle [window_name]: toggles visibility of specified window.
reload: creates a new astal instance and removes this one.
volume: wireplumber volume controller, see "volume help".
help, -h, --help: shows this help message.
2024 (c) retrozinndev's Hyprland-Dots, licensed under the MIT License.
2025 (c) retrozinndev's Hyprland-Dots, licensed under the MIT License.
https://github.com/retrozinndev/Hyprland-Dots
`.trim();
}
+42
View File
@@ -0,0 +1,42 @@
import { exec, execAsync, GObject, monitorFile, Process, readFileAsync, register, signal } from "astal";
import { Connectable } from "astal/binding";
/** !!TODO!! Needs more work and testing
* I(retrozinndev) don't have a monitor that has software-controlled brightness
*/
@register({ GTypeName: "Brightness" })
class Brightness extends GObject.Object implements Connectable {
private readonly backlight: string|undefined;
private max: number;
private brightness: number;
@signal(Number)
declare brightnessChanged: (value: number) => void;
constructor(backlightDevice?: string) {
super();
this.backlight = backlightDevice || "";
this.max = Number.parseInt(exec(`brightnessctl -d ${backlightDevice} max`))
this.brightness = Number.parseInt(exec(`brightnessctl -d ${backlightDevice} get`))
readFileAsync(`/sys/class/backlight/${backlightDevice}/brightness`).catch(() => {
throw new Error(`Couldn't find backlight ${backlightDevice}`);
});
monitorFile(`/sys/class/backlight/${backlightDevice}/brightness`, async () => {
this.brightness = Number.parseInt(await execAsync(`brightnessctl -d ${backlightDevice} get`));
this.max = Number.parseInt(await execAsync(`brightnessctl -d ${backlightDevice} max`));
this.emit("brightness-changed", this.brightness);
});
}
public setBrightness(newBrightness: number): void {
execAsync(`brightnessctl -d ${this.backlight} set ${newBrightness || this.brightness}`).catch(() => {
throw new Error(`Couldn't set brightness of backlight ${this.backlight}`);
});
this.emit("brightness-changed", newBrightness);
}
}
+15 -10
View File
@@ -1,29 +1,32 @@
import AstalNotifd from "gi://AstalNotifd";
import { timeout } from "astal/time";
import { Connectable } from "astal/binding";
import { GObject, register, property, signal } from "astal";
import { GObject, register, signal } from "astal";
import { Windows } from "../windows";
@register()
class Notifications extends GObject.Object implements Connectable {
@register({ GTypeName: "Notifications" })
class NotificationsClass extends GObject.Object implements Connectable {
private static instance: Notifications;
private static instance: NotificationsClass;
private notifd: AstalNotifd.Notifd;
public notifications: Array<AstalNotifd.Notification> = [];
public notificationHistory: Array<AstalNotifd.Notification> = [];
@signal()
declare "notification-added": (notification: AstalNotifd.Notification) => void;
@signal(AstalNotifd.Notification)
declare notificationAdded: (added: AstalNotifd.Notification) => void;
@signal(Number)
declare notificationRemoved: (id: number) => void;
public static getDefault(): Notifications {
if(!Notifications.instance) {
Notifications.instance = new Notifications();
public static getDefault(): NotificationsClass {
if(!NotificationsClass.instance) {
NotificationsClass.instance = new NotificationsClass();
this.instance._init();
}
return Notifications.instance;
return NotificationsClass.instance;
}
constructor() {
@@ -95,3 +98,5 @@ class Notifications extends GObject.Object implements Connectable {
return this.notifd;
}
}
export const Notifications = new NotificationsClass();
+9 -8
View File
@@ -1,10 +1,11 @@
import { GObject } from "astal";
import { GObject, register } from "astal";
import AstalWp from "gi://AstalWp";
export const Wireplumber = GObject.registerClass({
GTypeName: "Wireplumber",
Signals: {}
}, class WireplumberClass extends GObject.Object {
export { WireplumberClass as Wireplumber };
@register({ GTypeName: "Wireplumber" })
class WireplumberClass extends GObject.Object {
private static astalWireplumber: (AstalWp.Wp|null) = AstalWp.get_default();
private static inst: WireplumberClass;
@@ -14,8 +15,8 @@ export const Wireplumber = GObject.registerClass({
private maxSinkVolume: number = 100;
private maxSourceVolume: number = 100;
_init(...props: any[]) {
super._init(props);
constructor() {
super();
if(!WireplumberClass.astalWireplumber)
throw new Error("Audio features will not work correctly! Please install wireplumber first", {
@@ -145,4 +146,4 @@ export const Wireplumber = GObject.registerClass({
return this.muteSource();
}
});
}