X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/a7e6637162827a09c13e72a49412b3ab915cf473..4b9ac23960d2998f899287ffcf696ad33b63a69a:/lisp/mpc.el diff --git a/lisp/mpc.el b/lisp/mpc.el index 7d684d24c0..aa7fee6adb 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -1,6 +1,6 @@ ;;; mpc.el --- A client for the Music Player Daemon -*- lexical-binding: t -*- -;; Copyright (C) 2006-2015 Free Software Foundation, Inc. +;; Copyright (C) 2006-2016 Free Software Foundation, Inc. ;; Author: Stefan Monnier ;; Keywords: multimedia @@ -265,10 +265,7 @@ defaults to 6600 and HOST defaults to localhost." (let ((v (match-string 3 host))) (setq host (match-string 2 host)) (when (and (stringp v) (not (string= "" v))) - (setq port - (if (string-match "[^[:digit:]]" v) - (string-to-number v) - v))))) + (setq port v)))) (when (file-name-absolute-p host) ;; Expand file name because `file-name-absolute-p' ;; considers paths beginning with "~" as absolute @@ -796,6 +793,22 @@ The songs are returned as alists." ;; (setq mpc-queue-back nil mpc-queue nil) ) +(defun mpc-cmd-consume (&optional arg) + "Set consume mode state." + (mpc-proc-cmd (list "consume" arg) #'mpc-status-refresh)) + +(defun mpc-cmd-random (&optional arg) + "Set random (shuffle) mode state." + (mpc-proc-cmd (list "random" arg) #'mpc-status-refresh)) + +(defun mpc-cmd-repeat (&optional arg) + "Set repeat mode state." + (mpc-proc-cmd (list "repeat" arg) #'mpc-status-refresh)) + +(defun mpc-cmd-single (&optional arg) + "Set single mode state." + (mpc-proc-cmd (list "single" arg) #'mpc-status-refresh)) + (defun mpc-cmd-pause (&optional arg callback) "Pause or resume playback of the queue of songs." (let ((cb callback)) @@ -810,6 +823,9 @@ The songs are returned as alists." (mpc-proc-cmd "play") (mpc-status-refresh)) +(defun mpc-cmd-seekcur (time) + (mpc-proc-cmd (list "seekcur" time) #'mpc-status-refresh)) + (defun mpc-cmd-add (files &optional playlist) "Add the songs FILES to PLAYLIST. If PLAYLIST is t or nil or missing, use the main playlist." @@ -1010,30 +1026,29 @@ If PLAYLIST is t or nil or missing, use the main playlist." (substring time (match-end 0)) time))))) (`Cover - (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 ((dir (file-name-directory (cdr (assq 'file info))))) + ;; (debug) + (push `(equal ',dir (file-name-directory (cdr (assq 'file info)))) pred) + (if-let ((covers '(".folder.png" "cover.jpg" "folder.jpg")) + (cover (cl-loop for file in (directory-files (mpc-file-local-copy dir)) + if (member (downcase file) covers) + return (concat dir file))) + (file (with-demoted-errors "MPC: %s" + (mpc-file-local-copy cover)))) + (let (image) + (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'. @@ -1109,16 +1124,29 @@ 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 "s" 'mpc-toggle-play) (define-key map ">" 'mpc-next) (define-key map "<" 'mpc-prev) - (define-key map "g" nil) + (define-key map "g" 'mpc-seek-current) map)) (easy-menu-define mpc-mode-menu mpc-mode-map "Menu for MPC.el." '("MPC.el" - ["Next track" mpc-next] - ["Previous track" mpc-prev] + ["Play/Pause" mpc-toggle-play] ;FIXME: Add one of ⏯/▶/⏸ in there? + ["Next Track" mpc-next] ;FIXME: Add ⇥ there? + ["Previous Track" mpc-prev] ;FIXME: Add ⇤ there? + ["Seek Within Track" mpc-seek-current] + "--" + ["Repeat Playlist" mpc-toggle-repeat :style toggle + :selected (member '(repeat . "1") mpc-status)] + ["Shuffle Playlist" mpc-toggle-shuffle :style toggle + :selected (member '(random . "1") mpc-status)] + ["Repeat Single Track" mpc-toggle-single :style toggle + :selected (member '(single . "1") mpc-status)] + ["Consume Mode" mpc-toggle-consume :style toggle + :selected (member '(consume . "1") mpc-status)] + "--" ["Add new browser" mpc-tagbrowser] ["Update DB" mpc-update] ["Quit" mpc-quit])) @@ -1828,7 +1856,8 @@ A value of t means the main playlist.") (mpc-volume-widget (string-to-number (cdr (assq 'volume mpc-status))))) (let ((status-buf (mpc-proc-buffer (mpc-proc) 'status))) - (when status-buf (with-current-buffer status-buf (force-mode-line-update))))) + (when (buffer-live-p status-buf) + (with-current-buffer status-buf (force-mode-line-update))))) (defvar mpc-volume-step 5) @@ -2333,6 +2362,30 @@ This is used so that they can be compared with `eq', which is needed for (mpc-status-stop) (if proc (delete-process proc)))) +(defun mpc-toggle-consume () + "Toggle consume mode: removing played songs from the playlist." + (interactive) + (mpc-cmd-consume + (if (string= "0" (cdr (assq 'consume (mpc-cmd-status)))) "1" "0"))) + +(defun mpc-toggle-repeat () + "Toggle repeat mode." + (interactive) + (mpc-cmd-repeat + (if (string= "0" (cdr (assq 'repeat (mpc-cmd-status)))) "1" "0"))) + +(defun mpc-toggle-single () + "Toggle single mode." + (interactive) + (mpc-cmd-single + (if (string= "0" (cdr (assq 'single (mpc-cmd-status)))) "1" "0"))) + +(defun mpc-toggle-shuffle () + "Toggle shuffling of the playlist (random mode)." + (interactive) + (mpc-cmd-random + (if (string= "0" (cdr (assq 'random (mpc-cmd-status)))) "1" "0"))) + (defun mpc-stop () "Stop playing the current queue of songs." (interactive) @@ -2350,6 +2403,22 @@ This is used so that they can be compared with `eq', which is needed for (interactive) (mpc-cmd-pause "0")) +(defun mpc-seek-current (pos) + "Seek within current track." + (interactive + (list (read-string "Position to go ([+-]seconds): "))) + (mpc-cmd-seekcur pos)) + +(defun mpc-toggle-play () + "Toggle between play and pause. +If stopped, start playback." + (interactive) + (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop")) + (mpc-cmd-play) + (if (member (cdr (assq 'state (mpc-cmd-status))) '("pause")) + (mpc-resume) + (mpc-pause)))) + (defun mpc-play () "Start playing whatever is selected." (interactive)