feat(emacs): emms

This commit is contained in:
Pavel Korytov 2021-07-22 19:44:52 +03:00
parent d209886abc
commit bd3743e3a3
2 changed files with 288 additions and 78 deletions

View file

@ -138,6 +138,8 @@
(evil-collection-init
'(eww
proced
emms
calendar
dired
debug
guix
@ -2733,6 +2735,152 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
(evil-collection-define-key 'normal 'elfeed-show-mode-map
"gm" #'my/elfeed-open-mpv))
(use-package emms
:straight t
:commands (emms-smart-browse emms-browser)
:init
(my-leader-def
:infix "as"
"s" 'emms-smart-browse
"b" 'emms-browser
"p" 'emms-pause
"q" 'emms-stop
"h" 'emms-previous
"l" 'emms-next
"u" 'emms-player-mpd-connect)
:config
(require 'emms-setup)
(require 'emms-player-mpd)
(emms-all)
;; MPD setup
(setq emms-source-file-default-directory (expand-file-name "~/Music/"))
(add-to-list 'emms-info-functions 'emms-info-mpd)
(add-to-list 'emms-player-list 'emms-player-mpd)
(setq emms-player-mpd-server-name "localhost")
(setq emms-player-mpd-server-port "6600")
(setq emms-player-mpd-music-directory "~/Music")
(emms-player-mpd-connect)
;; Clear MPD playlist on clearing EMMS playlist
;; IDK if this is fine for MPD playlists, I don't use them anyhow
(add-hook 'emms-playlist-cleared-hook 'emms-player-mpd-clear)
(defun emms-info-mpd-process (track info)
(dolist (data info)
(let ((name (car data))
(value (cdr data)))
(setq name (cond ((string= name "artist") 'info-artist)
((string= name "albumartist") 'info-albumartist)
((string= name "composer") 'info-composer)
((string= name "performer") 'info-performer)
((string= name "title") 'info-title)
((string= name "album") 'info-album)
((string= name "track") 'info-tracknumber)
((string= name "disc") 'info-discnumber)
((string= name "date") 'info-year)
((string= name "genre") 'info-genre)
((string= name "time")
(setq value (string-to-number value))
'info-playing-time)
(t nil)))
(when name
(emms-track-set track name value)))))
(defun emms-player-mpd-get-alists (info)
"Turn the given parsed INFO from MusicPD into an list of alists.
The list will be in reverse order."
(when (and info
(null (car info)) ; no error has occurred
(cdr info)) ; data exists
(let ((alists nil)
(alist nil)
cell)
(dolist (line (cdr info))
(when (setq cell (emms-player-mpd-parse-line line))
(if (member (car cell) '("file" "directory" "playlist"))
(setq alists (cons alist alists)
alist (list cell))
(setq alist (cons cell alist)))))
(when alist
(setq alists (cons alist alists)))
alists))))
(with-eval-after-load 'emms-browser
(evil-collection-define-key 'normal 'emms-browser-mode-map
"q" 'quit-window))
(with-eval-after-load 'emms
(evil-collection-define-key 'normal 'emms-playlist-mode-map
"q" 'quit-window))
(defun my/toggle-shr-use-fonts ()
"Toggle the shr-use-fonts variable in buffer"
(interactive)
(setq-local shr-use-fonts (not shr-use-fonts)))
(my-leader-def "aw" 'eww)
(general-define-key
:keymaps 'eww-mode-map
"+" 'text-scale-increase
"-" 'text-scale-decrease)
(my-leader-def "ai" #'erc-tls)
(use-package erc-hl-nicks
:hook (erc-mode . erc-hl-nicks-mode)
:straight t)
(setq erc-server "sqrtminusone.xyz")
(setq erc-port 1984)
(setq erc-nick "sqrtminusone")
(setq erc-user-full-name "Pavel Korytov")
(setq erc-track-shorten-start 8)
(setq erc-kill-buffer-on-part t)
(use-package znc
:straight t
:after (erc))
(use-package google-translate
:straight t
:functions (my-google-translate-at-point google-translate--search-tkk)
:custom
(google-translate-backend-method 'curl)
:config
(require 'facemenu)
(defun google-translate--search-tkk ()
"Search TKK."
(list 430675 2721866130))
(defun my-google-translate-at-point()
"reverse translate if prefix"
(interactive)
(if current-prefix-arg
(google-translate-at-point)
(google-translate-at-point-reverse)))
(setq google-translate-translation-directions-alist
'(("en" . "ru")
("ru" . "en"))))
(my-leader-def
"atp" 'google-translate-at-point
"atP" 'google-translate-at-point-reverse
"atq" 'google-translate-query-translate
"atQ" 'google-translate-query-translate-reverse
"att" 'google-translate-smooth-translate)
(use-package elcord
:straight t
:if (and (or
(string= (system-name) "indigo")
(string= (system-name) "eminence"))
(not my/slow-ssh))
:config
(elcord-mode)
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (+ num) "-" (+ num) "-" (+ num) ".org" eos))
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (= 14 num) "-" (* not-newline) ".org" eos)))
(use-package tldr
:straight t
:commands (tldr)
@ -2754,23 +2902,8 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
(setq Man-width-max 180)
(my-leader-def "hM" 'man)
(my-leader-def "ai" #'erc-tls)
(use-package erc-hl-nicks
:hook (erc-mode . erc-hl-nicks-mode)
:straight t)
(setq erc-server "sqrtminusone.xyz")
(setq erc-port 1984)
(setq erc-nick "sqrtminusone")
(setq erc-user-full-name "Pavel Korytov")
(setq erc-track-shorten-start 8)
(setq erc-kill-buffer-on-part t)
(use-package znc
:straight t
:after (erc))
(evil-collection-define-key 'normal 'Info-mode-map
(kbd "RET") 'Info-follow-nearest-node)
(use-package docker
:straight t
@ -2821,32 +2954,16 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
(kbd "C-k") 'evil-window-up
(kbd "C-j") 'evil-window-down))
(use-package google-translate
:straight t
:functions (my-google-translate-at-point google-translate--search-tkk)
:custom
(google-translate-backend-method 'curl)
:config
(require 'facemenu)
(defun google-translate--search-tkk ()
"Search TKK."
(list 430675 2721866130))
(defun my-google-translate-at-point()
"reverse translate if prefix"
(interactive)
(if current-prefix-arg
(google-translate-at-point)
(google-translate-at-point-reverse)))
(setq google-translate-translation-directions-alist
'(("en" . "ru")
("ru" . "en"))))
(my-leader-def "ah" 'proced)
(add-hook 'proced-mode-hook (lambda ()
(visual-line-mode -1)
(setq-local truncate-lines t)))
(my-leader-def
"atp" 'google-translate-at-point
"atP" 'google-translate-at-point-reverse
"atq" 'google-translate-query-translate
"atQ" 'google-translate-query-translate-reverse
"att" 'google-translate-smooth-translate)
(use-package guix
:straight t
:commands (guix)
:init
(my-leader-def "ag" 'guix))
(use-package pomidor
:straight t
@ -2865,22 +2982,12 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
(kbd "RET") #'pomidor-stop
(kbd "M-RET") #'pomidor-break))
(defun my/toggle-shr-use-fonts ()
"Toggle the shr-use-fonts variable in buffer"
(interactive)
(setq-local shr-use-fonts (not shr-use-fonts)))
(setq calendar-date-style 'iso) ;; YYYY/mm/dd
(setq calendar-week-start-day 1)
(setq calendar-time-display-form '(24-hours ":" minutes))
(my-leader-def "aw" 'eww)
(general-define-key
:keymaps 'eww-mode-map
"+" 'text-scale-increase
"-" 'text-scale-decrease)
(my-leader-def "ah" 'proced)
(add-hook 'proced-mode-hook (lambda ()
(visual-line-mode -1)
(setq-local truncate-lines t)))
(setq calendar-latitude 59.9375)
(setq calendar-longitude 30.308611)
(use-package screenshot
:straight (:repo "tecosaur/screenshot" :host github :files ("screenshot.el"))
@ -2906,22 +3013,3 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
:action (lambda (elem)
(setq zone-programs (vector (cdr elem)))
(zone))))
(use-package elcord
:straight t
:if (and (or
(string= (system-name) "indigo")
(string= (system-name) "eminence"))
(not my/slow-ssh))
:config
(elcord-mode)
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (+ num) "-" (+ num) "-" (+ num) ".org" eos))
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (= 14 num) "-" (* not-newline) ".org" eos)))
(use-package guix
:straight t
:commands (guix)
:init
(my-leader-def "ag" 'guix))

126
Emacs.org
View file

@ -221,11 +221,14 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [[#open-emacs-config][Open Emacs config]]
- [[#open-magit-for-yadm][Open Magit for yadm]]
- [[#open-a-dotfile][Open a dotfile]]
- [[#internet][Internet]]
- [[#internet--multimedia][Internet & Multimedia]]
- [[#notmuch][Notmuch]]
- [[#elfeed][Elfeed]]
- [[#some-additions][Some additions]]
- [[#youtube][YouTube]]
- [[#emms][EMMS]]
- [[#some-keybindings][Some keybindings]]
- [[#fixes][Fixes]]
- [[#eww][EWW]]
- [[#erc][ERC]]
- [[#google-translate][Google Translate]]
@ -503,6 +506,7 @@ I don't enable the entire package, just the modes I need.
(evil-collection-init
'(eww
proced
emms
calendar
dired
debug
@ -4059,7 +4063,7 @@ Open a file managed by yadm.
(general-define-key "C-c f" 'my/open-yadm-file)
(my-leader-def "cf" 'my/open-yadm-file)
#+end_src
** Internet
** Internet & Multimedia
*** Notmuch
My notmuch config now resides in [[file:Mail.org][Mail.org]].
@ -4178,6 +4182,124 @@ And a function to open YouTube link from elfeed
(evil-collection-define-key 'normal 'elfeed-show-mode-map
"gm" #'my/elfeed-open-mpv))
#+end_src
*** EMMS
EMMS is the Emacs Multi-Media System. I am currently trying to control MPD from Emacs with its help.
References:
- [[https://www.gnu.org/software/emms/manual/][EMMS Manual]]
- [[https://www.youtube.com/watch?v=xTVN8UDScqk][Uncle Dave's video]]
#+begin_src emacs-lisp :noweb yes
(use-package emms
:straight t
:commands (emms-smart-browse emms-browser)
:init
(my-leader-def
:infix "as"
"s" 'emms-smart-browse
"b" 'emms-browser
"p" 'emms-pause
"q" 'emms-stop
"h" 'emms-previous
"l" 'emms-next
"u" 'emms-player-mpd-connect)
:config
(require 'emms-setup)
(require 'emms-player-mpd)
(emms-all)
;; MPD setup
(setq emms-source-file-default-directory (expand-file-name "~/Music/"))
(add-to-list 'emms-info-functions 'emms-info-mpd)
(add-to-list 'emms-player-list 'emms-player-mpd)
(setq emms-player-mpd-server-name "localhost")
(setq emms-player-mpd-server-port "6600")
(setq emms-player-mpd-music-directory "~/Music")
(emms-player-mpd-connect)
;; Clear MPD playlist on clearing EMMS playlist
;; IDK if this is fine for MPD playlists, I don't use them anyhow
(add-hook 'emms-playlist-cleared-hook 'emms-player-mpd-clear)
<<emms-fixes>>)
#+end_src
**** Some keybindings
#+begin_src emacs-lisp
(with-eval-after-load 'emms-browser
(evil-collection-define-key 'normal 'emms-browser-mode-map
"q" 'quit-window))
(with-eval-after-load 'emms
(evil-collection-define-key 'normal 'emms-playlist-mode-map
"q" 'quit-window))
#+end_src
**** Fixes
Some fixes until I submit a patch.
For some reason EMMS doesn't fetch =albumartist= from MPD. Overriding this function fixes that.
#+begin_src emacs-lisp :tangle no :noweb-ref emms-fixes
(defun emms-info-mpd-process (track info)
(dolist (data info)
(let ((name (car data))
(value (cdr data)))
(setq name (cond ((string= name "artist") 'info-artist)
((string= name "albumartist") 'info-albumartist)
((string= name "composer") 'info-composer)
((string= name "performer") 'info-performer)
((string= name "title") 'info-title)
((string= name "album") 'info-album)
((string= name "track") 'info-tracknumber)
((string= name "disc") 'info-discnumber)
((string= name "date") 'info-year)
((string= name "genre") 'info-genre)
((string= name "time")
(setq value (string-to-number value))
'info-playing-time)
(t nil)))
(when name
(emms-track-set track name value)))))
#+end_src
Also, =emms-player-mpd-get-alists= has an interesting bug. This function parses the response to =listallinfo=, which looks something like this:
#+begin_example
tag1: value1
tag2: value2
...
tag1: value1'
tag2: value2'
#+end_example
This structure has to be converted to list of alists, which looks like:
#+begin_example
(("tag1" . "value1"
"tag2" . "value2")
("tag1" . "value1'"
("tag2" . "value2'")))
#+end_example
The original implementation creates a new alist whenever it encounters a tag it has already put in the current alist. Which doesn't work too well if some tags don't repeat, if the order is messed up, etc.
Fortunately, according to the [[https://mpd.readthedocs.io/en/latest/protocol.html#command-lsinfo][protocol specification]], each new record has to start with =file=, =directory= or =playlist=. I've overridden the function with that in mind and it fixed the import, at least in my case.
#+begin_src emacs-lisp :tangle no :noweb-ref emms-fixes
(defun emms-player-mpd-get-alists (info)
"Turn the given parsed INFO from MusicPD into an list of alists.
The list will be in reverse order."
(when (and info
(null (car info)) ; no error has occurred
(cdr info)) ; data exists
(let ((alists nil)
(alist nil)
cell)
(dolist (line (cdr info))
(when (setq cell (emms-player-mpd-parse-line line))
(if (member (car cell) '("file" "directory" "playlist"))
(setq alists (cons alist alists)
alist (list cell))
(setq alist (cons cell alist)))))
(when alist
(setq alists (cons alist alists)))
alists)))
#+end_src
*** EWW
Emacs built-in web browser. +I wonder if anyone actually uses it.+