Changeset 2348
- Timestamp:
- 08/12/08 08:32:18 (5 months ago)
- Location:
- trunk
- Files:
-
- 3 modified
-
. (modified) (3 props)
-
source/nvwave.py (modified) (10 diffs)
-
source/synthDrivers/_espeak.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property bzr:revision-id:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
-
old new 176 176 2145 jamie@jantrid.net-20080807065623-wh0xcx1l34f41h39 177 177 2146 jamie@jantrid.net-20080812020217-6ofbi1u1q3sbq7ni 178 2147 jamie@jantrid.net-20080812071342-5fqd45cc29z5ugh6
-
- Property bzr:revision-info
-
old new 1 timestamp: 2008-08-12 1 2:02:17.473999977+10001 timestamp: 2008-08-12 17:13:42.000000000 +1000 2 2 committer: James Teh <jamie@jantrid.net> 3 3 properties:
-
- Property bzr:ancestry:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
-
old new 8 8 mick@kulgan.net-20080701041209-fd196zokjqabm0u6 9 9 jamie@jantrid.net-20080702061732-274iwmap8bkwbp8b 10 jamie@jantrid.net-20080810101432-te9chzpil51jwjtd
-
- Property bzr:revision-id:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
-
trunk/source/nvwave.py
r2343 r2348 9 9 10 10 from __future__ import with_statement 11 import time12 11 import threading 13 12 from ctypes import * … … 19 18 20 19 winmm = windll.winmm 20 kernel32 = windll.kernel32 21 22 INFINITE = 0xffffffff 21 23 22 24 HWAVEOUT = HANDLE … … 56 58 CALLBACK_NULL = 0 57 59 #CALLBACK_FUNCTION = 0x30000 60 CALLBACK_EVENT = 0x50000 58 61 #waveOutProc = CFUNCTYPE(HANDLE, UINT, DWORD, DWORD, DWORD) 59 62 #WOM_DONE = 0x3bd … … 93 96 """ 94 97 95 def __init__(self, channels, samplesPerSec, bitsPerSample, outputDevice=WAVE_MAPPER ):98 def __init__(self, channels, samplesPerSec, bitsPerSample, outputDevice=WAVE_MAPPER, closeWhenIdle=True): 96 99 """Constructor. 97 100 @param channels: The number of channels of audio; e.g. 2 for stereo, 1 for mono. … … 103 106 @param outputDevice: The device ID or name of the audio output device to use. 104 107 @type outputDevice: int or basestring 108 @param closeWhenIdle: If C{True}, close the output device when no audio is being played. 109 @type closeWhenIdle: bool 105 110 @note: If C{outputDevice} is a name and no such device exists, the default device will be used. 106 111 @raise WindowsError: If there was an error opening the audio output device. … … 112 117 outputDevice = outputDeviceNameToID(outputDevice, True) 113 118 self.outputDeviceID = outputDevice 114 self._open() 115 self._whdr_lock = threading.RLock() 116 117 def _open(self): 118 wfx = WAVEFORMATEX() 119 wfx.wFormatTag = WAVE_FORMAT_PCM 120 wfx.nChannels = self.channels 121 wfx.nSamplesPerSec = self.samplesPerSec 122 wfx.wBitsPerSample = self.bitsPerSample 123 wfx.nBlockAlign = self.bitsPerSample / 8 * self.channels 124 wfx.nAvgBytesPerSec = self.samplesPerSec * wfx.nBlockAlign 125 waveout = HWAVEOUT(0) 126 winmm.waveOutOpen(byref(waveout), self.outputDeviceID, LPWAVEFORMATEX(wfx), 0, 0, CALLBACK_NULL) 127 self._waveout = waveout.value 128 self._prev_whdr = None 119 #: If C{True}, close the output device when no audio is being played. 120 #: @type: bool 121 self.closeWhenIdle = closeWhenIdle 122 self._waveout = None 123 self._waveout_event = kernel32.CreateEventW(None, False, False, None) 124 self._waveout_lock = threading.RLock() 125 self._lock = threading.RLock() 126 self.open() 127 128 def open(self): 129 """Open the output device. 130 This will be called automatically when required. 131 It is not an error if the output device is already open. 132 """ 133 with self._waveout_lock: 134 if self._waveout: 135 return 136 wfx = WAVEFORMATEX() 137 wfx.wFormatTag = WAVE_FORMAT_PCM 138 wfx.nChannels = self.channels 139 wfx.nSamplesPerSec = self.samplesPerSec 140 wfx.wBitsPerSample = self.bitsPerSample 141 wfx.nBlockAlign = self.bitsPerSample / 8 * self.channels 142 wfx.nAvgBytesPerSec = self.samplesPerSec * wfx.nBlockAlign 143 waveout = HWAVEOUT(0) 144 winmm.waveOutOpen(byref(waveout), self.outputDeviceID, LPWAVEFORMATEX(wfx), self._waveout_event, 0, CALLBACK_EVENT) 145 self._waveout = waveout.value 146 self._prev_whdr = None 129 147 130 148 def feed(self, data): … … 140 158 whdr.lpData = data 141 159 whdr.dwBufferLength = len(data) 142 winmm.waveOutPrepareHeader(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) 143 try: 144 winmm.waveOutWrite(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) 160 with self._lock: 161 with self._waveout_lock: 162 self.open() 163 winmm.waveOutPrepareHeader(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) 164 try: 165 winmm.waveOutWrite(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) 166 except WindowsError, e: 167 self.close() 168 raise e 145 169 self.sync() 146 except WindowsError, e:147 self.close()148 self._open()149 raise e150 with self._whdr_lock:151 170 self._prev_whdr = whdr 152 171 … … 154 173 """Synchronise with playback. 155 174 This method blocks until the previously fed chunk of audio has finished playing. 156 It need only be called directly if there is no more audio to feed, but synchronisation is nevertheless desired.157 """ 158 with self._ whdr_lock:175 It is called automatically by L{feed}, so usually need not be called directly by the user. 176 """ 177 with self._lock: 159 178 if not self._prev_whdr: 160 179 return 161 # todo: Wait for an event instead of spinning.180 assert self._waveout, "waveOut None before wait" 162 181 while not (self._prev_whdr.dwFlags & WHDR_DONE): 163 time.sleep(0.005) 164 winmm.waveOutUnprepareHeader(self._waveout, LPWAVEHDR(self._prev_whdr), sizeof(WAVEHDR)) 182 kernel32.WaitForSingleObject(self._waveout_event, INFINITE) 183 with self._waveout_lock: 184 assert self._waveout, "waveOut None after wait" 185 winmm.waveOutUnprepareHeader(self._waveout, LPWAVEHDR(self._prev_whdr), sizeof(WAVEHDR)) 165 186 self._prev_whdr = None 166 187 … … 170 191 @type switch: bool 171 192 """ 172 if switch: 173 winmm.waveOutPause(self._waveout) 174 else: 175 winmm.waveOutRestart(self._waveout) 193 with self._waveout_lock: 194 if not self._waveout: 195 return 196 if switch: 197 winmm.waveOutPause(self._waveout) 198 else: 199 winmm.waveOutRestart(self._waveout) 200 201 def idle(self): 202 """Indicate that this player is now idle; i.e. the current continuous segment of audio is complete. 203 This will first call L{sync} to synchronise with playback. 204 If L{closeWhenIdle} is C{True}, the output device will be closed. 205 A subsequent call to L{feed} will reopen it. 206 """ 207 with self._lock: 208 self.sync() 209 with self._waveout_lock: 210 if not self._waveout: 211 return 212 if self.closeWhenIdle: 213 self._close() 176 214 177 215 def stop(self): 178 216 """Stop playback. 179 217 """ 180 try: 181 winmm.waveOutReset(self._waveout) 182 except WindowsError: 183 # waveOutReset seems to fail randomly on some systems. 184 pass 185 # Unprepare the previous buffer. 186 self.sync() 218 with self._waveout_lock: 219 if not self._waveout: 220 return 221 try: 222 # Pausing first seems to make waveOutReset respond faster on some systems. 223 winmm.waveOutPause(self._waveout) 224 winmm.waveOutReset(self._waveout) 225 except WindowsError: 226 # waveOutReset seems to fail randomly on some systems. 227 pass 228 # Unprepare the previous buffer and close the output device if appropriate. 229 self.idle() 187 230 188 231 def close(self): 189 232 """Close the output device. 190 @postcondition: The audio device is closed; this instance is no longer useable.191 233 """ 192 234 self.stop() 235 with self._lock: 236 with self._waveout_lock: 237 if not self._waveout: 238 return 239 self._close() 240 241 def _close(self): 193 242 winmm.waveOutClose(self._waveout) 194 243 self._waveout = None 244 245 def __del__(self): 246 self.close() 247 kernel32.CloseHandle(self._waveout_event) 248 self._waveout_event = None 195 249 196 250 def _getOutputDevices(): … … 241 295 # No such ID. 242 296 if useDefaultIfInvalid: 243 return -1297 return WAVE_MAPPER 244 298 else: 245 299 raise LookupError("No such device name") -
trunk/source/synthDrivers/_espeak.py
r2204 r2348 122 122 lastIndex = event.contents.user_data 123 123 if not wav: 124 player. sync()124 player.idle() 125 125 isSpeaking = False 126 126 return 0

NVDA is supported by