]> code.delx.au - gnu-emacs/blobdiff - lisp/mpc.el
Add bindings and menu items for prev and next tracks
[gnu-emacs] / lisp / mpc.el
index 3600b081f9b4c7f55a029213d080cd53aa80d14a..7d684d24c0f22d43c3a1e3c57a1ac2551f8d1f68 100644 (file)
@@ -44,7 +44,6 @@
 ;; - visual feedback for drag'n'drop
 ;; - display/set `repeat' and `random' state (and maybe also `crossfade').
 ;; - allow multiple *mpc* sessions in the same Emacs to control different mpds.
-;; - look for .folder.png (freedesktop) or folder.jpg (XP) as well.
 ;; - fetch album covers and lyrics from the web?
 ;; - improve MPC-Status: better volume control, add a way to show/hide the
 ;;   rest, plus add the buttons currently in the toolbar.
@@ -92,7 +91,9 @@
 ;; UI-commands       : mpc-
 ;; internal          : mpc--
 
-(eval-when-compile (require 'cl-lib))
+(eval-when-compile
+  (require 'cl-lib)
+  (require 'subr-x))
 
 (defgroup mpc ()
   "Client for the Music Player Daemon (mpd)."
@@ -268,7 +269,10 @@ defaults to 6600 and HOST defaults to localhost."
                 (if (string-match "[^[:digit:]]" v)
                     (string-to-number v)
                   v)))))
-    (when (string-prefix-p "/" host)    ;FIXME: Use file-name-absolute-p?
+    (when (file-name-absolute-p host)
+      ;; Expand file name because `file-name-absolute-p'
+      ;; considers paths beginning with "~" as absolute
+      (setq host (expand-file-name host))
       (setq local t))
 
     (mpc--debug "Connecting to %s:%s..." host port)
@@ -1006,27 +1010,30 @@ If PLAYLIST is t or nil or missing, use the main playlist."
                                                (substring time (match-end 0))
                                              time)))))
                     (`Cover
-                     (let* ((dir (file-name-directory (cdr (assq 'file info))))
-                            (cover (concat dir "cover.jpg"))
-                            (file (with-demoted-errors "MPC: %s"
-                                    (mpc-file-local-copy cover)))
-                            image)
-                       ;; (debug)
-                       (push `(equal ',dir (file-name-directory (cdr (assq 'file info)))) pred)
-                       (if (null file)
-                           ;; Make sure we return something on which we can
-                           ;; place the `mpc-pred' property, as
-                           ;; a negative-cache.  We could also use
-                           ;; a default cover.
-                           (progn (setq size nil) " ")
-                         (if (null size) (setq image (create-image file))
-                           (let ((tempfile (make-temp-file "mpc" nil ".jpg")))
-                             (call-process "convert" nil nil nil
-                                           "-scale" size file tempfile)
-                             (setq image (create-image tempfile))
-                             (mpc-tempfiles-add image tempfile)))
-                         (setq size nil)
-                         (propertize dir 'display image))))
+                     (if-let ((dir (file-name-directory
+                                    (mpc-file-local-copy (cdr (assq 'file info)))))
+                              (covers '(".folder.png" "cover.jpg" "folder.jpg"))
+                              (cover (cl-loop for file in (directory-files dir)
+                                              if (member (downcase file) covers)
+                                              return (concat dir file)))
+                              (file (with-demoted-errors "MPC: %s"
+                                      (mpc-file-local-copy cover))))
+                         (let (image)
+                           ;; (debug)
+                           (push `(equal ',dir (file-name-directory (cdr (assq 'file info)))) pred)
+                           (if (null size) (setq image (create-image file))
+                             (let ((tempfile (make-temp-file "mpc" nil ".jpg")))
+                               (call-process "convert" nil nil nil
+                                             "-scale" size file tempfile)
+                               (setq image (create-image tempfile))
+                               (mpc-tempfiles-add image tempfile)))
+                           (setq size nil)
+                           (propertize dir 'display image))
+                       ;; Make sure we return something on which we can
+                       ;; place the `mpc-pred' property, as
+                       ;; a negative-cache.  We could also use
+                       ;; a default cover.
+                       (progn (setq size nil) " ")))
                     (_ (let ((val (cdr (assq tag info))))
                          ;; For Streaming URLs, there's no other info
                          ;; than the URL in `file'.  Pretend it's in `Title'.
@@ -1083,8 +1090,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
 ;;; The actual UI code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defvar mpc-mode-map
-  (let ((map (make-keymap)))
-    (suppress-keymap map)
+  (let ((map (make-sparse-keymap)))
     ;; (define-key map "\e" 'mpc-stop)
     (define-key map "q" 'mpc-quit)
     (define-key map "\r" 'mpc-select)
@@ -1103,11 +1109,16 @@ If PLAYLIST is t or nil or missing, use the main playlist."
     ;; is applied elsewhere :-(
     ;; (define-key map [(double mouse-2)] 'mpc-play-at-point)
     (define-key map "p" 'mpc-pause)
+    (define-key map ">" 'mpc-next)
+    (define-key map "<" 'mpc-prev)
+    (define-key map "g" nil)
     map))
 
 (easy-menu-define mpc-mode-menu mpc-mode-map
   "Menu for MPC.el."
   '("MPC.el"
+    ["Next track" mpc-next]
+    ["Previous track" mpc-prev]
     ["Add new browser" mpc-tagbrowser]
     ["Update DB" mpc-update]
     ["Quit" mpc-quit]))
@@ -1151,10 +1162,9 @@ If PLAYLIST is t or nil or missing, use the main playlist."
      :help "Append to the playlist")
     map))
 
-(define-derived-mode mpc-mode fundamental-mode "MPC"
+(define-derived-mode mpc-mode special-mode "MPC"
   "Major mode for the features common to all buffers of MPC."
   (buffer-disable-undo)
-  (setq buffer-read-only t)
   (if (boundp 'tool-bar-map)            ; not if --without-x
       (setq-local tool-bar-map mpc-tool-bar-map))
   (setq-local truncate-lines t))
@@ -1257,7 +1267,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
   (let ((ol (make-overlay
              (line-beginning-position) (line-beginning-position 2))))
     (overlay-put ol 'mpc-select t)
-    (overlay-put ol 'face 'region)
+    (overlay-put ol 'face 'highlight)
     (overlay-put ol 'evaporate t)
     (push ol mpc-select)))
 
@@ -1556,7 +1566,7 @@ when constructing the set of constraints."
           (move-overlay mpc-tagbrowser-all-ol
                         (point) (line-beginning-position 2))
         (let ((ol (make-overlay (point) (line-beginning-position 2))))
-          (overlay-put ol 'face 'region)
+          (overlay-put ol 'face 'highlight)
           (overlay-put ol 'evaporate t)
           (setq-local mpc-tagbrowser-all-ol ol))))))
 
@@ -1876,7 +1886,6 @@ A value of t means the main playlist.")
 
 (defvar mpc-songs-mode-map
   (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map mpc-mode-map)
     (define-key map [remap mpc-select] 'mpc-songs-jump-to)
     map))
 
@@ -1954,7 +1963,7 @@ This is used so that they can be compared with `eq', which is needed for
             ;; I punt on it and just use file-name sorting, which does the
             ;; right thing if your library is properly arranged.
             (dolist (song (if dontsort active
-                            (sort active
+                            (sort (copy-sequence active)
                                   (lambda (song1 song2)
                                     (let ((cmp (mpc-compare-strings
                                                 (cdr (assq 'file song1))