diff options
| author | Rapptz <[email protected]> | 2017-04-18 02:29:43 -0400 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2017-04-18 03:49:48 -0400 |
| commit | 3b1b26ffb1c9a75ac9c3f958d6e134ccddd6be07 (patch) | |
| tree | dcaac87b10f4d2a2bdf82f260a5738c1367f425f /discord/abc.py | |
| parent | Don't clear state when READY is reached for auto sharded clients. (diff) | |
| download | discord.py-3b1b26ffb1c9a75ac9c3f958d6e134ccddd6be07.tar.xz discord.py-3b1b26ffb1c9a75ac9c3f958d6e134ccddd6be07.zip | |
Re-implement voice sending.
This is a complete redesign of the old voice code.
A list of major changes is as follows:
* The voice websocket will now automatically reconnect with
exponential back-off just like the regular Client does.
* Removal of the stream player concept.
* Audio now gracefully pauses and resumes when a disconnect is found.
* Introduce a discord.AudioSource concept to abstract streams
* Flatten previous stream player functionality with the
VoiceClient, e.g. player.stop() is now voice_client.stop()
* With the above re-coupling this means you no longer have to
store players anywhere.
* The after function now requires a single parameter, the error,
if any existed. This will typically be None.
A lot of this design is experimental.
Diffstat (limited to 'discord/abc.py')
| -rw-r--r-- | discord/abc.py | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/discord/abc.py b/discord/abc.py index 9c94c5dc..07d72093 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -25,19 +25,18 @@ DEALINGS IN THE SOFTWARE. """ import abc -import io -import os import asyncio from collections import namedtuple from .iterators import HistoryIterator from .context_managers import Typing -from .errors import InvalidArgument +from .errors import InvalidArgument, ClientException from .permissions import PermissionOverwrite, Permissions from .role import Role from .invite import Invite from .file import File +from .voice_client import VoiceClient from . import utils, compat class _Undefined: @@ -783,3 +782,67 @@ class Messageable(metaclass=abc.ABCMeta): counter += 1 """ return HistoryIterator(self, limit=limit, before=before, after=after, around=around, reverse=reverse) + + +class Callable(metaclass=abc.ABCMeta): + __slots__ = () + + @abc.abstractmethod + def _get_voice_client_key(self): + raise NotImplementedError + + @abc.abstractmethod + def _get_voice_state_pair(self): + raise NotImplementedError + + @asyncio.coroutine + def connect(self, *, timeout=10.0, reconnect=True): + """|coro| + + Connects to voice and creates a :class:`VoiceClient` to establish + your connection to the voice server. + + Parameters + ----------- + timeout: float + The timeout in seconds to wait for the + initial handshake to be completed. + reconnect: bool + Whether the bot should automatically attempt + a reconnect if a part of the handshake fails + or the gateway goes down. + + Raises + ------- + asyncio.TimeoutError + Could not connect to the voice channel in time. + ClientException + You are already connected to a voice channel. + OpusNotLoaded + The opus library has not been loaded. + + Returns + ------- + :class:`VoiceClient` + A voice client that is fully connected to the voice server. + """ + key_id, key_name = self._get_voice_client_key() + state = self._state + + if state._get_voice_client(key_id): + raise ClientException('Already connected to a voice channel.') + + voice = VoiceClient(state=state, timeout=timeout, channel=self) + + try: + yield from voice.connect(reconnect=reconnect) + except asyncio.TimeoutError as e: + try: + yield from voice.disconnect() + except: + # we don't care if disconnect failed because connection failed + pass + raise e # re-raise + + state._add_voice_client(key_id, voice) + return voice |