First thing is to set up emms.
I could simply enable all the emms features in one line,
``` (with-eval-after-load 'emms (emms-all))
```
But above setup makes filtering tracks very slow because it's too heavy weight.
So I use below setup,
``` (with-eval-after-load 'emms ;; minimum setup is more robust (emms-minimalistic)
;; `emms-info-native' supports mp3,flac and requires NO cli tools (unless (memq 'emms-info-native emms-info-functions) (require 'emms-info-native) (push 'emms-info-native emms-info-functions))
;; extract track info when loading the playlist (push 'emms-info-initialize-track emms-track-initialize-functions)
;; I also use emms to manage tv shows, so I use mplayer only (setq emms-player-list '(emms-player-mplayer)))
```
Play mp3&flac in "~/Dropbox/music",
``` (defun my-music () "My music." (interactive) (emms-stop) (when (bufferp emms-playlist-buffer-name) (kill-buffer emms-playlist-buffer-name)) (emms-play-directory-tree "~/Dropbox/music") (emms-shuffle) (emms-next))
```
Sometimes I need focus on challenge programming tasks and emms should play only Mozart&Bach.
``` (defvar my-emms-playlist-filter-keyword "mozart|bach" "Keyword to filter tracks in emms playlist. Space in the keyword matches any characters. \"|\" means OR operator in regexp.")
(defun my-strip-path (path strip-count) "Strip PATH with STRIP-COUNT." (let* ((i (1- (length path))) str) (while (and (> strip-count 0) (> i 0)) (when (= (aref path i) ?/) (setq strip-count (1- strip-count))) (setq i (1- i))) (setq str (if (= 0 strip-count) (substring path (1+ i)) path)) (replace-regexp-in-string "^/" "" str)))
(defun my-emms-track-description (track) "Description of TRACK." (let ((desc (emms-track-simple-description track)) (type (emms-track-type track))) (when (eq 'file type) (setq desc (my-strip-path desc 2))) desc))
(defvar my-emms-track-regexp-function #'my-emms-track-regexp-internal "Get regexp to search track.")
(defun my-emms-track-regexp-internal (keyword) "Convert KEYWORD into regexp for matching tracks." (let ((re (replace-regexp-in-string "|" "\\|" keyword))) (setq re (replace-regexp-in-string " +" "." re))))
(defun my-emms-track-match-p (track keyword) "Test if TRACK's information match KEYWORD." (let* ((case-fold-search t) (regexp (funcall my-emms-track-regexp-function keyword)) s) (or (string-match regexp (emms-track-force-description track)) (and (setq s (emms-track-get track 'info-genre)) (string-match regexp s)) (and (setq s (emms-track-get track 'info-title)) (string-match regexp s)) (and (setq s (emms-track-get track 'info-album)) (string-match regexp s)) (and (setq s (emms-track-get track 'info-composer)) (string-match regexp s)) (and (setq s (emms-track-get track 'info-artist)) (string-match regexp s)))))
(defun my-emms-show () "Show information of current track." (interactive) (let* ((emms-track-description-function (lambda (track) (let ((composer (emms-track-get track 'info-composer)) (artist (emms-track-get track 'info-artist))) (concat (if composer (format "%s(C) => " composer)) (if artist (format "%s(A) => " artist)) (my-emms-track-description track)))))) (emms-show)))
(defun my-emms-playlist-filter (&optional input-p) "Filter tracks in emms playlist. If INPUT-P is t, `my-emms-playlist-random-track-keyword' is input by user." (interactive "P") ;; shuffle the playlist (when input-p (setq my-emms-playlist-filter-keyword (read-string "Keyword to filter tracks in playlist: "))) (with-current-buffer emms-playlist-buffer-name (goto-char (point-min)) (let* ((case-fold-search t) track) (while (setq track (emms-playlist-track-at)) (cond ((my-emms-track-match-p track my-emms-playlist-filter-keyword) (forward-line 1)) (t (emms-playlist-mode-kill-track))))))
(emms-random) ;; show current track info (my-emms-show))
```
As you can see, a little EMMS api knowledge could go a long way.
If you want to study EMMS API by practice, run M-x emms-playlist-mode-go, then M-x eval-expression RETURN (emms-playlist-track-at) to get the information of the track at point.
Here is my real world emms setup where you can see below code,
``` (defvar my-emms-track-regexp-function (lambda (str) ;; can search track with Chinese information (my-emms-track-regexp-internal (my-extended-regexp str))) "Get regexp to search track.")
```
So I can use Pinyin to search track's Chinese information. I don't know any other multimedia manager can do the same thing.