Import([
	'env',
	'sourceDir',
])

import os
import ctypes

class espeak_VOICE(ctypes.Structure):
	_fields_=[
		('name',ctypes.c_char_p),
		('languages',ctypes.c_char_p),
		('identifier',ctypes.c_char_p),
		('gender',ctypes.c_byte),
		('age',ctypes.c_byte),
		('variant',ctypes.c_byte),
		('xx1',ctypes.c_byte),
		('score',ctypes.c_int),
		('spare',ctypes.c_void_p),
	]

env=env.Clone()
env.Append(CCFLAGS='/W0')
env.Append(CPPDEFINES=[('BUILDING_DLL',1)])
env.Prepend(CPPPATH='#include/espeak/platforms/windows/windows_dll/src')

_espeakInstance=None
def espeak_compileDict_action(target,source,env):
	global _espeakInstance
	if not _espeakInstance:
		_espeakInstance=ctypes.cdll.LoadLibrary(espeakLib[0].abspath)
		_espeakInstance.espeak_Initialize(0,0,synthDriversDir.abspath,0x8000)
	lang=source[0].name.split('_')[0]
	v=espeak_VOICE(languages=lang+'\x00')
	if _espeakInstance.espeak_SetVoiceByProperties(ctypes.byref(v))!=0:
		print "espeak_compileDict_action: failed to switch to language %s, skipping compilation"%lang
		return
	dictPath=os.path.split(source[0].abspath)[0]+'/'
	if _espeakInstance.espeak_CompileDictionary(dictPath,None,0)!=0:
		return 1

synthDriversDir=sourceDir.Dir('synthDrivers')
espeakDataDir=synthDriversDir.Dir('espeak-data')
tempSrcDir=Dir('src')

#make a temp copy of src, but using the windows dll version of speech.h
winFiles=['speech.h','stdafx.h']
for f in env.Glob('#include/espeak/src/*'):
	if f.name.lower() in winFiles: continue
	env.Command(tempSrcDir.File(f.name),f,Copy('$TARGET','$SOURCE'))
for f in winFiles:
	env.Command(tempSrcDir.File(f),File('#include/espeak/platforms/windows/windows_dll/src/%s'%f),Copy('$TARGET','$SOURCE'))

espeakLib=env.SharedLibrary(
	target='espeak',
	srcdir=tempSrcDir.name,
	source=[
		"speak_lib.cpp",
		"readclause.cpp",
		"compiledict.cpp",
		"dictionary.cpp",
		"intonation.cpp",
		"setlengths.cpp",
		"numbers.cpp",
		"synth_mbrola.cpp",
		"synthdata.cpp",
		"synthesize.cpp",
		"translate.cpp",
		"tr_languages.cpp",
		"voices.cpp",
		"wavegen.cpp",
		"espeak_command.cpp",
		"event.cpp",
		"fifo.cpp",
		"wave.cpp",	"debug.cpp",
		"phonemelist.cpp",
		"klatt.cpp",
		"sonic.cpp",
	],
	LIBS=['advapi32'],
)

dictDeps=[espeakLib]

#Make a copy of espeak-data, though excluding existing precompiled dict files
sourceDataPath=Dir('#include/espeak/espeak-data').abspath
for topDir,subDirs,files in os.walk(sourceDataPath):
	relTopDir=os.path.relpath(topDir,sourceDataPath)
	for f in files:
		if(topDir==sourceDataPath) and f.lower().endswith('_dict'): continue
		fNode=espeakDataDir.Dir(relTopDir).File(f)
		dictDeps.append(fNode)
		env.Command(fNode,Dir(topDir).File(f),Copy('$TARGET','$SOURCE'))
	if len(files)==0:
		env.Command(espeakDataDir.Dir(relTopDir),Dir(topDir),Mkdir('$TARGET'))

#Copy in the extra variants
for f in env.Glob('variants/*'):
	env.Command(espeakDataDir.File('voices/!v/%s'%f.name),f,Copy('$TARGET','$SOURCE'))

#Compile all dictionaries
for f in env.Glob('#include/espeak/dictsource/*_rules'):
	extras=[f.File(f.name.split('_')[0]+x) for x in '_list','_listx']
	dictFile=env.Command(espeakDataDir.File(f.name.split('_')[0]+'_dict'),[f,[x for x in extras if os.path.isfile(x.abspath)]],espeak_compileDict_action)
	env.Depends(dictFile,dictDeps)
	#Dictionaries can not be compiled in parallel, force SCons not to do this
	env.SideEffect('_espeak_compileDict',dictFile)

env.Requires(synthDriversDir,espeakDataDir)
env.Install(synthDriversDir,espeakLib)
env.Clean(espeakDataDir,espeakDataDir)
