diff --git a/discord/voice_client.py b/discord/voice_client.py index e31e8f878..e93b5180e 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -59,39 +59,54 @@ class StreamPlayer(threading.Thread): def __init__(self, stream, encoder, connected, player, after, **kwargs): threading.Thread.__init__(self, **kwargs) self.buff = stream - self.encoder = encoder + self.frame_size = encoder.frame_size self.player = player - self._event = threading.Event() + self._end = threading.Event() + self._paused = threading.Event() self._connected = connected self.after = after - self.delay = self.encoder.frame_length / 1000.0 + self.delay = encoder.frame_length / 1000.0 def run(self): self.loops = 0 - start = time.time() + self._start = time.time() while not self.is_done(): + if self._paused.is_set(): + continue + self.loops += 1 - data = self.buff.read(self.encoder.frame_size) - log.info('received {} bytes (out of {})'.format(len(data), self.encoder.frame_size)) - if len(data) != self.encoder.frame_size: + data = self.buff.read(self.frame_size) + log.info('received {} bytes (out of {})'.format(len(data), self.frame_size)) + if len(data) != self.frame_size: self.stop() break self.player(data) - next_time = start + self.delay * self.loops + next_time = self._start + self.delay * self.loops delay = max(0, self.delay + (next_time - time.time())) time.sleep(delay) def stop(self): - self._event.set() + self._end.set() if callable(self.after): try: self.after() except: pass + def pause(self): + self._paused.set() + + def resume(self): + self.loops = 0 + self._start = time.time() + self._paused.clear() + + def is_playing(self): + return not self._paused.is_set() and not self.is_done() + def is_done(self): - return not self._connected.is_set() or self._event.is_set() + return not self._connected.is_set() or self._end.is_set() class VoiceClient: """Represents a Discord voice connection. @@ -395,15 +410,21 @@ class VoiceClient: The following operations are valid on the ``StreamPlayer`` object: - +------------------+--------------------------------------------------+ - | Operation | Description | - +==================+==================================================+ - | player.start() | Starts the audio stream. | - +------------------+--------------------------------------------------+ - | player.stop() | Stops the audio stream. | - +------------------+--------------------------------------------------+ - | player.is_done() | Returns a bool indicating if the stream is done. | - +------------------+--------------------------------------------------+ + +---------------------+-----------------------------------------------------+ + | Operation | Description | + +=====================+=====================================================+ + | player.start() | Starts the audio stream. | + +---------------------+-----------------------------------------------------+ + | player.stop() | Stops the audio stream. | + +---------------------+-----------------------------------------------------+ + | player.is_done() | Returns a bool indicating if the stream is done. | + +---------------------+-----------------------------------------------------+ + | player.is_playing() | Returns a bool indicating if the stream is playing. | + +---------------------+-----------------------------------------------------+ + | player.pause() | Pauses the audio stream. | + +---------------------+-----------------------------------------------------+ + | player.resume() | Resumes the audio stream. | + +---------------------+-----------------------------------------------------+ The stream must have the same sampling rate as the encoder and the same number of channels. The defaults are 48000 Mhz and 2 channels. You