stumpwm-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [STUMP] [PATCH] Add battery2.lisp - works with multiple batteries, u


From: Rupert Swarbrick
Subject: Re: [STUMP] [PATCH] Add battery2.lisp - works with multiple batteries, uses sysfs.
Date: Sun, 20 Jul 2008 18:49:18 +0100
User-agent: Gnus/5.110011 (No Gnus v0.11) Emacs/22.2 (gnu/linux)

This looks nice! I hadn't used battery.lisp before, but I have spent
most of the day getting this working on my machine. As Julian Stecklina
seems to have found [1], sbcl hangs when reading from sysfs with the
normal functions with some versions of the kernel (including mine!).

So I coded up a non-blocking "read-line-noblock" function to use
instead, based on a suggestion Alistair Bridgewater gives in that
thread. No doubt it's slower than pukka CL:READ-LINE, but we're only
reading a line from a couple of files each time, so meh.

I also added a fall-back for the code to use energy_full and energy_now
if charge_full and charge_now don't exist on the machine (since they
don't here!).

I'm attaching both a new version of the file and a git diff: presumably
one will be of more interest to John and one for others.


Rupert


[1] http://article.gmane.org/gmane.lisp.steel-bank.devel/11557


Attachment: battery2.lisp
Description: Binary data

diff --git a/contrib/battery2.lisp b/contrib/battery2.lisp
index bcd1936..5e22e16 100644
--- a/contrib/battery2.lisp
+++ b/contrib/battery2.lisp
@@ -46,6 +46,46 @@
   "Don't update the battery information more often than once every 10
 seconds.")
 
+(defun read-line-noblock (stream &optional (blocksize 80))
+  "Read a line from the stream STREAM, which should be from a unix file. Read 
up
+to either EOF or #\Newline in chunks of size BLOCKSIZE. This uses non-blocking
+I/O so should work for files in e.g. /sys/ without hanging SBCL"
+
+  (let ((buf (make-array blocksize
+                         :element-type '(unsigned-byte 8)
+                         :initial-element 0))
+        (fd (sb-sys:fd-stream-fd stream))
+        (string-filled 0)
+        (string (make-string blocksize))
+        bytes-read
+        pos
+        (stringlen blocksize))
+    
+    (loop
+       ; Read in the raw bytes
+       (setf bytes-read
+             (sb-unix:unix-read fd (sb-sys:vector-sap buf) blocksize))
+
+       ; This is # bytes both read and in the correct line.
+       (setf pos (or (position (char-code #\Newline) buf) bytes-read))
+
+       ; Resize the string if necessary.
+       (when (> (+ pos string-filled) stringlen)
+         (setf stringlen (max (+ pos string-filled)
+                              (* 2 stringlen)))
+         (let ((new (make-string stringlen)))
+           (replace new string)
+           (setq string new)))
+
+       ; Translate read bytes to string
+       (setf (subseq string string-filled)
+             (sb-ext:octets-to-string (subseq buf 0 pos)))
+       
+       (incf string-filled pos)
+
+       (if (< pos blocksize)
+           (return (subseq string 0 string-filled))))))
+
 (defmacro defun-cached (name interval arglist &body body)
   "Creates a function that does simple caching. The body must be
 written in a functional style - the value returned is set as the
@@ -78,7 +118,7 @@ file doesn't exist, nil is returned."
   (with-open-file (s (merge-pathnames bat data)
                      :direction :input :if-does-not-exist nil)
     (when s
-      (let* ((val (read-line s nil))
+      (let* ((val (read-line-noblock s))
              (int (ignore-errors (parse-integer val))))
         (if int
             int
@@ -93,6 +133,7 @@ file doesn't exist, nil is returned."
   "Returns either how much battery time is left when discharging or
 how much time remains until fully charged. If any required info is
 missing, returns nil."
+
   (when (and status charge current full)
     (cond ((string= status "Full") "")
           ;; when switching from "Full" to "Discharging" status,
@@ -116,17 +157,29 @@ missing, returns nil."
          (charge (bat-data bat "charge_now"))
          (full (bat-data bat "charge_full"))
          (current (bat-data bat "current_now"))
-         (time (bat-time status charge current full))
          (status-icon (cond ((string= status "Full") "~")
                             ((string= status "Discharging") "↓")
                             ((string= status "Charging") "↑")
-                            (t "?")))
-         (perc (bat-perc charge full)))
-; if you don't have my bar-zone-color patch (mailed on 20080718), use this:
-;    (format nil "~A~A ~A%"
-;            time status-icon perc)))
-    (format nil "~A~A ^[~A~A%^]"
-            time status-icon (bar-zone-color perc 50 30 20 t) perc)))
+                            (t "?"))))
+    
+    ;; My kernel uses energy_full + energy_now, so if charge_* didn't work, try
+    ;; that.
+    (unless (and full charge)
+      (setf full (bat-data bat "energy_full"))
+      (setf charge (bat-data bat "energy_now")))
+
+    ;; If no bar-zone-color patch (mailed on 20080718):
+    (format nil "~A~A ~A%"
+            (bat-time status charge current full) status-icon
+            (bat-perc charge full))
+
+    ;; With bar-zone-color patch:
+;    (format nil "~A~A ^[~A~A%^]"
+;            (bat-time status charge current full)
+;            status-icon
+;            (bar-zone-color perc 50 30 20 t)
+;            (bat-perc charge full))
+    ))
 
 (defun-cached fmt-bat *bat-wait-time* (ml)
   "Prints the battery status of all batteries in *bat-list* not more

Attachment: pgpSb_nw2dJJ8.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]