#!/bin/bash
#
# A simple bash script to convert a mp3 based by-track-splitted audio book into one m4b file
#
set -o errexit
set -o nounset

if [ -z "$1" ]; then
	echo "The first param needs to be to folder to convert..."
	exit 1;
elif ! [ -d "$1" ]; then
	echo "$1 could not be found or is not a directory."
	exit 1;
fi

if ! [ -x "$(command -v ffmpeg)" ] || ! [ -x "$(command -v ffprobe)" ] || ! [ -x "$(command -v mpg123)" ]  || ! [ -x "$(command -v faac)" ]; then
  echo "Required programms are not installed. You need ffmpeg, ffprobe, mpg123 and faac." >&2
  exit 1;
fi

# some cleanup if the script has crashed
if [ -f /tmp/audiobookgen_tmp.m4b ]; then
	rm /tmp/audiobookgen_tmp.m4b
fi
if [ -f /tmp/audiobookgen_FFMETADATAFILE.txt ]; then
	rm /tmp/audiobookgen_FFMETADATAFILE.txt
fi

# some initial vars
startts=0
title=
artist=
album=
disc=
date=
chapters=
counttracks=0
# 183 is a audiobook, but it's not standard id3v2. check "id3v2 -L" for a complete list of supported types
genre=12

# let the script know where it is, where the source is and set the name of the m4b.
currentDir=$(pwd -P)
mp3audiobookdir=$(realpath "$1")
m4bfileName=$(basename "$mp3audiobookdir")

echo "checking mp3 files..."
cd "$mp3audiobookdir"
for f in *.mp3; do
	#all=$(ffprobe  -loglevel quiet -show_entries format_tags "$f");
	title=$(ffprobe -loglevel quiet -show_entries format_tags=title -of default=noprint_wrappers=1:nokey=1 "$f")
	track=$(ffprobe  -loglevel quiet -show_entries format_tags=track -of default=noprint_wrappers=1:nokey=1 "$f")
	if [ -z "$artist" ]; then	
		artist=$(ffprobe  -loglevel quiet -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$f")
	fi
	if [ -z "$album" ]; then	
		album=$(ffprobe  -loglevel quiet -show_entries format_tags=album -of default=noprint_wrappers=1:nokey=1 "$f")
	fi	
	if [ -z "$disc" ]; then	
		disc=$(ffprobe  -loglevel quiet -show_entries format_tags=disc -of default=noprint_wrappers=1:nokey=1 "$f")
	fi	
	if [ -z "$date" ]; then	
		date=$(ffprobe  -loglevel quiet -show_entries format_tags=date -of default=noprint_wrappers=1:nokey=1 "$f")
	fi

	duration=$(ffprobe -v error -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$f")
	duration=$(echo "$duration" | awk -F'.' '{print $1}')
	chapterstart=$(echo "$startts * 1000 + 1" | bc)
	chapterend=$(echo "($startts + $duration) * 1000" | bc)
	startts=$(echo "$startts + $duration" | bc)
	counttracks=$(echo "$counttracks + 1" | bc)

	chapters="$chapters\n\n[CHAPTER]\nTIMEBASE=1/1000\nSTART=$chapterstart\nEND=$chapterend\ntitle=$title"
done

coverparam=
if [ -f "cover.jpg" ]; then
	coverparam="--cover-art cover.jpg"
fi

# let's show you what i got...
clear
echo -e "Title:  $artist - $album\nTracks: $counttracks";
if [ -z "$date" ]; then	
	echo "Cover:  not found (place cover.jpg in your mp3 directory...)"
else
	echo "Cover:  found"
fi
echo -e	 "Target: $currentDir/$m4bfileName.m4b\n\nPress return to contiune (c for cancel) "
read -n 1 k <&1
if [[ $k = c ]] ; then
	exit 0
fi

clear
# i'm not setting a "track title" here. if you want to set it add '--title ="$album"' for example
mpg123 -s *.mp3 | faac -P -X -w -o /tmp/audiobookgen_tmp.m4b --artist "$artist" --album "$album" --genre "$genre" --year "$date" --disc "$disc" $coverparam -

cd "$currentDir"

ffmpeg -i /tmp/audiobookgen_tmp.m4b -f ffmetadata /tmp/audiobook_FFMETADATAFILE.txt
echo -e $chapters >> /tmp/audiobook_FFMETADATAFILE.txt
ffmpeg -i /tmp/audiobookgen_tmp.m4b -i /tmp/audiobook_FFMETADATAFILE.txt -map_metadata 1 -vn -sn -dn -acodec copy "$currentDir/$m4bfileName.m4b"

rm /tmp/audiobookgen_tmp.m4b
rm /tmp/audiobook_FFMETADATAFILE.txt

# if you have problems with the m4b ffmpeg creates, try these lines (https://trac.ffmpeg.org/ticket/8375):
#if [ -x "$(command -v MP4Box)" ]; then
#	MP4Box -brand M4A:0 -rb isom -rb iso2 "$currentDir/$m4bfileName.m4b"
#	MP4Box -brand M4A:0 -ab isom -ab iso2 "$currentDir/$m4bfileName.m4b"
#fi

echo -e "\ndone."