1
2
3
4
5
6
7 import locale
8 from collections import OrderedDict
9 import _winreg
10 from comtypes import COMObject, COMError
11 from ctypes import *
12 from synthDriverHandler import SynthDriver,VoiceInfo
13 from logHandler import log
14 import speech
15 from _sapi4 import *
16 import config
17 import nvwave
35
37
38 name="sapi4"
39 description="Microsoft Speech API version 4"
40 supportedSettings=[SynthDriver.VoiceSetting()]
41
42 @classmethod
44 try:
45 _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, r"CLSID\%s" % CLSID_TTSEnumerator).Close()
46 return True
47 except WindowsError:
48 return False
49
51 enginesList=[]
52 self._ttsEngines.Reset()
53 while True:
54 mode=TTSMODEINFO()
55 fetched=c_ulong()
56 try:
57 self._ttsEngines.Next(1,byref(mode),byref(fetched))
58 except:
59 log.error("can't get next engine",exc_info=True)
60 break
61 if fetched.value==0:
62 break
63 enginesList.append(mode)
64 return enginesList
65
78
80 self._bufSink._allowDelete = True
81
82 - def speak(self,speechSequence):
103
105 self._ttsCentral.AudioReset()
106 self.lastIndex=None
107
109 if switch:
110 try:
111 self._ttsCentral.AudioPause()
112 except COMError:
113 pass
114 else:
115 self._ttsCentral.AudioResume()
116
123
125 try:
126 val=GUID(val)
127 except:
128 val=self._enginesList[0].gModeID
129 mode=None
130 for mode in self._enginesList:
131 if mode.gModeID==val:
132 break
133 if mode is None:
134 raise ValueError("no such mode: %s"%val)
135 self._currentMode=mode
136 self._ttsAudio=CoCreateInstance(CLSID_MMAudioDest,IAudioMultiMediaDevice)
137 self._ttsAudio.DeviceNumSet(nvwave.outputDeviceNameToID(config.conf["speech"]["outputDevice"], True))
138 self._ttsCentral=POINTER(ITTSCentralW)()
139 self._ttsEngines.Select(self._currentMode.gModeID,byref(self._ttsCentral),self._ttsAudio)
140 self._ttsAttrs=self._ttsCentral.QueryInterface(ITTSAttributes)
141
142 hasRate=bool(mode.dwFeatures&TTSFEATURE_SPEED)
143 if hasRate:
144 try:
145 oldVal=DWORD()
146 self._ttsAttrs.SpeedGet(byref(oldVal))
147 self._ttsAttrs.SpeedSet(TTSATTR_MINSPEED)
148 newVal=DWORD()
149 self._ttsAttrs.SpeedGet(byref(newVal))
150 self._minRate=newVal.value
151 self._ttsAttrs.SpeedSet(TTSATTR_MAXSPEED)
152 self._ttsAttrs.SpeedGet(byref(newVal))
153
154 self._maxRate=newVal.value-1
155 self._ttsAttrs.SpeedSet(oldVal.value)
156 if self._maxRate<=self._minRate:
157 hasRate=False
158 except COMError:
159 hasRate=False
160 if hasRate:
161 if not self.isSupported('rate'):
162 self.supportedSettings.insert(1,SynthDriver.RateSetting())
163 else:
164 if self.isSupported("rate"): self.removeSetting("rate")
165
166 hasPitch=bool(mode.dwFeatures&TTSFEATURE_PITCH)
167 if hasPitch:
168 try:
169 oldVal=WORD()
170 self._ttsAttrs.PitchGet(byref(oldVal))
171 self._ttsAttrs.PitchSet(TTSATTR_MINPITCH)
172 newVal=WORD()
173 self._ttsAttrs.PitchGet(byref(newVal))
174 self._minPitch=newVal.value
175 self._ttsAttrs.PitchSet(TTSATTR_MAXPITCH)
176 self._ttsAttrs.PitchGet(byref(newVal))
177 self._maxPitch=newVal.value
178 self._ttsAttrs.PitchSet(oldVal.value)
179 if self._maxPitch<=self._minPitch:
180 hasPitch=False
181 except COMError:
182 hasPitch=False
183 if hasPitch:
184 if not self.isSupported('pitch'):
185 self.supportedSettings.insert(2,SynthDriver.PitchSetting())
186 else:
187 if self.isSupported('pitch'): self.removeSetting('pitch')
188
189 hasVolume=bool(mode.dwFeatures&TTSFEATURE_VOLUME)
190 if hasVolume:
191 try:
192 oldVal=DWORD()
193 self._ttsAttrs.VolumeGet(byref(oldVal))
194 self._ttsAttrs.VolumeSet(TTSATTR_MINVOLUME)
195 newVal=DWORD()
196 self._ttsAttrs.VolumeGet(byref(newVal))
197 self._minVolume=newVal.value
198 self._ttsAttrs.VolumeSet(TTSATTR_MAXVOLUME)
199 self._ttsAttrs.VolumeGet(byref(newVal))
200 self._maxVolume=newVal.value
201 self._ttsAttrs.VolumeSet(oldVal.value)
202 if self._maxVolume<=self._minVolume:
203 hasVolume=False
204 except COMError:
205 hasVolume=False
206 if hasVolume:
207 if not self.isSupported('volume'):
208 self.supportedSettings.insert(3,SynthDriver.VolumeSetting())
209 else:
210 if self.isSupported('volume'): self.removeSetting('volume')
211
213 return str(self._currentMode.gModeID)
214
216 voices=OrderedDict()
217 for mode in self._enginesList:
218 ID=str(mode.gModeID)
219 name="%s - %s"%(mode.szModeName,mode.szProductName)
220 try:
221 language=locale.windows_locale[mode.language.LanguageID]
222 except KeyError:
223 language=None
224 voices[ID]=VoiceInfo(ID,name,language)
225 return voices
226
231
235
240
244
246 val=DWORD()
247 self._ttsAttrs.VolumeGet(byref(val))
248 return self._paramToPercent(val.value&0xffff,self._minVolume&0xffff,self._maxVolume&0xffff)
249
254