Skip to content

Commit 8a6ae39

Browse files
committed
finish voice things, start voice-recv things
1 parent b27b438 commit 8a6ae39

File tree

9 files changed

+1311
-121
lines changed

9 files changed

+1311
-121
lines changed

discord/opus.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
if TYPE_CHECKING:
4545
T = TypeVar("T")
46+
APPLICATION_CTL = Literal['audio', 'voip', 'lowdelay']
4647
BAND_CTL = Literal["narrow", "medium", "wide", "superwide", "full"]
4748
SIGNAL_CTL = Literal["auto", "voice", "music"]
4849

@@ -61,6 +62,12 @@ class SignalCtl(TypedDict):
6162
music: int
6263

6364

65+
class ApplicationCtl(TypedDict):
66+
audio: int
67+
voip: int
68+
lowdelay: int
69+
70+
6471
__all__ = (
6572
"Encoder",
6673
"Decoder",
@@ -74,6 +81,7 @@ class SignalCtl(TypedDict):
7481
c_int_ptr = ctypes.POINTER(ctypes.c_int)
7582
c_int16_ptr = ctypes.POINTER(ctypes.c_int16)
7683
c_float_ptr = ctypes.POINTER(ctypes.c_float)
84+
OPUS_SILENCE = b'\xf8\xff\xfe'
7785

7886
_lib = None
7987

@@ -96,9 +104,11 @@ class DecoderStruct(ctypes.Structure):
96104
BAD_ARG = -1
97105

98106
# Encoder CTLs
99-
APPLICATION_AUDIO = 2049
100-
APPLICATION_VOIP = 2048
101-
APPLICATION_LOWDELAY = 2051
107+
application_ctl: ApplicationCtl = {
108+
'audio': 2049,
109+
'lowdelay': 2051,
110+
'voip': 2048,
111+
}
102112

103113
CTL_SET_BITRATE = 4002
104114
CTL_SET_BANDWIDTH = 4008
@@ -365,16 +375,37 @@ def get_opus_version() -> str:
365375

366376

367377
class Encoder(_OpusStruct):
368-
def __init__(self, application: int = APPLICATION_AUDIO):
378+
def __init__(
379+
self,
380+
*,
381+
application: APPLICATION_CTL = 'audio',
382+
bitrate: int = 128,
383+
fec: bool = True,
384+
expected_packet_loss: float = 0.15,
385+
bandwidth: BAND_CTL = 'full',
386+
signal_type: SIGNAL_TL = 'auto',
387+
) -> None:
388+
if application not in application_ctl:
389+
raise ValueError(
390+
'invalid application ctl type provided'
391+
)
392+
if not 16 <= bitrate <= 512:
393+
raise ValueError('bitrate must be between 16 and 512, both included')
394+
if not 0 < expected_packet_loss <= 1:
395+
raise ValueError(
396+
'expected_packet_loss must be between 0 and 1, including 1',
397+
)
398+
369399
_OpusStruct.get_opus_version()
370400

371-
self.application: int = application
401+
self.application: int = application_ctl[application]
372402
self._state: EncoderStruct = self._create_state()
373-
self.set_bitrate(128)
374-
self.set_fec(True)
375-
self.set_expected_packet_loss_percent(0.15)
376-
self.set_bandwidth("full")
377-
self.set_signal_type("auto")
403+
404+
self.set_bitrate(bitrate)
405+
self.set_fec(fec)
406+
self.set_expected_packet_loss_percent(expected_packet_loss)
407+
self.set_bandwidth(bandwidth)
408+
self.set_signal_type(signal_type)
378409

379410
def __del__(self) -> None:
380411
if hasattr(self, "_state"):

discord/sinks/core.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from .errors import SinkException
3838

3939
if TYPE_CHECKING:
40-
from ..voice_client import VoiceClient
40+
from ..voice.client import VoiceClient
4141

4242
__all__ = (
4343
"Filters",
@@ -103,9 +103,14 @@ class RawData:
103103
.. versionadded:: 2.0
104104
"""
105105

106-
def __init__(self, data, client):
107-
self.data = bytearray(data)
108-
self.client = client
106+
if TYPE_CHECKING:
107+
sequence: int
108+
timestamp: int
109+
ssrc: int
110+
111+
def __init__(self, data: bytes, client: VoiceClient):
112+
self.data: bytearray = bytearray(data)
113+
self.client: VoiceClient = client
109114

110115
unpacker = struct.Struct(">xxHII")
111116
self.sequence, self.timestamp, self.ssrc = unpacker.unpack_from(self.data[:12])
@@ -120,16 +125,16 @@ def __init__(self, data, client):
120125
else:
121126
cutoff = 12
122127

123-
self.header = data[:cutoff]
128+
self.header: bytes = data[:cutoff]
124129
self.data = self.data[cutoff:]
125130

126-
self.decrypted_data = getattr(self.client, f"_decrypt_{self.client.mode}")(
131+
self.decrypted_data: bytes = getattr(self.client, f"_decrypt_{self.client.mode}")(
127132
self.header, self.data
128133
)
129-
self.decoded_data = None
134+
self.decoded_data: bytes | None = None
130135

131-
self.user_id = None
132-
self.receive_time = time.perf_counter()
136+
self.user_id: int | None = None
137+
self.receive_time: float = time.perf_counter()
133138

134139

135140
class AudioData:

discord/state.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,8 @@ def parse_voice_state_update(self, data) -> None:
18531853
if int(data["user_id"]) == self_id:
18541854
voice = self._get_voice_client(guild.id)
18551855
if voice is not None:
1856-
coro = voice.on_voice_state_update(data)
1856+
payload = RawVoiceStateUpdateEvent(data=data, state=self)
1857+
coro = voice.on_voice_state_update(payload)
18571858
asyncio.create_task(
18581859
logging_coroutine(
18591860
coro, info="Voice Protocol voice state update handler"
@@ -1890,8 +1891,9 @@ def parse_voice_server_update(self, data) -> None:
18901891
key_id = int(data["channel_id"])
18911892

18921893
vc = self._get_voice_client(key_id)
1894+
payload = RawVoiceServerUpdateEvent(data=data, state=self)
18931895
if vc is not None:
1894-
coro = vc.on_voice_server_update(data)
1896+
coro = vc.on_voice_server_update(payload)
18951897
asyncio.create_task(
18961898
logging_coroutine(
18971899
coro, info="Voice Protocol voice server update handler"

0 commit comments

Comments
 (0)