123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- #!/usr/bin/env -S guile --no-auto-compile -e main -s
- !#
- (use-modules (ice-9 match)
- (ice-9 popen)
- (ice-9 rdelim)
- (srfi srfi-1)
- (srfi srfi-19))
- (define %sudo-binary
- "sudo")
- (define %halt-binary
- "halt")
- (define (off-time?)
- "Return true if off-time, false otherwise."
- (let* ((current (current-date))
- (current-hour (date-hour current)))
- (or (> (date-week-day current) 5)
- (<= current-hour 10)
- (>= current-hour 18))))
- ;;;
- ;;; Mouse
- ;;;
- (define %xdotool-binary
- "xdotool")
- (define (mouse-position)
- "Return current mouse position."
- (let* ((port (open-pipe* OPEN_READ %xdotool-binary "getmouselocation"))
- (output (read-string port)))
- (close-port port)
- (map (lambda (str)
- (match (string-split str #\:)
- ((key value)
- (cons (string->symbol key)
- (string->number value)))))
- (string-split (string-trim-right output #\newline)
- #\space))))
- (define (mouse-idle?)
- "Return true if mouse if idle, false otherwise."
- (define %mouse-position-count
- (or (getenv "AUTO_SHUTDOWN_MOUSE_POSITION")
- 2))
- (define %mouse-position-interval
- (or (getenv "AUTO_SHUTDOWN_MOUSE_POSITION_INTERVAL")
- 2))
- (define %mouse-attempt
- (or (getenv "AUTO_SHUTDOWN_MOUSE_ATTEMPT")
- 8))
- (let loop ((attempt 0)
- (value-parameter '())
- (value-count 0))
- (let ((mouse-idle? (>= value-count %mouse-position-count)))
- (if (or mouse-idle?
- (>= attempt %mouse-attempt))
- mouse-idle?
- (begin
- (let ((current-value (mouse-position)))
- (sleep %mouse-position-interval)
- (loop (1+ attempt)
- current-value
- (if (equal? value-parameter current-value)
- (1+ value-count)
- 0))))))))
- ;;;
- ;;; Monitor
- ;;;
- (define %xset-binary
- "xset")
- (define (monitor-on?)
- "Return true if monitor is on, or false if monitor if off."
- (let* ((port (open-pipe* OPEN_READ %xset-binary "q"))
- (output (read-string port)))
- (close-port port)
- (match (last
- (string-split
- (last
- (string-split (string-trim-right output #\newline)
- #\newline))
- #\space))
- ("On" #true)
- ("Off" #false))))
- (define (monitor-idle?)
- "Return true if monitor if idle, false otherwise."
- (define %monitor-count
- (or (getenv "AUTO_SHUTDOWN_MONITOR_COUNT")
- 2))
- (define %monitor-interval
- (or (getenv "AUTO_SHUTDOWN_MONITOR_INTERVAL")
- 2))
- (define %monitor-attempt
- (or (getenv "AUTO_SHUTDOWN_MONITOR_ATTEMPT")
- 8))
- (define (monitor-off?)
- (not (monitor-on?)))
- (let loop ((attempt 0)
- (value-count 0))
- (let ((monitor-idle? (>= value-count %monitor-count)))
- (if (or monitor-idle?
- (>= attempt %monitor-attempt))
- monitor-idle?
- (begin
- (let ((current-value (monitor-off?)))
- (sleep %monitor-interval)
- (loop (1+ attempt)
- (if current-value
- (1+ value-count)
- 0))))))))
- ;;;
- ;;; Audio
- ;;;
- (define (audio-off?)
- "Return true if audio is off, false otherwise."
- (let* ((port (open-pipe "parec --raw --channels=1 --latency=2 2>/dev/null | od -N2 -td2 | head -n1 | cut -d' ' -f2- | tr -d ' '"
- OPEN_READ))
- (output (read-string port)))
- (close-port port)
- (= (string->number (string-trim-right output #\newline))
- 0)))
- (define (audio-idle?)
- "Return true if audio if idle, false otherwise."
- (define %audio-count
- (or (getenv "AUTO_SHUTDOWN_AUDIO_COUNT")
- 5))
- (define %audio-interval
- (or (getenv "AUTO_SHUTDOWN_AUDIO_INTERVAL")
- 2))
- (define %audio-attempt
- (or (getenv "AUTO_SHUTDOWN_AUDIO_ATTEMPT")
- 8))
- (let loop ((attempt 0)
- (value-parameter '())
- (value-count 0))
- (let ((audio-idle? (>= value-count %audio-count)))
- (if (or audio-idle?
- (>= attempt %audio-attempt))
- audio-idle?
- (begin
- (let* ((current-value (audio-off?))
- (value-parameter (append value-parameter
- (list current-value))))
- (sleep %audio-interval)
- (loop (1+ attempt)
- value-parameter
- (if (every (lambda (value) (eq? value #t)) value-parameter)
- (1+ value-count)
- 0))))))))
- ;;;
- ;;; Processes
- ;;;
- (define %pgrep-binary
- "pgrep")
- (define (process-missing? process-name)
- (with-output-to-port (open-output-file "/dev/null")
- (lambda ()
- (= (system* %pgrep-binary "--full" "--list-full" process-name)
- 256))))
- ;;;
- ;;; Entry point
- ;;;
- (define (main . args)
- (if (and (off-time?)
- (process-missing? "bin/restic")
- (and (monitor-idle?) (audio-idle?))
- (mouse-idle?))
- (system* %sudo-binary %halt-binary)
- (exit 1)))
|