diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/dto/Request.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/dto/Request.kt index 50691af..124e7a2 100644 --- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/dto/Request.kt +++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/dto/Request.kt @@ -12,21 +12,30 @@ class Request private constructor( init { val body = extractBody(request) - val pathParams = extractPathParams(matchingResult) + val pathParameters = extractPathParameters(matchingResult) + val queryVariables = extractQueryVariables(request) luaTable.set("body", body) - luaTable.set("params", pathParams) + luaTable.set("query", queryVariables) + luaTable.set("path", pathParameters) } - private fun extractPathParams(matchingResult: UriTemplate.MatchingResult) = - LuaValue.tableOf().also { params -> + private fun extractPathParameters(matchingResult: UriTemplate.MatchingResult) = + LuaValue.tableOf().also { table -> matchingResult.variables .map { LuaValue.valueOf(it.key) to LuaValue.valueOf(it.value) } - .forEach { params.set(it.first, it.second) } + .forEach { table.set(it.first, it.second) } } + private fun extractQueryVariables(request: NanoHTTPD.IHTTPSession) = + LuaValue.tableOf().also { table -> + request.parms + .map { LuaValue.valueOf(it.key) to LuaValue.valueOf(it.value) } + .forEach { table.set(it.first, it.second) } + } + private fun extractBody(request: NanoHTTPD.IHTTPSession) = mutableMapOf().let { request.parseBody(it) diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/initializer/ScriptsInitializer.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/initializer/ScriptsInitializer.kt index 68af200..4235beb 100644 --- a/app/src/main/java/com/bartlomiejpluta/ttsserver/initializer/ScriptsInitializer.kt +++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/initializer/ScriptsInitializer.kt @@ -50,7 +50,9 @@ class ScriptsInitializer(private val context: Context, private val preferences: private const val INITIALIZED_FLAG = "flag_initialized" private val endpoints = mapOf( "say.lua" to R.raw.say, - "file.lua" to R.raw.file + "file.lua" to R.raw.file, + "sonos.lua" to R.raw.sonos, + "cache.lua" to R.raw.cache ) } } \ No newline at end of file diff --git a/app/src/main/res/raw/cache.lua b/app/src/main/res/raw/cache.lua new file mode 100644 index 0000000..6f8f9f3 --- /dev/null +++ b/app/src/main/res/raw/cache.lua @@ -0,0 +1,15 @@ +return { + uri = "/cache/{filename}.{ext}", + method = Method.GET, + consumer = function(request) + local filename = string.format("%s.%s", request.path.filename, request.path.ext) + local file = cache.file(filename) + local mime = Mime[request.path.ext:upper()] + + return { + mime = mime, + cached = true, + data = file + } + end +} \ No newline at end of file diff --git a/app/src/main/res/raw/file.lua b/app/src/main/res/raw/file.lua index 30b75a4..c1bc417 100644 --- a/app/src/main/res/raw/file.lua +++ b/app/src/main/res/raw/file.lua @@ -1,17 +1,16 @@ return { - uri = "/{format}", - method = Method.POST, - accepts = Mime.JSON, + uri = "/tts.{ext}", + method = Method.GET, consumer = function(request) - local body = json.decode(request.body) - local format = (request.params.format or "WAV"):upper() + local format = (request.path.ext or "wav"):upper() local audioFormat = AudioFormat[format] local mime = Mime[format] - local file = tts.sayToFile(body.text, body.language or "en", audioFormat) + local file = tts.sayToFile(request.query.phrase, request.query.lang or "en", audioFormat) return { mime = mime, + cached = false, data = file } end diff --git a/app/src/main/res/raw/sonos.lua b/app/src/main/res/raw/sonos.lua new file mode 100644 index 0000000..6006d17 --- /dev/null +++ b/app/src/main/res/raw/sonos.lua @@ -0,0 +1,47 @@ +local announcementUrl = "http://" .. server.address .. ":8080/cache" +local snapshot = nil + +function prepareTTSFile(phrase, language) + local file = tts.sayToFile(phrase, language, AudioFormat.MP3) + return announcementUrl .. "/" .. file:getName() +end + +function updateSnapshotIfFirst(device) + if(snapshot == nil) then + snapshot = device:snapshot() + end +end + +function announce(device, data, url) + device:stop() + device:setVolume(data.volume) + device:playUri(url, "") + while(device:getPlayState():name() ~= "STOPPED") do + thread.sleep(500) + end +end + +function restoreSnapshotIfLast(queueLength) + if(queueLength() == 0) then + if(snapshot ~= nil) then + snapshot:restore() + snapshot = nil + end + end +end + +return { + uri = "/sonos", + method = Method.POST, + accepts = Mime.JSON, + queued = true, + consumer = function(request, queueLength) + local body = json.decode(request.body) + local zone = config.sonosDevices[body.zone] + + local url = prepareTTSFile(body.text, body.language or "en") + updateSnapshotIfFirst(zone) + announce(zone, body, url) + restoreSnapshotIfLast(queueLength) + end +} \ No newline at end of file