
# BasicWriteMidi.lhs, BasicMidiFile.lhs are stripped versions of
#   WriteMidi.lhs, MidiFile.lhs
# ../ghc_add/IOExtensions.hs needs non-existing IOExts

OBJECT_DIR    := build/$(shell uname -s)-$(shell uname -m)
INTERFACE_DIR := build/Interface
#BUILD_DIR = `uname -s`-`uname -m`


BASICS   = Basic/Pitch.lhs Basic/Duration.lhs Basic/Tempo.lhs Basic/Interval.lhs Basic/Scale.lhs \
	   Composition/Trill.lhs Composition/Chord.lhs Composition/ChordType.lhs \
	   Composition/Drum.lhs Composition/Rhythm.lhs \
	   Basic/TimeOrderedList.lhs Basic/TimeOrderedListPad.lhs \
	   Basic/Timer.hs Basic/Timer/Immediate.hs \
	   Melody.lhs Melody/Standard.lhs \
	   Music.lhs Music/Standard.lhs Music/Rhythmic.lhs Music/GeneralMIDI.lhs \
	   Performance/Player.lhs Performance/BackEnd.lhs \
	   Performance/Default.lhs Performance/Fancy.lhs \
	   Performance.lhs Performance/Context.hs \
	   General/Utility.lhs General/IO.hs \
	   General/Monad.lhs General/Map.hs \
	   General/IdGenerator.lhs \
	   General/LoopTreeTagged.lhs General/LoopTreeRecursive.lhs \
	   General/LoopTreeTaggedGen.lhs General/LoopTreeRecursiveGen.lhs \
	   Process/Optimization.lhs Process/Format.lhs \
	   Interface/MML.lhs Interface/MED/Text.hs

MEDIA    = Medium.hs Medium/Temporal.hs \
	   Medium/Plain/List.hs Medium/Plain/Binary.hs Medium/Plain/ContextFreeGrammar.lhs \
	   Medium/Controlled/List.hs Medium/LabeledControlled/List.hs Medium/Controlled.hs \
	   Medium/Controlled/ContextFreeGrammar.lhs


MIDI     = Interface/MIDI.lhs \
           $(patsubst %, Interface/MIDI/%, \
	       InstrumentMap.lhs Note.lhs \
	       Read.lhs Write.lhs Render.lhs )

CSOUND   = Interface/CSound.lhs \
           $(patsubst %, Interface/CSound/%, \
	       Score.lhs InstrumentMap.lhs SoundMap.hs Note.lhs \
               Generator.lhs Orchestra.lhs OrchestraFunction.lhs Tutorial.lhs)

SUPERCOLLIDER = \
           $(patsubst %, Interface/SuperCollider/%, \
               SoundMap.hs Note.hs Performance.hs \
               Channel.hs Channel/State.hs Channel/File.hs Channel/Env.hs \
               Schedule.hs Schedule/Install.hs Schedule/Channel.hs Render.hs \
               Play.hs Play/Install.hs Play/Channel.hs Play/Life.hs \
               Example.hs Example/Air.hs Example/Morph.hs )

AUTOTRACK = $(patsubst %, Interface/AutoTrack/%.lhs, \
              ChartBar ChordChart ChordSymbol EventChart \
              Instrument ScaleChart Style Transposeable)

AUTOTRACK_PROG = $(patsubst %, src/Haskore/Interface/AutoTrack/%.lhs, \
                   Main Option)


EXAMPLES = $(patsubst %, Example/%, \
	       Miscellaneous.lhs \
	       Ssf.lhs NewResolutions.lhs \
	       ChildSong6.lhs Kantate147.hs WhiteChristmas.hs \
	       SelfSim.lhs Fractal.hs Flip.hs Guitar.lhs)

MODULES = $(BASICS) $(EXAMPLES) $(MIDI) $(CSOUND) $(AUTOTRACK)

MODULEPATH = src

# http://www.gnu.org/software/automake/manual/make/Syntax-of-Functions.html#Syntax-of-Functions
colon:= :
empty:=
space:= $(empty) $(empty)

# exclude installed versions of Haskore, because we want to use the local one
HUGS_PACKAGE_PATH = \
   {Hugs}/libraries:{Hugs}/libraries:{Hugs}/packages/*:$(subst $(space),$(colon),$(patsubst %,/usr/local/lib/hugs/packages/%,event-list midi markov-chain non-negative special-functors record-access))
#   $(subst $(space),$(colon),$(patsubst %,{Hugs}/packages/%,event-list midi markov-chain non-negative record-access))


GHC_MODULES = $(patsubst %, src/%, $(MEDIA) \
                  Test/Equivalence.lhs Test/Suite.lhs) \
              $(patsubst %, src/Haskore/%, \
                  $(MODULES) \
	          $(SUPERCOLLIDER) \
                  Basic/Timer/Thread.hs \
		  Interface/MIDI/Play.lhs Interface/CSound/Play.lhs )

GHC_DEPENDS = $(GHC_MODULES)

# names of literate modules after removing literary information
UNLIT_MODULES = $(patsubst %.lhs, %.hs, $(patsubst %.hs, , $(GHC_MODULES)))

# names of all modules without literary information
HS_MODULES = $(patsubst %.lhs, %.hs, $(GHC_MODULES))


STDINTERFACES = base/base haskell-src/haskell-src QuickCheck/QuickCheck

STDPACKAGES = base mtl haskell-src network Hsc QuickCheck HUnit

GHC_OPTIONS = -Wall -odir$(OBJECT_DIR) -hidir$(INTERFACE_DIR) \
              -i:$(MODULEPATH):src/Test
             # -threaded
             # -hide-package Haskore   # ignore modules compiled and registered by Cabal


HUGS_MODULES = $(patsubst %, src/%, $(MEDIA)) \
               $(patsubst %, src/Haskore/%, $(MODULES))


TEX_FILES = $(patsubst %, src/Doc/%, \
              Tutorial.tex Discussion.tex Introduction.tex Macros.tex Related.tex)

PICS = equiv haskore midi poly

PDF_PICS = $(patsubst %, src/Doc/Pics/%.pdf, $(PICS))



.INTERMEDIATE:	$(UNLIT_MODULES) PlayTmp.hs

.PHONY:	all clean cabal-configure cabal-build compile ghc-all ghci hugs playmidi \
	pdf autotrack-ps doc \
	test test-compile test-hugs testcases debug \
	jack jack-rt supercollider supercollider-rt scj fluid

all:	compile

clean:
	-(cd build && rm `find . -name "*.hi"` `find . -name "*.o"`)
	-rm $(UNLIT_MODULES)

test:   test-compile testcases pdf autotrack-ps doc

compile:	hugs ghc-all autotrack

test-compile:	test-hugs ghc-all autotrack

# disable optimization for GHC-6.4 and NewResolutions
cabal-configure:
	runhaskell Setup.lhs configure --user --disable-optimization

cabal-build:	cabal-configure
	runhaskell Setup.lhs build

ghc-all:	$(GHC_DEPENDS)
	-mkdir $(OBJECT_DIR)
	ghc --make $(GHC_OPTIONS) $(GHC_DEPENDS)

# start ghci using compiled objects from Cabal's 'dist/build' directory
ghci:	cabal-build
	ghci +RTS -M256m -c30 -RTS -Wall \
	   -odirdist/build -hidirdist/build -i:$(MODULEPATH):src/Test

# start ghci using compiled objects from 'build' directory
ghci-custom:	cabal-configure $(GHC_DEPENDS) ghci-quick

ghci-quick:
	ghci +RTS -M256m -c30 -RTS $(GHC_OPTIONS) $(GHC_DEPENDS)

hugs:	$(HUGS_MODULES)
# this version wouldn't stop on a failure :-(
#	echo ":quit" | hugs $(HUGS_MODULES)
# this worked as long as most of the modules were Haskell 98 compliant
#	hugs -P:$(MODULEPATH) $(HUGS_MODULES)

# for hugs version 2002-11
#	hugs +N -98 -h1000000 -P:$(MODULEPATH) $(HUGS_MODULES)

# for hugs version 2005-03
	hugs -98 -h1000000 -P$(MODULEPATH):$(HUGS_PACKAGE_PATH) $(HUGS_MODULES)

test-hugs:	$(HUGS_MODULES) # hugs
	@echo "***** If in test mode, enter :q in order to continue. *****"
	hugs -98 -h1000000 -P$(MODULEPATH):$(HUGS_PACKAGE_PATH) $(HUGS_MODULES)

doc:	$(HS_MODULES)
	haddock -o docs/html --dump-interface=docs/haskore.haddock -h \
	    $(patsubst %, --use-package=%, $(STDPACKAGES)) \
	    $(HS_MODULES)

olddoc:	$(HS_MODULES)
	haddock -o docs/html --dump-interface=docs/haskore.haddock -h \
	    $(patsubst %, -i /usr/local/share/ghc-6.2/html/libraries/%.haddock, $(STDINTERFACES)) \
	    $(HS_MODULES)


%.hs:	%.lhs
	unlit $< $@


pdf:	$(TEX_FILES) $(PDF_PICS) $(GHC_MODULES)
# src/Doc needed for Tutorial.bbl
	TEXINPUTS=src:src/Doc:$(TEXINPUTS) pdflatex $<
	mkindex Tutorial
	thumbpdf Tutorial
	-ln -s ../Tutorial.pdf docs/Tutorial.pdf

%.pdf:	%.eps
	epstopdf $<

testcases:	src/Test/Suite.lhs	src/Test/Equivalence.lhs
	-rm $(OBJECT_DIR)/Main.o
	ghc --make $(GHC_OPTIONS) -o $(OBJECT_DIR)/test $<
	$(OBJECT_DIR)/test +RTS -M4m -c30 -RTS
#	runhugs +N -98 -h2000000 -P:$(MODULEPATH) Test/Suite.lhs

flip:	src/Haskore/Example/FlipTest.hs
	ghc $(GHC_OPTIONS) -O --make -o $@ $<
#	$@ | timidity -B8,9 -

autotrack:	$(AUTOTRACK_PROG) $(GHC_DEPENDS)
	-rm $(OBJECT_DIR)/Main.o
	ghc $(GHC_OPTIONS) -i:src/Haskore/Interface/AutoTrack/ -O --make -o $@ $<

autotrack-ps:
	cd src/Haskore/Interface/AutoTrack/ && make doc


playmidi:
# install in NEdit menu:
#  cd haskore_dir/src/ ; make playmidi MODULE=%

# doesn't work, because Hugs supports only one visible module at the prompt
#	 echo TestMidi.testTimidity `xargs echo` | hugs +N -98 -h1000000 -P:$(MODULEPATH) Interface/MIDI/TestMidi.lhs $(MODULE)

	echo module Main where > PlayTmp.hs
	echo import TestMidi >> PlayTmp.hs
	MODULE_LHS=`basename $(MODULE) .lhs` && echo import `basename $$MODULE_LHS .hs` >> PlayTmp.hs
	echo main = TestMidi.testTimidity '('`xargs echo`')' >> PlayTmp.hs
	runhugs +N -98 -h1000000 -P:$(MODULEPATH) PlayTmp.hs

jack:
# -n 2 is default, larger values are not supported
	jackd -d alsa -r 44100 -n 3 -d hw:0 &
#	jackd -d alsa -r 44100 -d hw:0 &

jack-stop:
	kill `pgrep jackd`

supercollider:
	(export SC_JACK_DEFAULT_OUTPUTS=alsa_pcm:playback_1,alsa_pcm:playback_2; \
	 scsynth -u 57110 -D 0)

supercollider-stop:
	kill `pgrep scsynth`

scj:	jack supercollider


jack-rt:
# block size 4096 freezes the machine
# more than two buffer blocks (-n 2) are not supported
#	jackd --realtime -d alsa -r 44100 -p 4096 -d hw:0 &
	jackd --realtime -d alsa -r 44100 -d hw:0 &

scj-rt:	jack-rt supercollider
	echo "start with 'sudo make scj-rt'"


jack-sudo:
# causes repeated message "delay of 68264.000 usecs exceeds estimated spare time of 23188.000; restart ..."
#	sudo jackd -R -d alsa -r 44100 -n 2 -d hw:0 &
#	sudo jackd -P 15 -d alsa -r 44100 -n 2 -d hw:0 &
	sudo jackd --realtime -d alsa -r 44100 -n 2 -d hw:0 &

supercollider-sudo:
	echo 'export SC_JACK_DEFAULT_OUTPUTS=alsa_pcm:playback_1,alsa_pcm:playback_2; scsynth -u 57110 -D 0' | sudo bash

scj-sudo:	jack-sudo supercollider-sudo

# start fluidsynth as server
# search fluidsynth port with pmidi -l
# play MIDI files using pmidi -p 128:0 src/Test/MIDI/ChildSong6.mid
fluid:
	fluidsynth -a jack -j --verbose /usr/share/sounds/sf2/Vintage_Dreams_Waves_v2.sf2


debug:
	echo $(GHC_DEPENDS)
