@@ -38,11 +38,18 @@ class SpeechModule(reactContext: ReactApplicationContext) :
3838 private val queueLock = Any ()
3939
4040 private val isSupportedPausing = Build .VERSION .SDK_INT >= Build .VERSION_CODES .O
41+
4142 private lateinit var synthesizer: TextToSpeech
43+
44+ private var selectedEngine: String? = null
45+ private var cachedEngines: List <TextToSpeech .EngineInfo >? = null
46+
4247 private var isInitialized = false
4348 private var isInitializing = false
4449 private val pendingOperations = mutableListOf<Pair <() - > Unit , Promise >> ()
50+
4551 private var globalOptions: MutableMap <String , Any > = defaultOptions.toMutableMap()
52+
4653 private var isPaused = false
4754 private var isResuming = false
4855 private var currentQueueIndex = - 1
@@ -112,11 +119,12 @@ class SpeechModule(reactContext: ReactApplicationContext) :
112119 if (isInitializing) return
113120 isInitializing = true
114121
115- synthesizer = TextToSpeech (reactApplicationContext) { status ->
122+ synthesizer = TextToSpeech (reactApplicationContext, { status ->
116123 isInitialized = status == TextToSpeech .SUCCESS
117124 isInitializing = false
118125
119126 if (isInitialized) {
127+ cachedEngines = synthesizer.engines
120128 synthesizer.setOnUtteranceProgressListener(object : UtteranceProgressListener () {
121129 override fun onStart (utteranceId : String ) {
122130 synchronized(queueLock) {
@@ -187,7 +195,7 @@ class SpeechModule(reactContext: ReactApplicationContext) :
187195 } else {
188196 rejectPendingOperations()
189197 }
190- }
198+ }, selectedEngine)
191199 }
192200
193201 private fun ensureInitialized (promise : Promise , operation : () -> Unit ) {
@@ -223,7 +231,7 @@ class SpeechModule(reactContext: ReactApplicationContext) :
223231 globalOptions[" voice" ]?.let { voiceId ->
224232 synthesizer.voices?.forEach { voice ->
225233 if (voice.name == voiceId) {
226- synthesizer.setVoice( voice)
234+ synthesizer.voice = voice
227235 return @forEach
228236 }
229237 }
@@ -247,7 +255,7 @@ class SpeechModule(reactContext: ReactApplicationContext) :
247255 tempOptions[" voice" ]?.let { voiceId ->
248256 synthesizer.voices?.forEach { voice ->
249257 if (voice.name == voiceId) {
250- synthesizer.setVoice( voice)
258+ synthesizer.voice = voice
251259 return @forEach
252260 }
253261 }
@@ -443,12 +451,49 @@ class SpeechModule(reactContext: ReactApplicationContext) :
443451 }
444452 }
445453
454+ override fun getEngines (promise : Promise ) {
455+ ensureInitialized(promise) {
456+ val enginesArray = Arguments .createArray()
457+ cachedEngines?.forEach { engine ->
458+ enginesArray.pushMap(
459+ Arguments .createMap().apply {
460+ putString(" name" , engine.name)
461+ putString(" label" , engine.label)
462+ putBoolean(" isDefault" , engine.name == synthesizer.defaultEngine)
463+ }
464+ )
465+ }
466+ promise.resolve(enginesArray)
467+ }
468+ }
469+
470+ override fun setEngine (engineName : String , promise : Promise ) {
471+ if (cachedEngines?.any { it.name == engineName } == false ) {
472+ promise.reject(" engine_error" , " Engine '$engineName ' is not available" )
473+ return
474+ }
475+ if (isInitialized) {
476+ val activeEngine = selectedEngine ? : synthesizer.defaultEngine
477+ if (activeEngine == engineName) {
478+ promise.resolve(null )
479+ return
480+ }
481+ }
482+ selectedEngine = engineName
483+
484+ invalidate()
485+
486+ pendingOperations.add(Pair ({ promise.resolve(null ) }, promise))
487+ initializeTTS()
488+ }
489+
446490 override fun invalidate () {
447491 super .invalidate()
448492 if (::synthesizer.isInitialized) {
449493 synthesizer.stop()
450494 synthesizer.shutdown()
451495 resetQueueState()
452496 }
497+ isInitialized = false
453498 }
454499}
0 commit comments