diff options
Diffstat (limited to 'lib/media')
| -rw-r--r-- | lib/media/jao-lyrics.el | 2 | ||||
| -rw-r--r-- | lib/media/jao-mpc.el | 217 | ||||
| -rw-r--r-- | lib/media/jao-mpris.el | 35 | ||||
| -rw-r--r-- | lib/media/jao-random-album.el | 26 | ||||
| -rw-r--r-- | lib/media/jao-spt.el | 8 | 
5 files changed, 187 insertions, 101 deletions
diff --git a/lib/media/jao-lyrics.el b/lib/media/jao-lyrics.el index 5008fae..985c9d9 100644 --- a/lib/media/jao-lyrics.el +++ b/lib/media/jao-lyrics.el @@ -76,7 +76,7 @@    (use-local-map jao-lyrics-mode-map)    (setq major-mode 'jao-lyrics-mode)    (setq mode-name "lyrics") -  (toggle-read-only 1)) +  (read-only-mode))  (defun jao-lyrics-buffer ()    (or (get-buffer "*Lyrics*") diff --git a/lib/media/jao-mpc.el b/lib/media/jao-mpc.el index dc8ff6d..5228787 100644 --- a/lib/media/jao-mpc.el +++ b/lib/media/jao-mpc.el @@ -1,6 +1,6 @@  ;;; jao-mpc.el --- Using mpc to interact with mpd   -*- lexical-binding: t; -*- -;; Copyright (C) 2021, 2022  jao +;; Copyright (C) 2021, 2022, 2024, 2025  jao  ;; Author: jao <mail@jao.io>  ;; Keywords: convenience @@ -30,6 +30,7 @@  (require 'jao-themes)  (require 'jao-lyrics)  (require 'jao-random-album) +(require 'jao-notify)  (defconst jao-mpc--albums "*MPC Albums*")  (defconst jao-mpc--playlist "*MPC Playlist*") @@ -38,62 +39,90 @@  (defvar-local jao-mpc--port nil)  (defun jao-mpc--cmd (cmd &optional port) -  (let ((port (or port jao-mpc--port jao-mpc-port))) -    (shell-command-to-string (format "mpc -p %s %s" port cmd)))) +  (let* ((port (or port jao-mpc--port jao-mpc-port)) +         (r (shell-command-to-string (format "mpc -p %s %s" port cmd)))) +    (replace-regexp-in-string "^\\(warning: \\)?MPD .+\n" "" r))) + +(defun jao-mpc--fformat (fields) +  (mapconcat (lambda (f) (format "%s:::%%%s%%" f f)) fields "\n"))  (defconst jao-mpc--fields -  '(artist album composer originaldate genre title track position time name)) +  '(artist album composer originaldate genre title track position time name +    file))  (defconst jao-mpc--stfmt -  (mapconcat (lambda (f) (format "%s:::%%%s%%" f f)) jao-mpc--fields "\n")) +  (jao-mpc--fformat +   '(artist album composer originaldate genre title track name file))) + +(defconst jao-mpc--stfmtt +  (jao-mpc--fformat '(currenttime totaltime percenttime songpos length))) + +(defmacro jao-mpc--parse-fields (res-str res) +  `(dolist (s (split-string ,res-str "\n" t " ") ,res) +     (when (string-match "\\(.+\\):::\\(.+\\)" s) +       (push (cons (intern (match-string 1 s)) (match-string 2 s)) ,res))))  (defun jao-mpc--current (&optional port)    (let ((s (jao-mpc--cmd (format "-f '%s' current" jao-mpc--stfmt) port)) +        (st (jao-mpc--cmd (format "status '%s'" jao-mpc--stfmtt)))          (res)) -    (dolist (s (split-string s "\n" t " ") res) -      (when (string-match "\\(.+\\):::\\(.+\\)" s) -        (push (cons (intern (match-string 1 s)) (match-string 2 s)) res))))) +    (jao-mpc--parse-fields s res) +    (jao-mpc--parse-fields st res))) -(defun jao-mpc--playing-p (&optional port) -  (not (string-blank-p (jao-mpc--cmd "status|grep '\\[playing\\]'" port)))) +(defsubst jao-mpc-status (&optional port) +  (string-trim (jao-mpc--cmd "status %state%" port))) -(defun jao-mpc--queue-len (&optional port) -  (string-to-number (jao-mpc--cmd "playlist|wc -l" port))) +(defsubst jao-mpc-playing-p (&optional port) +  (string-prefix-p "playing" (jao-mpc-status port))) + +(defsubst jao-mpc--queue-len (&optional port) +  (string-to-number (jao-mpc--cmd "status %length%" port)))  (defsubst jao--put-face (str face)    (put-text-property 0 (length str) 'face face str)    str) -(defun jao-mpc--current-str (&optional port current len) -  (let* ((current (or current (jao-mpc--current port))) -         (len (or len (jao-mpc--queue-len port))) -         (title (alist-get 'title current (alist-get 'name current ""))) -         (album (alist-get 'album current)) -         (artist (alist-get 'artist current)) -         (composer (alist-get 'composer current)) -         (no (string-to-number (alist-get 'position current "0"))) -         (time (alist-get 'time current ""))) -    (format "> %s%s %s%s%s%s" ;;  -            (jao--put-face (if (zerop no) "" (format "%02d/%s " no len)) -                           'jao-themes-f02) -            (jao--put-face title 'jao-themes-f00) -            (jao--put-face artist 'jao-themes-f01) -            (jao--put-face (if composer (format " [%s]" composer) "") -                           'jao-themes-f01) -            (jao--put-face (if album (format " (%s)" album) "") 'jao-themes-f11) -            (if (string-blank-p time) -                "" -              (jao--put-face (format " [%s]" time) 'jao-themes-dimm))))) +(defun jao-mpc--current-timestr (playing-times &optional current) +  (let* ((current (or current (jao-mpc--current))) +         (time (alist-get 'totaltime current ""))) +    (if playing-times +        (format "%s/%s%s" +                (alist-get 'currenttime current "") +                time +                (alist-get 'percenttime current "")) +      (format "%s" time)))) + +(defun jao-mpc--current-str (&optional port times) +  (if-let* ((current (jao-mpc--current port)) +            (title (alist-get 'title current (alist-get 'name current)))) +    (let ((len (alist-get 'length current "0")) +          (album (alist-get 'album current)) +          (artist (alist-get 'artist current)) +          (composer (alist-get 'composer current)) +          (no (string-to-number (alist-get 'songpos current "0"))) +          (tims (concat " [" (jao-mpc--current-timestr times current) "]"))) +      (format "%s%s %s%s%s%s" ;;  +              (jao--put-face (if (zerop no) "" (format "%d/%s " no len)) +                             'jao-themes-f02) +              (jao--put-face (or title "") 'jao-themes-f00) +              (jao--put-face (or artist "") 'jao-themes-f01) +              (jao--put-face (if composer (format " [%s]" composer) "") +                             'jao-themes-f01) +              (jao--put-face (if album (format " (%s)" album) "") +                             'jao-themes-f11) +              (jao--put-face tims (if times 'jao-themes-f00 'jao-themes-dimm)))) +    ""))  (defvar jao-mpc-minibuffer-str "")  (defun jao-mpc--set-current-str (&optional port) -  (setq jao-mpc-minibuffer-str -        (if (jao-mpc--playing-p port) -            (jao-mpc--current-str port) -          (when (and (null port) jao-random-album-p (not (jao-mpc--current))) -            (jao-random-album-next)) -          "")) +  (let ((status (or (jao-mpc-status port) ""))) +    (setq jao-mpc-minibuffer-str +          (if (string= "playing" status) (jao-mpc--current-str port) "")) +    (when (and jao-random-album-active +               (or (string= status "stopped") (string= status "paused")) +               (string= "0\n" (jao-mpc--cmd "status %songpos%" port))) +      (jao-random-album-next)))    (jao-minibuffer-refresh))  (defvar jao-mpc--idle-procs nil) @@ -105,15 +134,19 @@          (make-process :name (format "jao-mpc-idleloop (%s)" port)                        :buffer nil                        :noquery t -                      :command `("mpc" "-p" ,(format "%s" (or port jao-mpc-port)) -                                 "idleloop" "player") -                      :filter (lambda (_p _s) (jao-mpc--set-current-str port))))) +                      :command +                      `("mpc" "-p" ,(format "%s" (or port jao-mpc-port)) +                        "idleloop" "player") +                      :filter (lambda (_p _s) +                                (jao-mpc--set-current-str port))))) + +(defvar jao-mpc--browser-port nil)  (define-derived-mode jao-mpc-albums-mode fundamental-mode "MPC Albums"    "Mode to display the list of albums known by mpd."    (read-only-mode -1)    (delete-region (point-min) (point-max)) -  (insert (jao-mpc--cmd "list album")) +  (insert (jao-mpc--cmd "list album" jao-mpc--browser-port))    (goto-char (point-min))    (read-only-mode 1)) @@ -124,12 +157,14 @@        (jao-mpc-albums-mode)        (current-buffer)))) -(defun jao-mpc--add-and-play (&optional album) +(defun jao-mpc--add-and-play (&optional album port idp)    (interactive) -  (let ((album (or album (string-trim (thing-at-point 'line))))) -    (jao-mpc--cmd "clear") -    (jao-mpc--cmd (format "findadd album \"%s\"" album)) -    (jao-mpc--cmd "play"))) +  (let ((a (or album (string-trim (thing-at-point 'line)))) +        (p (or port jao-mpc--browser-port))) +    (jao-mpc--cmd "clear" p) +    (jao-mpc--cmd (if idp (concat "add " a) (format "findadd album \"%s\"" a)) +                  p) +    (jao-mpc--cmd "play" p)))  (define-key jao-mpc-albums-mode-map (kbd "n") #'next-line)  (define-key jao-mpc-albums-mode-map (kbd "p") #'previous-line) @@ -161,7 +196,8 @@  (define-key jao-mpc-playlist-mode-map (kbd "n") #'next-line)  (define-key jao-mpc-playlist-mode-map (kbd "p") #'previous-line)  (define-key jao-mpc-playlist-mode-map (kbd "q") #'bury-buffer) -(define-key jao-mpc-playlist-mode-map (kbd ".") #'jao-mpc--playlist-goto-current) +(define-key jao-mpc-playlist-mode-map (kbd ".") +            #'jao-mpc--playlist-goto-current)  (define-key jao-mpc-playlist-mode-map (kbd "RET") #'jao-mpc--playlist-play)  (define-key jao-mpc-playlist-mode-map (kbd "C") #'jao-mpc-clear) @@ -170,15 +206,22 @@      (let ((jao-mpc-port (or port jao-mpc-port))) (jao-mpc-playlist-mode))      (current-buffer))) +(defun jao-mpc--with-delayed-random-album (cmd port) +  (let ((st jao-random-album-active)) +    (setq jao-random-album-active nil) +    (jao-mpc--cmd cmd port) +    (accept-process-output nil 0.5) +    (setq jao-random-album-active st))) +  ;;;###autoload  (defun jao-mpc-stop (&optional port)    (interactive) -  (jao-mpc--cmd "stop" port)) +  (jao-mpc--with-delayed-random-album "stop" port))  ;;;###autoload  (defun jao-mpc-toggle (&optional port)    (interactive) -  (jao-mpc--cmd "toggle" port)) +  (jao-mpc--with-delayed-random-album "toggle" port))  ;;;###autoload  (defun jao-mpc-play (&optional port) @@ -208,7 +251,29 @@  ;;;###autoload  (defun jao-mpc-echo-current (&optional port)    (interactive) -  (jao-notify (jao-mpc--current-str port))) +  (message "%s" (jao-mpc--current-str port t))) + +;;;###autoload +(defun jao-mpc-echo-current-times (&optional port) +  (interactive) +  (message "Playing time: %s" (jao-mpc--current-timestr t))) + +;;;###autoload +(defun jao-mpc-notify (&optional port) +  (interactive) +  (when-let* ((current (jao-mpc--current))) +    (let* ((artist (or (alist-get 'artist current) "Anonymous")) +           (title (or (alist-get 'title current) +                      (when-let* ((tl (alist-get 'file current))) +                        (file-name-base tl)) +                      "")) +           (album (or (alist-get 'album current) "")) +           (track (or (alist-get 'track current) "")) +           (times (jao-mpc--current-timestr t current))) +      (jao-notify (format "%s -- %s" artist times) +                  (format "%s %s" track title) +                  jao-notify-audio-icon +                  album))))  ;;;###autoload  (defun jao-mpc-add-url (url) @@ -216,9 +281,33 @@    (jao-mpc--cmd (format "add %s" url)))  ;;;###autoload -(defun jao-mpc-show-albums () +(defun jao-mpc-add-or-play-url (url &optional play) +  "Add the given URL to mpc's playing list, or just play it." +  (let ((p (or play (yes-or-no-p (format "Play %s right now?" url))))) +    (when p (jao-mpc-clear)) +    (jao-mpc-add-url url) +    (if p (jao-mpc-play) (message "%s added to mpc queue" url)))) + +(defvar jao-mpc-stream-urls +  '(("classic fm" . "http://media-ice.musicradio.com:80/ClassicFMMP3") +    ("wcpe" . "http://audio-mp3.ibiblio.org:8000/wcpe.mp3") +    ("davide of mimic" . "http://streaming01.zfast.co.uk:8018/stream") +    ("cinemix" . "http://94.23.51.96:8000") ;; 209.9.238.4:6022 209.9.238.4:6046 +    ("bbc gold" . "http://media-ice.musicradio.com:80/GoldMP3") +    ("irish gold" . "http://icecast2.rte.ie/gold"))) + +;;;###autoload +(defun jao-mpc-play-stream () +  "Select a predefined stream URL and add or play it in mpc." +  (interactive) +  (let ((s (completing-read "Stream: " jao-mpc-stream-urls))) +    (jao-mpc-add-or-play-url (cdr (assoc s jao-mpc-stream-urls)) t))) + +;;;###autoload +(defun jao-mpc-show-albums (&optional port)    "Show album list."    (interactive) +  (setq jao-mpc--browser-port port)    (pop-to-buffer (jao-mpc--album-buffer)))  ;;;###autoload @@ -239,35 +328,35 @@  (defun jao-mpc-connect (&optional port)    (interactive)    (jao-mpc--idle-loop port) -  (when (jao-mpc--playing-p port) (jao-mpc--set-current-str port))) +  (when (jao-mpc-playing-p port) (jao-mpc--set-current-str port)))  ;;;###autoload  (defun jao-mpc-setup (&optional secondary-port priority)    (setq jao-lyrics-info-function #'jao-mpc-lyrics-track-data)    (jao-random-album-setup #'jao-mpc--album-buffer                            #'jao-mpc--add-and-play -                          #'jao-mpc-stop -                          jao-notify-audio-icon) -  (jao-mpc-connect) +                          #'jao-mpc-stop) +  (let ((jao-random-album-active nil)) (jao-mpc-connect))    (when secondary-port (jao-mpc-connect secondary-port))    (when priority      (if (> priority 0)          (jao-minibuffer-add-variable 'jao-mpc-minibuffer-str priority)        (jao-minibuffer-add-msg-variable 'jao-mpc-minibuffer-str (- priority))))) -(defvar jao-mpc--album-titles nil)  (defconst jao-mpc--albums-cmd    "-f '%album% - %artist%' find \"(ALBUM =~ '.*')\" | uniq") +(defconst jao-mpc--simple-albums-cmd "list album")  ;;;###autoload -(defun jao-mpc-select-album (refresh) -  (interactive "P") -  (let ((albums (or (and (not refresh) jao-mpc--album-titles) -                    (setq jao-mpc--album-titles -                          (split-string (jao-mpc--cmd jao-mpc--albums-cmd) -                                        "\n" t))))) +(defun jao-mpc-select-album (&optional port) +  (interactive) +  (let* ((albums-str (jao-mpc--cmd jao-mpc--albums-cmd port)) +         (albums-str (if (string= "" albums-str) +                         (jao-mpc--cmd jao-mpc--simple-albums-cmd port) +                       albums-str)) +         (albums (split-string albums-str "\n" t)))      (when-let (album (completing-read "Play album: " albums nil t)) -      (jao-mpc--add-and-play (car (split-string album "-" t " ")))))) +      (jao-mpc--add-and-play (car (split-string album "-" t " ")) port))))  (provide 'jao-mpc)  ;;; jao-mpc.el ends here diff --git a/lib/media/jao-mpris.el b/lib/media/jao-mpris.el index 47a35a7..80d0675 100644 --- a/lib/media/jao-mpris.el +++ b/lib/media/jao-mpris.el @@ -1,6 +1,6 @@  ;;; jao-mpris.el --- mpris players control           -*- lexical-binding: t; -*- -;; Copyright (C) 2020, 2021, 2022  jao +;; Copyright (C) 2020, 2021, 2022, 2024, 2025  jao  ;; Author: jao <mail@jao.io>  ;; Keywords: multimedia @@ -119,7 +119,7 @@           (duration (cond (duration duration)                           ((stringp len) len)                           ((numberp len) (jao-mpris--fmt-time (/ len 1e6) ""))))) -    (format "> %s %s %s%s%s" +    (format "%s %s %s%s%s"              (jao--put-face (format "%s" (or track "")) 'jao-themes-f00)              (jao--put-face (or title "") 'jao-themes-f01)              (jao--put-face (or artist "") 'jao-themes-f11) @@ -130,6 +130,7 @@  (defun jao-mpris--track (&optional info)    (let ((info (or info (jao-playerctl--status)))) +    (setq jao-mpris--current info)      (if (string= "Playing" (jao-mpris--get 'status info))          (setq jao-mpris-track-string (jao-mpris--format info))        (setq jao-mpris-track-string ""))) @@ -157,25 +158,25 @@  (defun jao-mpris--handler (iname properties &rest _args)    (let ((inhibit-message t)) -    (message "Received properties: %S from %s" properties iname)) -  (when-let (md (caadr (assoc "Metadata" properties))) -    (let ((tno (caadr (assoc "xesam:trackNumber" md))) -          (tlt (caadr (assoc "xesam:title" md))) -          (art (caadr (assoc "xesam:artist" md))) -          (alb (caadr (assoc "xesam:album" md))) -          (len (caadr (assoc "mpris:length" md)))) -      (if (string= (or tlt "") "TIDAL") -          (jao-mpris-reset) +    (message "Received properties: %S from %s" properties iname) +    (when-let (md (caadr (assoc "Metadata" properties))) +      (let ((tno (caadr (assoc "xesam:trackNumber" md))) +            (tlt (caadr (assoc "xesam:title" md))) +            (art (caadr (assoc "xesam:artist" md))) +            (alb (caadr (assoc "xesam:album" md))) +            (len (caadr (assoc "mpris:length" md))))          (jao-mpris--set-current 'track tno)          (jao-mpris--set-current 'title tlt)          (jao-mpris--set-current 'artist art)          (jao-mpris--set-current 'album alb) -        (jao-mpris--set-current 'length len)))) -  (when-let (st (caadr (assoc "PlaybackStatus" properties))) -    (jao-mpris--set-current 'status st) -    (when (string= st "Stopped") -      (dolist (k '(track title artist album length)) -        (jao-mpris--del-current k)))) +        (jao-mpris--set-current 'length len))) +    (when-let (st (caadr (assoc "PlaybackStatus" properties))) +      (jao-mpris--set-current 'status st) +      (when (string= st "Stopped") +        (dolist (k '(track title artist album length)) +          (jao-mpris--del-current k)))) +    ;; (message "Current is: %S" jao-mpris--current) +    )    (jao-mpris--track jao-mpris--current))  ;;;###autoload diff --git a/lib/media/jao-random-album.el b/lib/media/jao-random-album.el index 2800115..3b2915b 100644 --- a/lib/media/jao-random-album.el +++ b/lib/media/jao-random-album.el @@ -1,6 +1,6 @@  ;; jao-random-album.el -- play random albums -;; Copyright (C) 2009, 2010, 2017, 2018, 2019, 2021 Jose Antonio Ortega Ruiz +;; Copyright (C) 2009, 2010, 2017-2019, 2021-2022, 2024 Jose Antonio Ortega Ruiz  ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>  ;; Start date: Sat Jul 04, 2009 13:06 @@ -18,13 +18,10 @@  ;; You should have received a copy of the GNU General Public License  ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. -(require 'jao-notify) - -(defvar jao-random-album-p t) +(defvar jao-random-album-active t)  (defvar jao-random-lines nil)  (defvar jao-random-lines-file (expand-file-name "~/.emacs.d/random-lines")) -(defvar jao-random-album-notify-p t) -(defvar jao-random-album-notify-icon jao-notify-audio-icon) +(defvar jao-random-album-notify nil)  (defvar jao-random-album-skip-lines 2)  (defun jao-random-lines () @@ -60,19 +57,19 @@  (defun jao-random-album-start ()    (interactive) -  (setq jao-random-album-p t) +  (setq jao-random-album-active t)    (jao-random-album-next))  (defun jao-random-album-stop ()    (interactive) -  (setq jao-random-album-p nil) +  (setq jao-random-album-active nil)    (funcall jao-random-album-stop))  (defun jao-random-album-toggle ()    (interactive) -  (setq jao-random-album-p (not jao-random-album-p)) +  (setq jao-random-album-active (not jao-random-album-active))    (message "Random album %s" -           (if jao-random-album-p "enabled" "disabled"))) +           (if jao-random-album-active "enabled" "disabled")))  (defun jao-random-album-next ()    (interactive) @@ -80,19 +77,18 @@      (jao-goto-random-album)      (let ((album (string-trim (thing-at-point 'line))))        (funcall jao-random-album-add-tracks-and-play album) -      (when jao-random-album-notify-p -        (jao-notify album "Next album" jao-random-album-notify-icon))))) +      (when jao-random-album-notify +        (funcall jao-random-album-notify album)))))  (defun jao-random-album-reset ()    (interactive)    (setq jao-random-lines nil)    (jao-random-lines-save)) -(defun jao-random-album-setup (album-buffer add-and-play stop &optional icon) +(defun jao-random-album-setup (album-buffer add-and-play stop)    (setq jao-random-album-buffer album-buffer          jao-random-album-add-tracks-and-play add-and-play -        jao-random-album-stop stop -        jao-random-album-notify-icon icon)) +        jao-random-album-stop stop))  (provide 'jao-random-album) diff --git a/lib/media/jao-spt.el b/lib/media/jao-spt.el index 4484ead..ba5d104 100644 --- a/lib/media/jao-spt.el +++ b/lib/media/jao-spt.el @@ -1,6 +1,6 @@  ;;; jao-spt.el --- Access to the spotify-tui CLI     -*- lexical-binding: t; -*- -;; Copyright (C) 2021, 2022  jao +;; Copyright (C) 2021, 2022, 2024  jao  ;; Author: jao <mail@jao.io>  ;; Keywords: multimedia @@ -27,7 +27,7 @@  (require 'jao-minibuffer)  (require 'jao-notify) -(defvar jao-spt-bin (expand-file-name "~/bin/spt")) +(defvar jao-spt-bin "spt")  (defvar jao-spt-format "'%s %t - %a [%r] %f'")  (defvar jao-spt-device nil) @@ -48,7 +48,7 @@      st))  (defun jao-spt--pb* (&rest args) -  (message (apply 'jao-spt--pb args))) +  (message "%s" (apply 'jao-spt--pb args)))  ;;;###autoload  (defun jao-spt-play-uri (uri) @@ -119,7 +119,7 @@  ;;;###autoload  (defun jao-spt-echo-current ()    (interactive) -  (let ((jao-notify-use-messages-p t)) +  (let ((jao-notify-use-messages t))      (jao-notify (jao-spt-update-status))))  ;;;###autoload  | 
