;; - 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.
;; 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)."
(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)
(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'.
;;; 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)
;; 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]))
: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))
(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)))
(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))))))
(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))
;; 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))