Remove unused code

This commit is contained in:
2020-07-02 21:58:13 +02:00
parent 7f2c328bc4
commit 81de38aa97
16 changed files with 17 additions and 374 deletions

View File

@@ -1,36 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.sonos.queue
import android.content.SharedPreferences
import com.bartlomiejpluta.ttsserver.core.sonos.worker.SonosWorker
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
import com.bartlomiejpluta.ttsserver.core.util.NetworkUtil
import com.bartlomiejpluta.ttsserver.core.web.dto.SonosDTO
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
class SonosQueue(
private val tts: TTSEngine,
private val preferences: SharedPreferences,
private val networkUtil: NetworkUtil
) {
val queue: BlockingQueue<SonosDTO> = LinkedBlockingQueue()
private var consumer: Thread? = null
fun run() {
consumer?.interrupt()
consumer = createWorkerThread()
consumer?.start()
}
private fun createWorkerThread(): Thread {
val worker = SonosWorker(tts, networkUtil.serverAddress, preferences, queue)
return Thread(worker).also { it.name = "SonosQueue" }
}
fun stop() {
consumer?.interrupt()
consumer = null
}
fun push(data: SonosDTO) = queue.add(data)
}

View File

@@ -1,79 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.sonos.worker
import android.content.SharedPreferences
import cafe.adriel.androidaudioconverter.model.AudioFormat
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
import com.bartlomiejpluta.ttsserver.core.web.dto.SonosDTO
import com.bartlomiejpluta.ttsserver.core.web.endpoint.Endpointx
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
import com.vmichalak.sonoscontroller.Snapshot
import com.vmichalak.sonoscontroller.SonosDevice
import com.vmichalak.sonoscontroller.SonosDiscovery
import com.vmichalak.sonoscontroller.model.PlayState
import java.util.concurrent.BlockingQueue
class SonosWorker(
private val tts: TTSEngine,
private val address: String,
private val preferences: SharedPreferences,
private val queue: BlockingQueue<SonosDTO>
) : Runnable {
private val gongUrl: String get() = address + Endpointx.GONG.trimmedUri
private val announcementUrl: String get() = address + Endpointx.SONOS_CACHE.trimmedUri
private var snapshot: Snapshot? = null
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 url = prepareTTSFile(data)
updateSnapshotIfFirst(it)
announce(it, data, url)
restoreSnapshotIfLast()
}
private fun prepareTTSFile(data: SonosDTO): String {
val filename = tts.createTTSFile(data.text, data.language, AudioFormat.MP3).name
return "$announcementUrl$filename"
}
private fun announce(device: SonosDevice, data: SonosDTO, url: String) {
device.stop()
device.volume = data.volume
if (preferences.getBoolean(PreferenceKey.ENABLE_GONG, false)) {
playUri(device, gongUrl)
}
playUri(device, url)
}
private fun playUri(device: SonosDevice, uri: String) {
device.playUri(uri, "")
while (device.playState != PlayState.STOPPED) {
Thread.sleep(500)
}
}
private fun updateSnapshotIfFirst(it: SonosDevice) {
if (snapshot == null) {
snapshot = it.snapshot()
}
}
private fun restoreSnapshotIfLast() {
if (queue.isEmpty()) {
snapshot!!.restore()
snapshot = null
}
}
}

View File

@@ -1,14 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.tts.listener
import android.media.MediaPlayer
import java.util.concurrent.LinkedBlockingQueue
class GongListener : MediaPlayer.OnCompletionListener {
private val queue = LinkedBlockingQueue<Any>()
override fun onCompletion(mp: MediaPlayer?) {
queue.add(Any())
}
fun await() = queue.take()
}

View File

@@ -1,5 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.tts.model
import java.io.InputStream
data class TTSStream(val stream: InputStream, val length: Long)

View File

@@ -1,8 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.web.dto
import java.util.*
class BaseDTO(json: String) : DTO(json) {
val language = nullableObject("language", Locale.US, { Locale(it) }, { it.toString() })
val text = requiredString("text")
}

View File

@@ -1,24 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.web.dto
import com.bartlomiejpluta.ttsserver.core.web.exception.WebException
import fi.iki.elonen.NanoHTTPD.Response
import org.json.JSONObject
abstract class DTO(json: String) : JSONObject(json) {
protected fun requiredString(key: String) = this.optString(key)
.takeIf { it.isNotBlank() }
?: throw WebException(Response.Status.BAD_REQUEST, "The '$key' field is required")
protected fun nullableInt(key: String, default: Int) = this.optInt(key, default)
.also { put(key, it) }
protected fun <T> nullableObject(
key: String,
default: T,
deserializer: (String) -> T,
serializer: (T) -> String
): T = this.optString(key)
.takeIf { it.isNotBlank() }
?.let { deserializer(it) }
?: default.also { put(key, serializer(it)) }
}

View File

@@ -1,4 +1,4 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
package com.bartlomiejpluta.ttsserver.core.web.dto
import com.bartlomiejpluta.ttsserver.core.web.uri.UriTemplate
import fi.iki.elonen.NanoHTTPD
@@ -35,6 +35,9 @@ class Request private constructor(
companion object {
fun of(request: NanoHTTPD.IHTTPSession, matchingResult: UriTemplate.MatchingResult) =
Request(request, matchingResult)
Request(
request,
matchingResult
)
}
}

View File

@@ -1,10 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.web.dto
import java.util.*
class SonosDTO(json: String) : DTO(json) {
val language = nullableObject("language", Locale.US, { Locale(it) }, { it.toString() })
val text = requiredString("text")
val zone = requiredString("zone")
val volume = nullableInt("volume", 50)
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
import com.bartlomiejpluta.ttsserver.core.web.dto.Request
import com.bartlomiejpluta.ttsserver.core.web.uri.UriTemplate
import fi.iki.elonen.NanoHTTPD.*
import org.luaj.vm2.LuaClosure

View File

@@ -1,17 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
import android.content.UriMatcher
import android.net.Uri
object EndpointMatcher {
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
init {
Endpointx.values().forEach {
uriMatcher.addURI("", it.uri, it.ordinal)
}
}
fun match(uri: String) =
Endpointx.of(uriMatcher.match(Uri.parse("content://$uri")))
}

View File

@@ -1,22 +0,0 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
enum class Endpointx(val uri: String, val id: Int) {
UNKNOWN("/", 1),
SAY("/say", 2),
WAVE("/wave", 3),
AAC("/aac", 4),
MP3("/mp3", 5),
M4A("/m4a", 6),
WMA("/wma", 7),
FLAC("/flac", 8),
SONOS("/sonos", 9),
SONOS_CACHE("/sonos/*", 10),
GONG("/gong.wav", 11);
val trimmedUri: String
get() = uri.replace("*", "")
companion object {
fun of(ordinal: Int) = values().firstOrNull { it.ordinal == ordinal } ?: UNKNOWN
}
}

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
import com.bartlomiejpluta.ttsserver.core.web.dto.Request
import com.bartlomiejpluta.ttsserver.core.web.uri.UriTemplate
import com.bartlomiejpluta.ttsserver.core.web.worker.Worker
import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoHTTPD.newFixedLengthResponse
import org.luaj.vm2.LuaClosure
@@ -13,7 +15,12 @@ class QueuedEndpoint(
consumer: LuaClosure
) : Endpoint {
private val queue = LinkedBlockingQueue<Request>()
private val worker = Thread(Worker(queue, consumer)).also { it.name = uri.template }
private val worker = Thread(
Worker(
queue,
consumer
)
).also { it.name = uri.template }
override fun hit(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response? {
if (session.method != method) {

View File

@@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.bartlomiejpluta.ttsserver.core.sonos.queue.SonosQueue
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
import com.bartlomiejpluta.ttsserver.core.tts.status.TTSStatus
import com.bartlomiejpluta.ttsserver.core.web.endpoint.Endpoint
@@ -15,7 +14,6 @@ import com.bartlomiejpluta.ttsserver.ui.main.MainActivity
import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoHTTPD.Response.Status.*
import org.json.JSONObject
import org.luaj.vm2.LuaError
@@ -24,25 +22,10 @@ class WebServer(
private val context: Context,
private val preferences: SharedPreferences,
private val tts: TTSEngine,
private val sonos: SonosQueue,
private val endpoints: List<Endpoint>
) : NanoHTTPD(port) {
private val queuedEndpoints = endpoints.mapNotNull { it as? QueuedEndpoint }
// private val speakersSilenceSchedulerEnabled: Boolean
// get() = preferences.getBoolean(PreferenceKey.ENABLE_SPEAKERS_SILENCE_SCHEDULER, false)
//
// private val sonosSilenceSchedulerEnabled: Boolean
// get() = preferences.getBoolean(PreferenceKey.ENABLE_SONOS_SILENCE_SCHEDULER, false)
//
// private val speakersSilenceSchedule: TimeRange
// get() = preferences.getString(PreferenceKey.SPEAKERS_SILENCE_SCHEDULE, "")!!
// .let { TimeRange.parse(it) }
//
// private val sonosSilenceSchedule: TimeRange
// get() = preferences.getString(PreferenceKey.SONOS_SILENCE_SCHEDULE, "")!!
// .let { TimeRange.parse(it) }
override fun serve(session: IHTTPSession?): Response {
try {
assertThatTTSIsReady()
@@ -90,126 +73,8 @@ class WebServer(
return newFixedLengthResponse(INTERNAL_ERROR, MIME_PLAINTEXT, stacktrace)
}
// private fun say(session: IHTTPSession): Response {
// if (!preferences.getBoolean(PreferenceKey.ENABLE_SAY_ENDPOINT, true)) {
// throw WebException(NOT_FOUND)
// }
//
// if (session.method != Method.POST) {
// throw WebException(METHOD_NOT_ALLOWED, "Only POST methods are allowed")
// }
//
// if (session.headers[CONTENT_TYPE]?.let { it != MIME_JSON } != false) {
// throw WebException(BAD_REQUEST, "Only JSON data is accepted")
// }
//
// if (speakersSilenceSchedulerEnabled && speakersSilenceSchedule.inRange(Calendar.getInstance())) {
// return newFixedLengthResponse(NO_CONTENT, MIME_JSON, "")
// }
//
// val dto = extractBody(session) { BaseDTO(it) }
//
// tts.performTTS(dto.text, dto.language)
// return newFixedLengthResponse(OK, MIME_JSON, SUCCESS_RESPONSE)
// }
// private fun <T> extractBody(session: IHTTPSession, provider: (String) -> T): T {
// return mutableMapOf<String, String>().let {
// session.parseBody(it)
// provider(it["postData"] ?: "{}")
// }
// }
// private fun file(session: IHTTPSession, audioFormat: AudioFormat): Response {
// if (!preferences.getBoolean(PreferenceKey.ENABLE_FILE_ENDPOINTS, true)) {
// throw WebException(NOT_FOUND)
// }
//
// if (session.method != Method.POST) {
// throw WebException(METHOD_NOT_ALLOWED, "Only POST methods are allowed")
// }
//
// if (session.headers[CONTENT_TYPE]?.let { it != MIME_JSON } != false) {
// throw WebException(BAD_REQUEST, "Only JSON data is accepted")
// }
//
// val dto = extractBody(session) { BaseDTO(it) }
//
// val (stream, size) = tts.fetchTTSStream(dto.text, dto.language, audioFormat)
// return newFixedLengthResponse(OK, MimeType.forAudioFormat(audioFormat).mimeType, stream, size)
// }
//
// private fun sonos(session: IHTTPSession): Response {
// if (!preferences.getBoolean(PreferenceKey.ENABLE_SONOS_ENDPOINT, true)) {
// throw WebException(NOT_FOUND)
// }
//
// if (session.method != Method.POST) {
// throw WebException(METHOD_NOT_ALLOWED, "Only POST methods are allowed")
// }
//
// if (session.headers[CONTENT_TYPE]?.let { it != MIME_JSON } != false) {
// throw WebException(BAD_REQUEST, "Only JSON data is accepted")
// }
//
// if (sonosSilenceSchedulerEnabled && sonosSilenceSchedule.inRange(Calendar.getInstance())) {
// return newFixedLengthResponse(NO_CONTENT, MIME_JSON, "")
// }
//
// val dto = extractBody(session) { SonosDTO(it) }
//
// sonos.push(dto)
//
// return newFixedLengthResponse(ACCEPTED, MIME_JSON, QUEUED_RESPONSE)
// }
//
// private fun sonosCache(session: IHTTPSession): Response {
// if (!preferences.getBoolean(PreferenceKey.ENABLE_SONOS_ENDPOINT, true)) {
// throw WebException(NOT_FOUND)
// }
//
// if (session.method != Method.GET) {
// throw WebException(METHOD_NOT_ALLOWED, "Only GET methods are allowed")
// }
//
// val filename = Uri.parse(session.uri).lastPathSegment ?: throw WebException(BAD_REQUEST)
// val file = File(context.cacheDir, filename)
//
// if (!file.exists()) {
// throw WebException(NOT_FOUND)
// }
//
// val stream = BufferedInputStream(FileInputStream(file))
// val size = file.length()
// return newFixedLengthResponse(OK, MimeType.forFile(file).mimeType, stream, size)
// }
//
// private fun gong(session: IHTTPSession): Response {
// if (!preferences.getBoolean(PreferenceKey.ENABLE_GONG, false)) {
// throw WebException(NOT_FOUND)
// }
//
// if (session.method != Method.GET) {
// throw WebException(METHOD_NOT_ALLOWED, "Only GET methods are allowed")
// }
//
// val uri = Uri.parse(
// preferences.getString(PreferenceKey.GONG, null) ?: throw TTSException()
// )
//
// val size = context.contentResolver.openFileDescriptor(uri, "r")?.statSize
// ?: throw TTSException()
//
// val stream = BufferedInputStream(
// context.contentResolver.openInputStream(uri) ?: throw TTSException()
// )
//
// return newFixedLengthResponse(OK, MimeType.WAV.mimeType, stream, size)
// }
override fun start() {
super.start()
sonos.run()
queuedEndpoints.forEach { it.runWorker() }
LocalBroadcastManager
@@ -221,7 +86,6 @@ class WebServer(
override fun stop() {
super.stop()
sonos.stop()
queuedEndpoints.forEach { it.stopWorker() }
LocalBroadcastManager
@@ -233,10 +97,5 @@ class WebServer(
companion object {
private const val MIME_JSON = "application/json"
private const val CONTENT_TYPE = "content-type"
private val SUCCESS_RESPONSE = response("Request has been completed")
private val QUEUED_RESPONSE = response("Request has been queued")
private fun response(status: String) = JSONObject().put("message", status).toString()
}
}

View File

@@ -3,7 +3,6 @@ package com.bartlomiejpluta.ttsserver.core.web.server
import android.content.Context
import android.content.SharedPreferences
import com.bartlomiejpluta.ttsserver.core.lua.loader.EndpointLoader
import com.bartlomiejpluta.ttsserver.core.sonos.queue.SonosQueue
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
@@ -11,7 +10,6 @@ class WebServerFactory(
private val preferences: SharedPreferences,
private val context: Context,
private val tts: TTSEngine,
private val sonos: SonosQueue,
private val endpointLoader: EndpointLoader
) {
fun createWebServer() = WebServer(
@@ -19,7 +17,6 @@ class WebServerFactory(
context,
preferences,
tts,
sonos,
endpointLoader.loadEndpoints()
)
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.ttsserver.core.web.endpoint
package com.bartlomiejpluta.ttsserver.core.web.worker
import com.bartlomiejpluta.ttsserver.core.web.dto.Request
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
import org.luaj.vm2.LuaClosure
@@ -20,9 +21,7 @@ class Worker(
Thread.currentThread().interrupt()
}
private fun consume(request: Request) {
consumer.call(request.luaTable, QueueSizeFunction(queue))
}
private fun consume(request: Request) = consumer.call(request.luaTable, QueueSizeFunction(queue))
class QueueSizeFunction(private val queue: BlockingQueue<Request>) : ZeroArgFunction() {
override fun call(): LuaInteger = LuaValue.valueOf(queue.size)

View File

@@ -5,7 +5,6 @@ import android.content.SharedPreferences
import android.speech.tts.TextToSpeech
import androidx.preference.PreferenceManager
import com.bartlomiejpluta.ttsserver.core.lua.loader.EndpointLoader
import com.bartlomiejpluta.ttsserver.core.sonos.queue.SonosQueue
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
import com.bartlomiejpluta.ttsserver.core.tts.status.TTSStatusHolder
import com.bartlomiejpluta.ttsserver.core.util.AudioConverter
@@ -44,13 +43,11 @@ class TTSModule {
preferences: SharedPreferences,
context: Context,
tts: TTSEngine,
sonos: SonosQueue,
endpointLoader: EndpointLoader
) = WebServerFactory(
preferences,
context,
tts,
sonos,
endpointLoader
)
@@ -67,11 +64,6 @@ class TTSModule {
@Singleton
fun adudioConverter(context: Context) = AudioConverter(context)
@Provides
@Singleton
fun sonosQueue(tts: TTSEngine, preferences: SharedPreferences, networkUtil: NetworkUtil) =
SonosQueue(tts, preferences, networkUtil)
@Provides
@Singleton
fun foregroundNotificationFactory(