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
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"

View File

@@ -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()
}
}

View File

@@ -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" />
<Button
android:id="@+id/stop"
@@ -36,7 +36,7 @@
android:layout_height="wrap_content"
android:layout_weight="2"
android:onClick="stopServer"
android:text="Stop" />
android:text="@string/main_activity_stop" />
</LinearLayout>
@@ -44,5 +44,5 @@
android:id="@+id/ttsSettings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TTS Settings" />
android:text="@string/main_activity_tts_settings" />
</LinearLayout>

View File

@@ -1,3 +1,15 @@
<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>