Christophe Weblog Wiki Code Publications Music
separate out display and state management
[squeeze-el.git] / squeeze.el
index c4c8b4ebed6c2faaf4328a5eb3716c31e316786d..7ac1841083cf3ffc6bf7e163de2211d73ff9692c 100644 (file)
 (defvar squeeze-control-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "SPC") 'squeeze-control-toggle-power)
-    (define-key map (kbd "g") 'squeeze-control-display-players)
+    (define-key map (kbd "g") 'squeeze-control-refresh)
     map))
 
 (define-derived-mode squeeze-control-mode special-mode "SqueezeControl"
   "Major mode for controlling Squeezebox Servers.\\<squeeze-control-mode-map>")
 
 (defun squeeze-update-state (string)
+  (let (done-something)
+    (dolist (line (split-string string "\n"))
+      (when (squeeze-update-state-from-line line)
+        (setq done-something t))))
+  (squeeze-control-display-players)
+  string)
+
+(defun squeeze-update-state-from-line (string)
   (cond
    ((string-match "^players 0" string)
-    (setq squeeze-players (squeeze-parse-players-line string))))
-  string)
+    (setq squeeze-players (squeeze-parse-players-line string))
+    t)
+   ((string-match "^\\([0-9a-f][0-9a-f]%3A[0-9a-f][0-9a-f]%3A[0-9a-f][0-9a-f]%3A[0-9a-f][0-9a-f]%3A[0-9a-f][0-9a-f]%3A[0-9a-f][0-9a-f]\\) power\\( \\([01]\\)\\)?" string)
+    (let ((state (match-string 3 string))
+          (id (url-unhex-string (match-string 1 string)))
+          player)
+      (dolist (p squeeze-players)
+        (when (string= id (squeeze-player-playerid p))
+          (setq player p)
+          (return)))
+      (if state
+          (setf (squeeze-player-power player) state)
+        (let ((current (squeeze-player-power player)))
+          (setf (squeeze-player-power player)
+                (cond ((string= current "0") "1")
+                      ((string= current "1") "0"))))))
+    t)))
 
 (defface squeeze-player-face
+  '((t))
+  "Face for displaying players"
+  :group 'squeeze)
+(defface squeeze-player-on-face
   '((t :weight bold))
-  "Face for displaying players")
+  "Face for displaying players which are on"
+  :inherit 'squeeze-player-face
+  :group 'squeeze)
+(defface squeeze-player-off-face
+  '((t :weight light))
+  "Face for displaying players which are off"
+  :inherit 'squeeze-player-face
+  :group 'squeeze)
 
 (defvar squeeze-players ())
 
+(defun squeeze-control-query-players ()
+  (interactive)
+  (comint-send-string (get-buffer-process "*squeeze*") (format "players ?\n")))
+
 (defun squeeze-control-toggle-power (&optional id)
   (interactive)
   (unless id
     (setq id (get-text-property (point) 'squeeze-playerid)))
   (comint-send-string (get-buffer-process "*squeeze*") (format "%s power ?\n" id)))
 
+(defun squeeze-control-player-face (player)
+  (let ((power (squeeze-player-power player)))
+    (cond ((string= power "1") 'squeeze-player-on-face)
+          ((string= power "0") 'squeeze-player-off-face)
+          (t 'squeeze-player-face))))
+
+(defun squeeze-control-refresh ()
+  (interactive)
+  (squeeze-control-query-players)
+  (dolist (player squeeze-players)
+    (squeeze-control-query-power (squeeze-player-playerid player))))
+
 (defun squeeze-control-display-players ()
   (interactive)
   (let ((players squeeze-players))
       (erase-buffer)
       (dolist (player players)
         (insert (propertize (squeeze-player-name player)
-                            'face 'squeeze-player-face
+                            'face (squeeze-control-player-face player)
                             'squeeze-playerid (squeeze-player-playerid player))
                 "\n"))
       (read-only-mode 1))))
 
 (cl-defstruct (squeeze-player (:constructor squeeze-make-player))
-  playerindex playerid uuid ip name model isplayer displaytype canpoweroff connected)
+  playerindex playerid uuid ip name model isplayer displaytype canpoweroff connected power)
 
 (defun squeeze-string-plistify (string start end)
   (save-match-data
     (let (result)
       (loop
        (message "start: %d" start)
-       (if (string-match "\\([a-z]+\\)%3A\\([^ ]+\\)" string start)
+       (if (string-match "\\([a-z]+\\)%3A\\([^ \n]+\\)" string start)
            (let ((mend (match-end 0)))
              (when (> mend end)
                (return))