#!/bin/bash

#####################################################################
#                                                                   #
#    Generates an API for Android or iOS based on a Faust object    #
#               (c) Romain Michon CCRMA and Grame, 2016             #
#                                                                   #
#####################################################################

# change if you want to get the log of what's happening
LOG="/dev/null"
#LOG="log"

# exit if a command fails
set -e

# global option variables
ANDROID="0"
IOS="0"
VOICES="0"
#PACKAGENAME="0"
POLY2="0"
MIDI="0"
NODOC="0"

echoHelp ()
{
    echo "$p wrong argument"
    echo ""
    echo "faust2api can be used to generate faust-based dsp objects for iOS and Android."
    echo "To generate an iOS API, run: faust2api -ios yourFaustCode.dsp"
    echo "To generate and Android API, run: faust2api -android yourFaustCode.dsp"
    echo ""
    echo "GLOBAL OPTIONS:"
    echo "   -polyvoices N : creates a polyphonic object with N voices."
    echo "   -poly2 : adds an effect to the polyphonic synth (this option is ignored if -polyvoices is not specified). The effect should be declared in a file called yourFaustCode_effect.dsp placed in the same folder than yourFaustCode.dsp."
	echo "   -nodoc : prevents documentation from being generated."
    echo ""
    echo "ANDROID-SPECIFIC OPTIONS:"
    echo "   -package : set the JAVA package name (e.g. '-package mypackage' will change the JAVA package name to 'mypackage.DspFaust'). The default package name is 'com.DspFaust.'"
    echo ""
    echo "IOS-SPECIFIC OPTIONS "
    echo "   -midi : add built-in RtMidi support to the API."
}

# dispatch command arguments
for p in $@; do
    if [ $p = "-help" ]; then
	echoHelp
    elif [ "$VOICES" = "-1" ]; then
	VOICES="$p"
    elif [ "$PACKAGENAME" = "-1" ]; then
	PACKAGENAME="$p"
    elif [[ -f "$p" ]]; then
	FILE="$p"
    elif [ $p = "-android" ]; then
	ANDROID=1
    elif [ $p = "-ios" ]; then
	IOS="1"
    elif [ "$p" = "-poly2" ]; then
        POLY2="1"
    elif [ "$p" = "-midi" ]; then
        MIDI="1"
	elif [ "$p" = "-nodoc" ]; then
        NODOC="1"
    elif [ $p = "-polyvoices" ]; then
	VOICES="-1"
    elif [ $p = "-package" ]; then
	PACKAGENAME="-1"
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p"
    else
	echoHelp
	exit
    fi
done

if [ -z $FILE ]; then
    echo "Please, provide a Faust file to process"
    exit
fi

###################################
# GENERATING API
###################################

APIFOLDER="dsp-faust"

rm -r "$APIFOLDER" 2> /dev/null || true
mkdir "$APIFOLDER"

if [ $ANDROID -eq 1 ]; then
    echo "Your dsp-faust.zip API package for Android is being created"
    CPPFOLDER="$APIFOLDER/cpp"
    JAVAFOLDER="$APIFOLDER/java"
    mkdir $CPPFOLDER
    mkdir $JAVAFOLDER
    cp -r /usr/local/share/faust/api/android/jni/*.java $JAVAFOLDER
    if [ -n "$PACKAGENAME" ]; then
	PACKAGENAME="$PACKAGENAME.DspFaust"
	sed -i "s/com.DspFaust/$PACKAGENAME/g" $JAVAFOLDER/*.java
    fi
    cp -r /usr/local/share/faust/api/android/DspFaust.h $CPPFOLDER
    cp -r /usr/local/share/faust/api/android/jni/java_interface_wrap.cpp $CPPFOLDER
    faust -i -a api/android/DspFaust.cpp "$FILE" -o "$CPPFOLDER/DspFaust.cpp" || exit
    if [ "$POLY2" = "1" ]; then
	faust -i -cn effect -a minimal-effect.cpp "${FILE%.dsp}_effect.dsp" | cat - "$CPPFOLDER/DspFaust.cpp" > temp && mv temp "$CPPFOLDER/DspFaust.cpp" || exit
	echo "#define POLY2 1" | cat - "$CPPFOLDER/DspFaust.cpp" > temp && mv temp "$CPPFOLDER/DspFaust.cpp"
    fi
    if [ "$VOICES" -gt "0" ]; then
	echo "#define POLY_VOICES $VOICES" | cat - "$CPPFOLDER/DspFaust.cpp" > temp && mv temp "$CPPFOLDER/DspFaust.cpp"
    fi
elif [ $IOS -eq 1 ]; then
    echo "Your dsp-faust.zip API package for iOS is being created"
    cp -r /usr/local/share/faust/api/iOS/DspFaust.h $APIFOLDER
    faust -i -a api/iOS/DspFaust.cpp "$FILE" -o "$APIFOLDER/DspFaust.cpp" || exit
    if [ "$POLY2" = "1" ]; then
	faust -i -cn effect -a minimal-effect.cpp "${FILE%.dsp}_effect.dsp" | cat - "$APIFOLDER/DspFaust.cpp" > temp && mv temp "$APIFOLDER/DspFaust.cpp" || exit
	echo "#define POLY2 1" | cat - "$APIFOLDER/DspFaust.cpp" > temp && mv temp "$APIFOLDER/DspFaust.cpp"
    fi
    if [ "$VOICES" -gt "0" ]; then
	echo "#define POLY_VOICES $VOICES" | cat - "$APIFOLDER/DspFaust.cpp" > temp && mv temp "$APIFOLDER/DspFaust.cpp"
    fi
    if [ "$MIDI" = "1" ]; then
	echo "#define IOS_MIDI_SUPPORT 1" | cat - "$APIFOLDER/DspFaust.cpp" > temp && mv temp "$APIFOLDER/DspFaust.cpp"
    fi
else
    echoHelp
    exit 1
fi

###################################
# GENERATING API DOCUMENTATION
###################################

if [ $NODOC -eq 0 ]; then
	if [ $ANDROID -eq 1 ]; then
		DOCHEADERFILE="/usr/local/share/faust/api/doc/Android.md"
		APIHEADERFILE="/usr/local/share/faust/api/android/DspFaust.h"
	elif [ $IOS -eq 1 ]; then
		DOCHEADERFILE="/usr/local/share/faust/api/doc/iOS.md"
		APIHEADERFILE="/usr/local/share/faust/api/iOS/DspFaust.h"
	fi
    
	PPFILE=pPrinter.cpp
	PPBINARY=pp
	READMEFILE="$APIFOLDER/README.md"
	
	CXXFLAGS=$MYGCCFLAGS
	MYGCCFLAGS="-O3"
	CXX=g++
	CXXFLAGS=$MYGCCFLAGS

	faust -i -a path-printer.cpp "$FILE" -o "$PPFILE" || exit
	if [ "$POLY2" = "1" ]; then
		faust -i -cn effect -a minimal-effect.cpp "${FILE%.dsp}_effect.dsp" | cat - "$PPFILE" > temp && mv temp "$PPFILE" || exit
		echo "#define POLY2 1" | cat - "$PPFILE" > temp && mv temp "$PPFILE"
	fi
	if [ "$VOICES" -gt "0" ]; then
		echo "#define POLY_VOICES $VOICES" | cat - "$PPFILE" > temp && mv temp "$PPFILE"
	fi

	# compile c++ to binary
	(
		$CXX $CXXFLAGS "$PPFILE" -o "$PPBINARY"
	) > /dev/null || exit
	rm "$PPFILE" || exit
	
	cp "$DOCHEADERFILE"  "$READMEFILE" || exit
	./"$PPBINARY" | cat "$READMEFILE" - > temp && mv temp "$READMEFILE" || exit
	rm "$PPBINARY" || exit
	
	faust2md "$APIHEADERFILE"  | cat "$READMEFILE" - > temp && mv temp "$READMEFILE" || exit
fi

###################################
# POST PROCESSING
###################################

ZIPOUT="$APIFOLDER.zip"

rm $ZIPOUT 2> /dev/null || true
zip -r $ZIPOUT $APIFOLDER > /dev/null || exit
rm -r $APIFOLDER || exit
