From 017e4adb39bd04d92781f27c6d633c95dc7cd205 Mon Sep 17 00:00:00 2001 From: David Hozic Date: Mon, 14 Aug 2023 01:21:24 +0200 Subject: [PATCH] feat: VoiceClient.play wait_finish parameter for awaiting end of stream (#2194) * wait_end * style(pre-commit): auto fixes from pre-commit.com hooks * Changelog * style(pre-commit): auto fixes from pre-commit.com hooks * wait_finish * Changelog --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Lala Sabathil --- CHANGELOG.md | 2 ++ discord/voice_client.py | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ceeaf33723..e2e3ef75f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,8 @@ These changes are available on the `master` branch, but have not yet been releas - Added `suppress` and `allowed_mentions` parameters to `Webhook` and `InteractionResponse` edit methods. ([#2138](https://github.com/Pycord-Development/pycord/pull/2138)) +- Added `wait_finish` parameter to `VoiceClient.play` for awaiting the end of a play. + ([#2194](https://github.com/Pycord-Development/pycord/pull/2194)) ### Changed diff --git a/discord/voice_client.py b/discord/voice_client.py index f1e16cf812..437311122a 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -624,7 +624,11 @@ def get_ssrc(self, user_id): ] def play( - self, source: AudioSource, *, after: Callable[[Exception | None], Any] = None + self, + source: AudioSource, + *, + after: Callable[[Exception | None], Any] = None, + wait_finish: bool = False, ) -> None: """Plays an :class:`AudioSource`. @@ -643,6 +647,14 @@ def play( The finalizer that is called after the stream is exhausted. This function must have a single parameter, ``error``, that denotes an optional exception that was raised during playing. + wait_finish: bool + If True, an awaitable will be returned, which can be used to wait for + audio to stop playing. This awaitable will return an exception if raised, + or None when no exception is raised. + + If False, None is returned and the function does not block. + + .. versionadded:: v2.5 Raises ------ @@ -668,8 +680,22 @@ def play( if not self.encoder and not source.is_opus(): self.encoder = opus.Encoder() + future = None + if wait_finish: + future = asyncio.Future() + after_callback = after + + def _after(exc: Exception | None): + if callable(after_callback): + after_callback(exc) + + future.set_result(exc) + + after = _after + self._player = AudioPlayer(source, self, after=after) self._player.start() + return future def unpack_audio(self, data): """Takes an audio packet received from Discord and decodes it into pcm audio data.