vertner.net

Scripting Your Car's Music Sync on a Mac

Hack everything. Even your car.Hack everything. Even your car.

As any tinkerer knows, cars tend to have some surprisingly old technology in them at a premium price. The only thing older and more expensive are aircraft avionics. I thought that my 2011 Volkswagen GTI was pretty awesome with an in-dash SD card reader, but evidently it only supports the SDHC standard with a maximum size of 32GB instead of the SDXC standard with a potential maximum size of 2TB. 32GB just isn’t going to cut it for my collection. It does have USB hard drive support, but at the cost of $30-50 for connector cable if your car didn’t happen to have one the dealer left in the glovebox. Now the big question is, “what’s the easiest way to keep that thing up-to-date?”

The Hardware

If your car has a USB port and the ability to accept a hard drive, you’re off to a good start. Typically, they’ll want it formatted in FAT, but consult your car’s documentation for particulars. Format that sucker into FAT (or whatever) using the easy way or the nerdy way.

The Easy Way

Open up your Applications folder and inside you’ll find a Utilities folder. Inside of that: Disk Utility. Alternatively, just Command+Space Bar to open up Spotlight and start typing Disk Utililty.

Utilize All of the Disks!Utilize All of the Disks!

Once you’ve launched this awesome application, you’ll see a list of your physical hard drives and their partitions. Select the hard drive that you’re going to use, select the Erase button, and you should see options to change the Format and Name. Select MS-DOS (FAT) and name it something memorable and useful. I named mine VW MUSIC.

That music is FAT. That was a dumb joke. Sorry.That music is FAT. That was a dumb joke. Sorry.

The Nerdy Way

The nerdy way is almost as easy, but way more educational. Plus, you’ll feel like a Mac pro/Linux nerd after doing it. Open up your Terminal (*conveniently located near your Disk Utility -or- launched using Spotlight) and type the following:

1
diskutil list

You should see a list of hard drives and their partitions, just as in the easy way above.

See? Same info. Just 20% cooler.See? Same info. Just 20% cooler.

Once you have identified the one you want to use, type the following:

1
diskutil eraseDisk (drive format) "(drive name)" /dev/(disk name)

Here’s what I typed:

1
diskutil eraseDisk FAT "VW MUSIC" /dev/disk4

If your car takes some other format, then make sure you change the format appropriately. As above, I named mine VW MUSIC, but go nuts with whatever you want yours to be named. Finally, if you’ll recall the results of our diskutil list command, we saw the device name; in my case it was disk4.

The Script

Now that our drive is all setup, let’s get to copying some music on it! One of my favorite utilities for copying and synchronizing large amounts of data is a command line utility called rsync. I wrote a quick Bash script that checks to make sure that you’ve got the right drive connected, runs rsync, ejects the hard drive (using our new/old friend diskutil, no less), and exits the Terminal window. Just open up your Terminal and type nano music_sync.command to open up your handy command line text editor and paste the following:

1
2
3
4
5
6
7
8
9
#! /bin/bash

if [ -d "/Volumes/VW MUSIC" ]; then
  rsync -av /path/to/music/* /Volumes/VW\ MUSIC;
  diskutil umount /Volumes/VW\ MUSIC;
  afplay /System/Library/Sounds/Funk.aiff;
  osascript -e 'tell app "System Events" to display dialog "Music Sync Complete! It's now safe to unplug your drive." buttons {"OK"}';
fi
exit

Make sure you point the path/to/music/ to wherever all of your music is stored. The iTunes default is /Users/Username/Music/iTunes/iTunes\ Media/ where Username is your Mac’s login. As a side note, you’ll notice that backslash between VW and MUSIC. Normally, Bash doesn’t like spaces in file names, so the backslash tells it to treat that next character as a space rather the beginning of another segment of the command. As you can see, I did the same thing for the iTunes Media folder just now. When it’s in quotes, like in our if statement, this isn’t necessary. Finally, make sure you change the name of the drive to whatever you named it when you formatted it.

Once you’re satisfied with your new script, hit Crtl+X to exit nano and confirm that you’re saving on exit. To make our new script executable, type the following:

1
chmod 755 music_sync.command

Now in your user directory, you’ve got a script that you can launch with a double-click and it will sync everything! It will even play a happy noise and throw up a dialog box to let you know everything finished up.

So far, so good!So far, so good!

Cleaning it Up

Now here are the parts where we put the extra polish on it and make it all just work. With just what we’ve done, we’ve created an executable script that we can launch with a double-click from the GUI. If you want to give it a snazzy custom icon, just Ctrl+C to copy any image from almost anywhere, right-click on the script in your GUI and select Get Info. Now click on the icon in the top left (it should have a blue glow now) and hit Ctrl+V to paste. Hooray! Custom icon! You can make it look really awesome by selecting the Hide Extension option. Finally, to ensure a smooth exit command, open up Terminal, go to Preferences, then Settings, and the Shell tab. For When the shell exits, select Close if the shell exited cleanly. This will make Terminal close itself assuming the exit command has been called.

That’s enough if we just want to make it look nice in the GUI, but what if we’re feeling really lazy and just want all of this to work automatically in the background as soon as we plug everything in?

Apple’s Launch Daemon!

First, stash that script somewhere safe where you’re not going to mess with it. Now, open up your trusty Terminal and type cd ~/Library/LaunchAgents to change your working directory. Now type nano com.music_sync.plist and paste the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTDPLIST 1.0//EN" \
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<dict>
  <key>Label</key>
  <string>com.music_sync</string>
  <key>LowPriorityIO</key>
  <true/>
  <key>ProgramArguments</key>
  <array>
  <string>/path/to/music_script.command</string>
  </array>
  <key>ThrottleInterval</key>
  <integer>10</integer>
  <key>WatchPaths</key>
  <array>
  <string>/Volumes</string>
  </array>
</dict>
</plist>

What we just created is a Daemon that will run in the background and run our script whenever anything is mounted to our Volumes directory. Make sure you change the /path/to/music_script.command entry so that it points to where you’ve actually got your script. That if command in our music_script.command makes a little more sense now, now helps us by making sure that the daemon doesn’t start our script for every USB drive we insert.

All of this XML basically defines the name of the daemon, any program arguments (none, in this case), where the script is that we want it to run (we could be really clever and try and write all of that in here if we wanted), the ThrottleInterval and LowPriorityIO are both good practices to ensure that it’s not going to interfere with everything else you’re doing, and finally the WatchPaths key tells the daemon what will trigger it.

As before, hit Ctrl+X to exit nano and save your changes to your new plist file. Now type the following to add it to your system as a Daemon:

1
launchctl load ~/Library/LaunchAgents/com.music_sync.plist

Boom. Now, whenever you update your music library, just bring in your hard drive from your car, plug it in, and wait for your happy alert to pop up letting you know that the sync is complete and it’s safe to unplug your drive. Everything will run in the background and the only indication you’ll have that something is going on is that your external hard drive’s light should be blinking like crazy. It doesn’t get much more automatic than that.

Comments