Enable synthesizing to wav files

This commit is contained in:
2020-05-06 19:57:02 +02:00
parent 543b10befb
commit c2db00d748
4 changed files with 78 additions and 28 deletions

View File

@@ -15,29 +15,27 @@ import io.bartek.R
import io.bartek.web.TTSServer import io.bartek.web.TTSServer
class WebService : Service() { class WebService : Service() {
private var port: Int = 8080
private var wakeLock: PowerManager.WakeLock? = null private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false private var isServiceStarted = false
private var ttsServer: TTSServer? = null private var ttsServer: TTSServer? = null
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
Log.d("TTSService", "Service has been created")
startForeground(1, createNotification()) startForeground(1, createNotification())
} }
private fun createNotification(): Notification { private fun createNotification(): Notification {
val notificationChannelId = "HTTP SERVER CHANNEL"
// depending on the Android API that we're dealing with we will have // depending on the Android API that we're dealing with we will have
// to use a specific method to create the notification // to use a specific method to create the notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager; val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
val channel = NotificationChannel( val channel = NotificationChannel(
notificationChannelId, NOTIFICATION_CHANNEL_ID,
"HTTP Server", resources.getString(R.string.service_notification_category_name),
NotificationManager.IMPORTANCE_HIGH NotificationManager.IMPORTANCE_HIGH
).let { ).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.enableLights(true)
it.lightColor = Color.RED it.lightColor = Color.RED
it.enableVibration(true) 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( val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
this, this,
notificationChannelId NOTIFICATION_CHANNEL_ID
) else Notification.Builder(this) ) else Notification.Builder(this)
return builder return builder
.setContentTitle("Endless Service") .setContentTitle(resources.getString(R.string.service_notification_title))
.setContentText("This is your favorite endless service working") .setContentText(resources.getString(R.string.service_notification_text, port))
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher) .setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Ticker text") .setTicker("Ticker text")
@@ -66,16 +64,15 @@ class WebService : Service() {
.build() .build()
} }
override fun onBind(intent: Intent): IBinder? { override fun onBind(intent: Intent) = null
Log.d("TTSService", "Something is willing to bind the service")
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("TTSService", "onStartCommand with startId: $startId")
intent?.let { intent?.let {
when(it.action) { when(it.action) {
START -> startService(it.getIntExtra(PORT, 8080)) START -> {
port = it.getIntExtra(PORT, port)
startService()
}
STOP -> stopService() STOP -> stopService()
} }
} }
@@ -87,13 +84,12 @@ class WebService : Service() {
ttsServer = null ttsServer = null
} }
private fun startService(port: Int) { private fun startService() {
if(isServiceStarted) return if(isServiceStarted) return
Log.d("TTSService", "Starting service...")
isServiceStarted = true isServiceStarted = true
wakeLock = wakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run { (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "EndlessService::lock").apply { newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WebService::lock").apply {
acquire() acquire()
} }
} }
@@ -101,7 +97,6 @@ class WebService : Service() {
} }
private fun stopService() { private fun stopService() {
Log.d("TTSService", "Stopping service...")
ttsServer?.stop() ttsServer?.stop()
ttsServer = null ttsServer = null
wakeLock?.let { wakeLock?.let {
@@ -115,6 +110,7 @@ class WebService : Service() {
} }
companion object { companion object {
private const val NOTIFICATION_CHANNEL_ID = "TTSService.NOTIFICATION_CHANNEL"
const val PORT = "TTSService.PORT" const val PORT = "TTSService.PORT"
const val START = "START" const val START = "START"
const val STOP = "STOP" const val STOP = "STOP"

View File

@@ -2,8 +2,13 @@ package io.bartek.web
import android.content.Context import android.content.Context
import android.speech.tts.TextToSpeech import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import android.util.Log
import android.widget.Toast import android.widget.Toast
import fi.iki.elonen.NanoHTTPD import fi.iki.elonen.NanoHTTPD
import io.bartek.R
import java.io.FileInputStream
import java.io.InputStream
import java.util.* import java.util.*
class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port), TextToSpeech.OnInitListener { 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 { override fun serve(session: IHTTPSession?): Response {
tts.language = Locale("pl_PL") 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 onInit(status: Int) = start()
override fun start() { override fun start() {
super.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() { override fun stop() {
super.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()
} }
} }

View File

@@ -18,7 +18,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:ems="10" android:ems="10"
android:hint="Server port" android:hint="@string/main_activity_server_port"
android:inputType="number" android:inputType="number"
android:text="8080" /> android:text="8080" />
@@ -28,7 +28,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:onClick="startServer" android:onClick="startServer"
android:text="Run" /> android:text="@string/main_activity_run" />
<Button <Button
android:id="@+id/stop" android:id="@+id/stop"
@@ -36,7 +36,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:onClick="stopServer" android:onClick="stopServer"
android:text="Stop" /> android:text="@string/main_activity_stop" />
</LinearLayout> </LinearLayout>
@@ -44,5 +44,5 @@
android:id="@+id/ttsSettings" android:id="@+id/ttsSettings"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="TTS Settings" /> android:text="@string/main_activity_tts_settings" />
</LinearLayout> </LinearLayout>

View File

@@ -1,3 +1,15 @@
<resources> <resources>
<string name="app_name">TTSServer</string> <string name="app_name">TTS Server</string>
<string name="service_notification_category_name">HTTP Server</string>
<string name="service_notification_category_description">The fixed notification keeping the HTTP server alive</string>
<string name="service_notification_title">Server is running</string>
<string name="service_notification_text">The HTTP server is listening on port %1$d</string>
<string name="server_toast_service_started">TTS-HTTP Server started</string>
<string name="server_toast_service_stopped">TTS-HTTP Server stopped</string>
<string name="main_activity_server_port">Server port</string>
<string name="main_activity_run">Run</string>
<string name="main_activity_stop">Stop</string>
<string name="main_activity_tts_settings">TTS Settings</string>
</resources> </resources>