Example #1
0
 def speak(self, speechSequence: SpeechSequence, priority: Spri):
     log._speechManagerUnitTest("speak (priority %r): %r", priority,
                                speechSequence)
     interrupt = self._queueSpeechSequence(speechSequence, priority)
     self._doRemoveCancelledSpeechCommands()
     # If speech isn't already in progress, we need to push the first speech.
     push = self._hasNoMoreSpeech() or not self._synthStillSpeaking()
     log._speechManagerDebug(
         f"Will interrupt: {interrupt}"
         f" Will push: {push}"
         f" | _indexesSpeaking: {self._indexesSpeaking!r}"
         f" | _curPriQueue valid: {not self._hasNoMoreSpeech()}"
         f" | _shouldPushWhenDoneSpeaking: {self._shouldPushWhenDoneSpeaking}"
         f" | _cancelledLastSpeechWithSynth {self._cancelledLastSpeechWithSynth}"
     )
     if interrupt:
         log._speechManagerDebug("Interrupting speech")
         getSynth().cancel()
         self._indexesSpeaking.clear()
         self._cancelCommandsForUtteranceBeingSpokenBySynth.clear()
         push = True
     if push:
         log._speechManagerDebug("Pushing next speech")
         self._pushNextSpeech(True)
     else:
         log._speechManagerDebug("Not pushing speech")
Example #2
0
 def _onSynthIndexReached(self, synth=None, index=None):
     log._speechManagerUnitTest(
         f"synthReachedIndex: {index}, synth: {synth}")
     if synth != getSynth():
         return
     # This needs to be handled in the main thread.
     queueHandler.queueFunction(queueHandler.eventQueue, self._handleIndex,
                                index)
Example #3
0
 def _onSynthDoneSpeaking(self,
                          synth: Optional[
                              synthDriverHandler.SynthDriver] = None):
     log._speechManagerUnitTest(f"synthDoneSpeaking synth:{synth}")
     if synth != getSynth():
         return
     # This needs to be handled in the main thread.
     queueHandler.queueFunction(queueHandler.eventQueue,
                                self._handleDoneSpeaking)
Example #4
0
 def _pushNextSpeech(self, doneSpeaking: bool):
     log._speechManagerDebug(
         f"pushNextSpeech - doneSpeaking: {doneSpeaking}")
     queue = self._getNextPriority()
     if not queue:
         # No more speech.
         log._speechManagerDebug("No more speech")
         self._curPriQueue = None
         return
     if self._hasNoMoreSpeech():
         # First utterance after no speech.
         self._curPriQueue = queue
     elif queue.priority > self._curPriQueue.priority:
         # Preempted by higher priority speech.
         if self._curPriQueue.enteredProfileTriggers:
             if not doneSpeaking:
                 # Wait for the synth to finish speaking.
                 # _handleDoneSpeaking will call us again.
                 self._shouldPushWhenDoneSpeaking = True
                 return
             self._exitProfileTriggers(
                 self._curPriQueue.enteredProfileTriggers)
         self._curPriQueue = queue
     elif queue.priority < self._curPriQueue.priority:
         # Resuming a preempted, lower priority queue.
         if queue.enteredProfileTriggers:
             if not doneSpeaking:
                 # Wait for the synth to finish speaking.
                 # _handleDoneSpeaking will call us again.
                 self._shouldPushWhenDoneSpeaking = True
                 return
             self._restoreProfileTriggers(queue.enteredProfileTriggers)
         self._curPriQueue = queue
     while queue.pendingSequences and isinstance(
             queue.pendingSequences[0][0], ConfigProfileTriggerCommand):
         if not doneSpeaking:
             # Wait for the synth to finish speaking.
             # _handleDoneSpeaking will call us again.
             self._shouldPushWhenDoneSpeaking = True
             return
         self._switchProfile()
     if not queue.pendingSequences:
         # The last commands in this queue were profile switches.
         # Call this method again in case other queues are waiting.
         return self._pushNextSpeech(True)
     seq = self._buildNextUtterance()
     if seq:
         # So that we can handle any accidentally skipped indexes.
         for item in seq:
             if isinstance(item, IndexCommand):
                 self._indexesSpeaking.append(item.index)
         self._cancelledLastSpeechWithSynth = False
         log._speechManagerUnitTest(f"Synth Gets: {seq}")
         getSynth().speak(seq)
Example #5
0
 def _handleIndex(self, index: int):
     log._speechManagerDebug(f"Handle index: {index}")
     # A synth (such as OneCore) may skip indexes
     # If before another index, with no text content in between.
     # Therefore, detect this and ensure we handle all skipped indexes.
     handleIndexes = []
     for oldIndex in list(self._indexesSpeaking):
         if self._isIndexABeforeIndexB(oldIndex, index):
             log.debugWarning("Handling skipped index %s" % oldIndex)
             handleIndexes.append(oldIndex)
     handleIndexes.append(index)
     valid, endOfUtterance = False, False
     for i in handleIndexes:
         try:
             self._indexesSpeaking.remove(i)
         except ValueError:
             log.debug(
                 "Unknown index %s, speech probably cancelled from main thread."
                 % i)
             break  # try the rest, this is a very unexpected path.
         if i != index:
             log.debugWarning("Handling skipped index %s" % i)
         # we must do the following for each index, any/all of them may be end of utterance, which must
         # trigger _pushNextSpeech
         _valid, _endOfUtterance = self._removeCompletedFromQueue(i)
         valid = valid or _valid
         endOfUtterance = endOfUtterance or _endOfUtterance
         if _valid:
             callbackCommand = self._indexesToCallbacks.pop(i, None)
             if callbackCommand:
                 try:
                     log._speechManagerUnitTest(
                         f"CallbackCommand Start: {callbackCommand!r}")
                     callbackCommand.run()
                     log._speechManagerUnitTest("CallbackCommand End")
                 except Exception:
                     log.exception("Error running speech callback")
     self._doRemoveCancelledSpeechCommands()
     shouldPush = (
         endOfUtterance
         and not self._synthStillSpeaking()  # stops double speaking errors
     )
     if shouldPush:
         if self._indexesSpeaking:
             log._speechManagerDebug(
                 f"Indexes speaking: {self._indexesSpeaking!r},"
                 f" queue: {self._curPriQueue.pendingSequences}")
         # Even if we have many indexes, we should only push next speech once.
         self._pushNextSpeech(False)
Example #6
0
 def cancel(self):
     log._speechManagerUnitTest("Cancel")
     getSynth().cancel()
     if self._curPriQueue and self._curPriQueue.enteredProfileTriggers:
         self._exitProfileTriggers(self._curPriQueue.enteredProfileTriggers)
     self._reset()
Example #7
0
 def removeCancelledSpeechCommands(self):
     log._speechManagerUnitTest("removeCancelledSpeechCommands")
     self._doRemoveCancelledSpeechCommands()