I used MacPorts to install the Firefly media server (mt-daapd), which is an open-source implementation of the daap protocol that is the guts of iTunes sharing.
sudo port install mt-daapd
Then as root I edited /etc/mt-daapd.conf to be sure these lines were right
web_root /opt/local/share/mt-daapd/admin-root
admin_pw ## (whatever you want besides the default)
db_dir /opt/local/var/db/mt-daapd
mp3_dir /path/to/your/Music/iTunes/iTunes Music
servername ## (whatever you want to show up in iTunes when connecting)
runas daemon ## (or whatever user you want who can read your iTunes music)
playlist /opt/local/etc/mt-daapd/mt-daapd.playlist
It's not so straightforward to get mt-daapd to run when the Mac reboots....
For one, my music is on an external drive which doesn't get mounted until somebody logs in. This post solved that one so now my external drive mounts right away when the mac reboots. As root, edit the file /Library/Preferences/SystemConfiguration/autodiskmount.plist and put this in it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AutomountDisksWithoutUserLogin</key><true/>
</dict>
</plist>
The next problem is that Apple runs daemons a little differently than *nix does. Since mt-daapd does the normal *nix thing and daemonizes itself (i.e. fork a child and then exit the originally launched program), it doesn't play well with Apple's launchd, which expects the processes it starts not to exit. I tried running mt-daapd in the foreground, but then it can't be started as root (which is the default do Apple's launchd), and the logs it produces don't show timestamps.
The other problem is that there's a race for getting the disk mounted (from the previous step) and starting the Firefly server.
In the end, I made a wrapper script that waits for the disk to mount and then starts the server and keeps running as long as the server is still running. I put this in /opt/local/sbin/mt-daapd-wrapper
#! /bin/bash
MT_DAAPD=$(dirname $0)/mt-daapd
CONF=/etc/mt-daapd.conf
RUNAS=$(sed -n '/^runas/{s/[^[:space:]]*[[:space:]]*//;p;}' $CONF)
MP3_DIR=$(sed -n '/^mp3_dir/{s/[^[:space:]]*[[:space:]]*//;p;}' $CONF)
# Kill the server if launchd kills us
trap 'echo $(date) Killed; killall mt-daapd; exit' TERM
killall mt-daapd
while [ ! -d "$MP3_DIR" ]; do
echo "$(date) Waiting for: $MP3_DIR"
sleep 10
done
echo "$(date) Music in: $MP3_DIR"
if [ -d "$MP3_DIR" ]; then
echo "$(date) Starting $MT_DAAPD"
$MT_DAAPD -c $CONF
sleep 1
PID=$(ps -u $RUNAS | awk '/mt-daapd/{print $2}' | head -n 1)
echo "$(date) mt-daapd pid: ${PID=-1}"
while ps -p $PID > /dev/null; do
sleep 10
done
fi
echo "$(date) $MT_DAAPD exited"
killall mt-daapd
Now that I have something that launchd will be happy with, I went ahead and set up a LaunchDaemon that will run it when the Mac starts up, before anyone logs in. I put this in /Library/LaunchDaemons/org.firefly.mt-daapd.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.firefly.mt-daapd</string>
<key>ProgramArguments</key>
<array>
<string>/opt/local/sbin/mt-daapd-wrapper</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardErrorPath</key>
<string>/opt/local/var/log/mt-daapd.stderr.log</string>
<key>StandardOutPath</key>
<string>/opt/local/var/log/mt-daapd.stdout.log</string>
</dict>
</plist>
If you want to manually start/stop the Firefly server, just use launchctl
sudo launchctl load /Library/LaunchDaemons/org.firefly.mt-daapd.plist
sudo launchctl unload /Library/LaunchDaemons/org.firefly.mt-daapd.plist
Thanks! I will try this out later
ReplyDeleteGreat, works a treat, thanks. And the article serves as a nice primer on launchd, too.
ReplyDelete