Client now keeps a reference to the VoiceClient constructed.

This commit is contained in:
Rapptz 2015-12-09 21:32:33 -05:00
parent 5335f468d2
commit eda3c626db
2 changed files with 30 additions and 11 deletions

View File

@ -72,6 +72,10 @@ class Client:
----------- -----------
user : Optional[:class:`User`] user : Optional[:class:`User`]
Represents the connected client. None if not logged in. 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` servers : list of :class:`Server`
The servers that the connected client is a member of. The servers that the connected client is a member of.
private_channels : list of :class:`PrivateChannel` private_channels : list of :class:`PrivateChannel`
@ -93,6 +97,7 @@ class Client:
self.ws = None self.ws = None
self.token = None self.token = None
self.gateway = None self.gateway = None
self.voice = None
self.loop = asyncio.get_event_loop() if loop is None else loop self.loop = asyncio.get_event_loop() if loop is None else loop
self._listeners = [] self._listeners = []
@ -112,10 +117,6 @@ class Client:
self._closed = False self._closed = False
self._is_logged_in = 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 # These two events correspond to the two events necessary
# for a connection to be made # for a connection to be made
self._voice_data_found = asyncio.Event(loop=self.loop) self._voice_data_found = asyncio.Event(loop=self.loop)
@ -569,10 +570,15 @@ class Client:
if self._closed: if self._closed:
return return
if self.is_voice_connected():
yield from self.voice.disconnect()
self.voice = None
yield from self.ws.close() yield from self.ws.close()
self.keep_alive.cancel() self.keep_alive.cancel()
self._closed = True self._closed = True
@asyncio.coroutine @asyncio.coroutine
def start(self, email, password): def start(self, email, password):
"""|coro| """|coro|
@ -2010,6 +2016,9 @@ class Client:
Joins a voice channel and creates a :class:`VoiceClient` to Joins a voice channel and creates a :class:`VoiceClient` to
establish your connection to the voice server. establish your connection to the voice server.
After this function is successfully called, :attr:`voice` is
set to the returned :class:`VoiceClient`.
Parameters Parameters
---------- ----------
channel : :class:`Channel` channel : :class:`Channel`
@ -2032,7 +2041,7 @@ class Client:
A voice client that is fully connected to the voice server. 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') raise ClientException('Already connected to a voice channel')
if getattr(channel, 'type', ChannelType.text) != ChannelType.voice: if getattr(channel, 'type', ChannelType.text) != ChannelType.voice:
@ -2060,7 +2069,6 @@ class Client:
kwargs = { kwargs = {
'user': self.user, 'user': self.user,
'connected': self._is_voice_connected,
'channel': self.voice_channel, 'channel': self.voice_channel,
'data': self._voice_data_found.data, 'data': self._voice_data_found.data,
'loop': self.loop, 'loop': self.loop,
@ -2068,6 +2076,11 @@ class Client:
'main_ws': self.ws 'main_ws': self.ws
} }
result = VoiceClient(**kwargs) self.voice = VoiceClient(**kwargs)
yield from result.connect() yield from self.voice.connect()
return result 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()

View File

@ -134,14 +134,16 @@ class VoiceClient:
The endpoint we are connecting to. The endpoint we are connecting to.
channel : :class:`Channel` channel : :class:`Channel`
The voice channel connected to. 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.user = user
self._connected = connected
self.main_ws = main_ws self.main_ws = main_ws
self.channel = channel self.channel = channel
self.session_id = session_id self.session_id = session_id
self.loop = loop self.loop = loop
self._connected = asyncio.Event(loop=self.loop)
self.token = data.get('token') self.token = data.get('token')
self.guild_id = data.get('guild_id') self.guild_id = data.get('guild_id')
self.endpoint = data.get('endpoint') self.endpoint = data.get('endpoint')
@ -296,6 +298,10 @@ class VoiceClient:
yield from self.main_ws.send(utils.to_json(payload)) 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 # audio related
def _get_voice_packet(self, data): def _get_voice_packet(self, data):