Initial commit
commit
667f953363
@ -0,0 +1,6 @@
|
||||
.idea/
|
||||
dist/
|
||||
vendor/
|
||||
*.sh
|
||||
brightness
|
||||
brightness.test
|
@ -0,0 +1,21 @@
|
||||
image: golang:latest
|
||||
|
||||
stages:
|
||||
- validate
|
||||
- build
|
||||
|
||||
fmt:
|
||||
stage: validate
|
||||
script:
|
||||
- gofmt -l -s -e .
|
||||
- exit $(gofmt -l -s -e . | wc -l)
|
||||
|
||||
vet:
|
||||
stage: validate
|
||||
script:
|
||||
- go vet -composites=false ./...
|
||||
|
||||
test:
|
||||
stage: validate
|
||||
script:
|
||||
- go test -race -v ./...
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Trevor Slocum <trevor@rocketnine.space>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,38 @@
|
||||
# brightness
|
||||
[](https://gitlab.com/tslocum/brightness/commits/master)
|
||||
[](https://liberapay.com/rocketnine.space)
|
||||
|
||||
Backlight utility
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
go get gitlab.com/tslocum/brightness
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Set
|
||||
|
||||
```bash
|
||||
brightness 60
|
||||
brightness 80%
|
||||
```
|
||||
|
||||
### Decrease
|
||||
|
||||
```bash
|
||||
brightness -10
|
||||
brightness -20%
|
||||
```
|
||||
|
||||
### Increase
|
||||
|
||||
```bash
|
||||
brightness 10
|
||||
brightness +20%
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
Please share issues and suggestions [here](https://gitlab.com/tslocum/brightness/issues).
|
@ -0,0 +1,212 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// TODO specify minimum brightness
|
||||
// TODO override max brightness
|
||||
// TODO TUI mode
|
||||
// TODO widget mode
|
||||
|
||||
var (
|
||||
acpiBacklight = regexp.MustCompile(`acpi_video[0-9]+$`)
|
||||
)
|
||||
|
||||
const backlightsDirectory = "/sys/class/backlight"
|
||||
|
||||
const (
|
||||
commandSet = 1
|
||||
commandSub = 2
|
||||
commandAdd = 3
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("")
|
||||
}
|
||||
|
||||
type backlight struct {
|
||||
identifier string
|
||||
current int
|
||||
max int
|
||||
|
||||
fallback bool
|
||||
}
|
||||
|
||||
func (b *backlight) setBrightness(brightness int) error {
|
||||
f, err := os.OpenFile(b.currentBrightnessPath(), os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.WriteString(fmt.Sprintf("%d\n", brightness))
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *backlight) currentBrightnessPath() string {
|
||||
return filepath.Join(backlightsDirectory, b.identifier, "brightness")
|
||||
}
|
||||
|
||||
func (b *backlight) maxBrightnessPath() string {
|
||||
return filepath.Join(backlightsDirectory, b.identifier, "max_brightness")
|
||||
}
|
||||
|
||||
func identifyBacklights() ([]*backlight, error) {
|
||||
var backlights []*backlight
|
||||
|
||||
// Locate backlight interfaces. Issues are commonly reported when the ACPI
|
||||
// backlight interface is used instead of other interfaces present on the
|
||||
// system. As a result, ACPI interfaces are only used when no other
|
||||
// interfaces are available.
|
||||
err := filepath.Walk(backlightsDirectory, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
} else if path == backlightsDirectory {
|
||||
return nil
|
||||
}
|
||||
|
||||
backlight := &backlight{
|
||||
identifier: filepath.Base(path),
|
||||
fallback: acpiBacklight.MatchString(path),
|
||||
}
|
||||
backlights = append(backlights, backlight)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list backlight interfaces: %s", err)
|
||||
}
|
||||
|
||||
// Fetch current and max brightness
|
||||
for _, backlight := range backlights {
|
||||
v, err := ioutil.ReadFile(backlight.currentBrightnessPath())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read current brightness of %s: %s", backlight.identifier, err)
|
||||
}
|
||||
backlight.current, err = strconv.Atoi(string(bytes.TrimSpace(v)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse current brightness of %s: %s", backlight.identifier, err)
|
||||
}
|
||||
|
||||
v, err = ioutil.ReadFile(backlight.maxBrightnessPath())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read maximum brightness of %s: %s", backlight.identifier, err)
|
||||
}
|
||||
backlight.max, err = strconv.Atoi(string(bytes.TrimSpace(v)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse maximum brightness of %s: %s", backlight.identifier, err)
|
||||
}
|
||||
}
|
||||
|
||||
return backlights, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
backlights, err := identifyBacklights()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to identify backlight interfaces: %s", err)
|
||||
}
|
||||
|
||||
mainIndex := -1
|
||||
if len(backlights) == 1 {
|
||||
mainIndex = 0
|
||||
} else {
|
||||
for i, backlight := range backlights {
|
||||
if backlight.fallback {
|
||||
continue
|
||||
}
|
||||
|
||||
if mainIndex != -1 {
|
||||
mainIndex = -1
|
||||
break
|
||||
}
|
||||
mainIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
if mainIndex == -1 {
|
||||
// TODO
|
||||
log.Fatal("multiple backlight interfaces were found, please specify which interface to use with --interface")
|
||||
}
|
||||
|
||||
backlight := backlights[mainIndex]
|
||||
|
||||
var v string
|
||||
var command string
|
||||
if len(os.Args) > 1 {
|
||||
command = os.Args[1]
|
||||
if len(os.Args) > 2 {
|
||||
v = os.Args[2]
|
||||
}
|
||||
}
|
||||
|
||||
var cmd int
|
||||
switch command {
|
||||
case "set":
|
||||
cmd = commandSet
|
||||
case "add", "inc", "up":
|
||||
cmd = commandAdd
|
||||
case "sub", "dec", "down":
|
||||
cmd = commandSub
|
||||
case "current":
|
||||
log.Printf("%d", backlight.current)
|
||||
return
|
||||
case "max":
|
||||
log.Printf("%d", backlight.max)
|
||||
return
|
||||
case "":
|
||||
log.Printf("%d/%d", backlight.current, backlight.max)
|
||||
return
|
||||
default:
|
||||
if len(os.Args) > 2 {
|
||||
log.Fatalf("unrecognized command %s", command)
|
||||
}
|
||||
|
||||
v = command
|
||||
if v[0] == '-' {
|
||||
cmd = commandSub
|
||||
v = v[1:]
|
||||
} else if v[0] == '+' {
|
||||
cmd = commandAdd
|
||||
v = v[1:]
|
||||
} else {
|
||||
cmd = commandSet
|
||||
}
|
||||
}
|
||||
|
||||
pct := v[len(v)-1] == '%'
|
||||
if pct {
|
||||
v = v[:len(v)-1]
|
||||
}
|
||||
setValue, err := strconv.ParseFloat(v, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("unrecognized command %s", command)
|
||||
}
|
||||
|
||||
if pct {
|
||||
setValue = float64(backlight.max) * (setValue / 100)
|
||||
}
|
||||
|
||||
value := backlight.current
|
||||
switch cmd {
|
||||
case commandSet:
|
||||
value = int(setValue)
|
||||
case commandSub:
|
||||
value -= int(setValue)
|
||||
case commandAdd:
|
||||
value += int(setValue)
|
||||
}
|
||||
|
||||
err = backlight.setBrightness(value)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to set brightness of %s to %d: %s", backlight.identifier, value, err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue