Browse Source

Add VoiceClient.wait_until_done

Adds a new function: `VoiceClient.wait_until_done`.  As the name
suggests, it waits until the player is done, similar to the other
`wait_until_` functions.
pull/9842/head
Imayhaveborkedit 11 months ago
parent
commit
482044302f
  1. 16
      discord/player.py
  2. 19
      discord/voice_client.py

16
discord/player.py

@ -21,6 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
from __future__ import annotations
import threading
@ -717,6 +718,8 @@ class AudioPlayer(threading.Thread):
self._current_error: Optional[Exception] = None
self._lock: threading.Lock = threading.Lock()
self._end_async: asyncio.Event = asyncio.Event(loop=client.loop)
if after is not None and not callable(after):
raise TypeError('Expected a callable for the "after" parameter.')
@ -774,7 +777,8 @@ class AudioPlayer(threading.Thread):
self.stop()
finally:
self._call_after()
self.source.cleanup()
self._cleanup()
self.client.loop.call_soon_threadsafe(self._end_async.set)
def _call_after(self) -> None:
error = self._current_error
@ -788,6 +792,12 @@ class AudioPlayer(threading.Thread):
elif error:
_log.exception('Exception in voice thread %s', self.name, exc_info=error)
def _cleanup(self) -> None:
try:
self.source.cleanup()
except Exception:
_log.exception("Error cleaning up audio source %s", self.source)
def stop(self) -> None:
self._end.set()
self._resumed.set()
@ -817,6 +827,10 @@ class AudioPlayer(threading.Thread):
self.source = source
self.resume(update_speaking=False)
async def wait_async(self) -> Optional[Exception]:
await self._end_async.wait()
return self._current_error
def _speak(self, speaking: SpeakingState) -> None:
try:
asyncio.run_coroutine_threadsafe(self.client.ws.speak(speaking), self.client.client.loop)

19
discord/voice_client.py

@ -538,6 +538,25 @@ class VoiceClient(VoiceProtocol):
self._player.set_source(value)
async def wait_until_done(self) -> Optional[Exception]:
"""|coro|
Waits for the audio player to finish playback and returns any encountered error.
Returns
--------
Optional[:class:`Exception`]
The exception the player encountered during playback, or ``None``.
"""
if not self.is_connected():
raise ClientException('Not connected to voice.')
if self._player is None:
raise ValueError('Not playing anything.')
return await self._player.wait_async()
def send_audio_packet(self, data: bytes, *, encode: bool = True) -> None:
"""Sends an audio packet composed of the data.

Loading…
Cancel
Save