diff --git a/app/src/main/java/io/bartek/tts/WebService.kt b/app/src/main/java/io/bartek/tts/WebService.kt index a8fef01..58fc3a1 100644 --- a/app/src/main/java/io/bartek/tts/WebService.kt +++ b/app/src/main/java/io/bartek/tts/WebService.kt @@ -15,29 +15,27 @@ import io.bartek.R import io.bartek.web.TTSServer class WebService : Service() { + private var port: Int = 8080 private var wakeLock: PowerManager.WakeLock? = null private var isServiceStarted = false private var ttsServer: TTSServer? = null override fun onCreate() { super.onCreate() - Log.d("TTSService", "Service has been created") startForeground(1, createNotification()) } private fun createNotification(): Notification { - val notificationChannelId = "HTTP SERVER CHANNEL" - // depending on the Android API that we're dealing with we will have // to use a specific method to create the notification if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager; val channel = NotificationChannel( - notificationChannelId, - "HTTP Server", + NOTIFICATION_CHANNEL_ID, + resources.getString(R.string.service_notification_category_name), NotificationManager.IMPORTANCE_HIGH ).let { - it.description = "HTTP Server channel with keeps the service running" + it.description = resources.getString(R.string.service_notification_category_description) it.enableLights(true) it.lightColor = Color.RED it.enableVibration(true) @@ -53,12 +51,12 @@ class WebService : Service() { val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder( this, - notificationChannelId + NOTIFICATION_CHANNEL_ID ) else Notification.Builder(this) return builder - .setContentTitle("Endless Service") - .setContentText("This is your favorite endless service working") + .setContentTitle(resources.getString(R.string.service_notification_title)) + .setContentText(resources.getString(R.string.service_notification_text, port)) .setContentIntent(pendingIntent) .setSmallIcon(R.mipmap.ic_launcher) .setTicker("Ticker text") @@ -66,16 +64,15 @@ class WebService : Service() { .build() } - override fun onBind(intent: Intent): IBinder? { - Log.d("TTSService", "Something is willing to bind the service") - return null - } + override fun onBind(intent: Intent) = null override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - Log.d("TTSService", "onStartCommand with startId: $startId") intent?.let { when(it.action) { - START -> startService(it.getIntExtra(PORT, 8080)) + START -> { + port = it.getIntExtra(PORT, port) + startService() + } STOP -> stopService() } } @@ -87,13 +84,12 @@ class WebService : Service() { ttsServer = null } - private fun startService(port: Int) { + private fun startService() { if(isServiceStarted) return - Log.d("TTSService", "Starting service...") isServiceStarted = true wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "EndlessService::lock").apply { + newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WebService::lock").apply { acquire() } } @@ -101,7 +97,6 @@ class WebService : Service() { } private fun stopService() { - Log.d("TTSService", "Stopping service...") ttsServer?.stop() ttsServer = null wakeLock?.let { @@ -115,6 +110,7 @@ class WebService : Service() { } companion object { + private const val NOTIFICATION_CHANNEL_ID = "TTSService.NOTIFICATION_CHANNEL" const val PORT = "TTSService.PORT" const val START = "START" const val STOP = "STOP" diff --git a/app/src/main/java/io/bartek/web/TTSServer.kt b/app/src/main/java/io/bartek/web/TTSServer.kt index b585445..e246416 100644 --- a/app/src/main/java/io/bartek/web/TTSServer.kt +++ b/app/src/main/java/io/bartek/web/TTSServer.kt @@ -2,8 +2,13 @@ package io.bartek.web import android.content.Context import android.speech.tts.TextToSpeech +import android.speech.tts.UtteranceProgressListener +import android.util.Log import android.widget.Toast import fi.iki.elonen.NanoHTTPD +import io.bartek.R +import java.io.FileInputStream +import java.io.InputStream import java.util.* class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port), TextToSpeech.OnInitListener { @@ -11,20 +16,57 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port), Text override fun serve(session: IHTTPSession?): Response { tts.language = Locale("pl_PL") - tts.speak(session?.uri, TextToSpeech.QUEUE_ADD, null, "") + val uuid = UUID.randomUUID().toString() + val file = createTempFile("tmp_tts_server", ".wav") + val lock = Object() + var error = false + tts.setOnUtteranceProgressListener(object : UtteranceProgressListener() { + override fun onDone(utteranceId: String?) { + if(utteranceId == uuid) { + synchronized(lock) { + lock.notifyAll() + } + } + } - return newFixedLengthResponse(""" { "message": "ok" } """) + override fun onError(utteranceId: String?) { + if(utteranceId == uuid) { + error = true + synchronized(lock) { + lock.notifyAll() + } + } + } + + override fun onStart(utteranceId: String?) {} + }) + + synchronized(lock) { + tts.synthesizeToFile(session?.uri, null, file, uuid) + lock.wait() + } + + val stream = FileInputStream(file) + val length = file.length() + + Log.d("WAV", stream.toString()) + Log.d("WAV", length.toString()) + + return when(error) { + false -> newFixedLengthResponse(Response.Status.OK, "audio/x-wav", stream, length) + else -> newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "TTS error on $uuid") + } } override fun onInit(status: Int) = start() override fun start() { super.start() - Toast.makeText(context, "TTS-HTTP Server started", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.resources.getString(R.string.server_toast_service_started), Toast.LENGTH_SHORT).show() } override fun stop() { super.stop() - Toast.makeText(context, "TTS-HTTP Server stopped", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.resources.getString(R.string.server_toast_service_stopped), Toast.LENGTH_SHORT).show() } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 6891a8b..f2a2d4e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -18,7 +18,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" - android:hint="Server port" + android:hint="@string/main_activity_server_port" android:inputType="number" android:text="8080" /> @@ -28,7 +28,7 @@ android:layout_height="wrap_content" android:layout_weight="2" android:onClick="startServer" - android:text="Run" /> + android:text="@string/main_activity_run" />