def finish(self): # There is no more text. # Call stop to clean up, but only after speech completely finishes. # Otherwise, if a different synth is being used for say all, # we might switch synths too early and truncate the final speech. # We do this by putting a CallbackCommand at the start of a new utterance. cb = speech.CallbackCommand(self.stop, name="say-all:stop") speech.speakWithoutPauses( [speech.EndUtteranceCommand(), cb, speech.EndUtteranceCommand()])
def nextLine(self): if not self.reader: # We were stopped. return if not self.reader.obj: # The object died, so we should too. self.finish() return bookmark = self.reader.bookmark # Expand to the current line. # We use move end rather than expand # because the user might start in the middle of a line # and we don't want to read from the start of the line in that case. # For lines after the first, it's also more efficient because # we're already at the start of the line, so there's no need to search backwards. delta = self.reader.move(textInfos.UNIT_READINGCHUNK, 1, endPoint="end") if delta <= 0: # No more text. if isinstance(self.reader.obj, textInfos.DocumentWithPageTurns): # Once the last line finishes reading, try turning the page. cb = speech.CallbackCommand(self.turnPage) speech.speakWithoutPauses([cb, speech.EndUtteranceCommand()]) else: self.finish() return # Call lineReached when we start speaking this line. # lineReached will move the cursor and trigger reading of the next line. cb = speech.CallbackCommand( lambda obj=self.reader.obj, state=self.speakTextInfoState.copy( ): self.lineReached(obj, bookmark, state)) spoke = speech.speakTextInfo(self.reader, unit=textInfos.UNIT_READINGCHUNK, reason=controlTypes.REASON_SAYALL, _prefixSpeechCommand=cb, useCache=self.speakTextInfoState) # Collapse to the end of this line, ready to read the next. try: self.reader.collapse(end=True) except RuntimeError: # This occurs in Microsoft Word when the range covers the end of the document. # without this exception to indicate that further collapsing is not possible, say all could enter an infinite loop. self.finish() return if not spoke: # This line didn't include a natural pause, so nothing was spoken. self.numBufferedLines += 1 if self.numBufferedLines < self.MAX_BUFFERED_LINES: # Move on to the next line. # We queue this to allow the user a chance to stop say all. queueHandler.queueFunction(queueHandler.eventQueue, self.nextLine) else: # We don't want to buffer too much. # Force speech. lineReached will resume things when speech catches up. speech.speakWithoutPauses(None) # The first buffered line has now started speaking. self.numBufferedLines -= 1
def nextLine(self): if not self.reader: log.debug("no self.reader") # We were stopped. return if not self.reader.obj: log.debug("no self.reader.obj") # The object died, so we should too. self.finish() return bookmark = self.reader.bookmark # Expand to the current line. # We use move end rather than expand # because the user might start in the middle of a line # and we don't want to read from the start of the line in that case. # For lines after the first, it's also more efficient because # we're already at the start of the line, so there's no need to search backwards. delta = self.reader.move(textInfos.UNIT_READINGCHUNK, 1, endPoint="end") if delta <= 0: # No more text. if isinstance(self.reader.obj, textInfos.DocumentWithPageTurns): # Once the last line finishes reading, try turning the page. cb = speech.CallbackCommand(self.turnPage, name="say-all:turnPage") speech.speakWithoutPauses([cb, speech.EndUtteranceCommand()]) else: self.finish() return # Copy the speakTextInfoState so that speak callbackCommand # and its associated callback are using a copy isolated to this specific line. state = self.speakTextInfoState.copy() # Call lineReached when we start speaking this line. # lineReached will move the cursor and trigger reading of the next line. def _onLineReached(obj=self.reader.obj, state=state): self.lineReached(obj, bookmark, state) cb = speech.CallbackCommand(_onLineReached, name="say-all:lineReached") # Generate the speech sequence for the reader textInfo # and insert the lineReached callback at the very beginning of the sequence. # _linePrefix on speakTextInfo cannot be used here # As it would be inserted in the sequence after all initial control starts which is too late. speechGen = speech.getTextInfoSpeech(self.reader, unit=textInfos.UNIT_READINGCHUNK, reason=controlTypes.REASON_SAYALL, useCache=state) seq = list(speech._flattenNestedSequences(speechGen)) seq.insert(0, cb) # Speak the speech sequence. spoke = speech.speakWithoutPauses(seq) # Update the textInfo state ready for when speaking the next line. self.speakTextInfoState = state.copy() # Collapse to the end of this line, ready to read the next. try: self.reader.collapse(end=True) except RuntimeError: # This occurs in Microsoft Word when the range covers the end of the document. # without this exception to indicate that further collapsing is not possible, say all could enter an infinite loop. self.finish() return if not spoke: # This line didn't include a natural pause, so nothing was spoken. self.numBufferedLines += 1 if self.numBufferedLines < self.MAX_BUFFERED_LINES: # Move on to the next line. # We queue this to allow the user a chance to stop say all. queueHandler.queueFunction(queueHandler.eventQueue, self.nextLine) else: # We don't want to buffer too much. # Force speech. lineReached will resume things when speech catches up. speech.speakWithoutPauses(None) # The first buffered line has now started speaking. self.numBufferedLines -= 1
def elten_command(ac): global eltenmod global eltenbraille global eltenbrailletext global eltenindex global eltenindexid global eltenqueue try: if(('ac' in ac)==False): return {} if(ac['ac']=="speak"): eltenindex=None eltenindexid=None text="" if('text' in ac): text=ac['text'] if(speech.isBlank(text)==False): queueHandler.queueFunction(queueHandler.eventQueue,speech.speakText,text) if(ac['ac']=="speakindexed"): eltenindex=None eltenindexid=None texts=[] indexes=[] indid=None if('texts' in ac): texts=ac['texts'] if('indexes' in ac): indexes=ac['indexes'] if('indid' in ac): indid=ac['indid'] v=[] for i in range(0, len(texts)): if is_python_3_or_above: if(speech.isBlank(texts[i])): continue if(i<len(indexes)): v.append(EltenIndexCallback(indexes[i], indid)) if(i<len(indexes) and i>0 and texts[i-1]!="" and texts[i-1][-1]=="\n"): v.append(speech.EndUtteranceCommand()) else: eltenindexid=indid if(i<len(indexes)): v.append(speech.IndexCommand(indexes[i])) v.append(texts[i]) speech.cancelSpeech() speech.speak(v) if(ac['ac']=='stop'): speech.cancelSpeech() eltenindex=None eltenindexid=None if(ac['ac']=='sleepmode'): st=eltenmod.sleepMode if('st' in ac): st=ac['st'] eltenmod.sleepMode=st return {'st': st} if(ac['ac']=='init'): pid=0 if('pid' in ac): pid=ac['pid'] eltenmod = appModuleHandler.getAppModuleFromProcessID(pid) def script_eltengesture(self, gesture): global eltenqueue eltenqueue['gestures']+=gesture.identifiers eltenmod.__class__.script_eltengesture = types.MethodType(script_eltengesture, eltenmod.__class__) eltenmod.bindGesture('kb(laptop):NVDA+A', 'eltengesture') eltenmod.bindGesture('kb(laptop):NVDA+L', 'eltengesture') eltenmod.bindGesture('kb(desktop):NVDA+downArrow', 'eltengesture') eltenmod.bindGesture('kb(desktop):NVDA+upArrow', 'eltengesture') if(ac['ac']=='braille'): text="" if('text' in ac): text=ac['text'] if('type' in ac and 'index' in ac): if ac['type']==-1: text=eltenbrailletext[:ac['index']]+eltenbrailletext[ac['index']+1:] elif ac['type']==1: text=eltenbrailletext[:ac['index']]+text+eltenbrailletext[ac['index']:] eltenbrailletext=text+" " regions=[] for phrase in re.split("([.,:/\n?!])", eltenbrailletext): if phrase=="": continue if len(regions)>10000: continue; region=braille.TextRegion(phrase) if hasattr(region, 'parseUndefinedChars'): region.parseUndefinedChars=False region.update() regions.append(region) eltenbraille.regions=regions if('pos' in ac): poses = eltenbraille.rawToBraillePos if(ac['pos']<len(text) and ac['pos']<len(poses)): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['pos']]) eltenbraille.scrollTo(reg, pos) if('cursor' in ac and ac['cursor'] is not None): poses = eltenbraille.rawToBraillePos reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['cursor']]) reg.cursorPos=reg.brailleToRawPos[pos] reg.update() eltenbraille.update() braille.handler.update() if(ac['ac']=='braillepos' and 'pos' in ac and len(eltenbraille.regions)>0): poses = eltenbraille.rawToBraillePos if(ac['pos']<len(poses)): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['pos']]) eltenbraille.scrollTo(reg, pos) reg.update() if('cursor' in ac and ac['cursor'] is not None): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['cursor']]) reg.cursorPos=reg.brailleToRawPos[pos] reg.update() eltenbraille.update() braille.handler.update() if(ac['ac']=='getversion'): return {'version': 33} if(ac['ac']=='getnvdaversion'): return {'version': buildVersion.version} if(ac['ac']=='getindex'): if(is_python_3_or_above): return {'index': eltenindex, 'indid': eltenindexid} else: return {'index': speech.getLastSpeechIndex(), 'indid': eltenindexid} except Exception as Argument: log.exception("Elten: command thread") return {} return {}
def q(self, args): "Enqueues text for speaking." text = " ".join(args) self._queue.extend([text, speech.EndUtteranceCommand()])