dot/emacs, el/dot-emacs.el: Show MPC status after play, previous, next.
[profile] / el / dot-emacs.el
index 704c486..5f27085 100644 (file)
@@ -768,6 +768,17 @@ options."
       (ad-set-arg 0 dir)
       ad-do-it)))
 
+(defun mdw-dired-run (args &optional syncp)
+  (interactive (let ((file (dired-get-filename t)))
+                (list (read-string (format "Arguments for %s: " file))
+                      current-prefix-arg)))
+  (funcall (if syncp 'shell-command 'async-shell-command)
+          (concat (shell-quote-argument (dired-get-filename nil))
+                  " " args)))
+
+(eval-after-load "dired"
+  '(define-key dired-mode-map "X" 'mdw-dired-run))
+
 ;;;--------------------------------------------------------------------------
 ;;; URL viewing.
 
@@ -1239,6 +1250,9 @@ doesn't match any of the regular expressions in
 (mdw-define-face comint-highlight-input
   (t nil))
 
+(mdw-define-face ido-subdir
+  (t :foreground "cyan" :weight bold))
+
 (mdw-define-face dired-directory
   (t :foreground "cyan" :weight bold))
 (mdw-define-face dired-symlink
@@ -3753,6 +3767,148 @@ there is sadness."
                       (if (> n 0) 'bold 'shadow))))))
 
 ;;;--------------------------------------------------------------------------
+;;; MPC configuration.
+
+(setq mpc-browser-tags '(Artist|Composer|Performer Album|Playlist))
+
+(defun mdw-mpc-now-playing ()
+  (interactive)
+  (require 'mpc)
+  (save-excursion
+    (set-buffer (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong"))))
+    (mpc--status-callback))
+  (let ((state (cdr (assq 'state mpc-status))))
+    (cond ((member state '("stop"))
+          (message "mpd stopped."))
+         ((member state '("play" "pause"))
+          (let* ((artist (cdr (assq 'Artist mpc-status)))
+                 (album (cdr (assq 'Album mpc-status)))
+                 (title (cdr (assq 'Title mpc-status)))
+                 (file (cdr (assq 'file mpc-status)))
+                 (duration-string (cdr (assq 'Time mpc-status)))
+                 (time-string (cdr (assq 'time mpc-status)))
+                 (time (and time-string
+                            (string-to-number
+                             (if (string-match ":" time-string)
+                                 (substring time-string
+                                            0 (match-beginning 0))
+                               (time-string)))))
+                 (duration (and duration-string
+                                (string-to-number duration-string)))
+                 (pos (and time duration
+                           (format " [%d:%02d/%d:%02d]"
+                                   (/ time 60) (mod time 60)
+                                   (/ duration 60) (mod duration 60))))
+                 (fmt (cond ((and artist title)
+                             (format "`%s' by %s%s" title artist
+                                     (if album (format ", from `%s'" album)
+                                       "")))
+                            (file
+                             (format "`%s' (no tags)" file))
+                            (t
+                             "(no idea what's playing!)"))))
+            (if (string= state "play")
+                (message "mpd playing %s%s" fmt (or pos ""))
+              (message "mpd paused in %s%s" fmt (or pos "")))))
+         (t
+          (message "mpd in unknown state `%s'" state)))))
+
+(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-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 ()
+  (unless (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)
+  (mpc-selection-refresh))
+
+(defun mdw-mpc-unselect (&optional arg interactivep)
+  (interactive (list current-prefix-arg t))
+  (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-unselect-one)
+  (mpc-selection-refresh))
+
+(defun mdw-mpc-unselect-backwards (arg)
+  (interactive "p")
+  (mdw-mpc-hack-lines (- arg) t 'mdw-mpc-unselect-one)
+  (mpc-selection-refresh))
+
+(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)))
+
+(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)
+     (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 "+" 'mpc-playlist-add)
+     (define-key mpc-songs-mode-map "-" 'mpc-playlist-delete)))
+
+;;;--------------------------------------------------------------------------
 ;;; Inferior Emacs Lisp.
 
 (setq comint-prompt-read-only t)