Complete Computing Environment: Music and Podcasts with MPD

Table of Contents

(provide 'cce-music)

Playing Music

I run a remote MPD with an http output; I run this thing on a server that has full access to my NAS's music folders, and it streams out to any Ogg-capable client.

export MPD_HOST=hypervisor01
export MPD_PORT=6600

I used to use a piece of kit called mopidy which worked well when paired with Subsonic, but this setup is broken in Debian, and doesn't install cleanly in the Body Computing System, so I'm going to stop relying on it, plus having MPD streaming a random HTTP URL means that I can eventually wire it in to my home sound system quite easily.

- name: mpc and ogg123 installed
  dnf:
    name: "{{item}}"
    state: installed
  when: ansible_pkg_mgr == "dnf"
  with_items:
  - mpc
  - vorbis-tools

- name: mpc and ogg123 installed
  apt:
    name: "{{item}}"
    state: installed
  when: ansible_pkg_mgr == "apt"
  with_items:
  - mpc
  - vorbis-tools

Mingus MPD frontend

Install Mingus, a neat little minimalist frontend for MPD. I don't use this much, but it's fairly nice to have around.

(add-to-list 'el-get-sources '(:name libmpdee
                               :type github
                               :pkgname "andyetitmoves/libmpdee"))
(add-to-list 'el-get-sources '(:name mingus
                               :type github
                               :pkgname "pft/mingus"))
(add-to-list 'cce/el-get-packages 'libmpdee)
(add-to-list 'cce/el-get-packages 'mingus)
(el-get 'sync cce/el-get-packages)

Hydra Controller

Mingus is a nifty little minimalist MPD frontend, but it doesn't ship with any keybindings out of the box. I'd like global MPD bindings, and this goes a long way to get there.

(defhydra hydra-mpd (global-map "C-c m" :columns 2)
  ("g" (progn (async-shell-command "mpg123 http://fort.kickass.systems/mpd.mp3"
                                   (get-buffer-create "*ogg123*")))
   "Start stream")
  ("p" (progn (save-window-excursion
                (async-shell-command "mpc toggle" (get-buffer-create "*tmp*"))))
   "Play/Pause")
  ("/" mingus-search "Search")
  ("s" mingus "Show Mingus")
  ("<" (progn (require 'mpc) (mpc-prev)) "Previous")
  (">" (progn (require 'mpc) (mpc-next)) "Next")
  ("+" (async-shell-command "pactl set-sink-volume 10 -- +10%") "Louder")
  ("-" (async-shell-command "pactl set-sink-volume 10 -- -10%") "Quieter")
  ("n" (progn (ansi-term (executable-find "ncmpc")))
   "ncmpc")
  ("q" nil "Quit"))

Current Track in ERC

I'm using mingus as a shitty frontend to MPD right now, basically read only right now. I'd like to get MPC working eventually but for now this is what I'm using. Basically I fire up mingus and then I can do /mpd to get the current track in chat

(add-hook 'after-cce-hook
          (lambda ()
            (require 'mingus)
            (setq mingus-mode-line-string-max 60)
            (defun erc-cmd-MPD (&rest ignore)
              "Display current MPD track using Mingus"
              (let ((mingus-output
                     (mingus-make-mode-line-string)))
                (erc-send-message
                 (concat "Listening to: [" mingus-output "]"))))))

Making Music

I am trying to get back in to the creation of music. I used to carry around a Gameboy with LSDJ and should probably start doing that again. But I've also been looking at other ways of doing it – trackers are a good way of going about it, generally, but I am not to the point where I can just put together good melodies. Having something to "jam" on that fits on my person is where I am stuck right now until I become a better musician. As such, I've looked at a number of software synthesizers that support, for lack of a better term, jamming.

The first thing I've reached for is SunVox, a piece of software I have been enamoured with since I discovered the PalmOS version of it so long ago. It's great to use, and as of late, there is a Raspberry Pi version of it with some neat things added like being able to read filter values from the GPIO headers, allowing you to add physical interaction to your music pieces. Unfortunately, SunVox doesn't really have any sort of way to function without an X11 server running which means it works against my core system, a computer that can be used in a form factor without a screen, and eliminates my ability to fuck around in idle spaces.

This led me down the path of trying to find or build something that can work with Emacs and thus Emacspeak. It might seem unintuitive to use a voice control system to work with audio software, but it's quite nice. In my research I discovered Sonic Pi, a Ruby livecoding interface on top of Open Sound Control, which wonderfully contains a Emacs-Lisp interface. This is what I am using to fool around right now, eventually reaching towards the repl-electric stuff as a whole. It looks mad fun.

- name: sonic-pi installed
  apt:
    name: sonic-pi
    state: installed
  when: ansible_hostname != "hypervisor01" and ansible_pkg_mgr == "apt"

- name: JACK installed
  apt:
    name: "{{item}}"
    state: installed
  with_items:
    - jackd2
    - alsa-utils
    - jack-tools
  when: ansible_hostname != "hypervisor01" and ansible_pkg_mgr == "apt"
(cce/with-any-domain '("main" "kusanagi" "pocket")
                     (package-install 'highlight)
                     (package-install 'osc)
                     (package-install 'dash)
                     (install-pkgs '(osc sonic-pi))
                     (require 'sonic-pi)

                     (setq sonic-pi-path "/opt/sonic-pi/"))
(defun cce/sonic-pi-send-block ()
  "Send the block at point to the Sonic Pi server."
  (interactive)
  (save-excursion
    (ruby-beginning-of-block)
    (push-mark)
    (ruby-end-of-block)
    (end-of-line)
    (sonic-pi-send-region)))

(add-hook 'sonic-pi-mode-hook
          (lambda ()
            (define-key ruby-mode-map (kbd "C-c C-d") 'cce/sonic-pi-send-block)
            (define-key ruby-mode-map "\C-c\C-b" 'sonic-pi-stop-all)))

Author: Ryan Rix

Created: 2017-10-03 Tue 10:06

Validate XHTML 1.0