;; jao-emms-info-track.el -- utilities to show tracks -*- lexical-binding:t; -*- ;; Copyright (C) 2009, 2010, 2013, 2017, 2020, 2021 Jose Antonio Ortega Ruiz ;; Author: Jose Antonio Ortega Ruiz ;; Start date: Sat Jul 04, 2009 13:47 ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3 of the License, or ;; (at your option) any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Code: (require 'emms) (require 'emms-tag-editor) (require 'emms-player-mpd) (require 'jao-emms) (require 'jao-minibuffer) (defgroup jao-emms-faces nil "Faces" :group 'faces :group 'jao-emms) (defface jao-emms-font-lock-album '((t (:foreground "lightgoldenrod2"))) "Album name in EMMS track message." :group 'jao-emms-faces) (defface jao-emms-font-lock-track '((t (:bold t))) "Track number in EMMS track message." :group 'jao-emms-faces) (defface jao-emms-font-lock-title '((t (:foreground "dodgerblue2"))) "Track title in EMMS track message." :group 'jao-emms-faces) (defface jao-emms-font-lock-artist '((t (:foreground "dodgerblue3"))) "Artist name in EMMS track message." :group 'jao-emms-faces) (defcustom jao-emms-show-osd-p nil "Whether to show osd notices on track change" :group 'jao-emms) (defun jao-emms-info-track-stream (track) "Return track info for streams" (let* ((name (emms-track-name track)) (title (or (emms-track-get track 'title nil) (car (emms-track-get track 'metadata nil)) (car (split-string (shell-command-to-string "mpc status") "\n")))) (title (if (string-match "https?://\\([^/]+\\)/.+" (or title "")) (match-string 1 title) title))) (format " %s (%s)" (or title "") (if title (emms-track-type track) name)))) (defsubst jao--put-face (str face) (put-text-property 0 (length str) 'face face str) str) (defun jao-emms--to-number (x) (or (and (numberp x) x) (and (stringp x) (string-match "\\`\\(:?[0-9]+\\)" x) (string-to-number (match-string 1 x))))) (defun jao-emms--fmt-time (x suffix) (if x (format "%02d:%02d%s" (/ x 60) (mod x 60) (or suffix "")) "")) (defun jao-emms--fmt-song-times (track lapsed pre post) (if lapsed (let ((time (when track (emms-track-get track 'info-playing-time)))) (format "%s%s%s%s" (or pre "") (jao-emms--fmt-time lapsed (when time "/")) (jao-emms--fmt-time time "") (or post ""))) "")) (defun jao-emms-info-track-file (track &optional lapsed plen titlesep) "Return a description of the current track." (let* ((no (jao-emms--to-number (emms-track-get track 'info-tracknumber "0"))) (time (emms-track-get track 'info-playing-time)) (year (emms-track-get track 'info-year)) (year (if year (format " (%s)" year) "")) (artist (emms-track-get track 'info-artist "")) (composer (emms-track-get track 'info-composer nil)) (title (emms-track-get track 'info-title "")) (album (emms-track-get track 'info-album)) (last-played (or (emms-track-get track 'last-played) '(0 0 0))) (play-count (or (emms-track-get track 'play-count) 0)) (playlength (if plen (format "/%02d" (string-to-number plen)) ""))) (if (or (not title) (not album)) (emms-track-simple-description track) (format " %s%s%s%s%s%s%s" (jao--put-face (if (zerop no) "" (format "%02d%s " no playlength)) 'jao-emms-font-lock-track) (jao--put-face title 'jao-emms-font-lock-title) (or titlesep " ") (jao-emms--fmt-song-times track lapsed "[" "] ") (jao--put-face artist 'jao-emms-font-lock-artist) (jao--put-face (if composer (format " [%s]" composer) "") 'jao-emms-font-lock-artist) (jao--put-face (if album (format " (%s%s)" album year) (format "%s *") year) 'jao-emms-font-lock-album))))) ;;;###autoload (defun jao-emms-info-track-description (track &optional lapsed plen tsep) (if (memq (emms-track-type track) '(streamlist url)) (jao-emms-info-track-stream track) (jao-emms-info-track-file track lapsed plen tsep))) ;;;###autoload (defun jao-emms-toggle-osd () (interactive) (setq jao-emms-show-osd-p (not jao-emms-show-osd-p)) (message "Emms OSD %s" (if jao-emms-show-osd-p "enabled" "disabled"))) (defvar jao-emms-show-icon nil) (defun jao-emms--with-mpd-track (callback) (emms-player-mpd-get-status nil (lambda (_ st) (let* ((lapsed (jao-emms--to-number (cdr (assoc "time" st)))) (plen (cdr (assoc "playlistlength" st))) (song (jao-emms--to-number (cdr (assoc "song" st)))) (track (emms-playlist-current-selected-track))) (when (and track song) (emms-track-set track 'info-tracknumber (format "%d" (1+ song)))) (funcall callback track lapsed plen))))) ;;;###autoload (defun jao-emms-show-osd () (interactive) (jao-emms--with-mpd-track (lambda (track lapsed play-len) (let* ((sep "~~~~~") (s (jao-emms-info-track-description track lapsed play-len sep)) (s (substring-no-properties s 2)) (cs (split-string s sep))) (jao-notify (car cs) (cadr cs) jao-emms-show-icon))))) (defun jao-emms-show-osd-hook () (interactive) (when jao-emms-show-osd-p (jao-emms-show-osd))) (defun jao-emms-install-id3v2 () (add-to-list 'emms-tag-editor-tagfile-functions '("mp3" "id3v2" ((info-artist . "-a") (info-title . "-t") (info-album . "-A") (info-tracknumber . "-T") (info-year . "-y") (info-genre . "-g") (info-composer . "--TCOM") (info-note . "-c"))))) (defvar jao-emms-echo-string "") (defun jao-emms--echo-string (v) (setq jao-emms-echo-string v) (jao-minibuffer-refresh)) (defun jao-emms-update-echo-string (&optional existing-track) (if emms-player-playing-p (jao-emms--with-mpd-track (lambda (track lapsed play-len) (jao-emms--echo-string (cond ((and emms-player-paused-p existing-track) (format "(%s/%s)" (emms-track-get existing-track 'info-tracknumber) play-len)) (emms-player-paused-p "") (t (jao-emms-info-track-description track nil play-len)))))) (jao-emms--echo-string ""))) (defun jao-emms-enable-minibuffer (minibuffer-order) (jao-minibuffer-add-msg-variable 'jao-emms-echo-string minibuffer-order) (dolist (h '(emms-track-updated-functions emms-player-finished-hook emms-player-stopped-hook emms-player-started-hook emms-player-paused-hook)) (add-hook h #'jao-emms-update-echo-string))) ;;;###autoload (defun jao-emms-info-setup (&optional minibuffer show-osd show-echo-line id3) (setq emms-track-description-function 'jao-emms-info-track-description) (setq jao-emms-show-osd-p show-osd) (add-hook 'emms-player-started-hook 'jao-emms-show-osd-hook) (when minibuffer (jao-emms-enable-minibuffer minibuffer)) (unless show-echo-line (eval-after-load 'emms-player-mpd '(remove-hook 'emms-player-started-hook 'emms-player-mpd-show))) (when id3 (jao-emms-install-id3v2)) (ignore-errors (emms-player-mpd-connect))) (provide 'jao-emms-info-track) ;;; jao-emms-info-track.el ends here