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):
#!/bin/bash # vim: set ts=4 sw=4 tw=79 et : # # rsyncs the music from an iPhone into the iphone directory if [[ ! -z "$1" ]]; then ADDRESS="$1" else # 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 DEVICE="Dominic-Scheirlincks-iPhone" # 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` fi echo "Connecting to iPhone at $ADDRESS" rsync -avz --progress \ "root@$ADDRESS:/private/var/mobile/Media/iTunes_Control/Music/" \ iphone
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.
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.
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://github.com/dominics/musicdir.git $ cd musicdir # python setup.py install
And then you're ready to rock:
$ musicdir --help usage: musicdir [-h] [--version] [--output OUTPUT] [--input INPUT] [--verbose] [--quiet] 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: action update Updates the output directory config Prints the current configuration
I hope it's useful to someone. It sure is to me :-)