Skip to content

Commit 75c580b

Browse files
authored
Merge 8c2aedf into 82fefa5
2 parents 82fefa5 + 8c2aedf commit 75c580b

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

source/synthDrivers/sapi5.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import Optional
88
from enum import IntEnum
99
import locale
10-
from collections import OrderedDict
10+
from collections import OrderedDict, deque
1111
import comtypes.client
1212
from comtypes import COMError
1313
import winreg
@@ -78,12 +78,23 @@ def Bookmark(self, streamNum, pos, bookmark, bookmarkId):
7878
log.debugWarning("Called Bookmark method on SapiSink while driver is dead")
7979
return
8080
synthIndexReached.notify(synth=synth, index=bookmarkId)
81+
# remove already triggered bookmarks
82+
if streamNum in synth._streamBookmarks:
83+
bookmarks = synth._streamBookmarks[streamNum]
84+
while bookmarks:
85+
if bookmarks.popleft() == bookmarkId:
86+
break
8187

8288
def EndStream(self, streamNum, pos):
8389
synth = self.synthRef()
8490
if synth is None:
8591
log.debugWarning("Called Bookmark method on EndStream while driver is dead")
8692
return
93+
# trigger all untriggered bookmarks
94+
if streamNum in synth._streamBookmarks:
95+
for bookmark in synth._streamBookmarks[streamNum]:
96+
synthIndexReached.notify(synth=synth, index=bookmark)
97+
del synth._streamBookmarks[streamNum]
8798
synthDoneSpeaking.notify(synth=synth)
8899
if synth._audioDucker:
89100
if audioDucking._isDebug():
@@ -138,6 +149,7 @@ def __init__(self, _defaultVoiceToken=None):
138149
self._audioDucker = audioDucking.AudioDucker()
139150
self._pitch = 50
140151
self._initTts(_defaultVoiceToken)
152+
self._streamBookmarks = dict() # key = stream num, value = deque of bookmarks
141153

142154
def terminate(self):
143155
self._eventsConnection = None
@@ -263,6 +275,7 @@ def _convertPhoneme(self, ipa):
263275

264276
def speak(self, speechSequence):
265277
textList = []
278+
bookmarks = deque()
266279

267280
# NVDA SpeechCommands are linear, but XML is hierarchical.
268281
# Therefore, we track values for non-empty tags.
@@ -298,6 +311,7 @@ def outputTags():
298311
textList.append(item.replace("<", "&lt;"))
299312
elif isinstance(item, IndexCommand):
300313
textList.append('<Bookmark Mark="%d" />' % item.index)
314+
bookmarks.append(item.index)
301315
elif isinstance(item, CharacterModeCommand):
302316
if item.state:
303317
tags["spell"] = {}
@@ -397,7 +411,8 @@ def outputTags():
397411
log.debug("Enabling audio ducking due to speak call")
398412
tempAudioDucker.enable()
399413
try:
400-
self.tts.Speak(text, flags)
414+
streamNum = self.tts.Speak(text, flags)
415+
self._streamBookmarks[streamNum] = bookmarks
401416
finally:
402417
if tempAudioDucker:
403418
if audioDucking._isDebug():

0 commit comments

Comments
 (0)