Christophe Weblog Wiki Code Publications Music
minimally useful squeeze control mode
authorChristophe Rhodes <csr21@cantab.net>
Fri, 21 Mar 2014 19:33:56 +0000 (19:33 +0000)
committerChristophe Rhodes <csr21@cantab.net>
Fri, 21 Mar 2014 19:33:56 +0000 (19:33 +0000)
I can turn players on and off!  Yes!

squeeze.el

index dbedd7af71bb39b692f15e759612aeebef71ffaf..c4c8b4ebed6c2faaf4328a5eb3716c31e316786d 100644 (file)
 
 (define-derived-mode squeeze-mode comint-mode "Squeeze"
   "Major mode for interacting with the Squeezebox Server CLI.\\<squeeze-mode-map>"
-  (add-hook 'comint-preoutput-filter-functions 'url-unhex-string nil t))
+  (add-hook 'comint-preoutput-filter-functions 'url-unhex-string nil t)
+  (add-hook 'comint-preoutput-filter-functions 'squeeze-update-state nil t))
+
+(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)
+    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)
+  (cond
+   ((string-match "^players 0" string)
+    (setq squeeze-players (squeeze-parse-players-line string))))
+  string)
+
+(defface squeeze-player-face
+  '((t :weight bold))
+  "Face for displaying players")
+
+(defvar squeeze-players ())
+
+(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-query-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-display-players ()
+  (interactive)
+  (let ((players squeeze-players))
+    (with-current-buffer (get-buffer-create "*squeeze-control*")
+      (squeeze-control-mode)
+      (read-only-mode -1)
+      (erase-buffer)
+      (dolist (player players)
+        (insert (propertize (squeeze-player-name player)
+                            'face 'squeeze-player-face
+                            '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)
+
+(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)
+           (let ((mend (match-end 0)))
+             (when (> mend end)
+               (return))
+             (push (intern (format ":%s" (substring string (match-beginning 1) (match-end 1)))) result)
+             (push (url-unhex-string (substring string (match-beginning 2) (match-end 2))) result)
+             (setq start mend))
+         (return)))
+      (nreverse result))))
+
+(defun squeeze-parse-players-line (string)
+  (let ((countpos (string-match " count%3A\\([0-9]\\) " string))
+        (startpos (match-end 0)))
+    (unless countpos
+      (message "no count found in players line"))
+    (let ((count (parse-integer string (match-beginning 1) (match-end 1)))
+          result endpos)
+      (dotimes (i (1- count))
+        (setq endpos (progn (string-match " connected%3A[0-1] " string startpos)
+                            (match-end 0)))
+        (push (apply 'squeeze-make-player (squeeze-string-plistify string startpos endpos)) result)
+        (setq startpos endpos))
+      (push (apply 'squeeze-make-player (squeeze-string-plistify string startpos (length string))) result)
+      result)))
 
 (defun squeeze-complete-command-at-point ()
   (save-excursion
 
             ;; Plugins commands and queries
             "favorites"
-            
             ))))
 
 (defun squeeze ()
                                              squeeze-server-port))))
     (switch-to-buffer buffer)
     (squeeze-mode)))
+
+(defun squeeze-control ()
+  (interactive)
+  (squeeze)
+  (let ((buffer (get-buffer-create "*squeeze-control*")))
+    (switch-to-buffer buffer)
+    (squeeze-control-display-players)))