From 6eaf27359d743338f328fabe1f260e7063f4becb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Fri, 15 May 2020 21:45:15 +0200 Subject: [PATCH] Refactor io.bartek.ttsserver.tts package --- .../java/io/bartek/ttsserver/di/TTSModule.kt | 10 +-- .../io/bartek/ttsserver/sonos/SonosQueue.kt | 6 +- .../tts/{TTS.kt => engine/TTSEngine.kt} | 73 ++++++++----------- .../{ => tts}/exception/TTSException.kt | 2 +- .../io/bartek/ttsserver/tts/listener/Lock.kt | 5 ++ .../tts/listener/TTSProcessListener.kt | 29 ++++++++ .../bartek/ttsserver/tts/model/TTSStream.kt | 5 ++ .../TTSStatus.kt} | 11 +-- .../ttsserver/tts/status/TTSStatusHolder.kt | 13 ++++ .../bartek/ttsserver/web/server/WebServer.kt | 6 +- .../ttsserver/web/server/WebServerFactory.kt | 4 +- 11 files changed, 97 insertions(+), 67 deletions(-) rename app/src/main/java/io/bartek/ttsserver/tts/{TTS.kt => engine/TTSEngine.kt} (58%) rename app/src/main/java/io/bartek/ttsserver/{ => tts}/exception/TTSException.kt (55%) create mode 100644 app/src/main/java/io/bartek/ttsserver/tts/listener/Lock.kt create mode 100644 app/src/main/java/io/bartek/ttsserver/tts/listener/TTSProcessListener.kt create mode 100644 app/src/main/java/io/bartek/ttsserver/tts/model/TTSStream.kt rename app/src/main/java/io/bartek/ttsserver/tts/{TTSStatusHolder.kt => status/TTSStatus.kt} (55%) create mode 100644 app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatusHolder.kt diff --git a/app/src/main/java/io/bartek/ttsserver/di/TTSModule.kt b/app/src/main/java/io/bartek/ttsserver/di/TTSModule.kt index 29b8da6..7a66331 100644 --- a/app/src/main/java/io/bartek/ttsserver/di/TTSModule.kt +++ b/app/src/main/java/io/bartek/ttsserver/di/TTSModule.kt @@ -8,8 +8,8 @@ import dagger.Module import dagger.Provides import io.bartek.ttsserver.service.ForegroundNotificationFactory import io.bartek.ttsserver.sonos.SonosQueue -import io.bartek.ttsserver.tts.TTS -import io.bartek.ttsserver.tts.TTSStatusHolder +import io.bartek.ttsserver.tts.engine.TTSEngine +import io.bartek.ttsserver.tts.status.TTSStatusHolder import io.bartek.ttsserver.util.NetworkUtil import io.bartek.ttsserver.web.server.WebServerFactory import javax.inject.Singleton @@ -29,14 +29,14 @@ class TTSModule { @Provides @Singleton fun tts(context: Context, textToSpeech: TextToSpeech, ttsStatusHolder: TTSStatusHolder) = - TTS(context, textToSpeech, ttsStatusHolder) + TTSEngine(context, textToSpeech, ttsStatusHolder) @Provides @Singleton fun webServerFactory( preferences: SharedPreferences, context: Context, - tts: TTS, + tts: TTSEngine, sonos: SonosQueue ) = WebServerFactory( @@ -56,7 +56,7 @@ class TTSModule { @Provides @Singleton - fun sonosQueue(tts: TTS, networkUtil: NetworkUtil, preferences: SharedPreferences) = + fun sonosQueue(tts: TTSEngine, networkUtil: NetworkUtil, preferences: SharedPreferences) = SonosQueue(tts, networkUtil, preferences) @Provides diff --git a/app/src/main/java/io/bartek/ttsserver/sonos/SonosQueue.kt b/app/src/main/java/io/bartek/ttsserver/sonos/SonosQueue.kt index c6ae738..610ce75 100644 --- a/app/src/main/java/io/bartek/ttsserver/sonos/SonosQueue.kt +++ b/app/src/main/java/io/bartek/ttsserver/sonos/SonosQueue.kt @@ -5,14 +5,14 @@ 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.TTS +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: TTS, + private val tts: TTSEngine, private val host: String, private val port: Int, private val queue: BlockingQueue @@ -40,7 +40,7 @@ private class Consumer( } class SonosQueue( - private val tts: TTS, + private val tts: TTSEngine, private val networkUtil: NetworkUtil, private val preferences: SharedPreferences ) { diff --git a/app/src/main/java/io/bartek/ttsserver/tts/TTS.kt b/app/src/main/java/io/bartek/ttsserver/tts/engine/TTSEngine.kt similarity index 58% rename from app/src/main/java/io/bartek/ttsserver/tts/TTS.kt rename to app/src/main/java/io/bartek/ttsserver/tts/engine/TTSEngine.kt index 301c543..5f04cd4 100644 --- a/app/src/main/java/io/bartek/ttsserver/tts/TTS.kt +++ b/app/src/main/java/io/bartek/ttsserver/tts/engine/TTSEngine.kt @@ -1,27 +1,28 @@ -package io.bartek.ttsserver.tts +package io.bartek.ttsserver.tts.engine import android.content.Context import android.speech.tts.TextToSpeech -import android.speech.tts.UtteranceProgressListener -import io.bartek.ttsserver.exception.TTSException +import io.bartek.ttsserver.tts.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.File import java.io.FileInputStream -import java.io.InputStream import java.security.MessageDigest import java.util.* -data class SpeechData(val stream: InputStream, val size: Long) - -class TTS( +class TTSEngine( private val context: Context, private val tts: TextToSpeech, - private val ttsStausHolder: TTSStatusHolder + private val ttsStatusHolder: TTSStatusHolder ) { private val messageDigest = MessageDigest.getInstance("SHA-256") val status: TTSStatus - get() = ttsStausHolder.status + get() = ttsStatusHolder.status fun createTTSFile(text: String, language: Locale): File { val digest = hash(text, language) @@ -32,7 +33,12 @@ class TTS( val uuid = UUID.randomUUID().toString() val lock = Lock() - tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock)) + tts.setOnUtteranceProgressListener( + TTSProcessListener( + uuid, + lock + ) + ) synchronized(lock) { tts.language = language @@ -53,12 +59,17 @@ class TTS( 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 uuid = UUID.randomUUID().toString() val lock = Lock() - tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock)) + tts.setOnUtteranceProgressListener( + TTSProcessListener( + uuid, + lock + ) + ) synchronized(lock) { tts.language = language @@ -75,13 +86,18 @@ class TTS( file.delete() - return SpeechData(stream, length) + return TTSStream(stream, length) } fun performTTS(text: String, language: Locale) { val uuid = UUID.randomUUID().toString() val lock = Lock() - tts.setOnUtteranceProgressListener(TTSProcessListener(uuid, lock)) + tts.setOnUtteranceProgressListener( + TTSProcessListener( + uuid, + lock + ) + ) synchronized(lock) { 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?) {} -} diff --git a/app/src/main/java/io/bartek/ttsserver/exception/TTSException.kt b/app/src/main/java/io/bartek/ttsserver/tts/exception/TTSException.kt similarity index 55% rename from app/src/main/java/io/bartek/ttsserver/exception/TTSException.kt rename to app/src/main/java/io/bartek/ttsserver/tts/exception/TTSException.kt index f45347f..8276aed 100644 --- a/app/src/main/java/io/bartek/ttsserver/exception/TTSException.kt +++ b/app/src/main/java/io/bartek/ttsserver/tts/exception/TTSException.kt @@ -1,3 +1,3 @@ -package io.bartek.ttsserver.exception +package io.bartek.ttsserver.tts.exception class TTSException : Exception("TTS process failed") \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/tts/listener/Lock.kt b/app/src/main/java/io/bartek/ttsserver/tts/listener/Lock.kt new file mode 100644 index 0000000..8d2d485 --- /dev/null +++ b/app/src/main/java/io/bartek/ttsserver/tts/listener/Lock.kt @@ -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() \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/tts/listener/TTSProcessListener.kt b/app/src/main/java/io/bartek/ttsserver/tts/listener/TTSProcessListener.kt new file mode 100644 index 0000000..1d55060 --- /dev/null +++ b/app/src/main/java/io/bartek/ttsserver/tts/listener/TTSProcessListener.kt @@ -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?) {} +} \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/tts/model/TTSStream.kt b/app/src/main/java/io/bartek/ttsserver/tts/model/TTSStream.kt new file mode 100644 index 0000000..bdf346b --- /dev/null +++ b/app/src/main/java/io/bartek/ttsserver/tts/model/TTSStream.kt @@ -0,0 +1,5 @@ +package io.bartek.ttsserver.tts.model + +import java.io.InputStream + +data class TTSStream(val stream: InputStream, val length: Long) \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/tts/TTSStatusHolder.kt b/app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatus.kt similarity index 55% rename from app/src/main/java/io/bartek/ttsserver/tts/TTSStatusHolder.kt rename to app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatus.kt index 18a73bf..23b4a7a 100644 --- a/app/src/main/java/io/bartek/ttsserver/tts/TTSStatusHolder.kt +++ b/app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatus.kt @@ -1,4 +1,4 @@ -package io.bartek.ttsserver.tts +package io.bartek.ttsserver.tts.status import android.speech.tts.TextToSpeech @@ -10,13 +10,4 @@ enum class TTSStatus(private val status: Int) { companion object { 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) - } } \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatusHolder.kt b/app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatusHolder.kt new file mode 100644 index 0000000..93ebda1 --- /dev/null +++ b/app/src/main/java/io/bartek/ttsserver/tts/status/TTSStatusHolder.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/bartek/ttsserver/web/server/WebServer.kt b/app/src/main/java/io/bartek/ttsserver/web/server/WebServer.kt index e32c3e2..7768ca5 100644 --- a/app/src/main/java/io/bartek/ttsserver/web/server/WebServer.kt +++ b/app/src/main/java/io/bartek/ttsserver/web/server/WebServer.kt @@ -11,8 +11,8 @@ 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.tts.TTS -import io.bartek.ttsserver.tts.TTSStatus +import io.bartek.ttsserver.tts.engine.TTSEngine +import io.bartek.ttsserver.tts.status.TTSStatus import io.bartek.ttsserver.web.dto.BaseDTO import io.bartek.ttsserver.web.dto.SonosDTO import io.bartek.ttsserver.web.endpoint.Endpoint @@ -26,7 +26,7 @@ class WebServer( port: Int, private val context: Context, private val preferences: SharedPreferences, - private val tts: TTS, + private val tts: TTSEngine, private val sonos: SonosQueue ) : NanoHTTPD(port) { override fun serve(session: IHTTPSession?): Response { diff --git a/app/src/main/java/io/bartek/ttsserver/web/server/WebServerFactory.kt b/app/src/main/java/io/bartek/ttsserver/web/server/WebServerFactory.kt index 8e6b70c..243f13a 100644 --- a/app/src/main/java/io/bartek/ttsserver/web/server/WebServerFactory.kt +++ b/app/src/main/java/io/bartek/ttsserver/web/server/WebServerFactory.kt @@ -4,12 +4,12 @@ import android.content.Context import android.content.SharedPreferences import io.bartek.ttsserver.preference.PreferenceKey import io.bartek.ttsserver.sonos.SonosQueue -import io.bartek.ttsserver.tts.TTS +import io.bartek.ttsserver.tts.engine.TTSEngine class WebServerFactory( private val preferences: SharedPreferences, private val context: Context, - private val tts: TTS, + private val tts: TTSEngine, private val sonos: SonosQueue ) { fun createWebServer() =