diff --git a/music-sync.sh b/music-sync.sh index 89b3fdc..b34b709 100755 --- a/music-sync.sh +++ b/music-sync.sh @@ -12,6 +12,8 @@ help=false temp="/tmp/converted" convertart=false coverartsize=200 +jobcount="-2" +multithread=false CheckDeps() { if [[ $1 == 0 ]]; then @@ -60,6 +62,17 @@ CheckDeps() { exit 1 fi VerboseOutput 0 "\`convert --version\` succeeded" + + # Check Gnu parallel + if [[ $multithread == true && ! $(parallel -h 2>/dev/null) ]]; then + VerboseOutput 5 "\`parallel -h\` failed" + VerboseOutput 5 "Sorry, It seems that parallel is not installed on your system" + VerboseOutput 5 "Please install gnu-parallel and env_parallel from your repositories and make sure it is available in your \$PATH" + VerboseOutput 5 "Otherwise disable multithreading" + ExecTime + exit 1 + fi + VerboseOutput 0 "\`parallel -h \` succeeded" fi VerboseOutput 1 "Dependency test OK" } @@ -67,8 +80,8 @@ CheckDeps() { GetOptions() { # https://stackoverflow.com/a/29754866 - OPTIONS=s:d:t:c::a::v::h - LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help + OPTIONS=s:d:t:c::a::v::hj:: + LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help,jobs:: # -use ! and PIPESTATUS to get exit code with errexit set # -temporarily store output to be able to check for errors @@ -140,6 +153,17 @@ GetOptions() { shift VerboseOutput 1 "Album art will ${coverartsize}px wide" ;; + -j|--jobs) + VerboseOutput 0 "--jobs given" + multithread=true + jobcount="-2" + if [[ $2 != "" ]]; then + jobcount=${2} + shift + fi + shift + VerboseOutput 1 "multithreading will use ${jobcount} threads" + ;; --) shift break @@ -170,7 +194,6 @@ GetOptions() { if [[ $dest == "-" ]] || [[ $source == "-" ]]; then help=true fi - VerboseOutput 1 "Checks OK. Going on" } @@ -267,109 +290,125 @@ CreateFileList() { done } -ConvertFiles() { +Execute() { curline=0 percentage=0 IFS=" "; - for line in $(cat "/tmp/music-sync-filelist") - do - VerboseOutput 0 "${source}/$line" - if [[ ! -f "${source}/$line" ]]; then - VerboseOutput 5 "Source-file ${source}/$line Unreachable" - ExecTime - exit 3 + if [[ $multithread == true ]]; then + VerboseOutput 3 "Running in parallel. Mind your load" + export -f ProcessFile + export -f ConvertFile + export -f CopyFile + export -f VerboseOutput + export -f ExecTime + export dest + export source + export bitrate + export convert + export temp + export coverartsize + export begin + parallel --jobs ${jobcount} --line-buffer --arg-file "/tmp/music-sync-filelist" ProcessFile + else + for line in $(cat "/tmp/music-sync-filelist") + do + + curline=$(expr ${curline} + 1) + total=$(cat /tmp/music-sync-filelist | wc -l) + percentage=$(echo "scale=4;${curline}/${total}" | bc) + percentage=$(echo "scale=2;${percentage}*100" | bc) + VerboseOutput 2 "Current file: $line" + VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%)" + ProcessFile $line + done + fi + VerboseOutput 2 "Done!" +} +ProcessFile() { + line=${1} + VerboseOutput 2 "Current File: $line" + if [[ $convert == true ]]; then + ConvertFile "$line" + fi + CopyFile "$line" +} + +ConvertFile() { + line=${1} + if [[ ! -f "${source}/$line" ]]; then + VerboseOutput 5 "Source-file ${source}/$line Unreachable" + ExecTime + exit 3 + fi + + if [[ "$temp/$line" = */* ]]; then + VerboseOutput 0 "Creating folder $temp/${line%/*}" + mkdir -p "$temp/${line%/*}"; + fi; + mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/') + if [[ ! -f "$temp/$mp3line" || "${source}/$mp3line" -nt "$temp/$mp3line" ]]; then + if [[ $line != *".mp3" ]]; then + VerboseOutput 3 "${line} will be converted to mp3-file ${mp3line}" fi + VerboseOutput 0 "Converting MP3-file $line" + ffmpeg -y -i "$source/$line" -acodec libmp3lame -map_metadata 0 -id3v2_version 3 -b:a ${bitrate}k "$temp/${mp3line}" 1>/dev/null 2>/dev/null + if [[ $convertart == true ]]; then + VerboseOutput 0 "Creating folder $temp/${mp3line}-images/" + mkdir -p "$temp/${mp3line}-images/" + VerboseOutput 0 "Extracted albumart" + eyeD3 --write-images "$temp/${mp3line}-images/" "$temp/${mp3line}" 1>/dev/null 2>/dev/null + frontcovers=(${temp}/${mp3line}-images/FRONT_COVER.*) + if [ -e "$frontcovers" ]; then + VerboseOutput 0 "Converting albumart" + convert "$temp/${mp3line}-images/FRONT_COVER.*" -resize ${coverartsize}x${coverartsize} "$temp/${mp3line}-images/FRONT_COVER.jpg" 1>/dev/null 2>/dev/null + eyeD3 --remove-all-images "$temp/${mp3line}" 1>/dev/null 2>/dev/null + VerboseOutput 0 "Embedding albumart" + eyeD3 --add-image "$temp/${mp3line}-images/FRONT_COVER.jpg:FRONT_COVER" "$temp/${mp3line}" 1>/dev/null 2>/dev/null + VerboseOutput 1 "Converted cover art: ${mp3line}" + else + VerboseOutput 4 "No front cover art found for ${mp3line}" + fi + fi + VerboseOutput 1 "Converted: $line" + else + VerboseOutput 3 "$line already converted" + fi; +} - curline=$(expr ${curline} + 1) - total=$(cat /tmp/music-sync-filelist | wc -l) - percentage=$(echo "scale=4;${curline}/${total}" | bc) - percentage=$(echo "scale=2;${percentage}*100" | bc) - VerboseOutput 1 "Converting: $line" - VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%) Step 1 of 2" +CopyFile() { + line=${1} + if [[ ! -d "$dest" ]]; then + VerboseOutput 5 "Destination unreachable" + ExecTime + exit 4 + fi - if [[ "$temp/$line" = */* ]]; then - VerboseOutput 0 "Creating folder $temp/${line%/*}" - mkdir -p "$temp/${line%/*}"; - fi; + if [[ $convert == true ]]; then mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/') - if [[ ! -f "$temp/$mp3line" || "${source}/$mp3line" -nt "$temp/$mp3line" ]]; then - if [[ $line != *".mp3" ]]; then - VerboseOutput 3 "${line} will be converted to mp3-file ${mp3line}" - fi - VerboseOutput 0 "Converting MP3-file $line" - ffmpeg -y -i "$source/$line" -acodec libmp3lame -map_metadata 0 -id3v2_version 3 -b:a ${bitrate}k "$temp/${mp3line}" 1>/dev/null 2>/dev/null - if [[ $convertart == true ]]; then - VerboseOutput 0 "Creating folder $temp/${mp3line}-images/" - mkdir -p "$temp/${mp3line}-images/" - VerboseOutput 0 "Extracted albumart" - eyeD3 --write-images "$temp/${mp3line}-images/" "$temp/${mp3line}" 1>/dev/null 2>/dev/null - frontcovers=(${temp}/${mp3line}-images/FRONT_COVER.*) - if [ -e "$frontcovers" ]; then - VerboseOutput 0 "Converting albumart" - convert "$temp/${mp3line}-images/FRONT_COVER.*" -resize ${coverartsize}x${coverartsize} "$temp/${mp3line}-images/FRONT_COVER.jpg" 1>/dev/null 2>/dev/null - eyeD3 --remove-all-images "$temp/${mp3line}" 1>/dev/null 2>/dev/null - VerboseOutput 0 "Embedding albumart" - eyeD3 --add-image "$temp/${mp3line}-images/FRONT_COVER.jpg:FRONT_COVER" "$temp/${mp3line}" 1>/dev/null 2>/dev/null - VerboseOutput 1 "Converted cover art: ${mp3line}" - else - VerboseOutput 4 "No front cover art found for ${mp3line}" - fi - fi - VerboseOutput 2 "Converted: $line" - else - VerboseOutput 3 "$line already converted" - fi; + else + mp3line=$(echo "$line") + fi - done - VerboseOutput 2 "Done converting files" + if [[ ! -f "${temp}/$mp3line" ]]; then + VerboseOutput 5 "Source-file ${temp}/$mp3line Unreachable" + ExecTime + exit 3 + fi + + destline=$(echo $mp3line | sed -e 's/\.*\//\//g') + VerboseOutput 1 "Copying: $line" + + if [[ "$dest/$line" = */* ]]; then + VerboseOutput 0 "Creating folder $dest/${line%/*}" + mkdir -p "$dest/${destline%/*}"; + fi; + + cp -f $temp/$mp3line $dest/${destline} 1>/dev/null 2>/dev/null + + VerboseOutput 1 "Copied: $line" } -CopyFiles() { - curline=0 - percentage=0 - IFS=" -"; - for line in $(cat "/tmp/music-sync-filelist") - do - if [[ ! -d "$dest" ]]; then - VerboseOutput 5 "Destination unreachable" - ExecTime - exit 4 - fi - - if [[ $convert == true ]]; then - mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/') - else - mp3line=$(echo "$line") - fi - - if [[ ! -f "${temp}/$mp3line" ]]; then - VerboseOutput 5 "Source-file ${temp}/$mp3line Unreachable" - ExecTime - exit 3 - fi - - curline=$(expr ${curline} + 1) - total=$(cat /tmp/music-sync-filelist | wc -l) - percentage=$(echo "scale=4;${curline}/${total}" | bc) - percentage=$(echo "scale=2;${percentage}*100" | bc) - destline=$(echo $mp3line | sed -e 's/\.*\//\//g') - VerboseOutput 1 "Copying: $line" - VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%) Step 2 of 2" - - if [[ "$dest/$line" = */* ]]; then - VerboseOutput 0 "Creating folder $dest/${line%/*}" - mkdir -p "$dest/${destline%/*}"; - fi; - - cp -f $temp/$mp3line $dest/${destline} 1>/dev/null 2>/dev/null - - VerboseOutput 2 "Copied: $line" - - done - VerboseOutput 2 "Done copying files" -} CleanUp() { VerboseOutput 1 "Cleaning Up" @@ -418,14 +457,12 @@ if [[ ! -f /tmp/music-sync-filelist ]]; then CleanUp exit 0 fi -if [[ $convert == true ]]; then - ConvertFiles -else +if [[ $convert == false ]]; then if [[ $temp != "/tmp/converted" ]]; then VerboseOutput 2 "Conversion not enabled. Ignoring cache folder" fi temp=$source -fi -CopyFiles +fi +Execute CleanUp ExecTime