From eda3c626db67281858ae5097d8fb07e37a4bf862 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Wed, 9 Dec 2015 21:32:33 -0500 Subject: [PATCH] Client now keeps a reference to the VoiceClient constructed. --- discord/client.py | 31 ++++++++++++++++++++++--------- discord/voice_client.py | 10 ++++++++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/discord/client.py b/discord/client.py index bfa54d532..0ffe73b81 100644 --- a/discord/client.py +++ b/discord/client.py @@ -72,6 +72,10 @@ class Client: ----------- user : Optional[:class:`User`] Represents the connected client. None if not logged in. + voice : Optional[:class:`VoiceClient`] + Represents the current voice connection. None if you are not connected + to a voice channel. To connect to voice use :meth:`join_voice_channel`. + To query the voice connection state use :meth:`is_voice_connected`. servers : list of :class:`Server` The servers that the connected client is a member of. private_channels : list of :class:`PrivateChannel` @@ -93,6 +97,7 @@ class Client: self.ws = None self.token = None self.gateway = None + self.voice = None self.loop = asyncio.get_event_loop() if loop is None else loop self._listeners = [] @@ -112,10 +117,6 @@ class Client: self._closed = False self._is_logged_in = False - # this is shared state between Client and VoiceClient - # could this lead to issues? Not sure. I want to say no. - self._is_voice_connected = asyncio.Event(loop=self.loop) - # These two events correspond to the two events necessary # for a connection to be made self._voice_data_found = asyncio.Event(loop=self.loop) @@ -569,10 +570,15 @@ class Client: if self._closed: return + if self.is_voice_connected(): + yield from self.voice.disconnect() + self.voice = None + yield from self.ws.close() self.keep_alive.cancel() self._closed = True + @asyncio.coroutine def start(self, email, password): """|coro| @@ -2010,6 +2016,9 @@ class Client: Joins a voice channel and creates a :class:`VoiceClient` to establish your connection to the voice server. + After this function is successfully called, :attr:`voice` is + set to the returned :class:`VoiceClient`. + Parameters ---------- channel : :class:`Channel` @@ -2032,7 +2041,7 @@ class Client: A voice client that is fully connected to the voice server. """ - if self._is_voice_connected.is_set(): + if self.is_voice_connected(): raise ClientException('Already connected to a voice channel') if getattr(channel, 'type', ChannelType.text) != ChannelType.voice: @@ -2060,7 +2069,6 @@ class Client: kwargs = { 'user': self.user, - 'connected': self._is_voice_connected, 'channel': self.voice_channel, 'data': self._voice_data_found.data, 'loop': self.loop, @@ -2068,6 +2076,11 @@ class Client: 'main_ws': self.ws } - result = VoiceClient(**kwargs) - yield from result.connect() - return result + self.voice = VoiceClient(**kwargs) + yield from self.voice.connect() + return self.voice + + + def is_voice_connected(self): + """bool : Indicates if we are currently connected to a voice channel.""" + return self.voice is not None and self.voice.is_connected() diff --git a/discord/voice_client.py b/discord/voice_client.py index e93b5180e..51f8929bd 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -134,14 +134,16 @@ class VoiceClient: The endpoint we are connecting to. channel : :class:`Channel` The voice channel connected to. + loop + The event loop that the voice client is running on. """ - def __init__(self, user, connected, main_ws, session_id, channel, data, loop): + def __init__(self, user, main_ws, session_id, channel, data, loop): self.user = user - self._connected = connected self.main_ws = main_ws self.channel = channel self.session_id = session_id self.loop = loop + self._connected = asyncio.Event(loop=self.loop) self.token = data.get('token') self.guild_id = data.get('guild_id') self.endpoint = data.get('endpoint') @@ -296,6 +298,10 @@ class VoiceClient: yield from self.main_ws.send(utils.to_json(payload)) + def is_connected(self): + """bool : Indicates if the voice client is connected to voice.""" + return self._connected.is_set() + # audio related def _get_voice_packet(self, data):