Initial commit of py
This commit is contained in:
parent
849f6072f4
commit
cc40380488
164
.gitignore
vendored
Normal file
164
.gitignore
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
.pylint.err
|
||||||
|
.pylint.log
|
82
wrapper/libtox.py
Normal file
82
wrapper/libtox.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from ctypes import CDLL
|
||||||
|
|
||||||
|
# You need a libs directory beside this directory
|
||||||
|
# and you need to link your libtoxcore.so and libtoxav.so
|
||||||
|
# and libtoxencryptsave.so into ../libs/
|
||||||
|
# Link all 3 to libtoxcore.so if you have only libtoxcore.so
|
||||||
|
try:
|
||||||
|
import utils.util as util
|
||||||
|
sLIBS_DIR = util.get_libs_directory()
|
||||||
|
except ImportError:
|
||||||
|
sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||||
|
'libs')
|
||||||
|
|
||||||
|
class LibToxCore:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
platform = sys.platform
|
||||||
|
if platform == 'win32':
|
||||||
|
libtoxcore = 'libtox.dll'
|
||||||
|
elif platform == 'darwin':
|
||||||
|
libtoxcore = 'libtoxcore.dylib'
|
||||||
|
else:
|
||||||
|
libtoxcore = 'libtoxcore.so'
|
||||||
|
|
||||||
|
# libtoxcore and libsodium may be installed in your os
|
||||||
|
# give libs/ precedence
|
||||||
|
libFile = os.path.join(sLIBS_DIR, libtoxcore)
|
||||||
|
assert os.path.isfile(libFile), libFile
|
||||||
|
if os.path.isfile(libFile):
|
||||||
|
self._libtoxcore = CDLL(libFile)
|
||||||
|
else:
|
||||||
|
self._libtoxcore = CDLL(libtoxcore)
|
||||||
|
|
||||||
|
def __getattr__(self, item):
|
||||||
|
return self._libtoxcore.__getattr__(item)
|
||||||
|
|
||||||
|
class LibToxAV:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
platform = sys.platform
|
||||||
|
if platform == 'win32':
|
||||||
|
# on Windows av api is in libtox.dll
|
||||||
|
self._libtoxav = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll'))
|
||||||
|
elif platform == 'darwin':
|
||||||
|
self._libtoxav = CDLL('libtoxcore.dylib')
|
||||||
|
else:
|
||||||
|
libFile = os.path.join(sLIBS_DIR, 'libtoxav.so')
|
||||||
|
assert os.path.isfile(libFile), libFile
|
||||||
|
if os.path.isfile(libFile):
|
||||||
|
self._libtoxav = CDLL(libFile)
|
||||||
|
else:
|
||||||
|
self._libtoxav = CDLL('libtoxav.so')
|
||||||
|
|
||||||
|
def __getattr__(self, item):
|
||||||
|
return self._libtoxav.__getattr__(item)
|
||||||
|
|
||||||
|
# figure out how to see if we have a combined library
|
||||||
|
|
||||||
|
class LibToxEncryptSave:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
platform = sys.platform
|
||||||
|
if platform == 'win32':
|
||||||
|
# on Windows profile encryption api is in libtox.dll
|
||||||
|
self._lib_tox_encrypt_save = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll'))
|
||||||
|
elif platform == 'darwin':
|
||||||
|
self._lib_tox_encrypt_save = CDLL('libtoxcore.dylib')
|
||||||
|
else:
|
||||||
|
libFile = os.path.join(sLIBS_DIR, 'libtoxencryptsave.so')
|
||||||
|
assert os.path.isfile(libFile), libFile
|
||||||
|
if os.path.isfile(libFile):
|
||||||
|
self._lib_tox_encrypt_save = CDLL(libFile)
|
||||||
|
else:
|
||||||
|
self._lib_tox_encrypt_save = CDLL('libtoxencryptsave.so')
|
||||||
|
|
||||||
|
def __getattr__(self, item):
|
||||||
|
return self._lib_tox_encrypt_save.__getattr__(item)
|
||||||
|
|
||||||
|
# figure out how to see if we have a combined library
|
3065
wrapper/tox.py
Normal file
3065
wrapper/tox.py
Normal file
File diff suppressed because it is too large
Load Diff
403
wrapper/toxav.py
Normal file
403
wrapper/toxav.py
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from ctypes import c_int, POINTER, c_void_p, byref, ArgumentError, c_uint32, CFUNCTYPE, c_size_t, c_uint8, c_uint16
|
||||||
|
from ctypes import c_char_p, c_int32, c_bool, cast
|
||||||
|
|
||||||
|
from wrapper.libtox import LibToxAV
|
||||||
|
from wrapper.toxav_enums import *
|
||||||
|
|
||||||
|
LOG = logging.getLogger('app.'+__name__)
|
||||||
|
def LOG_ERROR(a): print('EROR> '+a)
|
||||||
|
def LOG_WARN(a): print('WARN> '+a)
|
||||||
|
def LOG_INFO(a): print('INFO> '+a)
|
||||||
|
def LOG_DEBUG(a): print('DBUG> '+a)
|
||||||
|
def LOG_TRACE(a): pass # print('DEBUGx: '+a)
|
||||||
|
|
||||||
|
class ToxAV:
|
||||||
|
"""
|
||||||
|
The ToxAV instance type. Each ToxAV instance can be bound to only one Tox instance, and Tox instance can have only
|
||||||
|
one ToxAV instance. One must make sure to close ToxAV instance prior closing Tox instance otherwise undefined
|
||||||
|
behaviour occurs. Upon closing of ToxAV instance, all active calls will be forcibly terminated without notifying
|
||||||
|
peers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Creation and destruction
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def __init__(self, tox_pointer):
|
||||||
|
"""
|
||||||
|
Start new A/V session. There can only be only one session per Tox instance.
|
||||||
|
|
||||||
|
:param tox_pointer: pointer to Tox instance
|
||||||
|
"""
|
||||||
|
self.libtoxav = LibToxAV()
|
||||||
|
toxav_err_new = c_int()
|
||||||
|
f = self.libtoxav.toxav_new
|
||||||
|
f.restype = POINTER(c_void_p)
|
||||||
|
self._toxav_pointer = f(tox_pointer, byref(toxav_err_new))
|
||||||
|
toxav_err_new = toxav_err_new.value
|
||||||
|
if toxav_err_new == TOXAV_ERR_NEW['NULL']:
|
||||||
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
||||||
|
elif toxav_err_new == TOXAV_ERR_NEW['MALLOC']:
|
||||||
|
raise MemoryError('Memory allocation failure while trying to allocate structures required for the A/V '
|
||||||
|
'session.')
|
||||||
|
elif toxav_err_new == TOXAV_ERR_NEW['MULTIPLE']:
|
||||||
|
raise RuntimeError('Attempted to create a second session for the same Tox instance.')
|
||||||
|
|
||||||
|
self.call_state_cb = None
|
||||||
|
self.audio_receive_frame_cb = None
|
||||||
|
self.video_receive_frame_cb = None
|
||||||
|
self.call_cb = None
|
||||||
|
|
||||||
|
def kill(self):
|
||||||
|
"""
|
||||||
|
Releases all resources associated with the A/V session.
|
||||||
|
|
||||||
|
If any calls were ongoing, these will be forcibly terminated without notifying peers. After calling this
|
||||||
|
function, no other functions may be called and the av pointer becomes invalid.
|
||||||
|
"""
|
||||||
|
self.libtoxav.toxav_kill(self._toxav_pointer)
|
||||||
|
|
||||||
|
def get_tox_pointer(self):
|
||||||
|
"""
|
||||||
|
Returns the Tox instance the A/V object was created for.
|
||||||
|
|
||||||
|
:return: pointer to the Tox instance
|
||||||
|
"""
|
||||||
|
self.libtoxav.toxav_get_tox.restype = POINTER(c_void_p)
|
||||||
|
return self.libtoxav.toxav_get_tox(self._toxav_pointer)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# A/V event loop
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def iteration_interval(self):
|
||||||
|
"""
|
||||||
|
Returns the interval in milliseconds when the next toxav_iterate call should be. If no call is active at the
|
||||||
|
moment, this function returns 200.
|
||||||
|
|
||||||
|
:return: interval in milliseconds
|
||||||
|
"""
|
||||||
|
return self.libtoxav.toxav_iteration_interval(self._toxav_pointer)
|
||||||
|
|
||||||
|
def iterate(self):
|
||||||
|
"""
|
||||||
|
Main loop for the session. This function needs to be called in intervals of toxav_iteration_interval()
|
||||||
|
milliseconds. It is best called in the separate thread from tox_iterate.
|
||||||
|
"""
|
||||||
|
self.libtoxav.toxav_iterate(self._toxav_pointer)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Call setup
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def call(self, friend_number, audio_bit_rate, video_bit_rate):
|
||||||
|
"""
|
||||||
|
Call a friend. This will start ringing the friend.
|
||||||
|
|
||||||
|
It is the client's responsibility to stop ringing after a certain timeout, if such behaviour is desired. If the
|
||||||
|
client does not stop ringing, the library will not stop until the friend is disconnected. Audio and video
|
||||||
|
receiving are both enabled by default.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend that should be called.
|
||||||
|
:param audio_bit_rate: Audio bit rate in Kb/sec. Set this to 0 to disable audio sending.
|
||||||
|
:param video_bit_rate: Video bit rate in Kb/sec. Set this to 0 to disable video sending.
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
toxav_err_call = c_int()
|
||||||
|
LOG_DEBUG(f"toxav_call")
|
||||||
|
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))
|
||||||
|
toxav_err_call = toxav_err_call.value
|
||||||
|
if toxav_err_call == TOXAV_ERR_CALL['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif toxav_err_call == TOXAV_ERR_CALL['MALLOC']:
|
||||||
|
raise MemoryError('A resource allocation error occurred while trying to create the structures required for '
|
||||||
|
'the call.')
|
||||||
|
elif toxav_err_call == TOXAV_ERR_CALL['SYNC']:
|
||||||
|
raise RuntimeError('Synchronization error occurred.')
|
||||||
|
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_NOT_FOUND']:
|
||||||
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
||||||
|
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_NOT_CONNECTED']:
|
||||||
|
raise ArgumentError('The friend was valid, but not currently connected.')
|
||||||
|
elif toxav_err_call == TOXAV_ERR_CALL['FRIEND_ALREADY_IN_CALL']:
|
||||||
|
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']:
|
||||||
|
raise ArgumentError('Audio or video bit rate is invalid.')
|
||||||
|
|
||||||
|
def callback_call(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `call` event. Pass None to unset.
|
||||||
|
|
||||||
|
:param callback: The function for the call callback.
|
||||||
|
|
||||||
|
Should take pointer (c_void_p) to ToxAV object,
|
||||||
|
The friend number (c_uint32) from which the call is incoming.
|
||||||
|
True (c_bool) if friend is sending audio.
|
||||||
|
True (c_bool) if friend is sending video.
|
||||||
|
pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
if callback is None:
|
||||||
|
self.libtoxav.toxav_callback_call(self._toxav_pointer, POINTER(None)(), user_data)
|
||||||
|
self.call_cb = None
|
||||||
|
return
|
||||||
|
LOG_DEBUG(f"toxav_callback_call")
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_bool, c_void_p)
|
||||||
|
self.call_cb = c_callback(callback)
|
||||||
|
self.libtoxav.toxav_callback_call(self._toxav_pointer, self.call_cb, user_data)
|
||||||
|
|
||||||
|
def answer(self, friend_number, audio_bit_rate, video_bit_rate):
|
||||||
|
"""
|
||||||
|
Accept an incoming call.
|
||||||
|
|
||||||
|
If answering fails for any reason, the call will still be pending and it is possible to try and answer it later.
|
||||||
|
Audio and video receiving are both enabled by default.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend that is calling.
|
||||||
|
:param audio_bit_rate: Audio bit rate in Kb/sec. Set this to 0 to disable audio sending.
|
||||||
|
:param video_bit_rate: Video bit rate in Kb/sec. Set this to 0 to disable video sending.
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
toxav_err_answer = c_int()
|
||||||
|
LOG_DEBUG(f"toxav_answer")
|
||||||
|
result = self.libtoxav.toxav_answer(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
|
||||||
|
c_uint32(video_bit_rate), byref(toxav_err_answer))
|
||||||
|
toxav_err_answer = toxav_err_answer.value
|
||||||
|
if toxav_err_answer == TOXAV_ERR_ANSWER['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif toxav_err_answer == TOXAV_ERR_ANSWER['SYNC']:
|
||||||
|
raise RuntimeError('Synchronization error occurred.')
|
||||||
|
elif toxav_err_answer == TOXAV_ERR_ANSWER['CODEC_INITIALIZATION']:
|
||||||
|
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.')
|
||||||
|
elif toxav_err_answer == TOXAV_ERR_ANSWER['FRIEND_NOT_FOUND']:
|
||||||
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
||||||
|
elif toxav_err_answer == TOXAV_ERR_ANSWER['FRIEND_NOT_CALLING']:
|
||||||
|
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.')
|
||||||
|
elif toxav_err_answer == TOXAV_ERR_ANSWER['INVALID_BIT_RATE']:
|
||||||
|
raise ArgumentError('Audio or video bit rate is invalid.')
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Call state graph
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def callback_call_state(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `call_state` event. Pass None to unset.
|
||||||
|
|
||||||
|
:param callback: Python function.
|
||||||
|
The function for the call_state callback.
|
||||||
|
|
||||||
|
Should take pointer (c_void_p) to ToxAV object,
|
||||||
|
The friend number (c_uint32) for which the call state changed.
|
||||||
|
The bitmask of the new call state which is guaranteed to be different than the previous state. The state is set
|
||||||
|
to 0 when the call is paused. The bitmask represents all the activities currently performed by the friend.
|
||||||
|
pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
if callback is None:
|
||||||
|
self.libtoxav.toxav_callback_call_state(self._toxav_pointer, POINTER(None)(), user_data)
|
||||||
|
self.call_state_cb = None
|
||||||
|
return
|
||||||
|
LOG_DEBUG(f"callback_call_state")
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
||||||
|
self.call_state_cb = c_callback(callback)
|
||||||
|
self.libtoxav.toxav_callback_call_state(self._toxav_pointer, self.call_state_cb, user_data)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Call control
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def call_control(self, friend_number, control):
|
||||||
|
"""
|
||||||
|
Sends a call control command to a friend.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend this client is in a call with.
|
||||||
|
:param control: The control command to send.
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
toxav_err_call_control = c_int()
|
||||||
|
LOG_DEBUG(f"call_control")
|
||||||
|
result = self.libtoxav.toxav_call_control(self._toxav_pointer, c_uint32(friend_number), c_int(control),
|
||||||
|
byref(toxav_err_call_control))
|
||||||
|
toxav_err_call_control = toxav_err_call_control.value
|
||||||
|
if toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['SYNC']:
|
||||||
|
raise RuntimeError('Synchronization error occurred.')
|
||||||
|
elif toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_FOUND']:
|
||||||
|
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']:
|
||||||
|
raise RuntimeError('This client is currently not in a call with the friend. Before the call is answered, '
|
||||||
|
'only CANCEL is a valid control.')
|
||||||
|
elif toxav_err_call_control == 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 '
|
||||||
|
'that is not paused.')
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# TODO Controlling bit rates
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# A/V sending
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def audio_send_frame(self, friend_number, pcm, sample_count, channels, sampling_rate):
|
||||||
|
"""
|
||||||
|
Send an audio frame to a friend.
|
||||||
|
|
||||||
|
The expected format of the PCM data is: [s1c1][s1c2][...][s2c1][s2c2][...]...
|
||||||
|
Meaning: sample 1 for channel 1, sample 1 for channel 2, ...
|
||||||
|
For mono audio, this has no meaning, every sample is subsequent. For stereo, this means the expected format is
|
||||||
|
LRLRLR... with samples for left and right alternating.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend to which to send an audio frame.
|
||||||
|
:param pcm: An array of audio samples. The size of this array must be sample_count * channels.
|
||||||
|
:param sample_count: Number of samples in this frame. Valid numbers here are
|
||||||
|
((sample rate) * (audio length) / 1000), where audio length can be 2.5, 5, 10, 20, 40 or 60 milliseconds.
|
||||||
|
:param channels: Number of audio channels. Sulpported values are 1 and 2.
|
||||||
|
:param sampling_rate: Audio sampling rate used in this frame. Valid sampling rates are 8000, 12000, 16000,
|
||||||
|
24000, or 48000.
|
||||||
|
"""
|
||||||
|
toxav_err_send_frame = c_int()
|
||||||
|
LOG_DEBUG(f"toxav_audio_send_frame")
|
||||||
|
assert sampling_rate in [8000, 12000, 16000, 24000, 48000]
|
||||||
|
result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer,
|
||||||
|
c_uint32(friend_number),
|
||||||
|
cast(pcm, c_void_p),
|
||||||
|
c_size_t(sample_count), c_uint8(channels),
|
||||||
|
c_uint32(sampling_rate), byref(toxav_err_send_frame))
|
||||||
|
toxav_err_send_frame = toxav_err_send_frame.value
|
||||||
|
if toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['NULL']:
|
||||||
|
raise ArgumentError('The samples data pointer was NULL.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']:
|
||||||
|
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']:
|
||||||
|
raise RuntimeError('This client is currently not in a call with the friend.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['SYNC']:
|
||||||
|
raise RuntimeError('Synchronization error occurred.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['INVALID']:
|
||||||
|
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.')
|
||||||
|
elif toxav_err_send_frame == 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'
|
||||||
|
'payload.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['RTP_FAILED']:
|
||||||
|
RuntimeError('Failed to push frame through rtp interface.')
|
||||||
|
|
||||||
|
def video_send_frame(self, friend_number, width, height, y, u, v):
|
||||||
|
"""
|
||||||
|
Send a video frame to a friend.
|
||||||
|
|
||||||
|
Y - plane should be of size: height * width
|
||||||
|
U - plane should be of size: (height/2) * (width/2)
|
||||||
|
V - plane should be of size: (height/2) * (width/2)
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend to which to send a video frame.
|
||||||
|
:param width: Width of the frame in pixels.
|
||||||
|
:param height: Height of the frame in pixels.
|
||||||
|
:param y: Y (Luminance) plane data.
|
||||||
|
:param u: U (Chroma) plane data.
|
||||||
|
:param v: V (Chroma) plane data.
|
||||||
|
"""
|
||||||
|
toxav_err_send_frame = c_int()
|
||||||
|
LOG_DEBUG(f"toxav_video_send_frame")
|
||||||
|
result = self.libtoxav.toxav_video_send_frame(self._toxav_pointer, c_uint32(friend_number), c_uint16(width),
|
||||||
|
c_uint16(height), c_char_p(y), c_char_p(u), c_char_p(v),
|
||||||
|
byref(toxav_err_send_frame))
|
||||||
|
toxav_err_send_frame = toxav_err_send_frame.value
|
||||||
|
if toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['NULL']:
|
||||||
|
raise ArgumentError('One of Y, U, or V was NULL.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']:
|
||||||
|
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']:
|
||||||
|
raise RuntimeError('This client is currently not in a call with the friend.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['SYNC']:
|
||||||
|
raise RuntimeError('Synchronization error occurred.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['INVALID']:
|
||||||
|
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.')
|
||||||
|
elif toxav_err_send_frame == 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'
|
||||||
|
'payload.')
|
||||||
|
elif toxav_err_send_frame == TOXAV_ERR_SEND_FRAME['RTP_FAILED']:
|
||||||
|
RuntimeError('Failed to push frame through rtp interface.')
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# A/V receiving
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def callback_audio_receive_frame(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `audio_receive_frame` event. Pass None to unset.
|
||||||
|
|
||||||
|
:param callback: Python function.
|
||||||
|
Function for the audio_receive_frame callback. The callback can be called multiple times per single
|
||||||
|
iteration depending on the amount of queued frames in the buffer. The received format is the same as in send
|
||||||
|
function.
|
||||||
|
|
||||||
|
Should take pointer (c_void_p) to ToxAV object,
|
||||||
|
The friend number (c_uint32) of the friend who sent an audio frame.
|
||||||
|
An array (c_uint8) of audio samples (sample_count * channels elements).
|
||||||
|
The number (c_size_t) of audio samples per channel in the PCM array.
|
||||||
|
Number (c_uint8) of audio channels.
|
||||||
|
Sampling rate (c_uint32) used in this frame.
|
||||||
|
pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
if callback is None:
|
||||||
|
self.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, POINTER(None)(), user_data)
|
||||||
|
self.audio_receive_frame_cb = None
|
||||||
|
return
|
||||||
|
LOG_DEBUG(f"toxav_callback_audio_receive_frame")
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_uint8, c_uint32, c_void_p)
|
||||||
|
self.audio_receive_frame_cb = c_callback(callback)
|
||||||
|
self.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, self.audio_receive_frame_cb, user_data)
|
||||||
|
|
||||||
|
def callback_video_receive_frame(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `video_receive_frame` event. Pass None to unset.
|
||||||
|
|
||||||
|
:param callback: Python function.
|
||||||
|
The function type for the video_receive_frame callback.
|
||||||
|
|
||||||
|
Should take
|
||||||
|
toxAV pointer (c_void_p) to ToxAV object,
|
||||||
|
friend_number The friend number (c_uint32) of the friend who sent a video frame.
|
||||||
|
width Width (c_uint16) of the frame in pixels.
|
||||||
|
height Height (c_uint16) of the frame in pixels.
|
||||||
|
y
|
||||||
|
u
|
||||||
|
v Plane data (POINTER(c_uint8)).
|
||||||
|
The size of plane data is derived from width and height where
|
||||||
|
Y = MAX(width, abs(ystride)) * height,
|
||||||
|
U = MAX(width/2, abs(ustride)) * (height/2) and
|
||||||
|
V = MAX(width/2, abs(vstride)) * (height/2).
|
||||||
|
ystride
|
||||||
|
ustride
|
||||||
|
vstride Strides data (c_int32). Strides represent padding for each plane that may or may not be present. You must
|
||||||
|
handle strides in your image processing code. Strides are negative if the image is bottom-up
|
||||||
|
hence why you MUST abs() it when calculating plane buffer size.
|
||||||
|
user_data pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
if callback is None:
|
||||||
|
self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, POINTER(None)(), user_data)
|
||||||
|
self.video_receive_frame_cb = None
|
||||||
|
return
|
||||||
|
|
||||||
|
LOG_DEBUG(f"toxav_callback_video_receive_frame")
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16,
|
||||||
|
POINTER(c_uint8), POINTER(c_uint8), POINTER(c_uint8),
|
||||||
|
c_int32, c_int32, c_int32,
|
||||||
|
c_void_p)
|
||||||
|
self.video_receive_frame_cb = c_callback(callback)
|
||||||
|
self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, self.video_receive_frame_cb, user_data)
|
133
wrapper/toxav_enums.py
Normal file
133
wrapper/toxav_enums.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||||
|
|
||||||
|
TOXAV_ERR_NEW = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# One of the arguments to the function was NULL when it was not expected.
|
||||||
|
'NULL': 1,
|
||||||
|
# Memory allocation failure while trying to allocate structures required for the A/V session.
|
||||||
|
'MALLOC': 2,
|
||||||
|
# Attempted to create a second session for the same Tox instance.
|
||||||
|
'MULTIPLE': 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_ERR_CALL = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# A resource allocation error occurred while trying to create the structures required for the call.
|
||||||
|
'MALLOC': 1,
|
||||||
|
# Synchronization error occurred.
|
||||||
|
'SYNC': 2,
|
||||||
|
# The friend number did not designate a valid friend.
|
||||||
|
'FRIEND_NOT_FOUND': 3,
|
||||||
|
# The friend was valid, but not currently connected.
|
||||||
|
'FRIEND_NOT_CONNECTED': 4,
|
||||||
|
# Attempted to call a friend while already in an audio or video call with them.
|
||||||
|
'FRIEND_ALREADY_IN_CALL': 5,
|
||||||
|
# Audio or video bit rate is invalid.
|
||||||
|
'INVALID_BIT_RATE': 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_ERR_ANSWER = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# Synchronization error occurred.
|
||||||
|
'SYNC': 1,
|
||||||
|
# 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.
|
||||||
|
'CODEC_INITIALIZATION': 2,
|
||||||
|
# The friend number did not designate a valid friend.
|
||||||
|
'FRIEND_NOT_FOUND': 3,
|
||||||
|
# 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.
|
||||||
|
'FRIEND_NOT_CALLING': 4,
|
||||||
|
# Audio or video bit rate is invalid.
|
||||||
|
'INVALID_BIT_RATE': 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_FRIEND_CALL_STATE = {
|
||||||
|
# Set by the AV core if an error occurred on the remote end or if friend timed out. This is the final state after
|
||||||
|
# which no more state transitions can occur for the call. This call state will never be triggered in combination
|
||||||
|
# with other call states.
|
||||||
|
'ERROR': 1,
|
||||||
|
# The call has finished. This is the final state after which no more state transitions can occur for the call. This
|
||||||
|
# call state will never be triggered in combination with other call states.
|
||||||
|
'FINISHED': 2,
|
||||||
|
# The flag that marks that friend is sending audio.
|
||||||
|
'SENDING_A': 4,
|
||||||
|
# The flag that marks that friend is sending video.
|
||||||
|
'SENDING_V': 8,
|
||||||
|
# The flag that marks that friend is receiving audio.
|
||||||
|
'ACCEPTING_A': 16,
|
||||||
|
# The flag that marks that friend is receiving video.
|
||||||
|
'ACCEPTING_V': 32,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_CALL_CONTROL = {
|
||||||
|
# Resume a previously paused call. Only valid if the pause was caused by this client, if not, this control is
|
||||||
|
# ignored. Not valid before the call is accepted.
|
||||||
|
'RESUME': 0,
|
||||||
|
# Put a call on hold. Not valid before the call is accepted.
|
||||||
|
'PAUSE': 1,
|
||||||
|
# Reject a call if it was not answered, yet. Cancel a call after it was answered.
|
||||||
|
'CANCEL': 2,
|
||||||
|
# Request that the friend stops sending audio. Regardless of the friend's compliance, this will cause the
|
||||||
|
# audio_receive_frame event to stop being triggered on receiving an audio frame from the friend.
|
||||||
|
'MUTE_AUDIO': 3,
|
||||||
|
# Calling this control will notify client to start sending audio again.
|
||||||
|
'UNMUTE_AUDIO': 4,
|
||||||
|
# Request that the friend stops sending video. Regardless of the friend's compliance, this will cause the
|
||||||
|
# video_receive_frame event to stop being triggered on receiving a video frame from the friend.
|
||||||
|
'HIDE_VIDEO': 5,
|
||||||
|
# Calling this control will notify client to start sending video again.
|
||||||
|
'SHOW_VIDEO': 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_ERR_CALL_CONTROL = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# Synchronization error occurred.
|
||||||
|
'SYNC': 1,
|
||||||
|
# The friend_number passed did not designate a valid friend.
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
# This client is currently not in a call with the friend. Before the call is answered, only CANCEL is a valid
|
||||||
|
# control.
|
||||||
|
'FRIEND_NOT_IN_CALL': 3,
|
||||||
|
# Happens if user tried to pause an already paused call or if trying to resume a call that is not paused.
|
||||||
|
'INVALID_TRANSITION': 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_ERR_BIT_RATE_SET = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# Synchronization error occurred.
|
||||||
|
'SYNC': 1,
|
||||||
|
# The audio bit rate passed was not one of the supported values.
|
||||||
|
'INVALID_AUDIO_BIT_RATE': 2,
|
||||||
|
# The video bit rate passed was not one of the supported values.
|
||||||
|
'INVALID_VIDEO_BIT_RATE': 3,
|
||||||
|
# The friend_number passed did not designate a valid friend.
|
||||||
|
'FRIEND_NOT_FOUND': 4,
|
||||||
|
# This client is currently not in a call with the friend.
|
||||||
|
'FRIEND_NOT_IN_CALL': 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOXAV_ERR_SEND_FRAME = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# In case of video, one of Y, U, or V was NULL. In case of audio, the samples data pointer was NULL.
|
||||||
|
'NULL': 1,
|
||||||
|
# The friend_number passed did not designate a valid friend.
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
# This client is currently not in a call with the friend.
|
||||||
|
'FRIEND_NOT_IN_CALL': 3,
|
||||||
|
# Synchronization error occurred.
|
||||||
|
'SYNC': 4,
|
||||||
|
# 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.
|
||||||
|
'INVALID': 5,
|
||||||
|
# Either friend turned off audio or video receiving or we turned off sending for the said payload.
|
||||||
|
'PAYLOAD_TYPE_DISABLED': 6,
|
||||||
|
# Failed to push frame through rtp interface.
|
||||||
|
'RTP_FAILED': 7,
|
||||||
|
}
|
957
wrapper/toxcore_enums_and_consts.py
Normal file
957
wrapper/toxcore_enums_and_consts.py
Normal file
@ -0,0 +1,957 @@
|
|||||||
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||||
|
|
||||||
|
TOX_USER_STATUS = {
|
||||||
|
'NONE': 0,
|
||||||
|
'AWAY': 1,
|
||||||
|
'BUSY': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_MESSAGE_TYPE = {
|
||||||
|
'NORMAL': 0,
|
||||||
|
'ACTION': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_PROXY_TYPE = {
|
||||||
|
'NONE': 0,
|
||||||
|
'HTTP': 1,
|
||||||
|
'SOCKS5': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_SAVEDATA_TYPE = {
|
||||||
|
'NONE': 0,
|
||||||
|
'TOX_SAVE': 1,
|
||||||
|
'SECRET_KEY': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_OPTIONS_NEW = {
|
||||||
|
'OK': 0,
|
||||||
|
'MALLOC': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_NEW = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'MALLOC': 2,
|
||||||
|
'PORT_ALLOC': 3,
|
||||||
|
'PROXY_BAD_TYPE': 4,
|
||||||
|
'PROXY_BAD_HOST': 5,
|
||||||
|
'PROXY_BAD_PORT': 6,
|
||||||
|
'PROXY_NOT_FOUND': 7,
|
||||||
|
'LOAD_ENCRYPTED': 8,
|
||||||
|
'LOAD_BAD_FORMAT': 9,
|
||||||
|
'TCP_SERVER_ALLOC': 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_BOOTSTRAP = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'BAD_HOST': 2,
|
||||||
|
'BAD_PORT': 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_CONNECTION = {
|
||||||
|
'NONE': 0,
|
||||||
|
'TCP': 1,
|
||||||
|
'UDP': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_SET_INFO = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'TOO_LONG': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_ADD = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'TOO_LONG': 2,
|
||||||
|
'NO_MESSAGE': 3,
|
||||||
|
'OWN_KEY': 4,
|
||||||
|
'ALREADY_SENT': 5,
|
||||||
|
'BAD_CHECKSUM': 6,
|
||||||
|
'SET_NEW_NOSPAM': 7,
|
||||||
|
'MALLOC': 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_DELETE = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_BY_PUBLIC_KEY = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'NOT_FOUND': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_GET_PUBLIC_KEY = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_GET_LAST_ONLINE = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_QUERY = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_SET_TYPING = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_SEND_MESSAGE = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
'FRIEND_NOT_CONNECTED': 3,
|
||||||
|
'SENDQ': 4,
|
||||||
|
'TOO_LONG': 5,
|
||||||
|
'EMPTY': 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_FILE_KIND = {
|
||||||
|
'DATA': 0,
|
||||||
|
'AVATAR': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_FILE_CONTROL = {
|
||||||
|
'RESUME': 0,
|
||||||
|
'PAUSE': 1,
|
||||||
|
'CANCEL': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FILE_CONTROL = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
'FRIEND_NOT_CONNECTED': 2,
|
||||||
|
'NOT_FOUND': 3,
|
||||||
|
'NOT_PAUSED': 4,
|
||||||
|
'DENIED': 5,
|
||||||
|
'ALREADY_PAUSED': 6,
|
||||||
|
'SENDQ': 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FILE_SEEK = {
|
||||||
|
'OK': 0,
|
||||||
|
'FRIEND_NOT_FOUND': 1,
|
||||||
|
'FRIEND_NOT_CONNECTED': 2,
|
||||||
|
'NOT_FOUND': 3,
|
||||||
|
'DENIED': 4,
|
||||||
|
'INVALID_POSITION': 5,
|
||||||
|
'SENDQ': 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FILE_GET = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
'NOT_FOUND': 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FILE_SEND = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
'FRIEND_NOT_CONNECTED': 3,
|
||||||
|
'NAME_TOO_LONG': 4,
|
||||||
|
'TOO_MANY': 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FILE_SEND_CHUNK = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
'FRIEND_NOT_CONNECTED': 3,
|
||||||
|
'NOT_FOUND': 4,
|
||||||
|
'NOT_TRANSFERRING': 5,
|
||||||
|
'INVALID_LENGTH': 6,
|
||||||
|
'SENDQ': 7,
|
||||||
|
'WRONG_POSITION': 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_FRIEND_CUSTOM_PACKET = {
|
||||||
|
'OK': 0,
|
||||||
|
'NULL': 1,
|
||||||
|
'FRIEND_NOT_FOUND': 2,
|
||||||
|
'FRIEND_NOT_CONNECTED': 3,
|
||||||
|
'INVALID': 4,
|
||||||
|
'EMPTY': 5,
|
||||||
|
'TOO_LONG': 6,
|
||||||
|
'SENDQ': 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GET_PORT = {
|
||||||
|
'OK': 0,
|
||||||
|
'NOT_BOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_GROUP_PRIVACY_STATE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group is considered to be public. Anyone may join the group using the Chat ID.
|
||||||
|
#
|
||||||
|
# If the group is in this state, even if the Chat ID is never explicitly shared
|
||||||
|
# with someone outside of the group, information including the Chat ID, IP addresses,
|
||||||
|
# and peer ID's (but not Tox ID's) is visible to anyone with access to a node
|
||||||
|
# storing a DHT entry for the given group.
|
||||||
|
#
|
||||||
|
'PUBLIC': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group is considered to be private. The only way to join the group is by having
|
||||||
|
# someone in your contact list send you an invite.
|
||||||
|
#
|
||||||
|
# If the group is in this state, no group information (mentioned above) is present in the DHT;
|
||||||
|
# the DHT is not used for any purpose at all. If a public group is set to private,
|
||||||
|
# all DHT information related to the group will expire shortly.
|
||||||
|
#
|
||||||
|
'PRIVATE': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_GROUP_ROLE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# May kick and ban all other peers as well as set their role to anything (except founder).
|
||||||
|
# Founders may also set the group password, toggle the privacy state, and set the peer limit.
|
||||||
|
#
|
||||||
|
'FOUNDER': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# May kick, ban and set the user and observer roles for peers below this role.
|
||||||
|
# May also set the group topic.
|
||||||
|
#
|
||||||
|
'MODERATOR': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# May communicate with other peers normally.
|
||||||
|
#
|
||||||
|
'USER': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# May observe the group and ignore peers; may not communicate with other peers or with the group.
|
||||||
|
#
|
||||||
|
'OBSERVER': 3
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_NEW = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group name exceeded TOX_GROUP_MAX_GROUP_NAME_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_TOO_LONG': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# group_name is NULL or length is zero.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_EMPTY': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# TOX_GROUP_PRIVACY_STATE is an invalid type.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_PRIVACY': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group instance failed to initialize.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_INIT': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group state failed to initialize. This usually indicates that something went wrong
|
||||||
|
# related to cryptographic signing.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_STATE': 5,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group failed to announce to the DHT. This indicates a network related error.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_NEW_ANNOUNCE': 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_JOIN = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_JOIN_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group instance failed to initialize.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_JOIN_INIT': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The chat_id pointer is set to NULL or a group with chat_id already exists. This usually
|
||||||
|
# happens if the client attempts to create multiple sessions for the same group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_JOIN_BAD_CHAT_ID': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Password length exceeded TOX_GROUP_MAX_PASSWORD_SIZE.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_JOIN_TOO_LONG': 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_RECONNECT = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_RECONNECT_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_LEAVE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_LEAVE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Message length exceeded 'TOX_GROUP_MAX_PART_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_LEAVE_TOO_LONG': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The parting packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_LEAVE_FAIL_SEND': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group chat instance failed to be deleted. This may occur due to memory related errors.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_LEAVE_DELETE_FAIL': 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SELF_QUERY = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_QUERY_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SELF_NAME_SET = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Name length exceeded 'TOX_MAX_NAME_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The length given to the set function is zero or name is a NULL pointer.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_INVALID': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The name is already taken by another peer in the group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_TAKEN': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND': 5
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SELF_STATUS_SET = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_STATUS_SET_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# An invalid type was passed to the set function.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_STATUS_SET_INVALID': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND': 3
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_PEER_QUERY = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_PEER_QUERY_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ID passed did not designate a valid peer.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_STATE_QUERIES = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_STATE_QUERIES_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_TOPIC_SET = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Topic length exceeded 'TOX_GROUP_MAX_TOPIC_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_TOO_LONG': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to set the topic.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet could not be created. This error is usually related to cryptographic signing.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND': 5
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SEND_MESSAGE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The message pointer is null or length is zero.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_EMPTY': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The message type is invalid.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to send group messages.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS': 5,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND': 6
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ID passed did not designate a valid peer.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The message pointer is null or length is zero.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to send group messages.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS': 5,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND': 6
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SEND_CUSTOM_PACKET = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The message pointer is null or length is zero.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to send group messages.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS': 4
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_INVITE_FRIEND = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_FRIEND_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The friend number passed did not designate a valid friend.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Creation of the invite packet failed. This indicates a network related error.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND': 4
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_INVITE_ACCEPT = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_ACCEPT_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The invite data is not in the expected format.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group instance failed to initialize.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG': 3
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_GROUP_JOIN_FAIL = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# You are using the same nickname as someone who is already in the group.
|
||||||
|
#
|
||||||
|
'TOX_GROUP_JOIN_FAIL_NAME_TAKEN': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group peer limit has been reached.
|
||||||
|
#
|
||||||
|
'TOX_GROUP_JOIN_FAIL_PEER_LIMIT': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# You have supplied an invalid password.
|
||||||
|
#
|
||||||
|
'TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The join attempt failed due to an unspecified error. This often occurs when the group is
|
||||||
|
# not found in the DHT.
|
||||||
|
#
|
||||||
|
'TOX_GROUP_JOIN_FAIL_UNKNOWN': 3
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PASSWORD = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to set the password.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND': 4
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# 'TOX_GROUP_PRIVACY_STATE is an invalid type.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_INVALID': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to set the privacy state.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The privacy state could not be set. This may occur due to an error related to
|
||||||
|
# cryptographic signing of the new shared state.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND': 5
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions to set the peer limit.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The peer limit could not be set. This may occur due to an error related to
|
||||||
|
# cryptographic signing of the new shared state.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND': 4
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_TOGGLE_IGNORE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOGGLE_IGNORE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOGGLE_IGNORE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ID passed did not designate a valid peer.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_SET_ROLE = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ID passed did not designate a valid peer. Note: you cannot set your own role.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions for this action.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The role assignment is invalid. This will occur if you try to set a peer's role to
|
||||||
|
# the role they already have.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The role was not successfully set. This may occur if something goes wrong with role setting': ,
|
||||||
|
# or if the packet fails to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION': 5
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_REMOVE_PEER = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ID passed did not designate a valid peer.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_PEER_NOT_FOUND': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions for this action.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The peer could not be removed from the group.
|
||||||
|
#
|
||||||
|
# If a ban was set': , this error indicates that the ban entry could not be created.
|
||||||
|
# This is usually due to the peer's IP address already occurring in the ban list. It may also
|
||||||
|
# be due to the entry containing invalid peer information': , or a failure to cryptographically
|
||||||
|
# authenticate the entry.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_ACTION': 4,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_SEND': 5
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_REMOVE_BAN = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_BAN_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_BAN_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The caller does not have the required permissions for this action.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ban entry could not be removed. This may occur if ban_id does not designate
|
||||||
|
# a valid ban entry.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The packet failed to send.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_SEND': 4
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_GROUP_MOD_EVENT = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# A peer has been kicked from the group.
|
||||||
|
#
|
||||||
|
'KICK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# A peer has been banned from the group.
|
||||||
|
#
|
||||||
|
'BAN': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# A peer as been given the observer role.
|
||||||
|
#
|
||||||
|
'OBSERVER': 2,
|
||||||
|
|
||||||
|
#
|
||||||
|
# A peer has been given the user role.
|
||||||
|
#
|
||||||
|
'USER': 3,
|
||||||
|
|
||||||
|
#
|
||||||
|
# A peer has been given the moderator role.
|
||||||
|
#
|
||||||
|
'MODERATOR': 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_BAN_QUERY = {
|
||||||
|
|
||||||
|
#
|
||||||
|
# The function returned successfully.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_BAN_QUERY_OK': 0,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The group number passed did not designate a valid group.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND': 1,
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ban_id does not designate a valid ban list entry.
|
||||||
|
#
|
||||||
|
'TOX_ERR_GROUP_BAN_QUERY_BAD_ID': 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOX_GROUP_BAN_TYPE = {
|
||||||
|
|
||||||
|
'IP_PORT': 0,
|
||||||
|
|
||||||
|
'PUBLIC_KEY': 1,
|
||||||
|
|
||||||
|
'NICK': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_PUBLIC_KEY_SIZE = 32
|
||||||
|
|
||||||
|
TOX_ADDRESS_SIZE = TOX_PUBLIC_KEY_SIZE + 6
|
||||||
|
|
||||||
|
TOX_MAX_FRIEND_REQUEST_LENGTH = 1016
|
||||||
|
|
||||||
|
TOX_MAX_MESSAGE_LENGTH = 1372
|
||||||
|
|
||||||
|
TOX_GROUP_MAX_TOPIC_LENGTH = 512
|
||||||
|
|
||||||
|
TOX_GROUP_MAX_PART_LENGTH = 128
|
||||||
|
|
||||||
|
TOX_GROUP_MAX_GROUP_NAME_LENGTH = 48
|
||||||
|
|
||||||
|
TOX_GROUP_MAX_PASSWORD_SIZE = 32
|
||||||
|
|
||||||
|
TOX_GROUP_CHAT_ID_SIZE = 32
|
||||||
|
|
||||||
|
TOX_GROUP_PEER_PUBLIC_KEY_SIZE = 32
|
||||||
|
|
||||||
|
TOX_MAX_NAME_LENGTH = 128
|
||||||
|
|
||||||
|
TOX_MAX_STATUS_MESSAGE_LENGTH = 1007
|
||||||
|
|
||||||
|
TOX_SECRET_KEY_SIZE = 32
|
||||||
|
|
||||||
|
TOX_FILE_ID_LENGTH = 32
|
||||||
|
|
||||||
|
TOX_HASH_LENGTH = 32
|
||||||
|
|
||||||
|
TOX_MAX_CUSTOM_PACKET_SIZE = 1373
|
75
wrapper/toxencryptsave.py
Normal file
75
wrapper/toxencryptsave.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||||
|
from ctypes import c_size_t, create_string_buffer, byref, c_int, ArgumentError, c_char_p, c_bool
|
||||||
|
|
||||||
|
from wrapper import libtox
|
||||||
|
from wrapper.toxencryptsave_enums_and_consts import *
|
||||||
|
|
||||||
|
class ToxEncryptSave:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.libtoxencryptsave = libtox.LibToxEncryptSave()
|
||||||
|
|
||||||
|
def is_data_encrypted(self, data):
|
||||||
|
"""
|
||||||
|
Checks if given data is encrypted
|
||||||
|
"""
|
||||||
|
func = self.libtoxencryptsave.tox_is_data_encrypted
|
||||||
|
func.restype = c_bool
|
||||||
|
result = func(c_char_p(bytes(data)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def pass_encrypt(self, data, password):
|
||||||
|
"""
|
||||||
|
Encrypts the given data with the given password.
|
||||||
|
|
||||||
|
:return: output array
|
||||||
|
"""
|
||||||
|
out = create_string_buffer(len(data) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
|
||||||
|
tox_err_encryption = c_int()
|
||||||
|
self.libtoxencryptsave.tox_pass_encrypt(c_char_p(data),
|
||||||
|
c_size_t(len(data)),
|
||||||
|
c_char_p(bytes(password, 'utf-8')),
|
||||||
|
c_size_t(len(password)),
|
||||||
|
out,
|
||||||
|
byref(tox_err_encryption))
|
||||||
|
tox_err_encryption = tox_err_encryption.value
|
||||||
|
if tox_err_encryption == TOX_ERR_ENCRYPTION['OK']:
|
||||||
|
return out[:]
|
||||||
|
elif tox_err_encryption == TOX_ERR_ENCRYPTION['NULL']:
|
||||||
|
raise ArgumentError('Some input data, or maybe the output pointer, was null.')
|
||||||
|
elif tox_err_encryption == 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'
|
||||||
|
' lack of memory issue. The functions accepting keys do not produce this error.')
|
||||||
|
elif tox_err_encryption == TOX_ERR_ENCRYPTION['FAILED']:
|
||||||
|
raise RuntimeError('The encryption itself failed.')
|
||||||
|
|
||||||
|
def pass_decrypt(self, data, password):
|
||||||
|
"""
|
||||||
|
Decrypts the given data with the given password.
|
||||||
|
|
||||||
|
:return: output array
|
||||||
|
"""
|
||||||
|
out = create_string_buffer(len(data) - TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
|
||||||
|
tox_err_decryption = c_int()
|
||||||
|
self.libtoxencryptsave.tox_pass_decrypt(c_char_p(bytes(data)),
|
||||||
|
c_size_t(len(data)),
|
||||||
|
c_char_p(bytes(password, 'utf-8')),
|
||||||
|
c_size_t(len(password)),
|
||||||
|
out,
|
||||||
|
byref(tox_err_decryption))
|
||||||
|
tox_err_decryption = tox_err_decryption.value
|
||||||
|
if tox_err_decryption == TOX_ERR_DECRYPTION['OK']:
|
||||||
|
return out[:]
|
||||||
|
elif tox_err_decryption == TOX_ERR_DECRYPTION['NULL']:
|
||||||
|
raise ArgumentError('Some input data, or maybe the output pointer, was null.')
|
||||||
|
elif tox_err_decryption == TOX_ERR_DECRYPTION['INVALID_LENGTH']:
|
||||||
|
raise ArgumentError('The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes')
|
||||||
|
elif tox_err_decryption == 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'
|
||||||
|
' corrupted)')
|
||||||
|
elif tox_err_decryption == 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'
|
||||||
|
' lack of memory issue. The functions accepting keys do not produce this error.')
|
||||||
|
elif tox_err_decryption == TOX_ERR_DECRYPTION['FAILED']:
|
||||||
|
raise RuntimeError('The encrypted byte array could not be decrypted. Either the data was corrupt or the '
|
||||||
|
'password/key was incorrect.')
|
29
wrapper/toxencryptsave_enums_and_consts.py
Normal file
29
wrapper/toxencryptsave_enums_and_consts.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
TOX_ERR_ENCRYPTION = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# Some input data, or maybe the output pointer, was null.
|
||||||
|
'NULL': 1,
|
||||||
|
# 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.
|
||||||
|
'KEY_DERIVATION_FAILED': 2,
|
||||||
|
# The encryption itself failed.
|
||||||
|
'FAILED': 3
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_DECRYPTION = {
|
||||||
|
# The function returned successfully.
|
||||||
|
'OK': 0,
|
||||||
|
# Some input data, or maybe the output pointer, was null.
|
||||||
|
'NULL': 1,
|
||||||
|
# The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
|
||||||
|
'INVALID_LENGTH': 2,
|
||||||
|
# The input data is missing the magic number (i.e. wasn't created by this module, or is corrupted)
|
||||||
|
'BAD_FORMAT': 3,
|
||||||
|
# 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.
|
||||||
|
'KEY_DERIVATION_FAILED': 4,
|
||||||
|
# The encrypted byte array could not be decrypted. Either the data was corrupt or the password/key was incorrect.
|
||||||
|
'FAILED': 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_PASS_ENCRYPTION_EXTRA_LENGTH = 80
|
Loading…
Reference in New Issue
Block a user