+(defmacro mdw-define-mpc-wrapper (func bvl interactive &rest body)
+ `(defun ,func ,bvl
+ (interactive ,@interactive)
+ (require 'mpc)
+ ,@body
+ (mdw-mpc-now-playing)))
+
+(mdw-define-mpc-wrapper mdw-mpc-play-or-pause () nil
+ (if (member (cdr (assq 'state (mpc-cmd-status))) '("play"))
+ (mpc-pause)
+ (mpc-play)))
+
+(mdw-define-mpc-wrapper mdw-mpc-next () nil (mpc-next))
+(mdw-define-mpc-wrapper mdw-mpc-prev () nil (mpc-prev))
+(mdw-define-mpc-wrapper mdw-mpc-stop () nil (mpc-stop))
+
+(defun mdw-mpc-louder (step)
+ (interactive (list (if current-prefix-arg
+ (prefix-numeric-value current-prefix-arg)
+ +10)))
+ (mpc-proc-cmd (format "volume %+d" step)))
+
+(defun mdw-mpc-quieter (step)
+ (interactive (list (if current-prefix-arg
+ (prefix-numeric-value current-prefix-arg)
+ +10)))
+ (mpc-proc-cmd (format "volume %+d" (- step))))
+
+(defun mdw-mpc-hack-lines (arg interactivep func)
+ (if (and interactivep (use-region-p))
+ (let ((from (region-beginning)) (to (region-end)))
+ (goto-char from)
+ (beginning-of-line)
+ (funcall func)
+ (forward-line)
+ (while (< (point) to)
+ (funcall func)
+ (forward-line)))
+ (let ((n (prefix-numeric-value arg)))
+ (cond ((minusp n)
+ (unless (bolp)
+ (beginning-of-line)
+ (funcall func)
+ (incf n))
+ (while (minusp n)
+ (forward-line -1)
+ (funcall func)
+ (incf n)))
+ (t
+ (beginning-of-line)
+ (while (plusp n)
+ (funcall func)
+ (forward-line)
+ (decf n)))))))
+
+(defun mdw-mpc-select-one ()
+ (when (and (get-char-property (point) 'mpc-file)
+ (not (get-char-property (point) 'mpc-select)))
+ (mpc-select-toggle)))
+
+(defun mdw-mpc-unselect-one ()
+ (when (get-char-property (point) 'mpc-select)
+ (mpc-select-toggle)))
+
+(defun mdw-mpc-select (&optional arg interactivep)
+ (interactive (list current-prefix-arg t))
+ (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+
+(defun mdw-mpc-unselect (&optional arg interactivep)
+ (interactive (list current-prefix-arg t))
+ (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-unselect-one))
+
+(defun mdw-mpc-unselect-backwards (arg)
+ (interactive "p")
+ (mdw-mpc-hack-lines (- arg) t 'mdw-mpc-unselect-one))
+
+(defun mdw-mpc-unselect-all ()
+ (interactive)
+ (setq mpc-select nil)
+ (mpc-selection-refresh))
+
+(defun mdw-mpc-next-line (arg)
+ (interactive "p")
+ (beginning-of-line)
+ (forward-line arg))
+
+(defun mdw-mpc-previous-line (arg)
+ (interactive "p")
+ (beginning-of-line)
+ (forward-line (- arg)))
+
+(defun mdw-mpc-playlist-add (&optional arg interactivep)
+ (interactive (list current-prefix-arg t))
+ (let ((mpc-select mpc-select))
+ (when (or arg (and interactivep (use-region-p)))
+ (setq mpc-select nil)
+ (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+ (setq mpc-select (reverse mpc-select))
+ (mpc-playlist-add)))
+
+(defun mdw-mpc-playlist-delete (&optional arg interactivep)
+ (interactive (list current-prefix-arg t))
+ (setq mpc-select (nreverse mpc-select))
+ (mpc-select-save
+ (when (or arg (and interactivep (use-region-p)))
+ (setq mpc-select nil)
+ (mpc-selection-refresh)
+ (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+ (mpc-playlist-delete)))
+
+(defun mdw-mpc-hack-tagbrowsers ()
+ (setq-local mode-line-format
+ '("%e"
+ mode-line-frame-identification
+ mode-line-buffer-identification)))
+(add-hook 'mpc-tagbrowser-mode-hook 'mdw-mpc-hack-tagbrowsers)
+
+(defun mdw-mpc-hack-songs ()
+ (setq-local header-line-format
+ ;; '("MPC " mpc-volume " " mpc-current-song)
+ (list (propertize " " 'display '(space :align-to 0))
+ ;; 'mpc-songs-format-description
+ '(:eval
+ (let ((deactivate-mark) (hscroll (window-hscroll)))
+ (with-temp-buffer
+ (mpc-format mpc-songs-format 'self hscroll)
+ ;; That would be simpler than the hscroll handling in
+ ;; mpc-format, but currently move-to-column does not
+ ;; recognize :space display properties.
+ ;; (move-to-column hscroll)
+ ;; (delete-region (point-min) (point))
+ (buffer-string)))))))
+(add-hook 'mpc-songs-mode-hook 'mdw-mpc-hack-songs)
+
+(eval-after-load "mpc"
+ '(progn
+ (define-key mpc-mode-map "m" 'mdw-mpc-select)
+ (define-key mpc-mode-map "u" 'mdw-mpc-unselect)
+ (define-key mpc-mode-map "\177" 'mdw-mpc-unselect-backwards)
+ (define-key mpc-mode-map "\e\177" 'mdw-mpc-unselect-all)
+ (define-key mpc-mode-map "n" 'mdw-mpc-next-line)
+ (define-key mpc-mode-map "p" 'mdw-mpc-previous-line)
+ (define-key mpc-mode-map "/" 'mpc-songs-search)
+ (setq mpc-songs-mode-map (make-sparse-keymap))
+ (set-keymap-parent mpc-songs-mode-map mpc-mode-map)
+ (define-key mpc-songs-mode-map "l" 'mpc-playlist)
+ (define-key mpc-songs-mode-map "+" 'mdw-mpc-playlist-add)
+ (define-key mpc-songs-mode-map "-" 'mdw-mpc-playlist-delete)
+ (define-key mpc-songs-mode-map "\r" 'mpc-songs-jump-to)))