Skip to content

Commit

Permalink
Ensure that no reference is kept to sapi4 synth on terminate (PR nvac…
Browse files Browse the repository at this point in the history
…cess#10078)

When switching from SAPI4 to another synth, a reference to the sapi4 object is kept alive by a circular reference on the com Sink.

Modified the design of both SAPI4 and 5 to clarify the use of weakRefs
  • Loading branch information
LeonarddeR authored and feerrenrut committed Aug 16, 2019
1 parent dade58c commit a8e8db1
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 10 deletions.
20 changes: 13 additions & 7 deletions source/synthDrivers/sapi4.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,26 @@
from ._sapi4 import *
import config
import nvwave
import weakref


class SynthDriverBufSink(COMObject):
_com_interfaces_ = [ITTSBufNotifySink]

def __init__(self,synthDriver):
self._synthDriver=synthDriver
def __init__(self, synthRef: weakref.ReferenceType):
self.synthRef = synthRef
self._allowDelete = True
super(SynthDriverBufSink,self).__init__()

def ITTSBufNotifySink_BookMark(self, this, qTimeStamp, dwMarkNum):
synthIndexReached.notify(synth=self._synthDriver,index=dwMarkNum)
if self._synthDriver._finalIndex==dwMarkNum:
self._synthDriver._finalIndex=None
synthDoneSpeaking.notify(synth=self._synthDriver)
synth = self.synthRef()
if synth is None:
log.debugWarning("Called ITTSBufNotifySink_BookMark method on ITTSBufNotifySink while driver is dead")
return
synthIndexReached.notify(synth=synth, index=dwMarkNum)
if synth._finalIndex == dwMarkNum:
synth._finalIndex = None
synthDoneSpeaking.notify(synth=synth)

def IUnknown_Release(self, this, *args, **kwargs):
if not self._allowDelete and self._refcnt.value == 1:
Expand Down Expand Up @@ -69,7 +75,7 @@ def _fetchEnginesList(self):

def __init__(self):
self._finalIndex=None
self._bufSink=SynthDriverBufSink(self)
self._bufSink = SynthDriverBufSink(weakref.ref(self))
self._bufSinkPtr=self._bufSink.QueryInterface(ITTSBufNotifySink)
# HACK: Some buggy engines call Release() too many times on our buf sink.
# Therefore, don't let the buf sink be deleted before we release it ourselves.
Expand Down
6 changes: 3 additions & 3 deletions source/synthDrivers/sapi5.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ class SapiSink(object):
See https://msdn.microsoft.com/en-us/library/ms723587(v=vs.85).aspx
"""

def __init__(self, synth):
self.synthRef = weakref.ref(synth)
def __init__(self, synthRef: weakref.ReferenceType):
self.synthRef = synthRef

def Bookmark(self, streamNum, pos, bookmark, bookmarkId):
synth = self.synthRef()
Expand Down Expand Up @@ -230,7 +230,7 @@ def _initTts(self, voice=None):
outputDeviceID=nvwave.outputDeviceNameToID(config.conf["speech"]["outputDevice"], True)
if outputDeviceID>=0:
self.tts.audioOutput=self.tts.getAudioOutputs()[outputDeviceID]
self._eventsConnection = comtypes.client.GetEvents(self.tts, SapiSink(self))
self._eventsConnection = comtypes.client.GetEvents(self.tts, SapiSink(weakref.ref(self)))
self.tts.EventInterests = constants.SVEBookmark | constants.SVEEndInputStream
from comInterfaces.SpeechLib import ISpAudio
try:
Expand Down

0 comments on commit a8e8db1

Please sign in to comment.