#!/bin/bash # sync.sh - sync your iPod Shuffle, powered by ipod.referi.de # # Run this FROM the iPod root folder (the mounted drive). # Sends a small metadata manifest to the public API, which generates # voiceovers (espeak) and builds the iTunesSD database. The results # (database + voiceover WAVs) come back to the iPod. # # Usage: # cd /path/to/ipod # curl -fsSL https://ipod.referi.de | sh # # (override the drive path with: IPOD=/path/to/ipod curl -fsSL ... | sh) set -euo pipefail API="https://ipod.referi.de" IPOD="${IPOD:-$(pwd)}" PYTHON="${PYTHON:-python3}" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT # --- Checks ---------------------------------------------------------- if ! command -v unzip >/dev/null 2>&1; then echo "[ERROR] unzip not found. Install it first (e.g. sudo apt install unzip)" exit 1 fi if [ ! -d "$IPOD/iPod_Control/Music" ]; then echo "[ERROR] No iPod_Control/Music folder found in $(pwd)" echo " Run this command from inside the iPod drive root folder." exit 1 fi echo ">> iPod found at: $IPOD" MUSIC="$IPOD/iPod_Control/Music" # --- 1. Build metadata manifest locally ------------------------------ echo ">> Reading music metadata..." if ! "$PYTHON" -c "import mutagen" 2>/dev/null; then echo "[ERROR] Python mutagen not installed. Run: pip3 install mutagen" exit 1 fi curl -fsSL "$API/manifest.py" -o "$WORK/manifest.py" IPOD="$IPOD" "$PYTHON" "$WORK/manifest.py" "$WORK/manifest.json" MANIFEST_SIZE=$(du -h "$WORK/manifest.json" | cut -f1 | tr -d ' ') echo ">> Sending manifest ($MANIFEST_SIZE) to ipod.referi.de..." # --- 2. Sync via the public API -------------------------------------- HTTP=$(curl -s -w "%{http_code}" --max-time 300 \ -X POST -H "Content-Type: application/json" \ --data-binary @"$WORK/manifest.json" \ "$API/sync" -o "$WORK/result.zip") if [ "$HTTP" != "200" ]; then echo "[ERROR] API error (HTTP $HTTP): $(cat "$WORK/result.zip" 2>/dev/null | head -c 300)" exit 1 fi RESULT_SIZE=$(du -h "$WORK/result.zip" | cut -f1 | tr -d ' ') echo ">> Received database + voiceovers ($RESULT_SIZE)." # --- 3. Copy results onto the iPod ----------------------------------- echo ">> Copying database + voiceovers to iPod..." unzip -q -o "$WORK/result.zip" -d "$IPOD/" echo "" echo "[OK] iPod synced!" echo "" echo "Playlists:" "$PYTHON" -c " import json, sys, os m = json.load(open(sys.argv[1])) for pl in m['playlists']: album = os.path.basename(pl['dir'].rstrip('/')) artist = pl['tracks'][0]['artist'] if pl['tracks'] else 'Unknown' print(' %s - %s' % (album, artist)) " "$WORK/manifest.json" echo "" echo " Safely eject and enjoy."