This commit is contained in:
emdee 2023-12-11 15:06:07 +00:00
parent da3602293a
commit 9c9ce9fec8
2 changed files with 65 additions and 56 deletions

View File

@ -5,9 +5,14 @@ from ctypes import (CFUNCTYPE, POINTER, ArgumentError, byref, c_bool, c_char_p,
c_void_p, cast) c_void_p, cast)
from typing import Union, Callable from typing import Union, Callable
from wrapper.libtox import LibToxAV try:
from wrapper.toxav_enums import * from wrapper.libtox import LibToxAV
#? from wrapper.toxencryptsave_enums_and_consts import *
import wrapper.toxencryptsave_enums_and_consts as enum
except:
from wrapper.libtox import LibToxAV
#? from toxencryptsave_enums_and_consts import *
import toxencryptsave_enums_and_consts as enum
def LOG_ERROR(a: str) -> None: print('EROR> '+a) def LOG_ERROR(a: str) -> None: print('EROR> '+a)
def LOG_WARN(a: str) -> None: print('WARN> '+a) def LOG_WARN(a: str) -> None: print('WARN> '+a)
@ -37,12 +42,12 @@ class ToxAV:
f.restype = POINTER(c_void_p) f.restype = POINTER(c_void_p)
self._toxav_pointer = f(tox_pointer, byref(toxav_err_new)) self._toxav_pointer = f(tox_pointer, byref(toxav_err_new))
toxav_err_new = toxav_err_new.value toxav_err_new = toxav_err_new.value
if toxav_err_new == TOXAV_ERR_NEW['NULL']: if toxav_err_new == enum.TOXAV_ERR_NEW['NULL']:
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.') raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
elif toxav_err_new == TOXAV_ERR_NEW['MALLOC']: elif toxav_err_new == enum.TOXAV_ERR_NEW['MALLOC']:
raise MemoryError('Memory allocation failure while trying to allocate structures required for the A/V ' raise MemoryError('Memory allocation failure while trying to allocate structures required for the A/V '
'session.') 'session.')
elif toxav_err_new == TOXAV_ERR_NEW['MULTIPLE']: elif toxav_err_new == enum.TOXAV_ERR_NEW['MULTIPLE']:
raise RuntimeError('Attempted to create a second session for the same Tox instance.') raise RuntimeError('Attempted to create a second session for the same Tox instance.')
self.call_state_cb = None self.call_state_cb = None
@ -59,7 +64,7 @@ class ToxAV:
""" """
self.libtoxav.toxav_kill(self._toxav_pointer) self.libtoxav.toxav_kill(self._toxav_pointer)
def get_tox_pointer(self) -> None: def get_tox_pointer(self):
""" """
Returns the Tox instance the A/V object was created for. Returns the Tox instance the A/V object was created for.
@ -106,20 +111,20 @@ class ToxAV:
result = self.libtoxav.toxav_call(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate), result = self.libtoxav.toxav_call(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
c_uint32(video_bit_rate), byref(toxav_err_call)) c_uint32(video_bit_rate), byref(toxav_err_call))
toxav_err_call = toxav_err_call.value toxav_err_call = toxav_err_call.value
if toxav_err_call == TOXAV_ERR_CALL['OK']: if toxav_err_call == enum.TOXAV_ERR_CALL['OK']:
return bool(result) return bool(result)
elif toxav_err_call == TOXAV_ERR_CALL['MALLOC']: elif toxav_err_call == enum.TOXAV_ERR_CALL['MALLOC']:
raise MemoryError('A resource allocation error occurred while trying to create the structures required for ' raise MemoryError('A resource allocation error occurred while trying to create the structures required for '
'the call.') 'the call.')
elif toxav_err_call == TOXAV_ERR_CALL['SYNC']: elif toxav_err_call == enum.TOXAV_ERR_CALL['SYNC']:
raise RuntimeError('Synchronization error occurred.') raise RuntimeError('Synchronization error occurred.')
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_NOT_FOUND']: elif toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend number did not designate a valid friend.') raise ArgumentError('The friend number did not designate a valid friend.')
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_NOT_CONNECTED']: elif toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_NOT_CONNECTED']:
raise ArgumentError('The friend was valid, but not currently connected.') raise ArgumentError('The friend was valid, but not currently connected.')
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_ALREADY_IN_CALL']: elif toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_ALREADY_IN_CALL']:
raise ArgumentError('Attempted to call a friend while already in an audio or video call with them.') raise ArgumentError('Attempted to call a friend while already in an audio or video call with them.')
elif toxav_err_call == TOXAV_ERR_CALL['INVALID_BIT_RATE']: elif toxav_err_call == enum.TOXAV_ERR_CALL['INVALID_BIT_RATE']:
raise ArgumentError('Audio or video bit rate is invalid.') raise ArgumentError('Audio or video bit rate is invalid.')
def callback_call(self, callback: Callable, user_data) -> None: def callback_call(self, callback: Callable, user_data) -> None:
@ -164,19 +169,19 @@ class ToxAV:
c_uint32(video_bit_rate), c_uint32(video_bit_rate),
byref(toxav_err_answer)) byref(toxav_err_answer))
toxav_err_answer = toxav_err_answer.value toxav_err_answer = toxav_err_answer.value
if toxav_err_answer == TOXAV_ERR_ANSWER['OK']: if toxav_err_answer == enum.TOXAV_ERR_ANSWER['OK']:
return bool(result) return bool(result)
elif toxav_err_answer == TOXAV_ERR_ANSWER['SYNC']: elif toxav_err_answer == enum.TOXAV_ERR_ANSWER['SYNC']:
raise RuntimeError('Synchronization error occurred.') raise RuntimeError('Synchronization error occurred.')
elif toxav_err_answer == TOXAV_ERR_ANSWER['CODEC_INITIALIZATION']: elif toxav_err_answer == enum.TOXAV_ERR_ANSWER['CODEC_INITIALIZATION']:
raise RuntimeError('Failed to initialize codecs for call session. Note that codec initiation will fail if ' raise RuntimeError('Failed to initialize codecs for call session. Note that codec initiation will fail if '
'there is no receive callback registered for either audio or video.') 'there is no receive callback registered for either audio or video.')
elif toxav_err_answer == TOXAV_ERR_ANSWER['FRIEND_NOT_FOUND']: elif toxav_err_answer == enum.TOXAV_ERR_ANSWER['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend number did not designate a valid friend.') raise ArgumentError('The friend number did not designate a valid friend.')
elif toxav_err_answer == TOXAV_ERR_ANSWER['FRIEND_NOT_CALLING']: elif toxav_err_answer == enum.TOXAV_ERR_ANSWER['FRIEND_NOT_CALLING']:
raise ArgumentError('The friend was valid, but they are not currently trying to initiate a call. This is ' raise ArgumentError('The friend was valid, but they are not currently trying to initiate a call. This is '
'also returned if this client is already in a call with the friend.') 'also returned if this client is already in a call with the friend.')
elif toxav_err_answer == TOXAV_ERR_ANSWER['INVALID_BIT_RATE']: elif toxav_err_answer == enum.TOXAV_ERR_ANSWER['INVALID_BIT_RATE']:
raise ArgumentError('Audio or video bit rate is invalid.') raise ArgumentError('Audio or video bit rate is invalid.')
# Call state graph # Call state graph
@ -219,16 +224,16 @@ class ToxAV:
result = self.libtoxav.toxav_call_control(self._toxav_pointer, c_uint32(friend_number), c_int(control), result = self.libtoxav.toxav_call_control(self._toxav_pointer, c_uint32(friend_number), c_int(control),
byref(toxav_err_call_control)) byref(toxav_err_call_control))
toxav_err_call_control = toxav_err_call_control.value toxav_err_call_control = toxav_err_call_control.value
if toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['OK']: if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['OK']:
return bool(result) return bool(result)
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['SYNC']: elif toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['SYNC']:
raise RuntimeError('Synchronization error occurred.') raise RuntimeError('Synchronization error occurred.')
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_FOUND']: elif toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number passed did not designate a valid friend.') raise ArgumentError('The friend_number passed did not designate a valid friend.')
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_IN_CALL']: elif toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_IN_CALL']:
raise RuntimeError('This client is currently not in a call with the friend. Before the call is answered, ' raise RuntimeError('This client is currently not in a call with the friend. Before the call is answered, '
'only CANCEL is a valid control.') 'only CANCEL is a valid control.')
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['INVALID_TRANSITION']: elif toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['INVALID_TRANSITION']:
raise RuntimeError('Happens if user tried to pause an already paused call or if trying to resume a call ' raise RuntimeError('Happens if user tried to pause an already paused call or if trying to resume a call '
'that is not paused.') 'that is not paused.')
@ -262,23 +267,23 @@ class ToxAV:
c_size_t(sample_count), c_uint8(channels), c_size_t(sample_count), c_uint8(channels),
c_uint32(sampling_rate), byref(toxav_err_send_frame)) c_uint32(sampling_rate), byref(toxav_err_send_frame))
toxav_err_send_frame = toxav_err_send_frame.value toxav_err_send_frame = toxav_err_send_frame.value
if toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['OK']: if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['OK']:
return bool(result) return bool(result)
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['NULL']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['NULL']:
raise ArgumentError('The samples data pointer was NULL.') raise ArgumentError('The samples data pointer was NULL.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number passed did not designate a valid friend.') raise ArgumentError('The friend_number passed did not designate a valid friend.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']:
raise RuntimeError('This client is currently not in a call with the friend.') raise RuntimeError('This client is currently not in a call with the friend.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['SYNC']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['SYNC']:
raise RuntimeError('Synchronization error occurred.') raise RuntimeError('Synchronization error occurred.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['INVALID']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['INVALID']:
raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too ' raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too '
'large, or the audio sampling rate may be unsupported.') 'large, or the audio sampling rate may be unsupported.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']:
raise RuntimeError('Either friend turned off audio or video receiving or we turned off sending for the said' raise RuntimeError('Either friend turned off audio or video receiving or we turned off sending for the said'
'payload.') 'payload.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['RTP_FAILED']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['RTP_FAILED']:
RuntimeError('Failed to push frame through rtp interface.') RuntimeError('Failed to push frame through rtp interface.')
def video_send_frame(self, friend_number: int, width: int, height: int, y, u, v) -> None: def video_send_frame(self, friend_number: int, width: int, height: int, y, u, v) -> None:
@ -307,23 +312,23 @@ class ToxAV:
c_char_p(v), c_char_p(v),
byref(toxav_err_send_frame)) byref(toxav_err_send_frame))
toxav_err_send_frame = toxav_err_send_frame.value toxav_err_send_frame = toxav_err_send_frame.value
if toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['OK']: if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['OK']:
return bool(result) return bool(result)
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['NULL']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['NULL']:
raise ArgumentError('One of Y, U, or V was NULL.') raise ArgumentError('One of Y, U, or V was NULL.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number passed did not designate a valid friend.') raise ArgumentError('The friend_number passed did not designate a valid friend.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']:
raise RuntimeError('This client is currently not in a call with the friend.') raise RuntimeError('This client is currently not in a call with the friend.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['SYNC']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['SYNC']:
raise RuntimeError('Synchronization error occurred.') raise RuntimeError('Synchronization error occurred.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['INVALID']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['INVALID']:
raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too ' raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too '
'large, or the audio sampling rate may be unsupported.') 'large, or the audio sampling rate may be unsupported.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']:
raise RuntimeError('Either friend turned off audio or video receiving or we turned off sending for the said' raise RuntimeError('Either friend turned off audio or video receiving or we turned off sending for the said'
'payload.') 'payload.')
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['RTP_FAILED']: elif toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['RTP_FAILED']:
RuntimeError('Failed to push frame through rtp interface.') RuntimeError('Failed to push frame through rtp interface.')
# A/V receiving # A/V receiving

View File

@ -2,10 +2,12 @@
try: try:
from wrapper import libtox from wrapper import libtox
from wrapper.toxencryptsave_enums_and_consts import * #? from wrapper.toxencryptsave_enums_and_consts import *
import wrapper.toxencryptsave_enums_and_consts as enum
except: except:
import libtox import libtox
from toxencryptsave_enums_and_consts import * #? from toxencryptsave_enums_and_consts import *
import toxencryptsave_enums_and_consts as enum
from ctypes import (ArgumentError, byref, c_bool, c_char_p, c_int, c_size_t, from ctypes import (ArgumentError, byref, c_bool, c_char_p, c_int, c_size_t,
create_string_buffer) create_string_buffer)
@ -31,7 +33,7 @@ class ToxEncryptSave:
:return: output array :return: output array
""" """
out = create_string_buffer(len(data) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH) out = create_string_buffer(len(data) + enum.TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
tox_err_encryption = c_int() tox_err_encryption = c_int()
if type(password) != bytes: if type(password) != bytes:
password = bytes(password, 'utf-8') password = bytes(password, 'utf-8')
@ -42,17 +44,17 @@ class ToxEncryptSave:
out, out,
byref(tox_err_encryption)) byref(tox_err_encryption))
tox_err_encryption = tox_err_encryption.value tox_err_encryption = tox_err_encryption.value
if tox_err_encryption == TOX_ERR_ENCRYPTION['OK']: if tox_err_encryption == enum.TOX_ERR_ENCRYPTION['OK']:
return out[:] return out[:]
elif tox_err_encryption == TOX_ERR_ENCRYPTION['NULL']: elif tox_err_encryption == enum.TOX_ERR_ENCRYPTION['NULL']:
raise ArgumentError('Some input data, or maybe the output pointer, was null.') raise ArgumentError('Some input data, or maybe the output pointer, was null.')
elif tox_err_encryption == TOX_ERR_ENCRYPTION['KEY_DERIVATION_FAILED']: elif tox_err_encryption == enum.TOX_ERR_ENCRYPTION['KEY_DERIVATION_FAILED']:
raise RuntimeError('The crypto lib was unable to derive a key from the given passphrase, which is usually a' raise RuntimeError('The crypto lib was unable to derive a key from the given passphrase, which is usually a'
' lack of memory issue. The functions accepting keys do not produce this error.') ' lack of memory issue. The functions accepting keys do not produce this error.')
elif tox_err_encryption == TOX_ERR_ENCRYPTION['FAILED']: elif tox_err_encryption == enum.TOX_ERR_ENCRYPTION['FAILED']:
raise RuntimeError('The encryption itself failed.') raise RuntimeError('The encryption itself failed.')
def pass_decrypt(self, data, password) -> bytes: def pass_decrypt(self, data: bytes, password: str) -> bytes:
""" """
Decrypts the given data with the given password. Decrypts the given data with the given password.
@ -60,25 +62,27 @@ class ToxEncryptSave:
""" """
out = create_string_buffer(len(data) - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) out = create_string_buffer(len(data) - TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
tox_err_decryption = c_int() tox_err_decryption = c_int()
if type(password) != bytes:
password = bytes(password, 'utf-8')
self.libtoxencryptsave.tox_pass_decrypt(c_char_p(bytes(data)), self.libtoxencryptsave.tox_pass_decrypt(c_char_p(bytes(data)),
c_size_t(len(data)), c_size_t(len(data)),
c_char_p(bytes(password, 'utf-8')), c_char_p(password),
c_size_t(len(password)), c_size_t(len(password)),
out, out,
byref(tox_err_decryption)) byref(tox_err_decryption))
tox_err_decryption = tox_err_decryption.value tox_err_decryption = tox_err_decryption.value
if tox_err_decryption == TOX_ERR_DECRYPTION['OK']: if tox_err_decryption == enum.TOX_ERR_DECRYPTION['OK']:
return bytes(out[:]) return bytes(out[:])
elif tox_err_decryption == TOX_ERR_DECRYPTION['NULL']: elif tox_err_decryption == enum.TOX_ERR_DECRYPTION['NULL']:
raise ArgumentError('Some input data, or maybe the output pointer, was null.') raise ArgumentError('Some input data, or maybe the output pointer, was null.')
elif tox_err_decryption == TOX_ERR_DECRYPTION['INVALID_LENGTH']: elif tox_err_decryption == enum.TOX_ERR_DECRYPTION['INVALID_LENGTH']:
raise ArgumentError('The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes') raise ArgumentError('The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes')
elif tox_err_decryption == TOX_ERR_DECRYPTION['BAD_FORMAT']: elif tox_err_decryption == enum.TOX_ERR_DECRYPTION['BAD_FORMAT']:
raise ArgumentError('The input data is missing the magic number (i.e. wasn\'t created by this module, or is' raise ArgumentError('The input data is missing the magic number (i.e. wasn\'t created by this module, or is'
' corrupted)') ' corrupted)')
elif tox_err_decryption == TOX_ERR_DECRYPTION['KEY_DERIVATION_FAILED']: elif tox_err_decryption == enum.TOX_ERR_DECRYPTION['KEY_DERIVATION_FAILED']:
raise RuntimeError('The crypto lib was unable to derive a key from the given passphrase, which is usually a' raise RuntimeError('The crypto lib was unable to derive a key from the given passphrase, which is usually a'
' lack of memory issue. The functions accepting keys do not produce this error.') ' lack of memory issue. The functions accepting keys do not produce this error.')
elif tox_err_decryption == TOX_ERR_DECRYPTION['FAILED']: elif tox_err_decryption == enum.TOX_ERR_DECRYPTION['FAILED']:
raise RuntimeError('The encrypted byte array could not be decrypted. Either the data was corrupt or the ' raise RuntimeError('The encrypted byte array could not be decrypted. Either the data was corrupt or the '
'password/key was incorrect.') 'password/key was incorrect.')