emms-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Example Emms setups


From: Bob Newell
Subject: Re: Example Emms setups
Date: Tue, 22 Dec 2020 16:09:27 -1000

My setup. Kind of complicated but there are a few interesting bits,
mostly about compatibility between Linux and Termux, and some fancy
footwork with mpv volume control. The code is quite "raw" and let's
just say, unstylish. All the play choices are in a separate elisp
file, which I didn't think would be of much interest so it's not
included here.

;; Startup file for EMMS.

;;; 2020-12-03 'file' control is gone from mpv, so converted to
;;             ipc socket, requiring 'socat' utility.
;;; 2020-11-08 Minor fixes; remove redundant calls.
;;; 2019-04-09 Spotify startup code for helm-spotify-new.
;;; 2018-07-11 Some fixes needed for EMMS changes wrt file input.
;;; 2018-06-12 Made volume control keys persistent again.
;;; 2018-06-10 No more vlc or vlc volume control.
;;;            Everything is mpv and drop-file commands so we
;;;            can have almost the same code for both termux and linux.
;;; 2018-06-08 Moved emms stuff from startup.el and newage.el.
;;; 2018-04-03 Fixed volume reset problem so volume remains
;;;            stable between plays or repeat plays when using
;;;            mpv under Termux.
;;; 2017-10-10 Fixed playlist problems; vlc must be externally
;;;            set to no repeating. Use internal emms variables
;;;            to control track and playlist repeat.
;;; 2016-08-22 Went to autogeneration of play entries based
;;;            on ~/dwhelper directory, using aux. macro.
;;; 2016-07-30 Finally got relative seek working.
;;; 2016-07-10 With so many additions, now keeping play choices
;;;            in alpha order. Mostly.
;;; 2016-06-23 Added .mkv, which was somehow omitted.
;;; 2015-01-31 Streamlined; don't need to track play state
;;;            when switching playlists. Just kill any
;;;            previous play state first.
;;; 2015-01-08 Changed player from cvlc to vlc.

;;; Music content and EMMS setup. Nearly uniform between Linux and
;;; Termux. Uses mpv. Includes volume control and seeking.

(require 'emms-setup)
(emms-all)
(emms-default-players)
(setq emms-source-file-default-directory "~/dwhelper/")
(require 'emms-player-simple)

;;; Allow for multiple cards on one computer. Not used any longer?
;;; With mpv we use a drop-file command method of volume control, rather
;;; than changing system volume. This is to make volume control work with no
;;; changes between termux and linux.
;(if (string= (system-name) "dakine")
;    (setq emms-volume-amixer-card 1)
;    (setq emms-volume-amixer-card 0))

;;; Set up "new" mpv methods almost (not quite) universal across
;;; devices.

(require 'emms-player-mpv)
    (setq emms-player-mpv-ipc-method nil)
;;    (setq emms-player-mpv-ipc-method 'unix-socket)
    (setq emms-player-list '(emms-player-mpv))

(require 'emms-volume)

;;; Still not completely correct but fully working. In Linux the input
;;; file is shown twice, but it's necessary to work in Termux. I leave
;;; the Linux reference explicit to guard against future changes to
;;; EMMS. Note that --no-ytdl is necessary for some live streams to
;;; work correctly (found on the internet to solve the problem of an
;;; early stream termination). Also, --volume-max=150 allows for a
;;; boost when max volume isn't quite enough.

;;; Why won't ~ work here?
(if termuxing
    ;; remove --no-ytdl from termux, but don't remember why
       (setq emms-player-rjn-mpv-parameters
     (list "--quiet" "--really-quiet" "--volume-max=150" "--no-audio-display"
       
"--input-ipc-server=/data/data/com.termux.files/home/.emacs.d/emms/mpv-input.sock"
))
       (setq emms-player-rjn-mpv-parameters
     (list "--no-ytdl" "--quiet" "--really-quiet" "--volume-max=150"
"--no-audio-display"
       "--input-ipc-server=/home/bnewell/.emacs.d/emms/mpv-input.sock" )))

;;; Reset global and minor mode volume keys, as C-c + and C-c - are
;;; used in org-mode.

(defun emms-player-volume-keys (&rest args)
  (interactive)
;;;  (global-set-key (kbd "C-c e +") 'emms-volume-mode-plus)
;;;  (global-set-key (kbd "C-c e -") 'emms-volume-mode-minus)
  (global-set-key (kbd "C-c e +") 'emms-player-mpv-volume-up)
  (global-set-key (kbd "C-c e -") 'emms-player-mpv-volume-down)
;;; Over-ride minor mode key definitions to refer to mpv.
  (define-key emms-volume-minor-mode-map (kbd "+") 'emms-player-mpv-volume-up)
  (define-key emms-volume-minor-mode-map (kbd "-") 'emms-player-mpv-volume-down)
)
(emms-player-volume-keys)

;;; For volume control use 5% steps. A little slow but works okay, and
;;; 10% is too coarse.

   (defun emms-player-mpv-volume-up ()
     (interactive)
     (if (get-process "emms-player-mpv")
(progn
      (setq mpv-volume-value (+ mpv-volume-value 5))
      (emms-player-mpv-change-volume)
      (emms-volume-mode-start-or-extend))
       (message "EMMS player not playing")))

   (defun emms-player-mpv-volume-down ()
     (interactive)
     (if (get-process "emms-player-mpv")
(progn
     (setq mpv-volume-value (- mpv-volume-value 5))
     (emms-player-mpv-change-volume)
     (emms-volume-mode-start-or-extend))
       (message "EMMS player not playing")))

(defvar mpv-volume-value 100) ;; rather arbitrary
(defun emms-player-mpv-change-volume (&optional args)
     (if (> mpv-volume-value 150)
(setq mpv-volume-value 150))
     (if (< mpv-volume-value 0)
(setq mpv-volume-value 0))

     (let* ((mpv-volume-readable (number-to-string mpv-volume-value))
    (cmd (format "echo 'set volume %s' | socat - %s"
          mpv-volume-readable (concat start-home
"/.emacs.d/emms/mpv-ipc.sock"))))
       (message (concat "Vol " mpv-volume-readable " pct"))
       (call-process-shell-command cmd nil nil nil))) ;; end of volume function

   ;; Set volume to last known state, or default if none.
   ;; Otherwise the volume will reset itself on every play
   ;; or repeat play.

    (global-set-key (kbd "C-c e +") 'emms-player-mpv-volume-up)
    (global-set-key (kbd "C-c e -") 'emms-player-mpv-volume-down)

;;; To ensure stable volume between mpv invocations.
    (advice-add 'emms-player-mpv-start :before #'emms-player-mpv-rjn-setup)

;;; The list manipulations have to be done carefully.
(defun emms-player-mpv-rjn-setup (&optional args)
  (let ( (temp-parms emms-player-rjn-mpv-parameters))
  (setq emms-player-mpv-parameters
(add-to-list 'temp-parms
   (concat "--volume=" (number-to-string mpv-volume-value))
))))

;;; Control functions. Not all of them necessary, just nice mnemonics.

(defun play-playing () "What are we playing now" (interactive)
  (if (eq play-now-playing nil)
      (message "Nothing playing!")
      (message (concat "Now playing " play-now-playing))))

(defun play-restart () "Restart the music" (interactive)
(emms-seek-to 0))

(defun play-stop () "Stop the music" (interactive)
(play-stop-stuff)
(message "Play stopped"))

(defun play-pause () "Pause the music" (interactive)
  (emms-pause))

(defun play-seek (seek-time)
  "Move play position relatively"
  (interactive "nSeek +/- how many seconds? ")
  (play-pause)
  ;;; A number preceeded by + or - goes to relative point.
  (emms-player-mpv-seek seek-time)
  (play-resume))

(defun play-seek-abs (seek-time)
  "Move play position absolutely"
  (interactive "nSeek to what position in seconds? ")
  (play-pause)
  (emms-player-mpv-seek-to seek-time)
  (play-resume))

(defun play-resume () "Resume the music" (interactive)
; No check if it's really paused.
(emms-pause))

(defun play-playlist () "Go to playlist" (interactive)
  (play-stop-stuff)
  (emms-playlist-mode-go)
)

(defun play-stop-stuff ()
  (emms-stop)
  (spotify-kill)
 (setq play-now-playing nil)
 (sleep-for 2)
)

;;; Necessary? emms-player-volume-keys is called at startup of Emacs.
;;; But this undoes spotify volume keys, which don't seem to work.
(advice-add 'emms-play-file :before #'emms-player-volume-keys)
(advice-add 'emms-play-url :before #'emms-player-volume-keys)
(advice-add 'emms-play-playlist :before #'emms-player-volume-keys)

;; We load newage.elc from here, in order to do things in the right order.
(load-library (concat start-lisp-home "newage.elc"))

;; Experimental spotify. Seems like a waste of time.

;;(add-to-list 'load-path (concat start-lisp-home "/spotify"))
;;(require 'spotify)

(defun spotify-kill (&rest args)
  (interactive)
   (if (not termuxing)
    (if (not (string= (shell-command-to-string "pgrep -x \"spotify\"") ""))
       (async-shell-command "killall -9 spotify >/dev/null 2>&1"))
;;; This would be better but doesn't seem to work.
;;;       (start-process "kill-spotify" nil "killall" "spotify"))
))

(defun spotify-check (&rest args)
  (interactive)
  "See if spotify is running and if not, run it"
  (if (not termuxing)
   (if (string= (shell-command-to-string "pgrep -x \"spotify\"") "")
    (progn
       (play-stop-stuff)
       (message "Starting Spotify")
       (start-process "spotify" nil "spotify")
       (setq play-now-playing "Spotify")
       (spotify-player-volume-keys)
       (sleep-for 2))
    )
   (async-shell-command (concat "termux-open " args)))
  )
;;; To ensure spotify is running before trying to play stuff.
(advice-add 'helm-spotify-plus-play-href :before #'spotify-check)

;; Settings
(setq spotify-oauth2-client-secret "secret letters and numbers")
(setq spotify-oauth2-client-id "secret letters and numbers")

(defun spotify-player-volume-keys ()
  (interactive)
  (global-set-key (kbd "C-c e +") 'spotify-volume-plus)
  (global-set-key (kbd "C-c e -") 'spotify-volume-minus)
)

(defun spotify-volume-plus ()
  (interactive)
  (shell-command "~/data/code/spotvolplus.py")
  )

(defun spotify-volume-minus ()
  (interactive)
  (shell-command "~/data/code/spotvolminus.py")
  )

(provide 'startup-emms)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]