--[[
ģƣƵ
ģ鹦ܣdtmf롢ttsҪײ֧֣ƵļĲźֹͣ¼micspeakerĿ
ģ޸ʱ䣺2017.02.20
]]

--ģ,
local base = _G
local string = require"string"
local io = require"io"
local rtos = require"rtos"
local audio = require"audiocore"
local sys = require"sys"
local ril = require"ril"
module(...)

--سõȫֺ
local smatch = string.match
local print = base.print
local dispatch = sys.dispatch
local req = ril.request
local tonumber = base.tonumber
local assert = base.assert

--speakervolspeakerȼȡֵΧΪaudio.VOL0audio.VOL7audio.VOL0Ϊ
--audiochannelƵͨӲйأûҪӲ
--microphonevolmicȼȡֵΧΪaudio.MIC_VOL0audio.MIC_VOL15audio.MIC_VOL0Ϊ
local speakervol,audiochannel,microphonevol = audio.VOL4,audio.HANDSET,audio.MIC_VOL15
local ttscause
--Ƶļ·
local playname

--[[
print
  ӡӿڣļедӡaudioǰ׺
  
ֵ
]]
local function print(...)
	base.print("audio",...)
end

--[[
playtts
  tts
  
		textַ
		path"net"ʾ粥ţֵʾز
ֵtrue
]]
local function playtts(text,path)
	local action = path == "net" and 4 or 2

	req("AT+QTTS=1")
	req(string.format("AT+QTTS=%d,\"%s\"",action,text))
	return true
end

--[[
stoptts
  ֹͣtts
  
ֵ
]]
local function stoptts()
	req("AT+QTTS=3")
end

--[[
closetts
  رtts
  
		causeرԭ
ֵ
]]
local function closetts(cause)
	ttscause = cause
	req("AT+QTTS=0")
end

--[[
beginrecord
  ʼ¼
  
		id¼idid洢¼ļȡֵΧ0-4
		duration¼ʱλ
ֵtrue
]]
function beginrecord(id,duration)
	req(string.format("AT+AUDREC=0,0,1," .. id .. "," .. duration))
	return true
end

--[[
endrecord
  ¼
  
		id¼idid洢¼ļȡֵΧ0-4
		duration¼ʱλ
ֵtrue
]]
function endrecord(id,duration)
	req(string.format("AT+AUDREC=0,0,0," .. id .. "," .. duration))
	return true
end

--[[
delrecord
  ɾ¼ļ
  
		id¼idid洢¼ļȡֵΧ0-4
		duration¼ʱλ
ֵtrue
]]
function delrecord(id,duration)
	req(string.format("AT+AUDREC=0,0,4," .. id .. "," .. duration))
	return true
end

--[[
playrecord
  ¼ļ
  
		dlģУֱȣǷ¼ŵtruefalsenil
		loopǷѭţtrueΪѭfalsenilΪѭ
		id¼idid洢¼ļȡֵΧ0-4
		duration¼ʱλ
ֵtrue
]]
local function playrecord(dl,loop,id,duration)
	req(string.format("AT+AUDREC=" .. (dl and 1 or 0) .. "," .. (loop and 1 or 0) .. ",2," .. id .. "," .. duration))
	return true
end

--[[
stoprecord
  ֹͣ¼ļ
  
		dlģУֱȣǷ¼ŵtruefalsenil
		loopǷѭţtrueΪѭfalsenilΪѭ
		id¼idid洢¼ļȡֵΧ0-4
		duration¼ʱλ
ֵtrue
]]
local function stoprecord(dl,loop,id,duration)
	req(string.format("AT+AUDREC=" .. (dl and 1 or 0) .. "," .. (loop and 1 or 0) .. ",3," .. id .. "," .. duration))
	return true
end

--[[
_play
  Ƶļ
  
		nameƵļ·
		loopǷѭţtrueΪѭfalsenilΪѭ
ֵòŽӿǷɹtrueΪɹfalseΪʧ
]]
local function _play(name,loop)
	if loop then playname = name end
	return audio.play(name)
end

--[[
_stop
  ֹͣƵļ
  
ֵֹͣŽӿǷɹtrueΪɹfalseΪʧ
]]
local function _stop()
	playname = nil
	return audio.stop()
end

--[[
audiourc
  ģڡעĵײcoreͨ⴮ϱ֪ͨĴ
  
		dataַ֪ͨϢ
		prefix֪ͨǰ׺
ֵ
]]
local function audiourc(data,prefix)	
	--¼¼Ź
	if prefix == "+AUDREC" then
		local action,duration = string.match(data,"(%d),(%d+)")
		if action and duration then
			duration = base.tonumber(duration)
			--ʼ¼
			if action == "1" then
				dispatch("AUDIO_RECORD_IND",(duration > 0 and true or false),duration)
			--¼
			elseif action == "2" then
				if duration > 0 then
					playend()
				else
					playerr()
				end
			--ɾ¼
			--[[elseif action == "4" then
				dispatch("AUDIO_RECORD_IND",true,duration)]]
			end
		end
	--tts
	elseif prefix == "+QTTS" then
		local flag = string.match(data,": *(%d)",string.len(prefix)+1)
		--ֹͣtts
		if flag == "0" --[[or flag == "1"]] then
			playend()
		end	
	end
end

--[[
audiorsp
  ģڡͨ⴮ڷ͵ײcoreATӦ
  
		cmdӦӦAT
		successATִнtruefalse
		responseATӦеִнַ
		intermediateATӦемϢ
ֵ
]]
local function audiorsp(cmd,success,response,intermediate)
	local prefix = smatch(cmd,"AT(%+%u+%?*)")

	--¼߲¼ȷӦ
	if prefix == "+AUDREC" then
		local action = smatch(cmd,"AUDREC=%d,%d,(%d)")		
		if action=="1" then
			dispatch("AUDIO_RECORD_CNF",success)
		elseif action=="3" then
			recordstopind()
		end
	--tts߹رttsӦ
	elseif prefix == "+QTTS" then
		local action = smatch(cmd,"QTTS=(%d)")
		if not success then
			if action == "1" or action == "2" then
				playerr()
			end
		else
			if action == "0" then
				dispatch("TTS_CLOSE_IND",ttscause)
			end
		end
		if action=="3" then
			ttstopind()
		end
	end
end

--ע֪ͨĴ
ril.regurc("+AUDREC",audiourc)
ril.regurc("+QTTS",audiourc)
--עATӦ
ril.regrsp("+AUDREC",audiorsp,0)
ril.regrsp("+QTTS",audiorsp,0)

--[[
setspeakervol
  Ƶͨ
  
		volȼȡֵΧΪaudiocore.VOL0audiocore.VOL7audiocore.VOL0Ϊ
ֵ
]]
function setspeakervol(vol)
	audio.setvol(vol)
	speakervol = vol
end

--[[
getspeakervol
  ȡƵͨ
  
ֵȼ
]]
function getspeakervol()
	return speakervol
end

--[[
setaudiochannel
  Ƶͨ
  
		channelƵͨӲйأûҪӲãĿǰģ֧audiocore.LOUDSPEAKER
ֵ
]]
local function setaudiochannel(channel)
	audio.setchannel(channel)
	audiochannel = channel
end

--[[
getaudiochannel
  ȡƵͨ
  
ֵƵͨ
]]
local function getaudiochannel()
	return audiochannel
end

--[[
setloopback
  ûػ
  
		flagǷ򿪻ػԣtrueΪ򿪣falseΪر
		typԻػƵͨӲйأûҪӲ
		setvolǷtrueΪãfalse
		vol
ֵtrueóɹfalseʧ
]]
function setloopback(flag,typ,setvol,vol)
	return audio.setloopback(flag,typ,setvol,vol)
end

--[[
setmicrophonegain
  MIC
  
		volmicȼȡֵΧΪaudio.MIC_VOL0audio.MIC_VOL15audio.MIC_VOL0Ϊ
ֵ
]]
function setmicrophonegain(vol)
	audio.setmicvol(vol)
	microphonevol = vol
end

--[[
getmicrophonegain
  ȡMICȼ
  
ֵȼ
]]
function getmicrophonegain()
	return microphonevol
end

--[[
audiomsg
  ײϱrtos.MSG_AUDIOⲿϢ
  
		msgplay_end_indǷŽ
		     play_error_indǷ񲥷Ŵ
ֵ
]]
local function audiomsg(msg)
	if msg.play_end_ind == true then
		if playname then audio.play(playname) return end
		playend()
	elseif msg.play_error_ind == true then
		if playname then playname = nil end
		playerr()
	end
end

local ttsState,ttsText,ttsCbFnc = "IDLE"
function playTTS(text,vol,speed,cbFnc)
	if vol then setspeakervol(vol) end
	audio.openTTS(speed or 50)
	ttsState,ttsText,ttsCbFnc = "OPENING",text,cbFnc
end

function stopTTS(cbFnc)
	print("stopTTS",ttsState)
	if ttsState=="PLAYING" then
		audio.stopTTS()
		ttsState,ttsCbFnc = "STOPING_USER",cbFnc
	else
		cbFnc(true)
	end
end

local function ttsMsg(msg)
	print("ttsMsg",msg.type,msg.result,ttsState)
	
	if msg.type==0 then
		local state = ttsState
		ttsState = "IDLE"
		if ttsCbFnc and state then ttsCbFnc(state:match("ERR")==nil) end
	elseif msg.type==1 then
		if ttsState=="OPENING" then
			if msg.result then
				audio.playTTS(ttsText)
				ttsState = "PLAYING"
			else
				ttsState = "IDLE"
				if ttsCbFnc then ttsCbFnc(false) end
			end			
		end
	elseif msg.type==2 then
		if ttsState=="PLAYING" then
			audio.stopTTS()
			ttsState = "STOPING_"..(msg.result and "SUC" or "ERR")
		end
	elseif msg.type==3 then
		audio.closeTTS()
		ttsState = string.gsub(ttsState,"STOPING","CLOSING")
	end
end

--עײϱrtos.MSG_AUDIOⲿϢĴ
sys.regmsg(rtos.MSG_AUDIO,audiomsg)
sys.regmsg(rtos.MSG_TTS,ttsMsg)

--ĬƵͨΪLOUDSPEAKERΪĿǰģֻ֧LOUDSPEAKERͨ
setaudiochannel(audio.LOUDSPEAKER)
--ĬȼΪ44мȼΪ0Ϊ7
setspeakervol(audio.VOL4)
--ĬMICȼΪ1Ϊ0Ϊ15
setmicrophonegain(audio.MIC_VOL1)


--spriorityǰŵƵȼ
--stypǰŵƵ
--spathǰŵƵļ·
--svolǰ
--scbǰŽ߳Ļص
--sdupǰŵƵǷҪظ
--sduprdsdupΪtrueֵʾظŵļ(λ)Ĭ޼
--spendingҪŵƵǷҪڲŵƵ첽ٲ
--sstrategyȼͬʱĲŲԣ0(ʾڲŵƵ󲥷ŵƵ)1(ʾֹͣڲŵƵ󲥷ŵƵ)
local spriority,styp,spath,svol,scb,sdup,sduprd,sstrategy

--[[
playbegin
  رϴβźٲű
  
		priorityƵȼֵԽСȼԽ
		typƵͣĿǰ֧"FILE""TTS""TTSCC""RECORD"
		pathƵļ·
		volȡֵΧaudiocore.VOL0audiocore.VOL7˲ѡ
		cbƵŽ߳ʱĻصصʱһ0ʾųɹ1ʾų2ʾȼûвš˲ѡ
		dupǷѭţtrueѭfalsenilѭ˲ѡ
		duprdż(λ)dupΪtrueʱֵ塣˲ѡ
ֵóɹtrue򷵻nil
]]
local function playbegin(priority,typ,path,vol,cb,dup,duprd)
	print("playbegin")
	--¸ֵǰŲ
	spriority,styp,spath,svol,scb,sdup,sduprd,spending = priority,typ,path,vol,cb,dup,duprd

	--
	if vol then
		setspeakervol(vol)
    end
	
	--òŽӿڳɹ
	if (typ=="TTS" and playtts(path))
		or (typ=="TTSCC" and playtts(path,"net"))
		or (typ=="RECORD" and playrecord(true,false,tonumber(smatch(path,"(%d+)&")),tonumber(smatch(path,"&(%d+)"))))
		or (typ=="FILE" and _play(path,dup and (not duprd or duprd==0))) then
		return true
	--òŽӿʧ
	else
		spriority,styp,spath,svol,scb,sdup,sduprd,spending = nil
	end
end

--[[
setstrategy
  ȼͬʱĲŲ
  
		strategyȼͬʱĲŲ
				0ʾڲŵƵ󲥷ŵƵ
				1ʾֹͣڲŵƵ󲥷ŵƵ
ֵ
]]
function setstrategy(strategy)
	sstrategy=strategy
end

--[[
play
  Ƶ
  
		prioritynumberͣѡƵȼֵԽȼԽ
		typstringͣѡƵͣĿǰ֧"FILE""TTS""TTSCC""RECORD"
		pathѡƵļ·typйأ
		      typΪ"FILE"ʱstringͣʾƵļ·
			  typΪ"TTS"ʱstringͣʾҪݵUCS2ʮַ
			  typΪ"TTSCC"ʱstringͣʾҪŸͨԶݵUCS2ʮַ
			  typΪ"RECORD"ʱstringͣʾ¼ID&¼ʱ룩
		volnumberͣѡȡֵΧaudiocore.VOL0audiocore.VOL7
		cbfunctionͣѡƵŽ߳ʱĻصصʱһ0ʾųɹ1ʾų2ʾȼûв
		dupboolͣѡǷѭţtrueѭfalsenilѭ
		duprdnumberͣѡż(λ)dupΪtrueʱֵ
ֵóɹtrue򷵻nil
]]
function play(priority,typ,path,vol,cb,dup,duprd)
	assert(priority and typ,"play para err")
	print("play",priority,typ,path,vol,cb,dup,duprd,styp)
	--Ƶڲ
	if styp then
		--ҪŵƵȼ  ڲŵƵȼ
		if priority > spriority or (sstrategy==1 and priority==spriority) then
			--ڲŵƵлصִлص2
			if scb then scb(2) end
			--ֹͣڲŵƵ
			if not stop() then
				spriority,styp,spath,svol,scb,sdup,sduprd,spending = priority,typ,path,vol,cb,dup,duprd,true
				return
			end
		--ҪŵƵȼ  ڲŵƵȼ
		elseif priority < spriority or (sstrategy~=1 and priority==spriority) then
			if not sdup then return	end	
		end
	end

	playbegin(priority,typ,path,vol,cb,dup,duprd)
end

--[[
stop
  ֹͣƵ
  
ֵԳɹֹͬͣtrue򷵻nil
]]
function stop()
	if styp then
		local typ,path = styp,spath		
		spriority,styp,spath,svol,scb,sdup,sduprd,spending = nil
		--ֹͣѭŶʱ
		sys.timer_stop_all(play)
		--ֹͣƵ
		_stop()
		if typ=="TTS" or typ=="TTSCC" then stoptts() return end
		if typ=="RECORD" then stoprecord(true,false,tonumber(smatch(path,"(%d+)&")),tonumber(smatch(path,"&(%d+)"))) return end
	end
	return true
end

--[[
playend
  Ƶųɹ
  
ֵ
]]
function playend()
	print("playend",sdup,sduprd)
	if (styp=="TTS" or styp=="TTSCC") and not sdup then stoptts() end
	if styp=="RECORD" and not sdup then stoprecord(true,false,tonumber(smatch(spath,"(%d+)&")),tonumber(smatch(spath,"&(%d+)"))) end
	--Ҫظ
	if sdup then
		--ظż
		if sduprd then
			sys.timer_start(play,sduprd,spriority,styp,spath,svol,scb,sdup,sduprd)
		--ظż
		elseif styp=="TTS" or styp=="TTSCC" or styp=="RECORD" then
			play(spriority,styp,spath,svol,scb,sdup,sduprd)
		end
	--Ҫظ
	else
		--ڲŵƵлصִлص0
		if scb then scb(0) end
		spriority,styp,spath,svol,scb,sdup,sduprd,spending = nil
	end
end

--[[
playerr
  Ƶʧܴ
  
ֵ
]]
function playerr()
	print("playerr")
	if styp=="TTS" or styp=="TTSCC" then stoptts() end
	if styp=="RECORD" then stoprecord(true,false,tonumber(smatch(spath,"(%d+)&")),tonumber(smatch(spath,"&(%d+)"))) end
	--ڲŵƵлصִлص1
	if scb then scb(1) end
	spriority,styp,spath,svol,scb,sdup,sduprd,spending = nil
end

local stopreqcb
--[[
audstopreq
  libű䷢ϢAUDIO_STOP_REQĴ
  
		cbƵֹͣĻص
ֵ
]]
local function audstopreq(cb)
	if stop() and cb then cb() return end
	stopreqcb = cb
end

--[[
ttstopind
  stoptts()ӿںttsֹͣźϢ
  
ֵ
]]
function ttstopind()
	print("ttstopind",spending,stopreqcb)
	if stopreqcb then
		stopreqcb()
		stopreqcb = nil
	elseif spending then
		playbegin(spriority,styp,spath,svol,scb,sdup,sduprd)
	end
end

--[[
recordstopind
  stoprecord()ӿںrecordֹͣźϢ
  
ֵ
]]
function recordstopind()
	print("recordstopind",spending,stopreqcb)
	if stopreqcb then
		stopreqcb()
		stopreqcb = nil
	elseif spending then
		playbegin(spriority,styp,spath,svol,scb,sdup,sduprd)
	end
end

local procer =
{
	AUDIO_STOP_REQ = audstopreq,--libűͨϢʵƵֹͣûűҪʹϢ
}
--עϢ
sys.regapp(procer)
