Getting Saucy

Spotify, MPD, and NCMPCPP

Introduction

user

Jake Champlin

Husband, Hacker, Padawan, Operations Engineer, Gearhead, and Pancake Enthusiast


Spotify, MPD, and NCMPCPP

Posted by Jake Champlin on .
Featured

Spotify, MPD, and NCMPCPP

Posted by Jake Champlin on .

These days I rarely have music saved on my machine, it's usually streamed from Spotify. I missed the days of running my music through MPD and controlling it via ncmpcpp.

This has now changed.

alt

alt

alt

Everything works as expected in ncmpcpp. Your "local" media library just happens to be the entire spotify library. In the "browser" view of ncmpcpp, you have all of your pre-existing spotify playlists, already created! :)

alt

How to:

  • Update Homebrew:
brew update
  • Tap Mopidy:
brew tap mopidy/mopidy
  • Install Mopidy and Mopidy-Spotify:
brew install mopidy && brew install mopidy-spotify
  • Set Spotify Device Password:

In order for Mopidy to correctly connect to Spotify, you'll need to setup a device password to connect to your account. Head to http://www.spotify.com/account/set-device-password/ to set a device password that will be used in the following step.

  • Configure Mopidy:
emacs config/mopidy/mopidy.conf

Under the [spotify] section, you'll need to set the following parameters:

    [spotify]
    enabled = true
    username = device_username
    password = device_password
    # Mopidy defaults to 160Kb/s bitrate. I like to turn that up ;)
    bitrate = 320
  • Configure Launchd:

Mopidy is a python package that is installed using homebrew's python. In order to have OSX start Mopidy on boot, you'll need to either edit the provided launchd script at /usr/local/opt/mopidy/homebrew.mopidy.mopidy.plist or use the following script, and save it to ~/Library/LaunchAgents/homebrew.mopidy.mopidy.plist

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
<plist version="1.0">  
<dict>  
  <key>Label</key>
  <string>homebrew.mopidy.mopidy</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PYTHONPATH</key>
    <string>/usr/local/lib/python2.7/site-packages</string>
  </dict>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/opt/mopidy/bin/mopidy</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
</dict>  
</plist>  

This assumes, of course, that brew --prefix == /usr/local

  • Install ncmpcpp:
brew install ncmpcpp

You now should have a working instance of mpd running, and should be able to connect to it via ncmpcpp!

However, what about the lack of media key functionality?!

  • Better Touch Tool:

I use Better Touch Tool for window snapping, and setting up custom mouse gestures. You can download and install BTT here.

BTT will allow you to set custom keybindings to trigger terminal commands, thus providing us with media key functionality.

First install mpc as a way to control mpd from the terminal:

brew install mpc

Then in BTT, under the Keyboard section, create shortcuts for your media keys that execute the following terminal commands:

# Play/Pause
/usr/local/bin/mpc toggle
# Next Track
/usr/local/bin/mpc next
# Previous Track
/usr/local/bin/mpc prev

alt

Although, my keyboard doesn't have media keys, so I'm using unused function keys as a replacement.


And there you have it. The only thing missing would be to control mpd from Emacs, but I have yet to find a decent mpd client that can hold any weight to how powerful ncmpcpp really is.

I was, however, able to remap the keybindings in ncmpcpp to be more "emacs-esque".

╰─$ grep -v "#" .ncmpcpp/bindings
def_key "ctrl_p"
  scroll_up
def_key "ctrl_n"
  scroll_down
def_key "backspace"
  delete_playlist_items
def_key "ctrl_f"
  next_column
def_key "ctrl_f"
  slave_screen
def_key "ctrl_f"
  volume_up
def_key "ctrl_b"
  previous_column
def_key "ctrl_b"
  master_screen
def_key "ctrl_b"
  volume_down
def_key "delete"
  replay_song
def_key "ctrl_s"
  find
def_key "ctrl_s"
  find_item_forward

Screenshots were of iTerm2 using the Japanesque color scheme, and the following ncmpcpp configuration:

# NCMPCPP Config
mpd_crossfade_time = "3"

# Song Format
song_list_format = "{$6%a$9} $1|$9 {$7%t$9} $R $1|$9 {$2%b$9} $1|$9 {$6%l$9}"
song_library_format = "{%n - }{%t}|{%f}"
song_status_format = "$b{$6%a$9 $1|$9 } {$7%t$9} $1|$9 {$2%b$9} $1|$9 {$6%y$9} $1|$9"
tag_editor_album_format = "{%b} {(%y)}"
song_window_title_format = "{%b}"

# Columns settings
song_columns_list_format = "(6)[magenta]{l} (30)[red]{a} (30)[blue]{b} (53)[magenta]{t}"

# Misc
playlist_display_mode = "classic"
titles_visibility="yes"
browser_display_mode = "columns"
incremental_seeking = "yes"
autocenter_mode = "yes"
header_visibility = "yes"
statusbar_visibility = "yes"
cyclic_scrolling = "yes"
display_bitrate= "yes"
ignore_leading_the = "yes"
enable_window_title = "yes"
progressbar_look = "·· "

# Interface
user_interface="classic"
alternative_header_first_line_format ="{$b$6%a$9} $1««$9 {$6%t$9}"
alternative_header_second_line_format ="{$5%b$9} $1»»$9 {$5(%y)$9}"
alternative_ui_separator_color ="black"
playlist_separate_albums = "no"

# Colors
colors_enabled = "yes"
empty_tag_color = "blue"
header_window_color = "black"
volume_color = "black"
display_volume_level="yes"
state_line_color = "cyan"
state_flags_color = "red"
main_window_color = "blue"
main_window_highlight_color="blue"
color1 = "white"
color2 = "blue"
progressbar_color = "cyan"
statusbar_color = "black"
active_column_color = "magenta"
window_border_color = "red"
active_window_border = "red"
user

Jake Champlin

Husband, Hacker, Padawan, Operations Engineer, Gearhead, and Pancake Enthusiast