Christophe Weblog Wiki Code Publications Music
much better `squeeze-unhex-and-decode-utf8-string'
[squeeze-el.git] / squeeze.el
index 267fe2d59ce2cda7eb9b3c140364f3c9fa5d515d..25491596d5633e9b41ab235b8b1135376b9011b5 100644 (file)
     (define-key map (kbd "TAB") 'completion-at-point)
     map))
 
+(defun squeeze-unhex-string (string)
+  (with-temp-buffer
+    (let ((case-fold-search t)
+          (start 0))
+      (while (string-match "%[0-9a-f][0-9a-f]" string start)
+        (let* ((s (match-beginning 0))
+               (ch1 (url-unhex (elt string (+ s 1))))
+               (code (+ (* 16 ch1)
+                        (url-unhex (elt string (+ s 2))))))
+          (insert (substring string start s)
+                  (byte-to-string code))
+          (setq start (match-end 0))))
+      (insert (substring string start)))
+    (buffer-string)))
+
 (defun squeeze-unhex-and-decode-utf8-string (string)
-  (decode-coding-string (url-unhex-string string) 'utf-8))
+  (decode-coding-string (squeeze-unhex-string string) 'utf-8))
 
 (define-derived-mode squeeze-mode comint-mode "Squeeze"
   "Major mode for interacting with the Squeezebox Server CLI.\\<squeeze-mode-map>"
 
 (defvar squeeze-control-inhibit-display nil)
 
-(lexical-let ((buffer ""))
+(lexical-let ((buffer (get-buffer-create " *squeeze-update-state*")))
   (defun squeeze-update-state (string)
+    ;; FIXME: we could make this a lot more elegant by using the
+    ;; buffer abstraction more
     (if (cl-position ?\n string)
         (let (done-something)
-          (setq string (concat buffer string))
+          (with-current-buffer buffer
+            (insert string)
+            (setq string (buffer-string))
+            (erase-buffer))
           (dolist (line (split-string string "\n"))
             (when (squeeze-update-state-from-line line)
               (setq done-something t)))
           (when done-something
             (unless squeeze-control-inhibit-display
-              (squeeze-control-display-players)))
-          (setq buffer ""))
-      (setq buffer (concat buffer string)))
+              (squeeze-control-display-players))))
+      (with-current-buffer buffer
+        (insert string)))
     string))
 
 (defconst squeeze-player-line-regexp
   (save-match-data
     (let (result)
       (loop
-       (if (string-match "\\([a-z]+\\)%3A\\([^ \n]+\\)" string start)
+       (if (string-match "\\([a-z_]+\\)%3A\\([^ \n]+\\)" string start)
            (let ((mend (match-end 0)))
              (when (> mend end)
                (return))
             "serverstatus" "status" "displaystatus" "readdirectory"
 
             ;; Notifications
-            
+
             ;; Alarm commands and queries
             "alarm" "alarms"