diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4c2a923..795f887 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -30,7 +30,7 @@
android:parentActivityName="com.bartlomiejpluta.ttsserver.ui.main.MainActivity" />
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/sonos/worker/SonosWorker.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/sonos/worker/SonosWorker.kt
index ad100e6..b0cef44 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/sonos/worker/SonosWorker.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/sonos/worker/SonosWorker.kt
@@ -7,7 +7,7 @@ import com.bartlomiejpluta.ttsserver.core.web.dto.SonosDTO
import com.bartlomiejpluta.ttsserver.core.web.endpoint.Endpoint
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
import com.vmichalak.sonoscontroller.Snapshot
import com.vmichalak.sonoscontroller.SonosDevice
import com.vmichalak.sonoscontroller.SonosDiscovery
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/tts/engine/TTSEngine.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/tts/engine/TTSEngine.kt
index c59c1b9..4fb5d96 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/tts/engine/TTSEngine.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/tts/engine/TTSEngine.kt
@@ -14,7 +14,7 @@ import com.bartlomiejpluta.ttsserver.core.tts.model.TTSStream
import com.bartlomiejpluta.ttsserver.core.tts.status.TTSStatus
import com.bartlomiejpluta.ttsserver.core.tts.status.TTSStatusHolder
import com.bartlomiejpluta.ttsserver.core.util.AudioConverter
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/util/NetworkUtil.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/util/NetworkUtil.kt
index 7f7b373..b089403 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/util/NetworkUtil.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/util/NetworkUtil.kt
@@ -4,7 +4,7 @@ import android.content.Context
import android.content.Context.WIFI_SERVICE
import android.content.SharedPreferences
import android.net.wifi.WifiManager
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
import java.net.InetAddress
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServer.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServer.kt
index 85e682f..56d1b02 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServer.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServer.kt
@@ -18,13 +18,15 @@ import com.bartlomiejpluta.ttsserver.core.web.exception.WebException
import com.bartlomiejpluta.ttsserver.core.web.mime.MimeType
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.model.TimeRange
import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoHTTPD.Response.Status.*
import org.json.JSONObject
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
+import java.util.*
class WebServer(
@@ -34,6 +36,20 @@ class WebServer(
private val tts: TTSEngine,
private val sonos: SonosQueue
) : NanoHTTPD(port) {
+ 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()
@@ -97,6 +113,10 @@ class WebServer(
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)
@@ -142,6 +162,10 @@ class WebServer(
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)
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServerFactory.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServerFactory.kt
index f7aaa51..055cb3b 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServerFactory.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/core/web/server/WebServerFactory.kt
@@ -4,7 +4,7 @@ import android.content.Context
import android.content.SharedPreferences
import com.bartlomiejpluta.ttsserver.core.sonos.queue.SonosQueue
import com.bartlomiejpluta.ttsserver.core.tts.engine.TTSEngine
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
class WebServerFactory(
private val preferences: SharedPreferences,
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/di/module/AndroidModule.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/di/module/AndroidModule.kt
index ca06bf4..bb3748a 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/di/module/AndroidModule.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/di/module/AndroidModule.kt
@@ -3,7 +3,7 @@ package com.bartlomiejpluta.ttsserver.di.module
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.ui.help.HelpActivity
import com.bartlomiejpluta.ttsserver.ui.main.MainActivity
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferencesActivity
+import com.bartlomiejpluta.ttsserver.ui.preference.component.PreferencesActivity
import dagger.Module
import dagger.android.ContributesAndroidInjector
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/main/MainActivity.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/main/MainActivity.kt
index fbed55c..c16b797 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/main/MainActivity.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/main/MainActivity.kt
@@ -14,7 +14,7 @@ import com.bartlomiejpluta.ttsserver.core.util.NetworkUtil
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
import com.bartlomiejpluta.ttsserver.ui.help.HelpActivity
-import com.bartlomiejpluta.ttsserver.ui.preference.PreferencesActivity
+import com.bartlomiejpluta.ttsserver.ui.preference.component.PreferencesActivity
import dagger.android.support.DaggerAppCompatActivity
import javax.inject.Inject
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesActivity.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesActivity.kt
similarity index 75%
rename from app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesActivity.kt
rename to app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesActivity.kt
index 93f46c6..44128fd 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesActivity.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesActivity.kt
@@ -1,4 +1,4 @@
-package com.bartlomiejpluta.ttsserver.ui.preference
+package com.bartlomiejpluta.ttsserver.ui.preference.component
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
@@ -11,7 +11,9 @@ class PreferencesActivity : AppCompatActivity() {
setContentView(R.layout.activity_preferences)
supportFragmentManager
.beginTransaction()
- .replace(R.id.preferences, PreferencesFragment())
+ .replace(R.id.preferences,
+ PreferencesFragment()
+ )
.commit()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesFragment.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesFragment.kt
similarity index 57%
rename from app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesFragment.kt
rename to app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesFragment.kt
index 754e0cb..055423a 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/PreferencesFragment.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/component/PreferencesFragment.kt
@@ -1,5 +1,6 @@
-package com.bartlomiejpluta.ttsserver.ui.preference
+package com.bartlomiejpluta.ttsserver.ui.preference.component
+import android.app.TimePickerDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -15,6 +16,9 @@ import com.bartlomiejpluta.R
import com.bartlomiejpluta.ttsserver.core.web.mime.MimeType
import com.bartlomiejpluta.ttsserver.service.foreground.ForegroundService
import com.bartlomiejpluta.ttsserver.service.state.ServiceState
+import com.bartlomiejpluta.ttsserver.ui.preference.model.TimeRange
+import com.bartlomiejpluta.ttsserver.ui.preference.key.PreferenceKey
+import com.bartlomiejpluta.ttsserver.ui.preference.custom.IntEditTextPreference
class PreferencesFragment : PreferenceFragmentCompat() {
@@ -25,6 +29,8 @@ class PreferencesFragment : PreferenceFragmentCompat() {
private lateinit var httpDebugPreference: SwitchPreference
private lateinit var enableGongPreference: SwitchPreference
private lateinit var ttsEnginePreference: Preference
+ private lateinit var enableSonosSilenceScheduler: SwitchPreference
+ private lateinit var enableSpeakersSilenceScheduler: SwitchPreference
private lateinit var clearSonosCachePreference: Preference
private val receiver = object : BroadcastReceiver() {
@@ -75,6 +81,82 @@ class PreferencesFragment : PreferenceFragmentCompat() {
startActivity(Intent(ANDROID_TTS_SETTINGS))
true
}
+ enableSpeakersSilenceScheduler = findPreference(PreferenceKey.ENABLE_SPEAKERS_SILENCE_SCHEDULER)!!
+ enableSpeakersSilenceScheduler.setOnPreferenceClickListener { preference ->
+ if(!enableSpeakersSilenceScheduler.isChecked) {
+ return@setOnPreferenceClickListener true
+ }
+ enableSpeakersSilenceScheduler.isChecked = false
+
+ val schedule = preference
+ .sharedPreferences
+ .getString(
+ PreferenceKey.SPEAKERS_SILENCE_SCHEDULE,
+ DEFAULT_SCHEDULE
+ )!!
+ .let {
+ TimeRange.parse(
+ it
+ )
+ }
+
+ TimePickerDialog(context, { _, newBeginHour, newBeginMinute ->
+ TimePickerDialog(context, { _, newEndHour, newEndMinute ->
+ preference.sharedPreferences.edit()?.let { editor ->
+ val newSchedule =
+ TimeRange(
+ newBeginHour,
+ newBeginMinute,
+ newEndHour,
+ newEndMinute
+ )
+ editor.putString(PreferenceKey.SPEAKERS_SILENCE_SCHEDULE, newSchedule.toString())
+ editor.apply()
+ enableSpeakersSilenceScheduler.isChecked = true
+ }
+ }, schedule.endHour, schedule.endMinute, true).show()
+ }, schedule.beginHour, schedule.beginMinute, true).show()
+
+ true
+ }
+ enableSonosSilenceScheduler = findPreference(PreferenceKey.ENABLE_SONOS_SILENCE_SCHEDULER)!!
+ enableSonosSilenceScheduler.setOnPreferenceClickListener { preference ->
+ if(!enableSonosSilenceScheduler.isChecked) {
+ return@setOnPreferenceClickListener true
+ }
+ enableSonosSilenceScheduler.isChecked = false
+
+ val schedule = preference
+ .sharedPreferences
+ .getString(
+ PreferenceKey.SONOS_SILENCE_SCHEDULE,
+ DEFAULT_SCHEDULE
+ )!!
+ .let {
+ TimeRange.parse(
+ it
+ )
+ }
+
+ TimePickerDialog(context, { _, newBeginHour, newBeginMinute ->
+ TimePickerDialog(context, { _, newEndHour, newEndMinute ->
+ preference.sharedPreferences.edit()?.let { editor ->
+ val newSchedule =
+ TimeRange(
+ newBeginHour,
+ newBeginMinute,
+ newEndHour,
+ newEndMinute
+ )
+ editor.putString(PreferenceKey.SONOS_SILENCE_SCHEDULE, newSchedule.toString())
+ editor.apply()
+ enableSonosSilenceScheduler.isChecked = true
+ }
+ }, schedule.endHour, schedule.endMinute, true).show()
+ }, schedule.beginHour, schedule.beginMinute, true).show()
+
+ true
+ }
clearSonosCachePreference = findPreference(PreferenceKey.INVALIDATE_SONOS_CACHE)!!
clearSonosCachePreference.setOnPreferenceClickListener {
context?.cacheDir?.listFiles()?.forEach { it.delete() }
@@ -94,7 +176,9 @@ class PreferencesFragment : PreferenceFragmentCompat() {
.apply { type = MimeType.WAV.mimeType }
.let { Intent.createChooser(it, getString(R.string.preference_gong_picker_prompt)) }
- startActivityForResult(intent, PICKFILE_RESULT_CODE)
+ startActivityForResult(intent,
+ PICKFILE_RESULT_CODE
+ )
}
}
@@ -118,5 +202,6 @@ class PreferencesFragment : PreferenceFragmentCompat() {
companion object {
private const val ANDROID_TTS_SETTINGS = "com.android.settings.TTS_SETTINGS"
private const val PICKFILE_RESULT_CODE = 1
+ private val DEFAULT_SCHEDULE = "22:00-07:00"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/IntEditTextPreference.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/custom/IntEditTextPreference.kt
similarity index 93%
rename from app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/IntEditTextPreference.kt
rename to app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/custom/IntEditTextPreference.kt
index 76d46bf..0af2594 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/IntEditTextPreference.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/custom/IntEditTextPreference.kt
@@ -1,4 +1,4 @@
-package com.bartlomiejpluta.ttsserver.ui.preference
+package com.bartlomiejpluta.ttsserver.ui.preference.custom
import android.content.Context
import android.util.AttributeSet
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/Preference.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/key/Preference.kt
similarity index 57%
rename from app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/Preference.kt
rename to app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/key/Preference.kt
index da588c9..d3c9b7e 100644
--- a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/Preference.kt
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/key/Preference.kt
@@ -1,4 +1,4 @@
-package com.bartlomiejpluta.ttsserver.ui.preference
+package com.bartlomiejpluta.ttsserver.ui.preference.key
object PreferenceKey {
@@ -10,5 +10,9 @@ object PreferenceKey {
const val ENABLE_GONG = "preference_enable_gong"
const val GONG = "preference_gong"
const val TTS = "preference_tts"
+ const val ENABLE_SPEAKERS_SILENCE_SCHEDULER = "preference_enable_speakers_silence_scheduler"
+ const val SPEAKERS_SILENCE_SCHEDULE = "preference_speakers_silence_schedule"
+ const val ENABLE_SONOS_SILENCE_SCHEDULER = "preference_enable_sonos_silence_scheduler"
+ const val SONOS_SILENCE_SCHEDULE = "preference_sonos_silence_schedule"
const val INVALIDATE_SONOS_CACHE = "preference_invalidate_sonos_cache"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/model/TimeRange.kt b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/model/TimeRange.kt
new file mode 100644
index 0000000..855c6b4
--- /dev/null
+++ b/app/src/main/java/com/bartlomiejpluta/ttsserver/ui/preference/model/TimeRange.kt
@@ -0,0 +1,42 @@
+package com.bartlomiejpluta.ttsserver.ui.preference.model
+
+import java.util.*
+
+data class TimeRange(val beginHour: Int, val beginMinute: Int, val endHour: Int, val endMinute: Int) {
+ private val begin: Int
+ get() = beginHour * 60 + beginMinute
+
+ private val end: Int
+ get() = endHour * 60 + endMinute
+
+ fun inRange(calendar: Calendar): Boolean {
+ val current = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE)
+ return when {
+ begin <= end -> current in begin..end
+ else -> !(current in end..begin)
+ }
+ }
+
+ override fun toString() = "$beginHour:$beginMinute-$endHour:$endMinute"
+
+ companion object {
+ fun parse(range: String): TimeRange {
+ val (beginTime, endTime) = range.splitAndMap("-") { it }
+ val (beginHour, beginMinute) = beginTime.splitAndMap(":") { it.toInt() }
+ val (endHour, endMinute) = endTime.splitAndMap(":") { it.toInt() }
+ return TimeRange(
+ beginHour,
+ beginMinute,
+ endHour,
+ endMinute
+ )
+ }
+
+ private fun String.splitAndMap(delimiter: String, mapper: (String) -> T): List {
+ return this.split(delimiter)
+ .map { mapper(it) }
+ .takeIf { it.size == 2 }
+ ?: throw IllegalArgumentException("Expected format: HH:mm-HH:mm")
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0964b6b..68d1fc5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -30,11 +30,16 @@
Enable gong
Go to platform\'s TTS engine settings and adjust its parameters
TTS engine settings
+ Determine a time range when /say endpoint should be disabled
+ Enable silence scheduler
+ Determine a time range when /sonos endpoint should be disabled
+ Enable silence scheduler
Clear application cache directory from already generated Sonos TTS data for given sentences. You typically want to do it when you change the TTS engine\'s voice settings.
Invalidate Sonos cache
Server
Features
TTS engine
+ Speakers
Sonos
Sonos cache has been invalidated
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 0e05302..0fab131 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -2,7 +2,7 @@
-
+
+
+
+
+
+