#! /bin/bash -e

#########################################################################################
#                                                                                       #
#  Compiles Faust programs to OSX/iOS libraries suitable for the Unity environment      #
#                                                                                       #
#  (c) Grame, 2017                                                                      #
#                                                                                       #
#########################################################################################


#   This script shouldn't be used on its own, use the "faust2unity" script instead
#   The libraries are firstly wrapped by the unityplugin.cpp architecture file
#   They have to be used in the Unity environment
#   The libraries does not work by themselves, they need the FaustPlugin_<dspname>.cs and FaustUtilities_<dspname>.cs files to be functionnal
#   These files are automatically generated by the "faust2unity" script
#
#
#   Structure of a plugin for OSX
#-----------------------------------------
#   libFaustPlugin_foo.bundle/
#       Contents/
#           MacOS/
#               AudioPlugin<dspname>
#           Info.plist
#

. faustpath
. faustoptflags

CXXFLAGS=$MYGCCFLAGS

NVOICES=-1

#------------------------------------------------
# Compiler settings
ARCH="-arch x86_64"
CXXFLAGS+=" -fPIC"
LDFLAGS="-bundle"
CXX="c++"

#------------------------------------------------
# Generates the info.plist file

createInfoPList() {
cat > "$2" << DELIM
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BuildMachineOSBuild</key>
	<string>16D32</string>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>$1</string>
	<key>CFBundleIdentifier</key>
	<string>com.yourcompany.$1</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$1</string>
	<key>CFBundlePackageType</key>
	<string>BNDL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleSupportedPlatforms</key>
	<array>
		<string>MacOSX</string>
	</array>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>CFPlugInDynamicRegisterFunction</key>
	<string></string>
	<key>CFPlugInDynamicRegistration</key>
	<string>NO</string>
	<key>CFPlugInFactories</key>
	<dict>
		<key>00000000-0000-0000-0000-000000000000</key>
		<string>MyFactoryFunction</string>
	</dict>
	<key>CFPlugInTypes</key>
	<dict>
		<key>00000000-0000-0000-0000-000000000000</key>
		<array>
			<string>00000000-0000-0000-0000-000000000000</string>
		</array>
	</dict>
	<key>CFPlugInUnloadFunction</key>
	<string></string>
	<key>DTCompiler</key>
	<string>com.apple.compilers.llvm.clang.1_0</string>
	<key>DTPlatformBuild</key>
	<string>8C1002</string>
	<key>DTPlatformVersion</key>
	<string>GM</string>
	<key>DTSDKBuild</key>
	<string>16C58</string>
	<key>DTSDKName</key>
	<string>macosx10.12</string>
	<key>DTXcode</key>
	<string>0821</string>
	<key>DTXcodeBuild</key>
	<string>8C1002</string>
</dict>
</plist>
DELIM
}

#---------------------------------------
# Dispatch command arguments

CUR=$(pwd)
SOURCE=0

while [ $1 ] 
do
    p=$1

    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echo "faust2osxiosunity [-ios] [-universal] [additional Faust options (-vec -vs 8...)] <file1.dsp> [<file2.dsp>]"
        echo "Use '-ios' to create an iOS static library"
        echo "Use '-nvoices <num>' to produce a polyphonic self-contained DSP with <num> voices, ready to be used with MIDI"
        echo "Use '-universal' to generate a 64/32 bits external"
        echo "Use 'faust2unity -osx -ios' to also create the c# and JSON files"
        echo "See architecture/unity/README.md for more info"
        exit
    fi

    if [ $p = "-ios" ]; then
        IOS=1
        CXXFLAGS="-arch armv7 -arch armv7s -arch arm64 -pipe -O3 -gdwarf-2"
    elif [ $p = "-nvoices" ]; then
        shift
        NVOICES=$1
    elif [ $p = "-source" ]; then
    	SOURCE=1
    elif [ $p = "-universal" ]; then
    	ARCH="-arch i386 -arch x86_64"
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p"
    elif [[ -f "$p" ]]; then
        FILES="$FILES $p"
    else
        OPTIONS="$OPTIONS $p"
    fi

shift
done

#--------------------------------------
# Compiles all *.dsp files

for p in $FILES; do
    CUR=$(pwd)
    f=$(basename "$p")
    NAME=${f%.dsp}
    FNAME=FaustPlugin_$NAME
    SRCDIR=$(dirname "$p")

    if [ "$IOS" = "1" ]; then # iOS part

        FIN=$FNAME/iOS

        # creates a temporary dir
        TMP=$(mktemp -d iOS.XXXX)

        # checks if final dir exists, if not creates it
        if [ ! -d "$FIN" ]; then
            mkdir -p "$FIN"
        fi

        # compiles faust to c++
        faust -i -a $FAUSTARCH/unity/unityplugin.cpp "$SRCDIR/$NAME.dsp" -o $TMP/$NAME.cpp || (echo "$FNAME : Faust to C++ compilation failed in faust2osxiosunity -ios"; exit 1)

        $CXX $CXXFLAGS -DAPPLE -fembed-bitcode -DPLUGINNAME="libFaustPlugin_$NAME" -std=c++11 -stdlib=libc++ -c -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk $TMP/$NAME.cpp -o $TMP/$NAME.o || (echo "$FNAME : C++ to iOS library compilation failed in faust2osxiosunity -ios"; exit 1)
        libtool $TMP/$NAME.o -o $TMP/libFaustPlugin_$NAME.a
        rm $TMP/$NAME.o $TMP/$NAME.cpp

        # moves binary to final
        mv $TMP/* $FIN/
        rm -rf $TMP

        echo "$f : iOS compilation completed"

    else # MacOS part

        FIN=$FNAME/MacOS

        # creates a temporary dir
        TDR=$(mktemp -d faust.XXX)

        # creates the bundle inside
        BNDL="$TDR/lib$FNAME.bundle"
        MOS="$BNDL/Contents/MacOS/"
        mkdir -p "$MOS"

        # checks if final dir exists, if not creates it
        if [ ! -d "$FIN" ]; then
            mkdir -p "$FIN"
        fi

        # compile Faust DSP to c++
        faust -i -a $FAUSTARCH/unity/unityplugin.cpp "$SRCDIR/$NAME.dsp" -o "$MOS/$NAME.cpp" || (echo "$FNAME : Faust to C++ compilation failed in faust2osxiosunity"; exit 1)
        
        if [ $NVOICES == -1 ]; then
        	 $CXX $CXXFLAGS $ARCH $LDFLAGS -DAPPLE -DPLUGINNAME="$NAME" "$MOS/$NAME.cpp" -o "$MOS/lib$FNAME" || (echo "$FNAME : C++ to OSX library compilation failed in faust2osxiosunity"; exit 1)
        else
        	 $CXX $CXXFLAGS $ARCH $LDFLAGS -DPOLY -DAPPLE -DPLUGINNAME="$NAME" "$MOS/$NAME.cpp" -o "$MOS/lib$FNAME" || (echo "$FNAME : C++ to OSX library compilation failed in faust2osxiosunity"; exit 1)
        fi
       
        rm "$MOS/$NAME.cpp"
        createInfoPList "lib$FNAME" "$BNDL/Contents/Info.plist" || (echo "$FNAME : Info.plist gerenation failed in faust2osxiosunity"; exit 1)

        rm -rf "$SRCDIR/lib$FNAME.bundle"

        # moves binary to final
        mv $BNDL $FIN/
        rm -rf $TDR

        echo "$f : OSX compilation completed"

    fi

done
