Archived News for February 2012

Free-Software Unlimited-Computer Incremental iPhone Music Syncing (for the Obsessive and/or Awesome)

Syncing from the iPhone

I've had a lot of trouble syncing music to and from my iPhone. It simply doesn't support syncing a library (or a portion of one) between more than one computer. Apple will tell you your only iTunes option is to "manually manage" your music and videos – that's not syncing, it's dragging and dropping, painfully sorting out duplicates.

It looked like a good way to circumvent iTunes would be to rsync the music out from the iPhone's filesystem. The jailbreak went smoothly, and ten minutes later I had an rsynced music directory with the 60GB contents of my iPhone. Here's an easy, repeatable script (that way, I don't have to think about it next time):

# vim: set ts=4 sw=4 tw=79 et :
# rsyncs the music from an iPhone into the iphone directory

if [[ ! -z "$1" ]]; then
    # Attempt to use avahi to get the iPhone's IP
    #  - Make sure your iPhone is unlocked
    #  - Start Remote on the iPhone
    #  - Settings, Add library, (you'll be shown a passcode)
    #    - No, I don't know any way to get the iPhone to show up in mdns when
    #      it's not on this screen
    #  - Edit the device name below
    # If you've followed the instructions above, see the DvNm field in:
    #  avahi-browse -r -k _touch-remote._tcp

    ADDRESS=`avahi-resolve -n "$DEVICE.local" | col | cut -f 2`

echo "Connecting to iPhone at $ADDRESS"
rsync -avz --progress \
    "root@$ADDRESS:/private/var/mobile/Media/iTunes_Control/Music/" \

This is really nice: a completely wireless sync, incremental, fast, compressed and repeatable. Unfortunately, the contents of the rsynced directory looked like this:

$ tree ~/Music/iphone
├── F00
│   ├── AAXG.mp3
│   ├── ... and 180 other badly named files
│   └── ZRSJ.mp3
├── ... and fifty other directories exactly the same
└── F49

Yes, once your beautifully cataloged and named music is sucked into Apple's walled garden, it gets mangled.

Fixing Up Music Rsync'd from an iPhone

There are a few tools for managing music directories like this. Beets is a nice one, that's pretty easy to install. Unfortunately, it doesn't (yet) support symlinking in the underlying music. This means your music will be copied or moved as it's tagged by Beets - not so good when you're trying to keep your music rsyncable against the original source directory. Beetfs would solve this problem too, but if their documentation is up to date, it requires source changes to Beet.

So, that's where my project Musicdir comes in. A few hundred lines of Python, it'll use the existing ID3 tags on your music files to produce a sylinked mirror directory.

Put simply: musicdir --input=~/Music/iphone output=~/Music/output turns the above directory into something like this:

$ tree ~/Music/awesome
├── Arcade Fire
│   └── Neon Bible
│       ├── 1 - Black Mirror.mp3 -> ~/Music/iphone/F02/AXCH.mp3
│       ├── 2 - Keep the Car Running.mp3 -> ~/iphone/F36/DGOH.mp3
│       └── [...etc...]
├── Augie March
│   └── Moo, You Bloody Choir
│       ├── 1 - Moo, You Bloody Choir.mp3 -> ~/Music/iphone/F13/FMCL.mp3
│       ├── 2 - Victoria's Secrets.mp3 -> ~/Music/iphone/F36/DGOH.mp3
│       └── [...etc...]
├── Ben Folds
├── Blam Blam Blam
└── [...etc...]

Musicdir doesn't touch the input files, so it plays nice with rsyncing: the next time you run the sync, you'll only get the changes. It's got flexible configuration (the cascade goes good defaults, /etc/musicdir.cfg, ~/.musicdir.cfg, CLI) and can pull together multiple input directories. If you've got an existing MPD setup, or even just a backup or media server, Good News! Symlinks can cross over mount boundaries. Mount a few sources, rsync a few more, and Musicdir will pull them into a single coherent tree. Of course, MPD can just recurse anyway, so no problem there (MPD is the best). But you might want a unified directory tree for any number of reasons: copying off somewhere, loading into sucky media players (iTunes, anything that only has a file browser), or even just cool awk fun.

Use Your Format-Shifting Rights

Interesting legal digression: thanks to relatively sane New Zealand copyright law, I'm allowed to circumvent TPMs (technical protection measures) in non-infringing ways. That's really what the iPhone's lack of functionality in this area is: protection of their bottom line enforced by lack of features. n-device syncing isn't something Apple wants you to do; they want to sell you all your music on iTunes, in which case it "magically" appears on up to 5 computers.

This method is probably legal in the United States too, although it may not be soon, with the jailbreaking exemption to the DMCA expiring this year, athough I don't know what sort of format-shifting allowances they have.

I want to play music on a few of my devices: I have a couple of laptops, a gaming rig, a home server (slash backup server: more about that in another post.) I don't think I'm usual in this respect. Provided you have a copyright license for the original source music, and a copy of the original file (or physical CDs you've ripped), this sort of copying between devices is completely legal in New Zealand.

Installing Musicdir

There are instructions for installing Musicdir over on the project page. But, basically, it's this:

# apt-get install python2.7 python-argparse python-mutagen
$ git clone git://
$ cd musicdir
# python install

And then you're ready to rock:

$ musicdir --help
usage: musicdir [-h] [--version] [--output OUTPUT] [--input INPUT] [--verbose]
                action ...

Tool for mirroring ID3-tagged music with renamed symlinks

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --output OUTPUT, -o OUTPUT
                        The output directory where symlinks will be created
  --input INPUT, -i INPUT
                        An optional directory that contains source music, if
                        not provided, your config file settings will be used.
  --verbose, -v         Be louder (can be supplied multiple times)
  --quiet, -q           Be quiet (don't output anything, overide verbose in
                        config files)

Valid actions:
    update              Updates the output directory
    config              Prints the current configuration

I hope it's useful to someone. It sure is to me :-)

Newest Posts