Skip to content

Instantly share code, notes, and snippets.

@dpsk
Forked from RobertAudi/moc-on-osx.md
Last active December 24, 2015 21:49
Show Gist options
  • Save dpsk/6868634 to your computer and use it in GitHub Desktop.
Save dpsk/6868634 to your computer and use it in GitHub Desktop.
Remove Growl script. Add apple notification center script instead

MOC on OS X

I waited for years for a Homebrew formula for MOC. I finally found one today, but it didn't work for me. So I decided to try to compile it from source.

Requirements

Here is a list of requirements, taken directly from the MOC README:

  • UNIX system with POSIX threads (e.g., Linux or FreeBSD)
  • ncurses (probably already installed in your system)
  • C and C++ compilers (MOC is written in C, but libtool and some decoder plugins require a C++ compiler)
  • libdb version 4 or later (unless configured with --disable-cache)

To support audio formats you need:

For network streams:

For resampling (playing files with sample rate not supported by your hardware):

For JACK (low-latency audio server):

For librcc (fixes encoding in broken mp3 tags):

So first you need to install Xcode and Homebrew if you don't already have them installed; I'll let you Google on how to do that. You also need to install a dependency that is not listed above: BerkeleyDB. Luckily there is a Homebrew package for it:

% brew install berkeley-db

Edit: The BerkeleyDB dependency is actually listed above, as libdb. Thanks to John Fitzgerald, MOC's Maintainer, for the note.

NOTE: % is my prompt, don't copy it, copy just the brew command!

Then you need to install JACK, because it's the audio server that will be used by MOC:

% brew install jack

Finally you need to install the required library to play MP3s, and other audio formats. All my music is in MP3 so I just had to install two libraries:

% brew install libmad
% brew install libid3tag

Compiling MOC from source

First you need to download MOC from here. I downloaded the Development release (2.5.0-beta1). Next you need to go extract the archive you just downloaded:

% cd ~/Downloads
% tar xvjf moc-2.5.0-beta1.tar.bz2
% cd moc-2.5.0-beta1

Next you need to configure, compile and install MOC:

% ./configure --prefix=/usr/local/Cellar/moc/2.5.0-beta1 --with-jack --enable-debug --without-ffmpeg
% make
% make install

NOTE: I haven't compiled MOC with the --without-ffmpeg option myself, but it should work. If it doesn't, uninstall ffmpeg using brew uninstall ffmpeg. A big Thank you to jcf for the tip!

Configuring MOC

Now that you installed MOC, you need to configure it. The first thing I needed to do, is add the bin directory to my $PATH:

  • If you are using ZSH, add this line to your .zshrc:
path=( /usr/local/Cellar/moc/2.5.0-beta1/bin $path )
  • If you're using Bash, add this line to your .bashrc:
PATH=/usr/local/Cellar/moc/2.5.0-beta1/bin:$PATH

Next, you need to create a directory for MOC, in your home directory:

% mkdir ~/.moc

Let's skip the config file step for a minute and let's create a custom theme. First, create the themes directory:

% mkdir ~/.moc/themes

I use a theme I found on the CrunchBang forums. All you need to do is to create a new file for the theme with the following content:

% vim ~/.moc/themes/rhowaldt_theme
background           = default    default
frame                = default    default
window_title         = default    default
directory            = blue       default
selected_directory   = blue       default    reverse
playlist             = default    default
selected_playlist    = default    default    reverse
file                 = default    default
selected_file        = default    default    reverse
marked_file          = blue       default    bold
marked_selected_file = blue       default    reverse
info                 = default    default
selected_info        = default    default
marked_info          = blue       default    bold
marked_selected_info = blue       default    bold
status               = default    default
title                = blue       default    bold
state                = default    default
current_time         = default    default
time_left            = default    default
total_time           = default    default
time_total_frames    = default    default
sound_parameters     = default    default
legend               = default    default
disabled             = default    default
enabled              = blue       default    bold
empty_mixer_bar      = default    default
filled_mixer_bar     = default    default    reverse
empty_time_bar       = default    default
filled_time_bar      = default    default    reverse
entry                = default    default
entry_title          = default    default
error                = default    default    bold
message              = default    default    bold
plist_time           = default    default

NOTE: I removed the documentation comments from the theme, but you can find the whole theme file here

Now you need a config file. Let's copy the example config file that came with MOC:

% cp /usr/local/Cellar/moc/2.5.0-beta1/share/doc/moc/config.example ~/.moc/config

Next, edit it with the following config:

% vim ~/.moc/config

NOTE: This configuration assumes that you are using iTerm2. Feel free to fiddle with it.

ReadTags = yes
MusicDir = /Users/aziz/Music
StartInMusicDir = yes
SoundDriver = JACK
XTerms = xterm-256color
Theme = rhowaldt_theme
MOCDir = ~/.moc
UseRCC = no

And...you're done configuring MOC!

Running MOC

Before you run MOC, you need to run JACK, otherwise it won't work! You can run it manually using this command:

% jackd -d coreaudio

But that's tedious to do! So let's create a launch agent:

% vim ~/Library/LaunchAgents/org.jackaudio.jackd.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>org.jackaudio.jackd</string>
    <key>WorkingDirectory</key>
    <string>/Users/aziz/</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/Cellar/jack/1.9.7/bin/jackd</string>
      <string>-d</string>
      <string>coreaudio</string>
    </array>
    <key>EnableGlobbing</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
  </dict>
</plist>

And load that launch agent:

% launchctl load ~/Library/LaunchAgents/org.jackaudio.jackd.plist

Now you are finally ready to use MOC!!!

% mocp

To see the list of available commands, type ? once in MOC. The cool thing about this is that you can run MOC in the background: just type q (lowercase not upercast).

One more thing

#!/bin/bash

while out=$(/usr/local/Cellar/moc/2.5.0-beta1/bin/mocp -i); do

  # Parse mocp output.
  while IFS=: read -r field value; do
    case $field in
      Artist) artist=$value;;
      SongTitle) title=$value;;
    esac
  done <<< "$out"

  # Don't do anything if we're still on the same song.
  [[ "$artist-$title" = "$current" ]] && { sleep 1; continue; }

  # Send notification
  if [[ $artist && $title ]]; then
    terminal-notifier -title "Now Playing:" -message " $title by $artist"
  fi

  # Remember the current song.
  current="$artist-$title"

done

Note, that this one require terminal-notifier ruby gem that can be found here.

Put that script anywhere you want, it really doesn't matter. I've put it the bin directory in my Home directory. Make sure you make the script executable with chmod a+x moc-growl.sh. Again, you can run the script manually, but it's tedious, so I created a launch agent:

<?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>me.azizlight.mocgrowl</string>
    <key>WorkingDirectory</key>
    <string>/Users/aziz/</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/sh</string>
      <string>/Users/aziz/bin/moc-growl.sh</string>
    </array>
    <key>EnableGlobbing</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
  </dict>
</plist>

And don't forget to load the launch agent:

% launchctl load ~/Library/LaunchAgents/me.azizlight.mocgrowl.plist

The cherry on the cake

Yes there is YET ONE MORE THING! I managed to map the function keys F7, F8 and F9 to moc actions using applescript! Here is how to do it:

  • Open Automator
  • Create a new Service
  • Choose "Run AppleScript" from the list of actions
  • Insert the script below in the mini AppleScript editor
  • Save
  • Go in the Keyboard Shortcuts System Preferences
  • Locate your new service
  • Assign it a shortcut

I chose those function keys because they match the media keys. Do this for every script show below (three times in total):

-- This is the script to Play/Pause
do shell script "/usr/local/Cellar/moc/2.5.0-beta1/bin/mocp -G"
-- This is the script to go to the Next Song
do shell script "/usr/local/Cellar/moc/2.5.0-beta1/bin/mocp -f"
-- This is the script to go to the Previous Song
do shell script "/usr/local/Cellar/moc/2.5.0-beta1/bin/mocp -r"

Alfred Workflow

I also created an Alfred Workflow to show the current playing song and triggering the play/pause/next/previous functionality. The Workflow can be downloaded here. Once downloaded, just double-click on the file and it should install it.

Voila! A full headless command-line alternative to iTunes!

Enjoy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment