#!/bin/bash

#####################################################################
#                                                                   #
#       Generates a nodejs native addon from a Faust object         #
#               (c) Romain Michon CCRMA and Grame, 2017             #
#                                                                   #
#####################################################################

. faustpath
. faustoptflags
. usage.sh

# exit if a command fails
set -e

# global option variables
NVOICES=""
MIDI=""
SOUNDFILE=""
OSC=""
EFFECT=""
DRIVER=""
ELECTRON_VERSION=""
SOURCE="0"
LOG="/dev/null"

# compilation flags for the different targets
OSC_CFLAGS=""
OSC_LIBFLAGS=""
JACK_LIBRARIES_FLAGS="\`pkg-config --cflags --libs jack sndfile\`"
ALSA_LIBRARIES_FLAGS="\`pkg-config --cflags --libs alsa\` -pthread"
COREAUDIO_LIBRARIES_FLAGS="\`pkg-config --cflags --static --libs sndfile\` -framework CoreAudio -framework AudioUnit -framework CoreServices -framework CoreMIDI -framework CoreFoundation"
# TODO: missing rtaudio, portaudio, etc.

# useful variables
PLATFORM=$(uname)

echoHelp ()
{
    usage faust2nodejs "[driver] [Faust options] <file.dsp>"
    echo "Generate Faust-based nodejs native addons. The generated addons can embed most of the audio engines supported by Faust: ALSA, JACK, CoreAudio, RtAudio, PortAudio, etc. Since faust2nodejs essentially acts as a wrapper to faust2api, it offers the same features than this system (MIDI and OSC support, polyphony, separate effect file, etc.)."
    echo
    echo "The following drivers are available: -coreaudio // -alsa // -jack // -portaudio // -rtaudio // -dummy. For example, to create a native nodejs addon with a JACK audio engine, run: faust2nodjs -jack faustFile.dsp"
    echo
    echo "The following options are inherited directly from faust2api and can be used with faust2nodejs:"
    option
    options -osc -midi -soundfile
    option "-nvoices <num>"
    option "-effect <effect.dsp>"
    option -source "generates the source of the addon without compiling it"
    option "-electronv <VERSION>" "allows to specify the current version of electron if generating an addon for this framework"
    option -debug "prints compilation output"
    option "Faust options"
    exit
}

if [ "$#" -eq 0 ]; then
    echo 'Please, provide a Faust file to process !'
    echo ''
    echoHelp
fi

# dispatch command arguments
while [ $1 ]
do
    p=$1
    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echoHelp
    elif [[ -f "$p" ]]; then
        FILE="$p"
    elif [ $p = "-coreaudio" ] || [ $p = "-alsa" ] || [ $p = "-jack" ] || [ $p = "-portaudio" ] || [ $p = "-rtaudio" ] || [ $p = "-dummy" ] ; then
        DRIVER=$p
    elif [ "$p" = "-effect" ]; then
        shift
        EFFECT="-effect "$1
    elif [ "$p" = "-midi" ]; then
        MIDI="-midi"
    elif [ "$p" = "-soundfile" ]; then
        SOUNDFILE="-soundfile"
    elif [ "$p" = "-osc" ]; then
        OSC="-osc"
        OSC_CFLAGS="-DOSCCTR"
        OSC_LIBFLAGS="-lOSCFaust -pthread"
    elif [ "$p" = "-debug" ]; then
        LOG="/dev/stdout"
    elif [ "$p" = "-source" ]; then
        SOURCE="1"
    elif [ $p = "-nvoices" ]; then
        shift
        NVOICES="-nvoices "$1
    elif [ $p = "-electronv" ]; then
        shift
        ELECTRON_VERSION="--target="$1" --dist-url=https://atom.io/download/electron"
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p"
    elif [[ -f "$p" ]] && [ ${p: -4} == ".dsp" ]; then
        FILES="$FILES $p"
    else
        OPTIONS="$OPTIONS $p"
    fi
shift
done

NODE_NAME="${FILE%.dsp}"
NODE_FOLDER=$NODE_NAME"-faustnode"

# Creating project folder
mkdir $NODE_FOLDER

# Generating DSP engine
cd $NODE_FOLDER
faust2api $DRIVER -nodoc -nozip $MIDI $SOUNDFILE $OSC $NVOICES $EFFECT $OPTIONS "../"$FILE &> $LOG || exit 1

# Copying template files
cp "$FAUSTARCH/nodejs/binding.gyp" .
cp "$FAUSTARCH/nodejs/DspFaustNode.cpp" .
cp "$FAUSTARCH/nodejs/DspFaustNode.h" .
cp "$FAUSTARCH/nodejs/faust.cpp" .
cp "$FAUSTARCH/nodejs/README.md" .

# Customizing configuration file
# TODO: for now only ported compilation flags for alsa and JACK: missing
# portaudio, rtaudio, and coreaudio
if [ $DRIVER = "-jack" ]; then
    if [ $PLATFORM = "Darwin" ]; then
        sed -i "" "s/__CFLAGS__/$MYGCCFLAGS $FAUSTTOOLSFLAGS $OMP $OSC_CFLAGS/g" binding.gyp
        sed -i "" "s/__LIBFLAGS__/$JACK_LIBRARIES_FLAGS $OSC_LIBFLAGS/g" binding.gyp
    else
        sed -i "s/__CFLAGS__/$MYGCCFLAGS $FAUSTTOOLSFLAGS $OMP $OSC_CFLAGS/g" binding.gyp
        sed -i "s/__LIBFLAGS__/$JACK_LIBRARIES_FLAGS $OSC_LIBFLAGS/g" binding.gyp
    fi
elif [ $DRIVER = "-alsa" ]; then
    sed -i "s/__CFLAGS__/$MYGCCFLAGS $FAUSTTOOLSFLAGS $OMP $OSC_CFLAGS/g" binding.gyp
    sed -i "s/__LIBFLAGS__/$JACK_LIBRARIES_FLAGS $OSC_LIBFLAGS/g" binding.gyp
elif [ $DRIVER = "-coreaudio" ]; then
    sed -i "" "s/__CFLAGS__/$MYGCCFLAGS $FAUSTTOOLSFLAGS $OMP $OSC_CFLAGS/g" binding.gyp
    sed -i "" "s/__LIBFLAGS__/$COREAUDIO_LIBRARIES_FLAGS $OSC_LIBFLAGS/g" binding.gyp
fi

node-gyp $ELECTRON_VERSION configure &> $LOG || exit 1

if [ $SOURCE = "0" ]; then
    cd build
    make &> $LOG || exit 1
    cd ../..
    cp $NODE_FOLDER/build/Release/faust.node $NODE_NAME.node
    rm -rf $NODE_FOLDER
    echo "A native nodejs node \"$NODE_NAME.node\" was generated in the current folder."
else
    echo "A $NODE_FOLDER folder containing the source of the native Faust node was generated in the current folder. Please refer to the README in it for compilation instructions."
fi
