Refactor io.bartek.ttsserver.sonos package
This commit is contained in:
@@ -7,7 +7,7 @@ import androidx.preference.PreferenceManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.bartek.ttsserver.service.ForegroundNotificationFactory
|
||||
import io.bartek.ttsserver.sonos.SonosQueue
|
||||
import io.bartek.ttsserver.sonos.queue.SonosQueue
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
import io.bartek.ttsserver.tts.status.TTSStatusHolder
|
||||
import io.bartek.ttsserver.util.NetworkUtil
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package io.bartek.ttsserver.sonos
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import com.vmichalak.sonoscontroller.SonosDiscovery
|
||||
import io.bartek.ttsserver.preference.PreferenceKey
|
||||
import io.bartek.ttsserver.service.ForegroundService
|
||||
import io.bartek.ttsserver.service.ServiceState
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
import io.bartek.ttsserver.util.NetworkUtil
|
||||
import io.bartek.ttsserver.web.dto.BaseDTO
|
||||
import java.util.concurrent.BlockingQueue
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
||||
private class Consumer(
|
||||
private val tts: TTSEngine,
|
||||
private val host: String,
|
||||
private val port: Int,
|
||||
private val queue: BlockingQueue<BaseDTO>
|
||||
) : Runnable {
|
||||
|
||||
override fun run() = try {
|
||||
while (ForegroundService.state == ServiceState.RUNNING) {
|
||||
consume(queue.take())
|
||||
}
|
||||
} catch (e: InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
|
||||
|
||||
private fun consume(data: BaseDTO) =
|
||||
SonosDiscovery.discover().firstOrNull { it.zoneGroupState.name == data.zone }?.let {
|
||||
val file = tts.createTTSFile(data.text, data.language)
|
||||
val filename = file.name
|
||||
val url = "http://$host:$port/sonos/$filename"
|
||||
val currentVolume = it.volume
|
||||
it.volume = data.volume
|
||||
it.clip(url, "")
|
||||
it.volume = currentVolume
|
||||
}
|
||||
}
|
||||
|
||||
class SonosQueue(
|
||||
private val tts: TTSEngine,
|
||||
private val networkUtil: NetworkUtil,
|
||||
private val preferences: SharedPreferences
|
||||
) {
|
||||
private val queue: BlockingQueue<BaseDTO> = LinkedBlockingQueue()
|
||||
private val host: String
|
||||
get() = networkUtil.getIpAddress()
|
||||
private val port: Int
|
||||
get() = preferences.getInt(PreferenceKey.PORT, 8080)
|
||||
private var consumer: Thread? = null
|
||||
|
||||
fun run() {
|
||||
consumer?.interrupt()
|
||||
consumer = Thread(Consumer(tts, host, port, queue)).also { it.name = "SonosQueue" }
|
||||
consumer?.start()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
consumer?.interrupt()
|
||||
consumer = null
|
||||
}
|
||||
|
||||
fun push(data: BaseDTO) = queue.add(data)
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
package io.bartek.ttsserver.sonos
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.bartek.ttsserver.sonos.queue
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import io.bartek.ttsserver.preference.PreferenceKey
|
||||
import io.bartek.ttsserver.sonos.worker.SonosWorker
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
import io.bartek.ttsserver.util.NetworkUtil
|
||||
import io.bartek.ttsserver.web.dto.SonosDTO
|
||||
import java.util.concurrent.BlockingQueue
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
||||
class SonosQueue(
|
||||
private val tts: TTSEngine,
|
||||
private val networkUtil: NetworkUtil,
|
||||
private val preferences: SharedPreferences
|
||||
) {
|
||||
private val queue: BlockingQueue<SonosDTO> = LinkedBlockingQueue()
|
||||
private var consumer: Thread? = null
|
||||
private val host: String
|
||||
get() = networkUtil.getIpAddress()
|
||||
private val port: Int
|
||||
get() = preferences.getInt(PreferenceKey.PORT, 8080)
|
||||
|
||||
fun run() {
|
||||
consumer?.interrupt()
|
||||
consumer = Thread(
|
||||
SonosWorker(
|
||||
tts,
|
||||
host,
|
||||
port,
|
||||
queue
|
||||
)
|
||||
).also { it.name = "SonosQueue" }
|
||||
consumer?.start()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
consumer?.interrupt()
|
||||
consumer = null
|
||||
}
|
||||
|
||||
fun push(data: SonosDTO) = queue.add(data)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.bartek.ttsserver.sonos.worker
|
||||
|
||||
import com.vmichalak.sonoscontroller.SonosDevice
|
||||
import com.vmichalak.sonoscontroller.SonosDiscovery
|
||||
import com.vmichalak.sonoscontroller.model.PlayState
|
||||
import io.bartek.ttsserver.service.ForegroundService
|
||||
import io.bartek.ttsserver.service.ServiceState
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
import io.bartek.ttsserver.web.dto.SonosDTO
|
||||
import java.util.concurrent.BlockingQueue
|
||||
|
||||
class SonosWorker(
|
||||
private val tts: TTSEngine,
|
||||
private val host: String,
|
||||
private val port: Int,
|
||||
private val queue: BlockingQueue<SonosDTO>
|
||||
) : Runnable {
|
||||
|
||||
override fun run() = try {
|
||||
while (ForegroundService.state == ServiceState.RUNNING) {
|
||||
consume(queue.take())
|
||||
}
|
||||
} catch (e: InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
|
||||
private fun consume(data: SonosDTO) =
|
||||
SonosDiscovery.discover().firstOrNull { it.zoneGroupState.name == data.zone }?.let {
|
||||
val file = tts.createTTSFile(data.text, data.language)
|
||||
val filename = file.name
|
||||
val url = "http://$host:$port/sonos/$filename"
|
||||
it.announce(url, data.volume)
|
||||
}
|
||||
|
||||
private fun SonosDevice.announce(url: String, volume: Int) {
|
||||
val currentPlayState = this.playState
|
||||
val currentVolume = this.volume
|
||||
|
||||
this.stop()
|
||||
this.volume = volume
|
||||
this.clip(url, "")
|
||||
|
||||
this.volume = currentVolume
|
||||
when(currentPlayState) {
|
||||
PlayState.PLAYING -> this.play()
|
||||
else -> this.stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,15 @@
|
||||
package io.bartek.ttsserver.web.dto
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
import fi.iki.elonen.NanoHTTPD.ResponseException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
data class BaseDTO(val text: String, val language: Locale, val zone: String, val volume: Int) {
|
||||
data class BaseDTO(val text: String, val language: Locale) : DTO() {
|
||||
companion object {
|
||||
fun fromJSON(json: String): BaseDTO {
|
||||
val root = JSONObject(json)
|
||||
fun fromJSON(json: String) = JSONObject(json).let {root ->
|
||||
val language = root.nullableString("language") ?.let { Locale(it) } ?: Locale.US
|
||||
val text = root.requiredString("text")
|
||||
|
||||
val language = root.optString("language")
|
||||
.takeIf { it.isNotBlank() }
|
||||
?.let { Locale(it) }
|
||||
?: Locale.US
|
||||
val text = root.optString("text") ?: throw ResponseException(
|
||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||
""
|
||||
)
|
||||
val zone = root.optString("zone") ?: throw ResponseException(
|
||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||
""
|
||||
)
|
||||
val volume = root.optInt("volume", 50)
|
||||
|
||||
return BaseDTO(
|
||||
text,
|
||||
language,
|
||||
zone,
|
||||
volume
|
||||
)
|
||||
BaseDTO(text, language)
|
||||
}
|
||||
}
|
||||
}
|
||||
16
app/src/main/java/io/bartek/ttsserver/web/dto/DTO.kt
Normal file
16
app/src/main/java/io/bartek/ttsserver/web/dto/DTO.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
package io.bartek.ttsserver.web.dto
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD.Response
|
||||
import fi.iki.elonen.NanoHTTPD.ResponseException
|
||||
import org.json.JSONObject
|
||||
|
||||
abstract class DTO {
|
||||
companion object {
|
||||
fun JSONObject.requiredString(key: String) = this.nullableString(key)
|
||||
?: throw ResponseException(Response.Status.BAD_REQUEST, "")
|
||||
|
||||
|
||||
fun JSONObject.nullableString(key: String) = this.optString(key)
|
||||
.takeIf { it.isNotBlank() }
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,18 @@
|
||||
package io.bartek.ttsserver.web.dto
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
import fi.iki.elonen.NanoHTTPD.ResponseException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
data class SonosDTO(val text: String, val language: Locale) {
|
||||
data class SonosDTO(val text: String, val language: Locale, val zone: String, val volume: Int) :
|
||||
DTO() {
|
||||
companion object {
|
||||
fun fromJSON(json: String): SonosDTO {
|
||||
val root = JSONObject(json)
|
||||
fun fromJSON(json: String) = JSONObject(json).let { root ->
|
||||
val language = root.nullableString("language") ?.let { Locale(it) } ?: Locale.US
|
||||
val text = root.requiredString("text")
|
||||
val zone = root.requiredString("zone")
|
||||
val volume = root.optInt("volume", 50)
|
||||
|
||||
val language = root.optString("language")
|
||||
.takeIf { it.isNotBlank() }
|
||||
?.let { Locale(it) }
|
||||
?: Locale.US
|
||||
val text = root.optString("text") ?: throw ResponseException(
|
||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||
""
|
||||
)
|
||||
|
||||
return SonosDTO(text, language)
|
||||
SonosDTO(text, language, zone, volume)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import fi.iki.elonen.NanoHTTPD.Response.Status.*
|
||||
import io.bartek.ttsserver.preference.PreferenceKey
|
||||
import io.bartek.ttsserver.service.ForegroundService
|
||||
import io.bartek.ttsserver.service.ServiceState
|
||||
import io.bartek.ttsserver.sonos.SonosQueue
|
||||
import io.bartek.ttsserver.sonos.queue.SonosQueue
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
import io.bartek.ttsserver.tts.status.TTSStatus
|
||||
import io.bartek.ttsserver.web.dto.BaseDTO
|
||||
@@ -73,7 +73,7 @@ class WebServer(
|
||||
}
|
||||
|
||||
val (text, language) = extractBody(session) {
|
||||
SonosDTO.fromJSON(
|
||||
BaseDTO.fromJSON(
|
||||
it
|
||||
)
|
||||
}
|
||||
@@ -103,7 +103,7 @@ class WebServer(
|
||||
}
|
||||
|
||||
val (text, language) = extractBody(session) {
|
||||
SonosDTO.fromJSON(
|
||||
BaseDTO.fromJSON(
|
||||
it
|
||||
)
|
||||
}
|
||||
@@ -127,7 +127,7 @@ class WebServer(
|
||||
}
|
||||
|
||||
val data = extractBody(session) {
|
||||
BaseDTO.fromJSON(
|
||||
SonosDTO.fromJSON(
|
||||
it
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.bartek.ttsserver.web.server
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import io.bartek.ttsserver.preference.PreferenceKey
|
||||
import io.bartek.ttsserver.sonos.SonosQueue
|
||||
import io.bartek.ttsserver.sonos.queue.SonosQueue
|
||||
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||
|
||||
class WebServerFactory(
|
||||
|
||||
Reference in New Issue
Block a user