From 4b5d1347a4eba415292b53de71b85697ed03561a Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 17 Oct 2016 17:30:07 -0500 Subject: [PATCH] more voice --- disco/gateway/events.py | 2 + disco/voice/client.py | 120 +++++--------------------------------- disco/voice/opus.py | 125 ++++++++++++++++++++++++++++++++++++++++ disco/voice/player.py | 93 ++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 106 deletions(-) create mode 100644 disco/voice/opus.py create mode 100644 disco/voice/player.py diff --git a/disco/gateway/events.py b/disco/gateway/events.py index 5b2e8b5..6d55690 100644 --- a/disco/gateway/events.py +++ b/disco/gateway/events.py @@ -49,6 +49,8 @@ class GatewayEvent(six.with_metaclass(GatewayEventMeta, Model)): """ Create this GatewayEvent class from data and the client. """ + cls.raw_data = obj + # If this event is wrapping a model, pull its fields if hasattr(cls, '_wraps_model'): alias, model = cls._wraps_model diff --git a/disco/voice/client.py b/disco/voice/client.py index b293ec3..2ca00ba 100644 --- a/disco/voice/client.py +++ b/disco/voice/client.py @@ -3,7 +3,6 @@ import socket import struct import time -from six.moves import queue from holster.enum import Enum from holster.emitter import Emitter @@ -23,11 +22,6 @@ VoiceState = Enum( VOICE_CONNECTED=6, ) -# TODO: -# - player implementation -# - encryption -# - cleanup - class VoiceException(Exception): def __init__(self, msg, client): @@ -45,18 +39,14 @@ class UDPVoiceClient(LoggingClass): self.run_task = None self.connected = False - self.seq = 0 - self.ts = 0 - - def send_frame(self, frame): - self.seq += 1 - data = '\x80\x78' - data += struct.pack('>H', self.seq) - data += struct.pack('>I', self.ts) - data += struct.pack('>I', self.vc.ssrc) - data += ''.join(frame) - self.send(data) - self.ts += 960 + def send_frame(self, frame, sequence, timestamp): + data = bytearray(12) + data[0] = 0x80 + data[1] = 0x78 + struct.pack_into('>H', data, 2, sequence) + struct.pack_into('>I', data, 4, timestamp) + struct.pack_into('>i', data, 8, self.vc.ssrc) + self.send(data + ''.join(frame)) def run(self): while True: @@ -126,7 +116,6 @@ class VoiceClient(LoggingClass): def set_state(self, state): prev_state = self.state self.state = state - print 'State Change %s to %s' % (prev_state, state) self.state_emitter.emit(state, prev_state) def heartbeat(self, interval): @@ -208,7 +197,6 @@ class VoiceClient(LoggingClass): self.log.warning('Voice websocket error: {}'.format(err)) def on_open(self): - print 'open' self.send(VoiceOPCode.IDENTIFY, { 'server_id': self.channel.guild_id, 'user_id': self.client.state.me.id, @@ -217,9 +205,12 @@ class VoiceClient(LoggingClass): }) def on_close(self, code, error): - # TODO self.log.warning('Voice websocket disconnected (%s, %s)', code, error) + if self.state == VoiceState.CONNECTED: + self.log.info('Attempting voice reconnection') + self.connect() + def connect(self, timeout=5, mute=False, deaf=False): self.set_state(VoiceState.AWAITING_ENDPOINT) @@ -255,88 +246,5 @@ class VoiceClient(LoggingClass): 'channel_id': None, }) - def send_frame(self, frame): - self.udp.send_frame(frame) - - -class OpusItem(object): - __slots__ = ('frames', 'idx') - - def __init__(self): - self.frames = [] - self.idx = 0 - - @classmethod - def from_raw_file(cls, path): - inst = cls() - obj = open(path, 'r') - - while True: - buff = obj.read(2) - if not buff: - return inst - size = struct.unpack('