From 6efc84e4c57ecfddcc3d8fcb0327c55af0e1536b Mon Sep 17 00:00:00 2001 From: Tim Vaughan Date: Thu, 5 Dec 2019 23:21:36 +0100 Subject: [PATCH] It's actually playing music. --- emus.el | 153 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 23 deletions(-) diff --git a/emus.el b/emus.el index 616d183..eb3d566 100644 --- a/emus.el +++ b/emus.el @@ -3,7 +3,7 @@ ;; Author: Tim Vaughan ;; Version: 1.0 ;; Keywords: multimedia -;; URL: http://github.com/tgvaughan/emus +;; URL: https://thelambdalab.xyz/emus ;;; Commentary: @@ -16,7 +16,7 @@ ;; (defgroup emus nil - "Simple music player for Emacs inspired by CMUS." + "Simple music player for Emacs." :group 'multimedia) (defcustom emus-directory "~/Music/" @@ -37,29 +37,58 @@ "Get all mp3 files in main emus directory." (directory-files-recursively emus-directory ".*\\.mp3")) -(defvar emus-tags nil) +(defvar emus-records nil) -(defun emus-update-tags () - "Get ID3 tags for given filename" +(defun emus-make-record (filename tagstr) + (let ((artist "") + (album "") + (title "")) + (dolist (line (split-string tagstr "\n")) + (let ((found-artist (elt (split-string line "@I ID3v2.artist:") 1)) + (found-album (elt (split-string line "@I ID3v2.album:") 1)) + (found-title (elt (split-string line "@I ID3v2.title:") 1))) + (cond + (found-artist (setq artist found-artist)) + (found-album (setq album found-album)) + (found-title (setq title found-title))))) + (list artist album title filename))) + +(defun emus-record-artist (record) + (elt record 0)) + +(defun emus-record-album (record) + (elt record 1)) + +(defun emus-record-title (record) + (elt record 2)) + +(defun emus-record-file (record) + (elt record 3)) + +(defun emus-update-records (then) (let ((proc (emus-get-process)) - (depth 0) (tagstr "") (filenames (emus-get-audio-files))) - (setq emus-tags nil) + (setq emus-records nil) (set-process-filter proc (lambda (proc string) (setq tagstr (concat tagstr string)) - (cond - ((string-suffix-p "}\n" string) (setq depth (- depth 1))) - ((string-suffix-p "{\n" string) (setq depth (+ depth 1)))) - (when (and (= depth 0) (string-suffix-p "\n" string)) - (add-to-list 'emus-tags `(,(car filenames) ,tagstr)) + (when (string-suffix-p "@P 1\n" string) + (add-to-list 'emus-records + (emus-make-record (car filenames) + tagstr)) (setq tagstr "") (setq filenames (cdr filenames)) (if filenames (emus-send-cmd "lp" (car filenames)) - (set-process-filter proc nil))))) + (set-process-filter proc nil) + (funcall then))))) (emus-send-cmd "lp" (car filenames)))) +;;; mpg123 process +;; + +(defvar emus-proc-in-use nil) + (defun emus-get-process () "Return current or new mpg123 process." (let* ((emus-process-raw (get-process "emus-process")) @@ -80,27 +109,105 @@ (seq-reduce (lambda (s1 s2) (concat s1 " " s2)) args cmd) "\n"))) +;;; Playback +;; + +(defvar emus-currently-playing nil) + +(defun emus-play-record (record) + (setq emus-currently-playing record) + (emus-send-cmd "l" (emus-record-file record))) + +(defun emus-stop () + (interactive) + (emus-send-cmd "s") + (setq emus-currently-playing nil)) + +(defun emus-playpause () + (interactive) + (emus-send-cmd "p")) + + +(defun emus-volume (pct) + (emus-send-cmd "v" (number-to-string pct))) + +(defvar emus-current-volume 10) + +(defun emus-volume-delta (delta) + (setq emus-current-volume (max 0 (min 100 (+ emus-current-volume delta)))) + (emus-volume emus-current-volume)) + +(defun emus-volume-up () + (interactive) + (emus-volume-delta 10)) + +(defun emus-volume-down () + (interactive) + (emus-volume-delta -10)) + + ;;; Browser ;; +(defun emus-render-record (record) + (insert-text-button + (concat + (propertize (format "%-20.20s" (emus-record-artist record)) + 'face 'font-lock-keyword-face) + (propertize (format "% -20.20s" (emus-record-album record)) + 'face 'font-lock-function-name-face) + (propertize (format " %s" (emus-record-title record)) + 'face 'font-lock-string-face)) + 'action #'emus-click-record + 'follow-link t + 'emus-record record) + (insert "\n")) + +(defun emus-render-records () + (with-current-buffer "*emus*" + (let ((inhibit-read-only t)) + (save-excursion + (erase-buffer) + (goto-char (point-min)) + (dolist (record emus-records) + (emus-render-record record)))))) + +(defun emus-click-record (button) + (emus-play-record (button-get button 'emus-record))) + (defun emus-browse () "Switch to *emus* audio library browser." (interactive) (switch-to-buffer "*emus*") - (emus-mode)) + (emus-mode) + (emus-volume emus-current-volume) + (if emus-records + (emus-render-records) + (emus-update-records #'emus-render-records))) + +(defvar emus-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "SPC") 'emus-playpause) + (define-key map (kbd "o") 'emus-stop) + (define-key map (kbd "+") 'emus-volume-up) + (define-key map (kbd "=") 'emus-volume-up) + (define-key map (kbd "-") 'emus-volume-down) + (when (fboundp 'evil-define-key*) + (evil-define-key* 'motion map + (kbd "SPC") 'emus-playpause + (kbd "o") 'emus-stop + (kbd "+") 'emus-volume-up + (kbd "=") 'emus-volume-up + (kbd "-") 'emus-volume-down)) + map) + "Keymap for emus.") (define-derived-mode emus-mode special-mode "Emus" "Major mode for EMUS music player.") -;;; Debugging - -(defun emus-test () - (message (emus-get-file-tags "/Users/vaughant/Music/Floex_-_Zorya/Floex - Zorya - 01 Ursa Major.mp3"))) - -(defun emus-test-play () - (emus-send-cmd "lp" "/Users/vaughant/Music/Floex_-_Zorya/Floex - Zorya - 01 Ursa Major.mp3") - (emus-send-cmd "silence") - (emus-send-cmd "p")) +(when (fboundp 'evil-set-initial-state) + (evil-set-initial-state 'emus-mode 'motion)) +;;; Debugging ;;; emus.el ends here -- 2.20.1