asta.nix/windows/Bar/services/brightness.ts
Chris Toph 8746fa0a6e Adds brightness control & biome config
• Updates IDE settings for improved file nesting and exclusions
• Introduces biome configuration file for consistent project formatting
• Implements brightness service and UI component for monitor brightness control
• Refactors layout and code formatting for consistency across components
2025-05-10 19:28:47 -04:00

113 lines
2.7 KiB
TypeScript

import { exec } from 'astal'
import GObject, { register, property, signal } from 'astal/gobject'
@register({ GTypeName: 'BrightnessService' })
export default class BrightnessService extends GObject.Object {
private declare _value: number
private declare _buses: string[]
private declare _max: number
@property(Number)
get value() {
return this._value
}
set value(value: number) {
// Ensure value is between 0-100
this._value = Math.min(100, Math.max(0, Math.round(value)))
console.log(`Setting brightness to ${this._value}%`)
this._buses.forEach((bus) => {
exec(`ddcutil setvcp 10 ${this._value} --bus ${bus}`)
})
this.emit('value_changed', this._value)
this.refreshUI()
}
@property(String)
get iconName() {
if (this._value < 25) {
return 'display-brightness-low-symbolic'
} else if (this._value < 75) {
return 'display-brightness-medium-symbolic'
} else {
return 'display-brightness-high-symbolic'
}
}
constructor() {
super()
this._value = 0
this._max = 100 // DDC brightness is typically 0-100
this._buses = this.detectBuses()
// Initialize
this.init()
}
detectBuses() {
try {
const detectOutput = exec('ddcutil detect')
const busRegex = /I2C bus:\s+\/dev\/i2c-(\d+)/g
const buses = []
let match
while ((match = busRegex.exec(detectOutput)) !== null) {
buses.push(match[1])
}
return buses
} catch (error) {
console.error('Error detecting monitors:', error)
return []
}
}
// Initial setup - validate monitors and get initial brightness
init() {
if (this._buses.length === 0) {
console.warn('No valid DDC monitors detected')
return
}
// Get initial brightness values from monitors
this.fetchBrightness()
}
// Fetch actual brightness values from monitors
fetchBrightness() {
let totalBrightness = 0
let validMonitors = 0
console.log('Fetching brightness from monitors...')
// Get brightness from each monitor
this._buses.forEach((bus) => {
try {
const brightnessOutput = exec(`ddcutil getvcp 10 --bus ${bus}`)
const match = brightnessOutput.match(/current value\s*=\s*(\d+)/)
if (match) {
totalBrightness += parseInt(match[1], 10)
validMonitors++
}
} catch (error) {
console.error(`Error getting brightness for bus ${bus}:`, error)
}
})
if (validMonitors > 0) {
this._value = Math.round(totalBrightness / validMonitors)
this.refreshUI()
}
}
refreshUI() {
this.notify('icon-name')
this.notify('value')
this.emit('value-changed', this._value)
}
@signal(Number)
declare valueChanged: (value: Number) => void
}