Refactor io.bartek.ttsserver.tts package
This commit is contained in:
@@ -8,8 +8,8 @@ import dagger.Module
|
|||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import io.bartek.ttsserver.service.ForegroundNotificationFactory
|
import io.bartek.ttsserver.service.ForegroundNotificationFactory
|
||||||
import io.bartek.ttsserver.sonos.SonosQueue
|
import io.bartek.ttsserver.sonos.SonosQueue
|
||||||
import io.bartek.ttsserver.tts.TTS
|
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||||
import io.bartek.ttsserver.tts.TTSStatusHolder
|
import io.bartek.ttsserver.tts.status.TTSStatusHolder
|
||||||
import io.bartek.ttsserver.util.NetworkUtil
|
import io.bartek.ttsserver.util.NetworkUtil
|
||||||
import io.bartek.ttsserver.web.server.WebServerFactory
|
import io.bartek.ttsserver.web.server.WebServerFactory
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@@ -29,14 +29,14 @@ class TTSModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun tts(context: Context, textToSpeech: TextToSpeech, ttsStatusHolder: TTSStatusHolder) =
|
fun tts(context: Context, textToSpeech: TextToSpeech, ttsStatusHolder: TTSStatusHolder) =
|
||||||
TTS(context, textToSpeech, ttsStatusHolder)
|
TTSEngine(context, textToSpeech, ttsStatusHolder)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun webServerFactory(
|
fun webServerFactory(
|
||||||
preferences: SharedPreferences,
|
preferences: SharedPreferences,
|
||||||
context: Context,
|
context: Context,
|
||||||
tts: TTS,
|
tts: TTSEngine,
|
||||||
sonos: SonosQueue
|
sonos: SonosQueue
|
||||||
) =
|
) =
|
||||||
WebServerFactory(
|
WebServerFactory(
|
||||||
@@ -56,7 +56,7 @@ class TTSModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun sonosQueue(tts: TTS, networkUtil: NetworkUtil, preferences: SharedPreferences) =
|
fun sonosQueue(tts: TTSEngine, networkUtil: NetworkUtil, preferences: SharedPreferences) =
|
||||||
SonosQueue(tts, networkUtil, preferences)
|
SonosQueue(tts, networkUtil, preferences)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import com.vmichalak.sonoscontroller.SonosDiscovery
|
|||||||
import io.bartek.ttsserver.preference.PreferenceKey
|
import io.bartek.ttsserver.preference.PreferenceKey
|
||||||
import io.bartek.ttsserver.service.ForegroundService
|
import io.bartek.ttsserver.service.ForegroundService
|
||||||
import io.bartek.ttsserver.service.ServiceState
|
import io.bartek.ttsserver.service.ServiceState
|
||||||
import io.bartek.ttsserver.tts.TTS
|
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||||
import io.bartek.ttsserver.util.NetworkUtil
|
import io.bartek.ttsserver.util.NetworkUtil
|
||||||
import io.bartek.ttsserver.web.dto.BaseDTO
|
import io.bartek.ttsserver.web.dto.BaseDTO
|
||||||
import java.util.concurrent.BlockingQueue
|
import java.util.concurrent.BlockingQueue
|
||||||
import java.util.concurrent.LinkedBlockingQueue
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
|
|
||||||
private class Consumer(
|
private class Consumer(
|
||||||
private val tts: TTS,
|
private val tts: TTSEngine,
|
||||||
private val host: String,
|
private val host: String,
|
||||||
private val port: Int,
|
private val port: Int,
|
||||||
private val queue: BlockingQueue<BaseDTO>
|
private val queue: BlockingQueue<BaseDTO>
|
||||||
@@ -40,7 +40,7 @@ private class Consumer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SonosQueue(
|
class SonosQueue(
|
||||||
private val tts: TTS,
|
private val tts: TTSEngine,
|
||||||
private val networkUtil: NetworkUtil,
|
private val networkUtil: NetworkUtil,
|
||||||
private val preferences: SharedPreferences
|
private val preferences: SharedPreferences
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
package io.bartek.ttsserver.tts
|
package io.bartek.ttsserver.tts.engine
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.speech.tts.TextToSpeech
|
import android.speech.tts.TextToSpeech
|
||||||
import android.speech.tts.UtteranceProgressListener
|
import io.bartek.ttsserver.tts.exception.TTSException
|
||||||
import io.bartek.ttsserver.exception.TTSException
|
import io.bartek.ttsserver.tts.listener.Lock
|
||||||
|
import io.bartek.ttsserver.tts.listener.TTSProcessListener
|
||||||
|
import io.bartek.ttsserver.tts.model.TTSStream
|
||||||
|
import io.bartek.ttsserver.tts.status.TTSStatus
|
||||||
|
import io.bartek.ttsserver.tts.status.TTSStatusHolder
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.InputStream
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class SpeechData(val stream: InputStream, val size: Long)
|
class TTSEngine(
|
||||||
|
|
||||||
class TTS(
|
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val tts: TextToSpeech,
|
private val tts: TextToSpeech,
|
||||||
private val ttsStausHolder: TTSStatusHolder
|
private val ttsStatusHolder: TTSStatusHolder
|
||||||
) {
|
) {
|
||||||
private val messageDigest = MessageDigest.getInstance("SHA-256")
|
private val messageDigest = MessageDigest.getInstance("SHA-256")
|
||||||
|
|
||||||
val status: TTSStatus
|
val status: TTSStatus
|
||||||
get() = ttsStausHolder.status
|
get() = ttsStatusHolder.status
|
||||||
|
|
||||||
fun createTTSFile(text: String, language: Locale): File {
|
fun createTTSFile(text: String, language: Locale): File {
|
||||||
val digest = hash(text, language)
|
val digest = hash(text, language)
|
||||||
@@ -32,7 +33,12 @@ class TTS(
|
|||||||
|
|
||||||
val uuid = UUID.randomUUID().toString()
|
val uuid = UUID.randomUUID().toString()
|
||||||
val lock = Lock()
|
val lock = Lock()
|
||||||
tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock))
|
tts.setOnUtteranceProgressListener(
|
||||||
|
TTSProcessListener(
|
||||||
|
uuid,
|
||||||
|
lock
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
tts.language = language
|
tts.language = language
|
||||||
@@ -53,12 +59,17 @@ class TTS(
|
|||||||
return digest.fold("", { str, it -> str + "%02x".format(it) })
|
return digest.fold("", { str, it -> str + "%02x".format(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchTTSStream(text: String, language: Locale): SpeechData {
|
fun fetchTTSStream(text: String, language: Locale): TTSStream {
|
||||||
val file = createTempFile("tmp_tts_server", ".wav")
|
val file = createTempFile("tmp_tts_server", ".wav")
|
||||||
|
|
||||||
val uuid = UUID.randomUUID().toString()
|
val uuid = UUID.randomUUID().toString()
|
||||||
val lock = Lock()
|
val lock = Lock()
|
||||||
tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock))
|
tts.setOnUtteranceProgressListener(
|
||||||
|
TTSProcessListener(
|
||||||
|
uuid,
|
||||||
|
lock
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
tts.language = language
|
tts.language = language
|
||||||
@@ -75,13 +86,18 @@ class TTS(
|
|||||||
|
|
||||||
file.delete()
|
file.delete()
|
||||||
|
|
||||||
return SpeechData(stream, length)
|
return TTSStream(stream, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun performTTS(text: String, language: Locale) {
|
fun performTTS(text: String, language: Locale) {
|
||||||
val uuid = UUID.randomUUID().toString()
|
val uuid = UUID.randomUUID().toString()
|
||||||
val lock = Lock()
|
val lock = Lock()
|
||||||
tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock))
|
tts.setOnUtteranceProgressListener(
|
||||||
|
TTSProcessListener(
|
||||||
|
uuid,
|
||||||
|
lock
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
tts.language = language
|
tts.language = language
|
||||||
@@ -95,32 +111,3 @@ class TTS(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
|
||||||
// TODO: Investigate the Kotlin way to achieve the same
|
|
||||||
private data class Lock(var success: Boolean = false) : Object()
|
|
||||||
|
|
||||||
private class TTSProcessListener(
|
|
||||||
private val uuid: String,
|
|
||||||
private val lock: Lock
|
|
||||||
) : UtteranceProgressListener() {
|
|
||||||
|
|
||||||
override fun onDone(utteranceId: String?) {
|
|
||||||
if (utteranceId == uuid) {
|
|
||||||
synchronized(lock) {
|
|
||||||
lock.success = true
|
|
||||||
lock.notifyAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(utteranceId: String?) {
|
|
||||||
if (utteranceId == uuid) {
|
|
||||||
synchronized(lock) {
|
|
||||||
lock.success = false
|
|
||||||
lock.notifyAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart(utteranceId: String?) {}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
package io.bartek.ttsserver.exception
|
package io.bartek.ttsserver.tts.exception
|
||||||
|
|
||||||
class TTSException : Exception("TTS process failed")
|
class TTSException : Exception("TTS process failed")
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.bartek.ttsserver.tts.listener
|
||||||
|
|
||||||
|
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||||
|
// TODO: Investigate the Kotlin way to achieve the same
|
||||||
|
data class Lock(var success: Boolean = false) : Object()
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package io.bartek.ttsserver.tts.listener
|
||||||
|
|
||||||
|
import android.speech.tts.UtteranceProgressListener
|
||||||
|
|
||||||
|
class TTSProcessListener(
|
||||||
|
private val uuid: String,
|
||||||
|
private val lock: Lock
|
||||||
|
) : UtteranceProgressListener() {
|
||||||
|
|
||||||
|
override fun onDone(utteranceId: String?) {
|
||||||
|
if (utteranceId == uuid) {
|
||||||
|
synchronized(lock) {
|
||||||
|
lock.success = true
|
||||||
|
lock.notifyAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(utteranceId: String?) {
|
||||||
|
if (utteranceId == uuid) {
|
||||||
|
synchronized(lock) {
|
||||||
|
lock.success = false
|
||||||
|
lock.notifyAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart(utteranceId: String?) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.bartek.ttsserver.tts.model
|
||||||
|
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
data class TTSStream(val stream: InputStream, val length: Long)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package io.bartek.ttsserver.tts
|
package io.bartek.ttsserver.tts.status
|
||||||
|
|
||||||
import android.speech.tts.TextToSpeech
|
import android.speech.tts.TextToSpeech
|
||||||
|
|
||||||
@@ -10,13 +10,4 @@ enum class TTSStatus(private val status: Int) {
|
|||||||
companion object {
|
companion object {
|
||||||
fun of(status: Int) = values().firstOrNull { it.status == status } ?: UNLOADED
|
fun of(status: Int) = values().firstOrNull { it.status == status } ?: UNLOADED
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class TTSStatusHolder : TextToSpeech.OnInitListener {
|
|
||||||
var status = TTSStatus.UNLOADED
|
|
||||||
private set
|
|
||||||
|
|
||||||
override fun onInit(status: Int) {
|
|
||||||
this.status = TTSStatus.of(status)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package io.bartek.ttsserver.tts.status
|
||||||
|
|
||||||
|
import android.speech.tts.TextToSpeech
|
||||||
|
import io.bartek.ttsserver.tts.status.TTSStatus
|
||||||
|
|
||||||
|
class TTSStatusHolder : TextToSpeech.OnInitListener {
|
||||||
|
var status = TTSStatus.UNLOADED
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun onInit(status: Int) {
|
||||||
|
this.status = TTSStatus.of(status)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,8 +11,8 @@ import io.bartek.ttsserver.preference.PreferenceKey
|
|||||||
import io.bartek.ttsserver.service.ForegroundService
|
import io.bartek.ttsserver.service.ForegroundService
|
||||||
import io.bartek.ttsserver.service.ServiceState
|
import io.bartek.ttsserver.service.ServiceState
|
||||||
import io.bartek.ttsserver.sonos.SonosQueue
|
import io.bartek.ttsserver.sonos.SonosQueue
|
||||||
import io.bartek.ttsserver.tts.TTS
|
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||||
import io.bartek.ttsserver.tts.TTSStatus
|
import io.bartek.ttsserver.tts.status.TTSStatus
|
||||||
import io.bartek.ttsserver.web.dto.BaseDTO
|
import io.bartek.ttsserver.web.dto.BaseDTO
|
||||||
import io.bartek.ttsserver.web.dto.SonosDTO
|
import io.bartek.ttsserver.web.dto.SonosDTO
|
||||||
import io.bartek.ttsserver.web.endpoint.Endpoint
|
import io.bartek.ttsserver.web.endpoint.Endpoint
|
||||||
@@ -26,7 +26,7 @@ class WebServer(
|
|||||||
port: Int,
|
port: Int,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val preferences: SharedPreferences,
|
private val preferences: SharedPreferences,
|
||||||
private val tts: TTS,
|
private val tts: TTSEngine,
|
||||||
private val sonos: SonosQueue
|
private val sonos: SonosQueue
|
||||||
) : NanoHTTPD(port) {
|
) : NanoHTTPD(port) {
|
||||||
override fun serve(session: IHTTPSession?): Response {
|
override fun serve(session: IHTTPSession?): Response {
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import android.content.Context
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import io.bartek.ttsserver.preference.PreferenceKey
|
import io.bartek.ttsserver.preference.PreferenceKey
|
||||||
import io.bartek.ttsserver.sonos.SonosQueue
|
import io.bartek.ttsserver.sonos.SonosQueue
|
||||||
import io.bartek.ttsserver.tts.TTS
|
import io.bartek.ttsserver.tts.engine.TTSEngine
|
||||||
|
|
||||||
class WebServerFactory(
|
class WebServerFactory(
|
||||||
private val preferences: SharedPreferences,
|
private val preferences: SharedPreferences,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val tts: TTS,
|
private val tts: TTSEngine,
|
||||||
private val sonos: SonosQueue
|
private val sonos: SonosQueue
|
||||||
) {
|
) {
|
||||||
fun createWebServer() =
|
fun createWebServer() =
|
||||||
|
|||||||
Reference in New Issue
Block a user