#!/bin/bash
# ---------------------------------------------------------------------------- #
## \file mp3style.sh
## \author Sebastien Beaugrand
## \sa http://beaugrand.chez.com/
## \copyright CeCILL 2.1 Free Software license
# ---------------------------------------------------------------------------- #
# Trouver les répertoires sans liste m3u :
#  find . -type d -exec test ! -f {}/00.m3u \; -print
# ---------------------------------------------------------------------------- #
if [ "$1" = "-i" ]; then
    interactive=1
    shift
else
    interactive=0
fi
if [ "$1" = "m4a" ]; then
    ext="m4a"
    if ! which boxdumper >/dev/null 2>&1; then
        echo "error: boxdumper not found"
        exit 1
    fi
else
    ext="mp3"
    if ! which id3ed >/dev/null 2>&1; then
        echo "error: id3ed not found"
        exit 1
    fi
    if ! which mpg123 >/dev/null 2>&1; then
        echo "error: mpg123 not found"
        exit 1
    fi
    if ! which id3v2 >/dev/null 2>&1; then
        echo "error: id3v2 not found"
        exit 1
    fi
fi

if find . -print | grep -P "[^a-zA-Z0-9()',./ [\]_%+-]"; then
    exit 1
fi

dirs=mp3style-dir.tmp
mp3s=mp3style-mp3.tmp
find . -type d -print | LC_ALL=C sort >$dirs
ndir=`cat $dirs | wc -l`
trap "rm $dirs; echo; exit 0" SIGINT

# ---------------------------------------------------------------------------- #
# rdexec
# ---------------------------------------------------------------------------- #
rdexec()
{
    for ((rj = 1; rj <= ndir; ++rj)); do
        rd=`head -n $rj $dirs | tail -n 1`
        eval $1 \""$rd"\" \""$2"\"
    done
}

# ---------------------------------------------------------------------------- #
# rfexec
# ---------------------------------------------------------------------------- #
rfexec()
{
    cd "$1"
    find . -maxdepth 1 -name "*.$ext" -print | LC_ALL=C sort >$mp3s
    nmp3=`cat $mp3s | wc -l`
    for ((ri = 1; ri <= nmp3; ++ri)); do
        rf=`head -n $ri $mp3s | tail -n 1`
        eval $2 \""$rf"\"
    done
    rm $mp3s
    cd - >/dev/null 2>&1
}

# ---------------------------------------------------------------------------- #
# fffb
# ---------------------------------------------------------------------------- #
fffb()
{
    echo -n "$1"
    s=`hexdump -e '/1 "%02X"' -v "$1" | grep -b -o FFFB | \
        head -n 1 | cut -d ':' -f 1`
    if [ -n "$s" ] && ((s > 1)); then
        s=`echo $s | awk '{ print rshift($0, 1) }'`
        echo -n " $s"
        dd status=noxfer if="$1" ibs=$s skip=1 of=mp3.tmp 2>/dev/null
        mv mp3.tmp "$1"
    fi
    echo
}

# ---------------------------------------------------------------------------- #
# ucfirst
# ---------------------------------------------------------------------------- #
ucfirst()
{
    echo "$1"
    echo "$1" | cut -c3- |\
    awk 'BEGIN { FS = " *|_" }
    {
        printf "mv \"%s\" \"", $0;
        for(j = 1; j <= NF; j++) {
            if (j == 2 && $j != "-") {
                printf "- ";
            }
            size = length($j);
            printf "%c",toupper(substr($j, 1, 1));
            for(i = 2; i <= size; i++) {
                if (substr($j, i - 1, 1) == "(") {
                    printf "%s",toupper(substr($j, i, 1));
                } else {
                    printf "%c",tolower(substr($j, i, 1));
                }
            }
            if (j < NF) {
                printf " ";
            }
        }
        printf "\"\n";
    }
    ' | awk '{ system($0) }' 2>/dev/null
}

# ---------------------------------------------------------------------------- #
# tag
# ---------------------------------------------------------------------------- #
tag()
{
    echo "$1"
    size=`stat -c "%s" "$1"`
    if ((size == 0)); then
        return
    fi
    f=`basename "$1"`
    i=`echo ${f:0:2} | awk '{ print $0 + 0 }'`
    id3v2 -D "$f" >/dev/null
    title=`echo "${f%.$ext}" | cut -c6-`
    id3ed -n "$artist" -a "$album" -y "$year" -k $i -s "$title" -q "$f" \
        >/dev/null
}

# ---------------------------------------------------------------------------- #
# rtag
# ---------------------------------------------------------------------------- #
rtag()
{
    dir="$1"
    if [ "$dir" = "." ]; then
        dir=`pwd`
    fi
    dir=${dir##*/}
    artist=`echo "$dir" | awk -F ' - ' '{ print $1 }'`
      year=`echo "$dir" | awk -F ' - ' '{ print $2 }'`
     album=`echo "$dir" | awk -F ' - ' '{ print $3 }'`
    echo "artist=$artist year=$year album=$album"
    if [ -z "$album" ]; then
        return
    fi
    rfexec "$1" tag
}

# ---------------------------------------------------------------------------- #
# list
# ---------------------------------------------------------------------------- #
list()
{
    echo "$1"
    size=`stat -c "%s" "$1"`
    if ((size == 0)); then
        echo "warn: size = 0"
        return
    fi
    f=`basename "$1"`
    i=`echo ${f:0:2} | awk '{ print $0 + 0 }'`
    title=`echo "${f%.$ext}" | cut -c6-`
    mp3=`printf %02d $i`" - $title.$ext"
    if [ $ext = "mp3" ]; then
        time=`mpg123 -t "$mp3" 2>&1 | tail -n 1`
        time=`echo $time | cut -d ']' -f 1 | cut -d '[' -f 2 |\
            awk -F ':' '{ print $1 * 60 + $2 }'`
    else
        time=`boxdumper "$mp3" | grep -m 1 duration`
        time=`echo $time | cut -d '.' -f 1 | cut -d '(' -f 2 |\
            awk -F ':' '{ print $1 * 3600 + $2 * 60 + $3 }'`
    fi
    if ((time == 0)); then
        echo "warn: time = 0"
        return
    fi
    echo "#EXTINF:$time,$artist - $title" >>00.m3u
    echo "$mp3" >>00.m3u
}

# ---------------------------------------------------------------------------- #
# rlist
# ---------------------------------------------------------------------------- #
rlist()
{
    dir="$1"
    if [ "$dir" = "." ]; then
        dir=`pwd`
    fi
    dir=${dir##*/}
    artist=`echo "$dir" | awk -F ' - ' '{ print $1 }'`
      year=`echo "$dir" | awk -F ' - ' '{ print $2 }'`
     album=`echo "$dir" | awk -F ' - ' '{ print $3 }'`
    echo "artist=$artist year=$year album=$album"
    if [ -z "$album" ]; then
        return
    fi
    echo "#EXTM3U" >"$1/00.m3u"
    rfexec "$1" list
}

# ---------------------------------------------------------------------------- #
# myRead
# ---------------------------------------------------------------------------- #
myRead()
{
    if [ $interactive = 0 ]; then
        return 0
    fi

    echo -n "$1 ? (o/N) "
    read ret
    if [ "$ret" != o ]; then
        return 1
    else
        return 0
    fi
}

# ---------------------------------------------------------------------------- #
# main
# ---------------------------------------------------------------------------- #
myRead "rchmod644" && find . -type f -exec chmod 644 {} \;
if [ $ext = "mp3" ]; then
    myRead "fffb" && rdexec rfexec fffb
fi
myRead "dirnames"  && rdexec ucfirst
find . -type d -print | LC_ALL=C sort >$dirs
myRead "filenames" && rdexec rfexec ucfirst
if [ $ext = "mp3" ]; then
    myRead "tags" && rdexec rtag
fi
myRead "lists" && rdexec rlist

rm $dirs

exit 0