
-- return the window size
function getWindowSize()
	return 818, 318
end

-- return the main font
-- the return is a list of font filename and size options
-- the first one found will be used
function getFont()
	if isMac then
		return { { name="Monaco.dfont", size=12 } }
	else
		return { { name="arial.ttf", size=12 } }
	end
end
-- return the label font
function getLabelFont()
	if isMac then
		return { { name="GillSans.dfont", size=11 }, { name="Monaco.dfont", size=9 } }
	else
		return { { name="tahoma.ttf", size=11 }, { name="arial.ttf", size=9 } }
	end
end
-- return the text field font
function getTextFieldFont()
	if isMac then
		return { { name="GillSans.dfont", size=12 }, { name="Monaco.dfont", size=10 } }
	else
		return { { name="tahoma.ttf", size=12 }, { name="arial.ttf", size=10 } }
	end
end

-- create and lay out all the controls
function createUI()

	-- load textures
	atlas = texture( "buttons.png" )
	atlas_n = texture( "buttons_n.png" )
	background = texture( "bgtile.png" )
	background_n = texture( "bgtile_n.png" )
	setBackgroundTexture( background, background_n )

	-- constants
	local kKnobSize = 37
	local kKnobSpace = 48
	local kTextFieldH = 12
	local kMeterW = 5
	local kMeterH = 81
	local pad = 10.0
	local ww, wh = getWindowSize()
	local kInfoW = 115

	-- make renderers
	theKnobRenderer = knobRenderer( atlas, atlas_n, 1, 1, kKnobSize )

	-- set window background colour
	setBackgroundColour( 0.22, 0.05, 0.2 )

	-- set location of the banner
	setBannerPosition( wh - 30 )

	-- set outline colours for groups
	setGroupActiveColour( 0.8, 0.75, 0.7, 0.8 )
	setGroupInactiveColour( 0.5, 0.5, 0.7, 0.5 )
	
	local function knobAndTextField( group, param, label, x, y, size, textH, textW )
		textW = textW or size
		local knobx = x + 0.5 * ( textW - size )
		group:add( knob( param, "", knobx, y+textH+1, size ) )
		group:add( textField( param, label, x, y, textW, textH ) )
	end

	-- make groups and knobs
	--

	mixGroup = group( "Mix" )
	knobAndTextField( mixGroup, "Dry Level",			"Dry",		0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( mixGroup, "Wet Level",			"Wet",		1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( mixGroup, "Osc Level",			"Osc",		2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( mixGroup, "Dry Ring Mod Level", 	"Dry RM",	3*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( mixGroup, "Wet Ring Mod Level", 	"Wet RM",	4*kKnobSpace, 0, kKnobSize, kTextFieldH )

	oscGroup = group( "Pitch" )
	knobAndTextField( oscGroup, "Pitch Offset",				"Pitch",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscGroup, "Pitch Offset Sweepable",	"Sweep",	1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscGroup, "Sync Cycles",				"Sync",		2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscGroup, "Osc Pitch",				"Osc",		3*kKnobSpace, 0, kKnobSize, kTextFieldH )

	envGroup = group( "Envelope" )
	knobAndTextField( envGroup, "Env Pre Gain",		"Gain",			0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envGroup, "Env Attack",		"Attack",		1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envGroup, "Env Release",		"Release",		2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envGroup, "Env Gate",			"Gate",			3*kKnobSpace, 0, kKnobSize, kTextFieldH )

	envModGroup = group( "Env Mod" )
	knobAndTextField( envModGroup, "Osc Env Follow", 	"Osc Env",		0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envModGroup, "Trigger Level",		"Trigger",		1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envModGroup, "Pitch Env Depth", 	"Pitch",		2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envModGroup, "Filter Env Depth",	"Filter",		3*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( envModGroup, "PWM Env Depth",		"PWM",			4*kKnobSpace, 0, kKnobSize, kTextFieldH )

	infilterGroup = group( "Input Filter" )
	knobAndTextField( infilterGroup, "Highpass Cutoff",			"Highpass",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( infilterGroup, "Lowpass Cutoff",			"Lowpass",	1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( infilterGroup, "Use Filtered For Dry", 	"Filt Dry", 2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( infilterGroup, "Use Filtered For Wet", 	"Filt Wet", 3*kKnobSpace, 0, kKnobSize, kTextFieldH )

	filterGroup = group( "Filter" )
	knobAndTextField( filterGroup, "Filter Cutoff",		"Cutoff",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( filterGroup, "Filter Q",			"Q",		1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( filterGroup, "Filter Type",		"Type",		2*kKnobSpace, 0, kKnobSize, kTextFieldH )

	pitchLfoGroup = group( "Pitch LFO" )
	knobAndTextField( pitchLfoGroup, "Pitch LFO Shape",			"Shape",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( pitchLfoGroup, "Pitch LFO Speed",			"Speed",	1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( pitchLfoGroup, "Pitch LFO Amount",		"Amount",	2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( pitchLfoGroup, "Pitch LFO Amount Fine",	"Fine",		3*kKnobSpace, 0, kKnobSize, kTextFieldH )

	filterLfoGroup = group( "Filter LFO" )
	knobAndTextField( filterLfoGroup, "Filter LFO Shape",	"Shape",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( filterLfoGroup, "Filter LFO Speed",	"Speed",	1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( filterLfoGroup, "Filter LFO Amount",	"Amount",	2*kKnobSpace, 0, kKnobSize, kTextFieldH )

	pwmLfoGroup = group( "PWM LFO" )
	knobAndTextField( pwmLfoGroup, "PWM LFO Shape",		"Shape",	0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( pwmLfoGroup, "PWM LFO Speed",		"Speed",	1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( pwmLfoGroup, "PWM LFO Amount",	"Amount",	2*kKnobSpace, 0, kKnobSize, kTextFieldH )

	oscMixGroup = group( "Oscillator" )
	knobAndTextField( oscMixGroup, "Triangle",		"Tri",		0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscMixGroup, "Saw",			"Saw",		1*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscMixGroup, "Square",		"Square",	2*kKnobSpace, 0, kKnobSize, kTextFieldH )
	knobAndTextField( oscMixGroup, "Pulse Width",	"PWM",		3*kKnobSpace, 0, kKnobSize, kTextFieldH )

	miscGroup = group( "OSC" )
	knobAndTextField( miscGroup, "OSC Port Offset",	"Port",		0*kKnobSpace, 0, kKnobSize, kTextFieldH )
	
	-- positions!

	local pad = 10

	local xbase = 20
	local ybase = 30
	local x = xbase
	local y = ybase

	oscMixGroup:setPosition( x, y )
	x = x + oscMixGroup:width() + pad

	oscGroup:setPosition( x, y )
	x = x + oscGroup:width() + pad

	local infoX = x - 10
	local infoY = y - 10
	x = x + kInfoW + pad

	mixGroup:setPosition( x, y )
	x = x + mixGroup:width() + pad

	x = xbase
	y = y + mixGroup:height() + pad

	infilterGroup:setPosition( x, y )
	x = x + infilterGroup:width() + pad

	envGroup:setPosition( x, y )
	x = x + envGroup:width() + pad

	local meterX = x - 10
	local meterY = y - 20
	x = x + 5 * kMeterW + pad

	envModGroup:setPosition( x, y )
	x = x + envModGroup:width() + pad

	x = xbase
	y = y + filterGroup:height() + pad

	pitchLfoGroup:setPosition( x, y )
	x = x + pitchLfoGroup:width() + pad

	filterGroup:setPosition( x, y )
	x = x + filterGroup:width() + pad

	filterLfoGroup:setPosition( x, y )
	x = x + filterLfoGroup:width() + pad

	pwmLfoGroup:setPosition( x, y )
	x = x + pwmLfoGroup:width() + pad

	miscGroup:setPosition( x, y )

	-- add directly positioned objects
	--

	x = infoX
	y = infoY

	-- add the prefs button
	add( button( "Prefs", "Prefs", x, y, kInfoW, 30 ) )
	y = y + 40

	-- add the info display object
	add( infoDisplay( x, y, kInfoW, 40 ) )

	-- meters
	
	x = meterX
	y = meterY
	
	meters = levelMeters( atlas, 128-5, 0, kMeterW, kMeterH )
	meters:add( "peak", 0, x, y )
	x = x + kMeterW + 1
	meters:add( "peak", 1, x, y )
	x = x + kMeterW
	x = x + kMeterW
	meters:add( "envelope", 0, x, y )
	x = x + kMeterW + 1
	meters:add( "envelope", 1, x, y )
	x = x + kMeterW

end		-- of createUI()
