Skip to content

Instantly share code, notes, and snippets.

@mkaito
Created February 12, 2012 02:50
Show Gist options
  • Save mkaito/1805933 to your computer and use it in GitHub Desktop.
Save mkaito/1805933 to your computer and use it in GitHub Desktop.
This takes my playlists, managed by mpd, fixes them up, and places them in a staging folder, ready to sync with my Android phone. The script also asks if you'd like to sync the music after staging. Who needs iTunes anyway.
#!/usr/bin/env zsh
# Takes all my playlists from ~/.mpd/playlists, fixes them up, and creates a
# folder for each, along with the music they reference.
# The sync stage requires an sshd server to run on your phone, as well as the rsync executable.
# - http://linux.wxs.ro/2011/08/05/rsync-your-android/
MPD_MUSIC_ROOT="${HOME}/Music" # Root of your MPD library
MPD_PLAYLIST_ROOT="${HOME}/.mpd/playlists" # MPD playlist folder
SYNC_MUSIC_ROOT="${HOME}/Android/Sync/Music" # Staging folder (receives all files prior to sync)
PLAYLIST_ROOT="${SYNC_MUSIC_ROOT}/playlists" # Where to place playlist files (m3u) for sync
PHONE_MUSIC_ROOT="/sdcard/Music" # Where the music will live on your phone
PHONE_ADDRESS="Nexus" # Address to access your phone over ssh for sync
# Output stuff to stdout if $DEBUG evaluates to anything
# $ DEBUG=1 plsync.sh
function debug()
{
[[ ! -z "$DEBUG" ]] && echo $*
}
# Sync stuff with phone over rsync+ssh
function sync() {
rsync -vzrL --delete-after --no-perms --no-t ${SYNC_MUSIC_ROOT}/ ${PHONE_ADDRESS}:${PHONE_MUSIC_ROOT}/
}
# Ask for confirmation on something
function confirm()
{
echo -n "$@ [y/N] "
read answer
for response in y Y yes YES Yes Sure sure SURE OK ok Ok kk; do
[[ "_$answer" == "_$response" ]] && return 0
done
return 1
}
[[ ! -d "$PLAYLIST_ROOT" ]] && mkdir -p "$PLAYLIST_ROOT"
for pl in ~/.mpd/playlists/*.m3u; do
plname="$(basename ${pl})"
plname="${plname%%.*}"
plfolder="${SYNC_MUSIC_ROOT}/${plname}"
plfile="${PLAYLIST_ROOT}/${plname}.m3u"
[[ -f "$plfile" ]] && rm -f "$plfile"
[[ -d "$plfolder" ]] && rm -rf "$plfolder"
[[ ! -d "$plfolder" ]] && mkdir -p "$plfolder" && touch "$plfile"
while read line; do
f="${MPD_MUSIC_ROOT}/${line}"
bn=$(basename "$f")
if [[ -f "$f" && ! -f "${plfolder}/${bn}" ]]; then
ln -s "$f" "$plfolder"
echo "${PHONE_MUSIC_ROOT}/${plname}/${bn}" >> "$plfile"
fi
done < "$pl"
done
confirm "Would you like to sync with your phone? (Make sure sshd runs on the device)" && sync
@klodeckl
Copy link

How could I add a list of playlists to sync? Not every playlist should get synced. for pl in ~/.mpd/playlists/*.m3u; do?

Copy link

ghost commented Aug 14, 2016

You can define an array of playlist names you want to sync, and then check for those when you're iterating all of your playlists.
I modified my script to use bash instead, but this should also work in zsh.

I defined my set of playlists to synchronize similar to this:

# Array of playlist basenames to synchronize
syncpl=(workout cardio work minimal chill jungle)

Another more comfortable way to maintain the list might be to have a list in another text file and then read it, so you don't have to touch the script any time you want to add another playlist.

I then added a function to check whether a string is contained in an array, which I totally stole from stackoverflow:

# Check if an array contains a certain value
array_contains () {
    local seeking=$1; shift
    local in=1
    for element; do
        if [[ $element == $seeking ]]; then
            in=0
            break
        fi
    done
    return $in
}

Now in the for loop, after the basename of a playlist is determined, I can easily check if it is contained in the set of lists I want to synchronize:

# Jump to the next for loop iteration if we don't want to sync this playlist
array_contains "${plname}" "${syncpl[@]}" || continue

I hope you get the idea. It's probably best if you modify this script to fit your needs better, as did I.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment