Skip to content

Commit 16e6786

Browse files
authored
Merge 0ee3ac4 into 56a6209
2 parents 56a6209 + 0ee3ac4 commit 16e6786

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

source/nvwave.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import config
1919
from logHandler import log
2020
import os.path
21+
import core
2122

2223
__all__ = (
2324
"WavePlayer", "getOutputDeviceNames", "outputDeviceIDToName", "outputDeviceNameToID",
@@ -100,6 +101,9 @@ class WavePlayer(object):
100101
"""
101102
#: Minimum length of buffer (in ms) before audio is played.
102103
MIN_BUFFER_MS = 300
104+
#: The time (in ms) to wait after L{idle} is called before closing the audio
105+
#: device. This is only applicable if L{closeWhenIdle} is C{True}.
106+
IDLE_CLOSE_DELAY_MS = 10000
103107
#: Flag used to signal that L{stop} has been called.
104108
STOPPING = "stopping"
105109
#: A lock to prevent WaveOut* functions from being called simultaneously, as this can cause problems even if they are for different HWAVEOUTs.
@@ -141,6 +145,7 @@ def __init__(self, channels, samplesPerSec, bitsPerSample,
141145
#: If C{True}, close the output device when no audio is being played.
142146
#: @type: bool
143147
self.closeWhenIdle = closeWhenIdle
148+
self._closeTimer = None
144149
if buffered:
145150
#: Minimum size of the buffer before audio is played.
146151
#: However, this is ignored if an C{onDone} callback is provided to L{feed}.
@@ -158,13 +163,22 @@ def __init__(self, channels, samplesPerSec, bitsPerSample,
158163
self._lock = threading.RLock()
159164
self.open()
160165

166+
def _callOnMainThread(self, func, *args):
167+
if threading.get_ident() == core.mainThreadId:
168+
func(*args)
169+
else:
170+
wx.CallAfter(func, *args)
171+
161172
def open(self):
162173
"""Open the output device.
163174
This will be called automatically when required.
164175
It is not an error if the output device is already open.
165176
"""
177+
import inputCore; inputCore.logTimeSinceInput()
166178
with self._waveout_lock:
167179
if self._waveout:
180+
if self._closeTimer and self._closeTimer.IsRunning():
181+
self._callOnMainThread(self._closeTimer.Stop)
168182
return
169183
wfx = WAVEFORMATEX()
170184
wfx.wFormatTag = WAVE_FORMAT_PCM
@@ -269,7 +283,8 @@ def pause(self, switch):
269283
def idle(self):
270284
"""Indicate that this player is now idle; i.e. the current continuous segment of audio is complete.
271285
This will first call L{sync} to synchronise with playback.
272-
If L{closeWhenIdle} is C{True}, the output device will be closed.
286+
If L{closeWhenIdle} is C{True}, the output device will be closed if there
287+
is no further audio within L{IDLE_CLOSE_DELAY_MS}.
273288
A subsequent call to L{feed} will reopen it.
274289
"""
275290
if not self._minBufferSize:
@@ -286,7 +301,13 @@ def _idleUnbuffered(self):
286301
if not self._waveout:
287302
return
288303
if self.closeWhenIdle:
289-
self._close()
304+
if not self._closeTimer:
305+
# We need a cancellable timer, so we can't use core.callLater.
306+
self._closeTimer = wx.PyTimer(self._close)
307+
self._callOnMainThread(
308+
self._closeTimer.Start, self.IDLE_CLOSE_DELAY_MS,
309+
wx.TIMER_ONE_SHOT
310+
)
290311
if self._audioDucker: self._audioDucker.disable()
291312

292313
def stop(self):

0 commit comments

Comments
 (0)