示例#1
0
 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
示例#2
0
 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()])
示例#3
0
    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
示例#4
0
def readTextHelper_generator(cursor):
	if cursor==CURSOR_CARET:
		try:
			reader=api.getCaretObject().makeTextInfo(textInfos.POSITION_CARET)
		except (NotImplementedError, RuntimeError):
			return
	else:
		reader=api.getReviewPosition()

	lastSentIndex=0
	lastReceivedIndex=0
	cursorIndexMap={}
	keepReading=True
	speakTextInfoState=speech.SpeakTextInfoState(reader.obj)
	with SayAllProfileTrigger():
		while True:
			if not reader.obj:
				# The object died, so we should too.
				return
			# lastReceivedIndex might be None if other speech was interspersed with this say all.
			# In this case, we want to send more text in case this was the last chunk spoken.
			if lastReceivedIndex is None or (lastSentIndex-lastReceivedIndex)<=10:
				if keepReading:
					bookmark=reader.bookmark
					index=lastSentIndex+1
					delta=reader.move(textInfos.UNIT_READINGCHUNK,1,endPoint="end")
					if delta<=0:
						speech.speakWithoutPauses(None)
						keepReading=False
						continue
					speech.speakTextInfo(reader,unit=textInfos.UNIT_READINGCHUNK,reason=controlTypes.REASON_SAYALL,index=index,useCache=speakTextInfoState)
					lastSentIndex=index
					cursorIndexMap[index]=(bookmark,speakTextInfoState.copy())
					try:
						reader.collapse(end=True)
					except RuntimeError: #MS Word when range covers end of document
						# Word specific: without this exception to indicate that further collapsing is not posible, say-all could enter an infinite loop.
						speech.speakWithoutPauses(None)
						keepReading=False
			else:
				# We'll wait for speech to catch up a bit before sending more text.
				if speech.speakWithoutPauses.lastSentIndex is None or (lastSentIndex-speech.speakWithoutPauses.lastSentIndex)>=10:
					# There is a large chunk of pending speech
					# Force speakWithoutPauses to send text to the synth so we can move on.
					speech.speakWithoutPauses(None)
			receivedIndex=speech.getLastSpeechIndex()
			if receivedIndex!=lastReceivedIndex and (lastReceivedIndex!=0 or receivedIndex!=None): 
				lastReceivedIndex=receivedIndex
				bookmark,state=cursorIndexMap.get(receivedIndex,(None,None))
				if state:
					state.updateObj()
				if bookmark is not None:
					updater=reader.obj.makeTextInfo(bookmark)
					if cursor==CURSOR_CARET:
						updater.updateCaret()
					if cursor!=CURSOR_CARET or config.conf["reviewCursor"]["followCaret"]:
						api.setReviewPosition(updater)
			elif not keepReading and lastReceivedIndex==lastSentIndex:
				# All text has been sent to the synth.
				# Turn the page and start again if the object supports it.
				if isinstance(reader.obj,textInfos.DocumentWithPageTurns):
					try:
						reader.obj.turnPage()
					except RuntimeError:
						break
					else:
						reader=reader.obj.makeTextInfo(textInfos.POSITION_FIRST)
						keepReading=True
				else:
					break

			while speech.isPaused:
				yield
			yield

		# Wait until the synth has actually finished speaking.
		# Otherwise, if there is a triggered profile with a different synth,
		# we will switch too early and truncate speech (even up to several lines).
		# Send another index and wait for it.
		index=lastSentIndex+1
		speech.speak([speech.IndexCommand(index)])
		while speech.getLastSpeechIndex()<index:
			yield
			yield
		# Some synths say they've handled the index slightly sooner than they actually have,
		# so wait a bit longer.
		for i in xrange(30):
			yield
示例#5
0
def readTextHelper_generator(cursor):
    if cursor == CURSOR_CARET:
        try:
            reader = api.getCaretObject().makeTextInfo(
                textInfos.POSITION_CARET)
        except (NotImplementedError, RuntimeError):
            return
    else:
        reader = api.getReviewPosition()

    lastSentIndex = 0
    lastReceivedIndex = 0
    cursorIndexMap = {}
    keepReading = True
    speakTextInfoState = speech.SpeakTextInfoState(reader.obj)

    start = time.time()

    with SayAllProfileTrigger():
        while True:
            if not reader.obj:
                # The object died, so we should too.
                return
            # lastReceivedIndex might be None if other speech was interspersed with this say all.
            # In this case, we want to send more text in case this was the last chunk spoken.
            if lastReceivedIndex is None or (lastSentIndex -
                                             lastReceivedIndex) <= 10:
                if keepReading:
                    bookmark = reader.bookmark
                    index = lastSentIndex + 1
                    delta = reader.move(textInfos.UNIT_READINGCHUNK,
                                        1,
                                        endPoint="end")
                    if delta <= 0:
                        speech.speakWithoutPauses(None)
                        keepReading = False
                        continue
                    speech.speakTextInfo(reader,
                                         unit=textInfos.UNIT_READINGCHUNK,
                                         reason=controlTypes.REASON_SAYALL,
                                         index=index,
                                         useCache=speakTextInfoState)
                    lastSentIndex = index
                    cursorIndexMap[index] = (bookmark,
                                             speakTextInfoState.copy())
                    try:
                        reader.collapse(end=True)
                    except RuntimeError:  #MS Word when range covers end of document
                        # Word specific: without this exception to indicate that further collapsing is not posible, say-all could enter an infinite loop.
                        speech.speakWithoutPauses(None)
                        keepReading = False
            else:
                # We'll wait for speech to catch up a bit before sending more text.
                if speech.speakWithoutPauses.lastSentIndex is None or (
                        lastSentIndex -
                        speech.speakWithoutPauses.lastSentIndex) >= 10:
                    # There is a large chunk of pending speech
                    # Force speakWithoutPauses to send text to the synth so we can move on.
                    speech.speakWithoutPauses(None)
            receivedIndex = speech.getLastSpeechIndex()
            if receivedIndex != lastReceivedIndex and (
                    lastReceivedIndex != 0 or receivedIndex != None):
                lastReceivedIndex = receivedIndex
                bookmark, state = cursorIndexMap.get(receivedIndex,
                                                     (None, None))
                if state:
                    state.updateObj()
                if bookmark is not None:
                    updater = reader.obj.makeTextInfo(bookmark)
                    if cursor == CURSOR_CARET:
                        updater.updateCaret()
                    if cursor != CURSOR_CARET or config.conf["reviewCursor"][
                            "followCaret"]:
                        api.setReviewPosition(updater,
                                              isCaret=cursor == CURSOR_CARET)
            elif not keepReading and lastReceivedIndex == lastSentIndex:
                # All text has been sent to the synth.
                # Turn the page and start again if the object supports it.
                if isinstance(reader.obj, textInfos.DocumentWithPageTurns):
                    try:
                        reader.obj.turnPage()
                    except RuntimeError:
                        break
                    else:
                        reader = reader.obj.makeTextInfo(
                            textInfos.POSITION_FIRST)
                        keepReading = True
                else:
                    break

            while speech.isPaused:
                yield
            yield

            now = time.time()

            if (now - start) > int(min) * 60 + int(sec):
                speech.cancelSpeech()
                break

        # Wait until the synth has actually finished speaking.
        # Otherwise, if there is a triggered profile with a different synth,
        # we will switch too early and truncate speech (even up to several lines).
        # Send another index and wait for it.
        index = lastSentIndex + 1
        speech.speak([speech.IndexCommand(index)])
        while speech.getLastSpeechIndex() < index:
            yield
            yield
        # Some synths say they've handled the index slightly sooner than they actually have,
        # so wait a bit longer.
        for i in xrange(30):
            yield
示例#6
0
def readTextHelper_generator(cursor):
	if cursor==CURSOR_CARET:
		try:
			reader=api.getCaretObject().makeTextInfo(textInfos.POSITION_CARET)
		except (NotImplementedError, RuntimeError):
			return
	else:
		reader=api.getReviewPosition()

	lastSentIndex=0
	lastReceivedIndex=0
	cursorIndexMap={}
	keepReading=True
	while True:
		if not reader.obj:
			# The object died, so we should too.
			return
		# lastReceivedIndex might be None if other speech was interspersed with this say all.
		# In this case, we want to send more text in case this was the last chunk spoken.
		if lastReceivedIndex is None or (lastSentIndex-lastReceivedIndex)<=10:
			if keepReading:
				bookmark=reader.bookmark
				index=lastSentIndex+1
				delta=reader.move(textInfos.UNIT_READINGCHUNK,1,endPoint="end")
				if delta<=0:
					speech.speakWithoutPauses(None)
					keepReading=False
					continue
				speech.speakTextInfo(reader,unit=textInfos.UNIT_READINGCHUNK,reason=controlTypes.REASON_SAYALL,index=index)
				lastSentIndex=index
				cursorIndexMap[index]=bookmark
				try:
					reader.collapse(end=True)
				except RuntimeError: #MS Word when range covers end of document
					speech.speakWithoutPauses(None)
					keepReading=False
		else:
			# We'll wait for speech to catch up a bit before sending more text.
			if speech.speakWithoutPauses.lastSentIndex is None or (lastSentIndex-speech.speakWithoutPauses.lastSentIndex)>=10:
				# There is a large chunk of pending speech
				# Force speakWithoutPauses to send text to the synth so we can move on.
				speech.speakWithoutPauses(None)
		receivedIndex=speech.getLastSpeechIndex()
		if receivedIndex!=lastReceivedIndex and (lastReceivedIndex!=0 or receivedIndex!=None): 
			lastReceivedIndex=receivedIndex
			bookmark=cursorIndexMap.get(receivedIndex,None)
			if bookmark is not None:
				updater=reader.obj.makeTextInfo(bookmark)
				if cursor==CURSOR_CARET:
					updater.updateCaret()
				if cursor!=CURSOR_CARET or config.conf["reviewCursor"]["followCaret"]:
					api.setReviewPosition(updater)
		elif not keepReading and lastReceivedIndex==lastSentIndex:
			# All text has been spoken.
			# Turn the page and start again if the object supports it.
			if isinstance(reader.obj,textInfos.DocumentWithPageTurns):
				try:
					reader.obj.turnPage()
				except RuntimeError:
					break
				else:
					reader=reader.obj.makeTextInfo(textInfos.POSITION_FIRST)
					keepReading=True
			else:
				break

		while speech.isPaused:
			yield
		yield