Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VoiceClient.wait_until_done #9842

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion discord/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""

from __future__ import annotations

import threading
Expand Down Expand Up @@ -717,6 +718,8 @@ def __init__(
self._current_error: Optional[Exception] = None
self._lock: threading.Lock = threading.Lock()

self._end_future = client.loop.create_future()

if after is not None and not callable(after):
raise TypeError('Expected a callable for the "after" parameter.')

Expand Down Expand Up @@ -774,7 +777,8 @@ def run(self) -> None:
self.stop()
finally:
self._call_after()
self.source.cleanup()
self._cleanup()
self.client.loop.call_soon_threadsafe(self._end_future.set_result, self._current_error)

def _call_after(self) -> None:
error = self._current_error
Expand All @@ -788,6 +792,12 @@ def _call_after(self) -> None:
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()
Expand Down Expand Up @@ -817,6 +827,9 @@ def set_source(self, source: AudioSource) -> None:
self.source = source
self.resume(update_speaking=False)

async def wait_async(self) -> Optional[Exception]:
return await self._end_future

def _speak(self, speaking: SpeakingState) -> None:
try:
asyncio.run_coroutine_threadsafe(self.client.ws.speak(speaking), self.client.client.loop)
Expand Down
21 changes: 21 additions & 0 deletions discord/voice_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,27 @@ def source(self, value: AudioSource) -> None:

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.

.. versionadded:: 2.4

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.

Expand Down
Loading