├── ci_scripts ├── 04-source.bat ├── 03-build.bat ├── 02-opus.bat ├── build.sh ├── Dockerfile ├── 01-openssl.bat └── install.ps1 ├── docs ├── _static │ └── css │ │ └── my_theme.css ├── module │ ├── utils.rst │ └── tgvoip.rst ├── Makefile ├── make.bat ├── guides │ ├── install.rst │ └── usage.rst ├── index.rst └── conf.py ├── MANIFEST.in ├── .gitmodules ├── NOTICE ├── src ├── tgvoip │ ├── __init__.py │ ├── utils.py │ └── tgvoip.py ├── FindTGVoIP.cmake ├── _tgvoip.pyi ├── _tgvoip.h ├── _tgvoip_module.cpp ├── _tgvoip.cpp └── libtgvoip.cmake ├── .gitignore ├── README.md ├── CMakeLists.txt ├── appveyor.yml ├── setup.py ├── COPYING.lesser └── COPYING /ci_scripts/04-source.bat: -------------------------------------------------------------------------------- 1 | python setup.py sdist 2 | -------------------------------------------------------------------------------- /docs/_static/css/my_theme.css: -------------------------------------------------------------------------------- 1 | @import url("theme.css"); 2 | 3 | .wy-nav-content { 4 | max-width: none; 5 | } 6 | -------------------------------------------------------------------------------- /docs/module/utils.rst: -------------------------------------------------------------------------------- 1 | Utility functions 2 | ================= 3 | 4 | .. module:: tgvoip.utils 5 | 6 | .. automodule:: tgvoip.utils 7 | :members: 8 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING COPYING.lesser NOTICE CMakeLists.txt 2 | recursive-include 3rdparty * 3 | recursive-include cmake * 4 | recursive-include src *.py *.pyi *.cpp *.h *.hpp *.cmake -------------------------------------------------------------------------------- /ci_scripts/03-build.bat: -------------------------------------------------------------------------------- 1 | xcopy /E /I /C /Y ..\openssl_1_1_1\out64 ..\openssl_1_1_1\out32 2 | xcopy /E /I /C /Y ..\opus\win32\VS2015\x64 ..\opus\win32\VS2015\Win32 3 | python setup.py build 4 | python setup.py bdist_wheel 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdparty/pybind11"] 2 | path = 3rdparty/pybind11 3 | url = https://github.com/pybind/pybind11/ 4 | [submodule "3rdparty/libtgvoip"] 5 | path = 3rdparty/libtgvoip 6 | url = https://github.com/telegramdesktop/libtgvoip/ 7 | [submodule "cmake"] 8 | path = cmake 9 | url = https://github.com/desktop-app/cmake_helpers/ 10 | -------------------------------------------------------------------------------- /ci_scripts/02-opus.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | 3 | if "%PYTHON_ARCH%"=="32" ( 4 | set BUILD_PLATFORM=Win32 5 | ) else ( 6 | set BUILD_PLATFORM=x64 7 | ) 8 | 9 | if exist "opus" goto ALREADY_BUILT 10 | 11 | echo Building Opus... 12 | git clone https://github.com/telegramdesktop/opus.git 13 | cd opus 14 | git checkout tdesktop 15 | cd win32\VS2015 16 | msbuild opus.sln /property:Configuration=Release /property:Platform="%BUILD_PLATFORM%" 17 | cd ..\..\.. 18 | goto FINISH 19 | 20 | :ALREADY_BUILT 21 | echo Opus is already built 22 | 23 | :FINISH 24 | cd pytgvoip 25 | -------------------------------------------------------------------------------- /ci_scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -xe 4 | 5 | if [[ ! -f "/opt/python/$1/bin/python" ]]; then 6 | echo "Interpreter \"$1\" was not found" 7 | exit 1 8 | fi 9 | 10 | /opt/python/$1/bin/pip3 install wheel auditwheel 11 | cd /tmp 12 | git clone https://github.com/bakatrouble/pytgvoip --recursive 13 | cd pytgvoip 14 | BUILD=1 /opt/python/$1/bin/python setup.py bdist_wheel 15 | /opt/python/$1/bin/auditwheel repair --plat manylinux2010_x86_64 dist/*.whl 16 | cp dist/*.whl /dist/ 17 | cp wheelhouse/*.whl /dist/ 18 | cd .. 19 | rm -rf pytgvoip 20 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /ci_scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/pypa/manylinux2010_x86_64 2 | 3 | RUN yum install -y gcc \ 4 | openssl \ 5 | openssl-devel \ 6 | opus \ 7 | opus-devel 8 | 9 | RUN cd /tmp \ 10 | && git clone https://github.com/grishka/libtgvoip/ \ 11 | && cd libtgvoip \ 12 | && git checkout b6ac2911 \ 13 | && export CFLAGS="-O3 -std=c99" \ 14 | && export CXXFLAGS="-O3 -D__STDC_FORMAT_MACROS" \ 15 | && autoreconf --force --install \ 16 | && ./configure --enable-audio-callback --enable-static=no \ 17 | && make -j9 \ 18 | && make install \ 19 | && cd .. \ 20 | && rm -rf libtgvoip 21 | 22 | COPY build.sh / 23 | ENTRYPOINT ["sh", "/build.sh"] 24 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | PytgVoIP - Telegram VoIP Library for Python 2 | Copyright (C) 2020 bakatrouble 3 | 4 | This file is part of PytgVoIP. 5 | 6 | PytgVoIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | PytgVoIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with PytgVoIP. If not, see . -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /src/tgvoip/__init__.py: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | 20 | from tgvoip.tgvoip import * 21 | from tgvoip.tgvoip import __all__ 22 | 23 | __version__ = '0.0.7.1' 24 | -------------------------------------------------------------------------------- /ci_scripts/01-openssl.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | 3 | if "%PYTHON_ARCH%"=="32" ( 4 | set COMPILER=VC-WIN32 5 | ) else ( 6 | set COMPILER=VC-WIN64A 7 | ) 8 | 9 | if exist "openssl_1_1_1" goto ALREADY_BUILT 10 | 11 | echo Building OpenSSL... 12 | 13 | curl -L -o nasminst.exe http://libgd.blob.core.windows.net/nasm/nasm-2.07-installer.exe 14 | start /wait nasminst.exe /S 15 | set PATH=C:\Program Files (x86)\nasm;%PATH% 16 | 17 | choco install strawberryperl -y 18 | set PATH=C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin;%PATH% 19 | 20 | git clone https://github.com/openssl/openssl.git openssl_1_1_1 21 | cd openssl_1_1_1 22 | git checkout OpenSSL_1_1_1-stable 23 | 24 | perl Configure no-shared "%COMPILER%" 25 | nmake 26 | mkdir "out%PYTHON_ARCH%" 27 | move libcrypto.lib "out%PYTHON_ARCH%" 28 | move libssl.lib "out%PYTHON_ARCH%" 29 | move ossl_static.pdb "out%PYTHON_ARCH%" 30 | 31 | cd .. 32 | goto FINISH 33 | 34 | :ALREADY_BUILT 35 | echo OpenSSL is already built 36 | 37 | :FINISH 38 | cd pytgvoip 39 | -------------------------------------------------------------------------------- /docs/guides/install.rst: -------------------------------------------------------------------------------- 1 | .. _install: 2 | 3 | Installation 4 | ============ 5 | 6 | 7 | Requirements 8 | ------------ 9 | On Linux and macOS to install this library you must have ``make``, ``cmake``, C++11 compatible compiler, Python headers, Opus and OpenSSL libraries and headers installed: 10 | 11 | - Debian-based distributions 12 | 13 | .. code-block:: bash 14 | 15 | $ apt install make cmake gcc g++ python3-dev gcc g++ openssl libssl-dev libopus0 libopus-dev 16 | 17 | 18 | - Archlinux-based distributions 19 | 20 | .. code-block:: bash 21 | 22 | $ pacman -S make cmake gcc python3 openssl opus 23 | 24 | 25 | - macOS 26 | 27 | .. code-block:: bash 28 | 29 | $ brew install make cmake gcc g++ python3 openssl opus 30 | 31 | 32 | Install pytgvoip 33 | ---------------- 34 | - Stable version: 35 | 36 | .. code-block:: bash 37 | 38 | $ pip install pytgvoip 39 | 40 | 41 | - Development version: 42 | 43 | .. code-block:: bash 44 | 45 | $ pip install git+https://github.com/bakatrouble/pytgvoip#egg=pytgvoip 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | /.idea 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | *.so 7 | .Python 8 | build/ 9 | develop-eggs/ 10 | dist/ 11 | downloads/ 12 | eggs/ 13 | .eggs/ 14 | lib/ 15 | lib64/ 16 | parts/ 17 | sdist/ 18 | var/ 19 | wheels/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | MANIFEST 24 | *.manifest 25 | *.spec 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | htmlcov/ 29 | .tox/ 30 | .coverage 31 | .coverage.* 32 | .cache 33 | nosetests.xml 34 | coverage.xml 35 | *.cover 36 | .hypothesis/ 37 | .pytest_cache/ 38 | *.mo 39 | *.pot 40 | *.log 41 | local_settings.py 42 | db.sqlite3 43 | instance/ 44 | .webassets-cache 45 | .scrapy 46 | docs/_build/ 47 | target/ 48 | .ipynb_checkpoints 49 | .python-version 50 | celerybeat-schedule 51 | *.sage.py 52 | .env 53 | .venv 54 | env/ 55 | venv/ 56 | ENV/ 57 | env.bak/ 58 | venv.bak/ 59 | .spyderproject 60 | .spyproject 61 | .ropeproject 62 | /site 63 | .mypy_cache/ 64 | CMakeCache.txt 65 | CMakeFiles 66 | CMakeScripts 67 | Testing 68 | cmake_install.cmake 69 | install_manifest.txt 70 | compile_commands.json 71 | CTestTestfile.cmake 72 | cmake-build-* 73 | 74 | *.session 75 | *.raw 76 | *.mp3 77 | *.mp4 78 | *.wav 79 | unknown_errors.txt 80 | example/config.ini 81 | -------------------------------------------------------------------------------- /docs/module/tgvoip.rst: -------------------------------------------------------------------------------- 1 | libtgvoip wrapper 2 | ================= 3 | 4 | .. module:: tgvoip.tgvoip 5 | 6 | 7 | VoIPController 8 | -------------- 9 | 10 | .. autoclass:: tgvoip.VoIPController 11 | :members: 12 | 13 | 14 | VoIPServerConfig 15 | ---------------- 16 | 17 | .. autoclass:: tgvoip.VoIPServerConfig 18 | :members: 19 | 20 | 21 | Enums 22 | ----- 23 | 24 | .. autoclass:: tgvoip.NetType 25 | :members: 26 | 27 | .. autoclass:: tgvoip.DataSaving 28 | :members: 29 | 30 | .. autoclass:: tgvoip.CallState 31 | :members: 32 | 33 | .. autoclass:: tgvoip.CallError 34 | :members: 35 | 36 | 37 | Data structures 38 | --------------- 39 | 40 | 41 | .. py:class:: tgvoip.Stats 42 | 43 | Object storing call stats 44 | 45 | .. attribute:: bytes_sent_wifi 46 | 47 | Amount of data sent over WiFi 48 | :type: ``int`` 49 | 50 | .. attribute:: bytes_sent_mobile 51 | 52 | Amount of data sent over mobile network 53 | :type: ``int`` 54 | 55 | .. attribute:: bytes_recvd_wifi 56 | 57 | Amount of data received over WiFi 58 | :type: ``int`` 59 | 60 | .. attribute:: bytes_recvd_mobile 61 | 62 | Amount of data received over mobile network 63 | :type: ``int`` 64 | 65 | 66 | .. py:class:: tgvoip.Endpoint 67 | 68 | Object storing endpoint info 69 | 70 | :param _id: Endpoint ID 71 | :type _id: ``int`` 72 | :param ip: Endpoint IPv4 address 73 | :type ip: ``str`` 74 | :param ipv6: Endpoint IPv6 address 75 | :type ipv6: ``str`` 76 | :param port: Endpoint port 77 | :type port: ``int`` 78 | :param peer_tag: Endpoint peer tag 79 | :type peer_tag: ``bytes`` 80 | -------------------------------------------------------------------------------- /src/FindTGVoIP.cmake: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | 20 | # - Find tgvoip 21 | # Find the native tgvoip includes and libraries 22 | # 23 | # TGVOIP_INCLUDE_DIR - where to find VoIPController.h, etc. 24 | # TGVOIP_LIBRARIES - List of libraries when using tgvoip. 25 | # TGVOIP_FOUND - True if tgvoip found. 26 | 27 | if(TGVOIP_INCLUDE_DIR) 28 | set(TGVOIP_FIND_QUIETLY TRUE) 29 | endif(TGVOIP_INCLUDE_DIR) 30 | 31 | set(FIND_TGVOIP_PATHS 32 | ~/Library/Frameworks 33 | /Library/Frameworks 34 | /usr/local 35 | /usr 36 | /sw 37 | /opt/local 38 | /opt/csw 39 | /opt 40 | $ENV{TGVOIP_LIBRARY_ROOT} 41 | $ENV{TGVOIP_INCLUDE_ROOT} 42 | ) 43 | 44 | find_path(TGVOIP_INCLUDE_DIR 45 | VoIPController.h 46 | PATH_SUFFIXES tgvoip libtgvoip 47 | PATHS ${FIND_TGVOIP_PATHS} 48 | ) 49 | find_library(TGVOIP_LIBRARY 50 | NAMES tgvoip tgvoip_static libtgvoip libtgvoip_static libtgvoip.dll 51 | PATHS ${FIND_TGVOIP_PATHS} 52 | ) 53 | 54 | message(STATUS ${TGVOIP_INCLUDE_DIR}) 55 | message(STATUS ${TGVOIP_LIBRARY}) 56 | 57 | include(FindPackageHandleStandardArgs) 58 | find_package_handle_standard_args(TGVOIP DEFAULT_MSG TGVOIP_INCLUDE_DIR TGVOIP_LIBRARY) 59 | 60 | if(TGVOIP_FOUND) 61 | set(TGVOIP_LIBRARIES ${TGVOIP_LIBRARY}) 62 | else(TGVOIP_FOUND) 63 | set(TGVOIP_LIBRARIES) 64 | endif(TGVOIP_FOUND) 65 | 66 | mark_as_advanced(TGVOIP_INCLUDE_DIR) 67 | mark_as_advanced(TGVOIP_LIBRARY) 68 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to pytgvoip 2 | =================== 3 | 4 | |pypi| |libwheels-win| |libtgvoip-win| |license| 5 | 6 | **Telegram VoIP Library for Python** 7 | 8 | `Community`_ 9 | 10 | **PytgVoIP** is a `Telegram`_ VoIP library written in Python and C++. 11 | 12 | It uses `libtgvoip`_ (a library used in official clients) for voice 13 | encoding and transmission, and `pybind11`_ for simple generation of 14 | Python extension written in C++. 15 | 16 | Features 17 | -------- 18 | 19 | - Making and receiving Telegram calls 20 | - Python callbacks for sending and receiving audio stream frames allow 21 | flexible control 22 | - Pre-built Windows wheels in PyPI 23 | 24 | Requirements 25 | ------------ 26 | 27 | - Python 3.4 or higher 28 | - An MTProto client (i.e. Pyrogram, Telethon) 29 | 30 | Installing 31 | ---------- 32 | 33 | Refer the corresponding section: :ref:`install` 34 | 35 | Encoding audio streams 36 | ---------------------- 37 | 38 | Streams consumed by ``libtgvoip`` should be encoded in 16-bit signed PCM 39 | audio. 40 | 41 | .. code-block:: bash 42 | 43 | $ ffmpeg -i input.mp3 -f s16le -ac 1 -ar 48000 -acodec pcm_s16le input.raw # encode 44 | $ ffmpeg -f s16le -ac 1 -ar 48000 -acodec pcm_s16le -i output.raw output.mp3 # decode 45 | 46 | .. _copyright--license: 47 | 48 | Copyright & License 49 | ------------------- 50 | 51 | - Copyright (C) 2019 `bakatrouble`_ 52 | - Licensed under the terms of the `GNU Lesser General Public License v3 or later (LGPLv3+)`_ 53 | 54 | 55 | .. _Community: https://t.me/pytgvoip 56 | .. _Telegram: https://telegram.org/ 57 | .. _libtgvoip: https://github.com/grishka/libtgvoip 58 | .. _pybind11: https://github.com/pybind/pybind11 59 | .. _bakatrouble: https://github.com/bakatrouble 60 | .. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/bakatrouble/pytgvoip/blob/master/COPYING.lesser 61 | 62 | .. |pypi| image:: https://img.shields.io/pypi/v/pytgvoip.svg?style=flat 63 | :target: https://pypi.org/project/pytgvoip/ 64 | .. |libwheels-win| image:: https://img.shields.io/appveyor/ci/bakatrouble/pylibtgvoip.svg?label=windows%20wheels%20build&style=flat 65 | :target: https://ci.appveyor.com/project/bakatrouble/pylibtgvoip 66 | .. |libtgvoip-win| image:: https://img.shields.io/appveyor/ci/bakatrouble/libtgvoip.svg?label=libtgvoip%20windows%20build&style=flat 67 | :target: https://ci.appveyor.com/project/bakatrouble/libtgvoip 68 | .. |license| image:: https://img.shields.io/pypi/l/pytgvoip.svg?style=flat 69 | 70 | 71 | .. toctree:: 72 | :hidden: 73 | 74 | self 75 | guides/install 76 | guides/usage 77 | 78 | .. toctree:: 79 | :hidden: 80 | :caption: Module 81 | 82 | module/tgvoip 83 | module/utils 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pytgvoip 2 | 3 | [![Read the Docs](https://img.shields.io/readthedocs/pytgvoip.svg)](https://pytgvoip.rtfd.io) [![PyPI](https://img.shields.io/pypi/v/pytgvoip.svg?style=flat)](https://pypi.org/project/pytgvoip/) [![AppVeyor (windows wheels)](https://img.shields.io/appveyor/ci/bakatrouble/pylibtgvoip.svg?label=windows%20wheels%20build&style=flat)](https://ci.appveyor.com/project/bakatrouble/pylibtgvoip) ![LGPLv3+](https://img.shields.io/pypi/l/pytgvoip.svg?style=flat) 4 | 5 | **Telegram VoIP Library for Python** 6 | 7 | [Community](https://t.me/pytgvoip) | [Documentation](https://pytgvoip.rtfd.io) 8 | 9 | **PytgVoIP** is a [Telegram](https://telegram.org/) VoIP library written in Python and C++. 10 | 11 | It uses [libtgvoip](https://github.com/grishka/libtgvoip) (a library used in official clients) 12 | for voice encoding and transmission, and [pybind11](https://github.com/pybind/pybind11) for simple 13 | generation of Python extension written in C++. 14 | 15 | It is targeted to MTProto client library developers, detailed usage guide is available [here](https://pytgvoip.readthedocs.io/en/latest/guides/usage.html). 16 | 17 | An example of usage with [Pyrogram](https://github.com/pyrogram/pyrogram) is available [here](https://github.com/bakatrouble/pytgvoip_pyrogram) ([`pytgvoip_pyrogram` in PyPI](https://pypi.org/project/pytgvoip_pyrogram/)), could be used as reference. 18 | 19 | Hopefully this module support will be [integrated in Pyrogram itself](https://github.com/pyrogram/pyrogram/pull/218), also [@cher-nov](https://github.com/cher-nov) has plans to integrate it into [Telethon](https://github.com/LonamiWebs/Telethon) as well 20 | 21 | ## Features 22 | * Python callbacks for sending and receiving audio stream frames allow flexible control 23 | * Pre-built Windows wheels in PyPI 24 | 25 | ## Requirements 26 | * Python 3.5 or higher 27 | 28 | Linux, MacOS: (use binary wheels from PyPI for Windows) 29 | * [libtgvoip](https://pytgvoip.readthedocs.io/en/latest/guides/libtgvoip.html) 30 | * CMake, C++11-compatible compiler, Python headers 31 | 32 | ## Installing 33 | ```pip3 install pytgvoip``` 34 | 35 | Install [`pytgvoip_pyrogram`](https://github.com/bakatrouble/pytgvoip_pyrogram) to use this module with Pyrogram. 36 | 37 | 38 | ## Encoding audio streams 39 | Streams consumed by `libtgvoip` should be encoded in 16-bit signed PCM audio. 40 | ```bash 41 | $ ffmpeg -i input.mp3 -f s16le -ac 1 -ar 48000 -acodec pcm_s16le input.raw # encode 42 | $ ffmpeg -f s16le -ac 1 -ar 48000 -acodec pcm_s16le -i output.raw output.mp3 # decode 43 | ``` 44 | 45 | ## Copyright & License 46 | * Copyright (C) 2019 [bakatrouble](https://github.com/bakatrouble) 47 | * Licensed under the terms of the [GNU Lesser General Public License v3 or later (LGPLv3+)](COPYING.lesser) 48 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | 20 | cmake_minimum_required(VERSION 3.13) 21 | project(pylibtgvoip) 22 | set(CMAKE_CXX_STANDARD 14) 23 | cmake_policy(SET CMP0028 NEW) 24 | 25 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src") 26 | if(UNIX AND NOT APPLE) 27 | set(LINUX TRUE) 28 | endif() 29 | if(APPLE) 30 | set(OPENSSL_ROOT_DIR /usr/local/opt/openssl/) 31 | endif() 32 | add_definitions( 33 | -DTGVOIP_USE_CALLBACK_AUDIO_IO 34 | -DWITHOUT_ALSA 35 | -DWITHOUT_PULSE 36 | ) 37 | 38 | add_subdirectory(3rdparty/pybind11) 39 | include_directories(${TGVOIP_INCLUDE_DIR}) 40 | 41 | if(WIN32) 42 | get_filename_component(libs_loc .. REALPATH) 43 | else() 44 | set(DESKTOP_APP_USE_PACKAGED TRUE) 45 | endif() 46 | include(cmake/nice_target_sources.cmake) 47 | include(cmake/target_link_frameworks.cmake) 48 | include(cmake/target_link_static_libraries.cmake) 49 | include(cmake/init_target.cmake) 50 | include(cmake/options.cmake) 51 | add_subdirectory(cmake/external/openssl) 52 | add_subdirectory(cmake/external/opus) 53 | get_filename_component(third_party_loc 3rdparty REALPATH) 54 | include(src/libtgvoip.cmake) 55 | 56 | nice_target_sources(lib_tgvoip ${tgvoip_loc} 57 | PRIVATE 58 | audio/AudioIOCallback.cpp 59 | audio/AudioIOCallback.h 60 | ) 61 | 62 | list(APPEND SOURCES 63 | src/_tgvoip.cpp 64 | src/_tgvoip_module.cpp 65 | ) 66 | 67 | pybind11_add_module(_tgvoip ${SOURCES}) 68 | target_link_libraries(_tgvoip PRIVATE lib_tgvoip) 69 | 70 | if ((CMAKE_CXX_COMPILER_ID STREQUAL GNU) AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)) 71 | target_compile_options(_tgvoip PRIVATE 72 | -Wno-error=deprecated-copy 73 | ) 74 | endif() 75 | 76 | if (WIN32) 77 | target_compile_options(lib_tgvoip PRIVATE /wd4477 /wd4267) 78 | endif() 79 | # macOS and its weird paths 80 | target_include_directories(lib_tgvoip PRIVATE /usr/local/include) 81 | target_link_directories(_tgvoip PRIVATE /usr/local/lib) 82 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.0.{build} 2 | 3 | branches: 4 | only: 5 | - master 6 | 7 | skip_non_tags: true 8 | 9 | image: Visual Studio 2019 10 | platform: x64 11 | 12 | environment: 13 | BUILD: true 14 | PYPI_PASSWORD: 15 | secure: bBLT+ICiuwrkYZEBrL++Jw== 16 | 17 | matrix: 18 | - PYTHON: "C:\\Python38" 19 | SOURCE: "TRUE" 20 | 21 | - PYTHON: "C:\\Python38" 22 | PYTHON_VERSION: "3.8.x" 23 | PYTHON_ARCH: "32" 24 | LIBTGVOIP_JOB: "Environment: PLATFORM=x86" 25 | 26 | - PYTHON: "C:\\Python38-x64" 27 | PYTHON_VERSION: "3.8.x" 28 | PYTHON_ARCH: "64" 29 | LIBTGVOIP_JOB: "Environment: PLATFORM=x64" 30 | 31 | - PYTHON: "C:\\Python37" 32 | PYTHON_VERSION: "3.7.x" 33 | PYTHON_ARCH: "32" 34 | LIBTGVOIP_JOB: "Environment: PLATFORM=x86" 35 | 36 | - PYTHON: "C:\\Python37-x64" 37 | PYTHON_VERSION: "3.7.x" 38 | PYTHON_ARCH: "64" 39 | LIBTGVOIP_JOB: "Environment: PLATFORM=x64" 40 | 41 | - PYTHON: "C:\\Python36" 42 | PYTHON_VERSION: "3.6.x" 43 | PYTHON_ARCH: "32" 44 | LIBTGVOIP_JOB: "Environment: PLATFORM=x86" 45 | 46 | - PYTHON: "C:\\Python36-x64" 47 | PYTHON_VERSION: "3.6.x" 48 | PYTHON_ARCH: "64" 49 | LIBTGVOIP_JOB: "Environment: PLATFORM=x64" 50 | 51 | - PYTHON: "C:\\Python35" 52 | PYTHON_VERSION: "3.5.x" 53 | PYTHON_ARCH: "32" 54 | LIBTGVOIP_JOB: "Environment: PLATFORM=x86" 55 | 56 | - PYTHON: "C:\\Python35-x64" 57 | PYTHON_VERSION: "3.5.x" 58 | PYTHON_ARCH: "64" 59 | LIBTGVOIP_JOB: "Environment: PLATFORM=x64" 60 | 61 | 62 | 63 | clone_folder: c:\projects\pytgvoip 64 | 65 | cache: 66 | - ../openssl_1_1_1 -> ci_scripts/01-openssl.bat 67 | - ../opus -> ci_scripts/02-opus.bat 68 | 69 | init: 70 | - if "%PYTHON_ARCH%"=="32" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" 71 | - if "%PYTHON_ARCH%"=="64" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" 72 | 73 | install: 74 | - ps: if (-not(Test-Path($env:PYTHON))) { & ci_scripts\install.ps1 } 75 | - set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% 76 | - python --version 77 | - python -c "import struct; print(struct.calcsize('P') * 8)" 78 | - python -m pip install wheel pip twine -U 79 | 80 | - git submodule update --init --recursive 81 | 82 | build_script: 83 | - if not "%SOURCE%"=="TRUE" ci_scripts\01-openssl.bat 84 | - if not "%SOURCE%"=="TRUE" ci_scripts\02-opus.bat 85 | - if not "%SOURCE%"=="TRUE" ci_scripts\03-build.bat 86 | - if "%SOURCE%"=="TRUE" ci_scripts\04-source.bat 87 | 88 | after_build: 89 | - ps: ls dist 90 | 91 | deploy_script: 92 | - echo "Starting Artifact Deployment" 93 | # populate pypirc file for twine 94 | - echo [distutils] > %USERPROFILE%\\.pypirc 95 | - echo index-servers = >> %USERPROFILE%\\.pypirc 96 | - echo pypi >> %USERPROFILE%\\.pypirc 97 | - echo [pypi] >> %USERPROFILE%\\.pypirc 98 | - echo username=bakatrouble >> %USERPROFILE%\\.pypirc 99 | - echo password=%PYPI_PASSWORD% >> %USERPROFILE%\\.pypirc 100 | # upload to pypi for windows 101 | - set HOME=%USERPROFILE% 102 | - twine upload --skip-existing dist/* 2>$null 103 | - echo "Finished Artifact Deployment" 104 | 105 | artifacts: 106 | - path: dist\* 107 | -------------------------------------------------------------------------------- /src/_tgvoip.pyi: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | 20 | from enum import Enum 21 | from typing import Optional, List 22 | 23 | 24 | class NetType(Enum): 25 | UNKNOWN = ... 26 | GPRS = ... 27 | EDGE = ... 28 | NET_3G = ... 29 | HSPA = ... 30 | LTE = ... 31 | WIFI = ... 32 | ETHERNET = ... 33 | OTHER_HIGH_SPEED = ... 34 | OTHER_LOW_SPEED = ... 35 | DIALUP = ... 36 | OTHER_MOBILE = ... 37 | 38 | 39 | class CallState(Enum): 40 | WAIT_INIT = ... 41 | WAIT_INIT_ACK = ... 42 | ESTABLISHED = ... 43 | FAILED = ... 44 | RECONNECTING = ... 45 | 46 | 47 | class DataSaving(Enum): 48 | NEVER = ... 49 | MOBILE = ... 50 | ALWAYS = ... 51 | 52 | 53 | class CallError(Enum): 54 | UNKNOWN = ... 55 | INCOMPATIBLE = ... 56 | TIMEOUT = ... 57 | AUDIO_IO = ... 58 | PROXY = ... 59 | 60 | 61 | class Stats: 62 | bytes_sent_wifi = ... 63 | bytes_sent_mobile = ... 64 | bytes_recvd_wifi = ... 65 | bytes_recvd_mobile = ... 66 | 67 | 68 | # class AudioInputDevice: 69 | # _id = ... 70 | # display_name = ... 71 | 72 | 73 | # class AudioOutputDevice: 74 | # _id = ... 75 | # display_name = ... 76 | 77 | 78 | class Endpoint: 79 | _id: int = ... 80 | ip: str = ... 81 | ipv6: str = ... 82 | port: int = ... 83 | peer_tag: bytes = ... 84 | 85 | def __init__(self, _id: int, ip: str, ipv6: str, port: int, peer_tag: bytes): ... 86 | 87 | 88 | class VoIPController: 89 | LIBTGVOIP_VERSION: str = ... 90 | CONNECTION_MAX_LAYER: int = ... 91 | 92 | def __init__(self, persistent_state_file: str = ''): ... 93 | def _init(self) -> None: ... 94 | def start(self) -> None: ... 95 | def connect(self) -> None: ... 96 | def set_proxy(self, address: str, port: int, username: str, password: str) -> None: ... 97 | def set_encryption_key(self, key: bytes, is_outgoing: bool) -> None: ... 98 | def set_remote_endpoints(self, endpoints: list, allow_p2p: bool, tcp: bool, connection_max_layer: int) -> None: ... 99 | def get_debug_string(self) -> str: ... 100 | def set_network_type(self, _type: NetType) -> None: ... 101 | def set_mic_mute(self, mute: bool) -> None: ... 102 | def set_config(self, recv_timeout: float, init_timeout: float, data_saving_mode: DataSaving, enable_aec: bool, 103 | enable_ns: bool, enable_agc: bool, log_file_path: str, status_dump_path: str, 104 | log_packet_stats: bool) -> None: ... 105 | def debug_ctl(self, request: int, param: int) -> None: ... 106 | def get_preferred_relay_id(self) -> int: ... 107 | def get_last_error(self) -> CallError: ... 108 | def get_stats(self) -> Stats: ... 109 | def get_debug_log(self) -> str: ... 110 | def set_audio_output_gain_control_enabled(self, enabled: bool) -> None: ... 111 | def set_echo_cancellation_strength(self, strength: int) -> None: ... 112 | def get_peer_capabilities(self) -> int: ... 113 | def need_rate(self) -> bool: ... 114 | 115 | # @staticmethod 116 | # def enumerate_audio_inputs() -> List[AudioInputDevice]: ... 117 | # 118 | # @staticmethod 119 | # def enumerate_audio_outputs() -> List[AudioOutputDevice]: ... 120 | # 121 | # def set_current_audio_input(self, _id: str) -> None: ... 122 | # def set_current_audio_output(self, _id: str) -> None: ... 123 | # def get_current_audio_input_id(self) -> str: ... 124 | # def get_current_audio_output_id(self) -> str: ... 125 | 126 | def _native_io_get(self) -> bool: ... 127 | 128 | def _native_io_set(self, val: bool) -> None: ... 129 | 130 | def play(self, path: str) -> bool: ... 131 | 132 | def play_on_hold(self, paths: List[str]) -> None: ... 133 | 134 | def set_output_file(self, path: str) -> bool: ... 135 | 136 | def clear_play_queue(self) -> None: ... 137 | 138 | def clear_hold_queue(self) -> None: ... 139 | 140 | def unset_output_file(self) -> None: ... 141 | 142 | def _handle_state_change(self, state: CallState) -> None: 143 | raise NotImplementedError() 144 | 145 | def _handle_signal_bars_change(self, count: int) -> None: 146 | raise NotImplementedError() 147 | 148 | def _send_audio_frame_impl(self, length: int) -> bytes: ... 149 | def _recv_audio_frame_impl(self, frame: bytes) -> None: ... 150 | 151 | 152 | class VoIPServerConfig: 153 | @staticmethod 154 | def set_config(json_string: str): ... 155 | 156 | 157 | __version__: str = ... 158 | -------------------------------------------------------------------------------- /docs/guides/usage.rst: -------------------------------------------------------------------------------- 1 | Usage 2 | ===== 3 | 4 | 5 | Common 6 | ------ 7 | * You should have a protocol object: ``phoneCallProtocol(min_layer=65, max_layer=VoIPController.CONNECTION_MAX_LAYER, udp_p2p=True, udp_reflector=True)`` 8 | * All VoIP-related updates have type of ``updatePhoneCall`` with ``phone_call`` field of types ``phoneCallEmpty``, ``phoneCallWaiting``, ``phoneCallRequested``, ``phoneCallAccepted``, ``phoneCall`` or ``phoneCallDiscarded`` 9 | * Use :meth:`tgvoip.utils.generate_visualization` with ``auth_key`` and ``g_a`` for outgoing or ``g_a_or_b`` for incoming calls to get emojis if you need them 10 | 11 | 12 | Starting conversation 13 | --------------------- 14 | * Create a :class:`VoIPController` instance 15 | * Call :meth:`tgvoip.VoIPController.set_send_audio_frame_callback` (see docs for arguments) if needed, otherwise silence will be sent 16 | * Call :meth:`tgvoip.VoIPController.set_recv_audio_frame_callback` (see docs for arguments) if needed, otherwise nothing will be done to incoming audio stream 17 | * Add state change handlers to :attr:`tgvoip.VoIPController.call_state_changed_handlers` (see docs for handler format) list if needed 18 | * Add signal bars change handlers to :attr:`tgvoip.VoIPController.signal_bars_changed_handlers` (see docs for handler format) list if needed 19 | * Invoke ``help.getConfig()`` (result is later referred as ``config``) 20 | * Call :meth:`tgvoip.VoIPController.set_config` (arguments are: ``config.call_packet_timeout_ms / 1000., config.call_connect_timeout_ms / 1000., DataSaving.NEVER, call.id``) 21 | * Call :meth:`tgvoip.VoIPController.set_encryption_key` (arguments are: ``i2b(auth_key), is_outgoing`` where ``is_outgoing`` is a corresponding boolean value) 22 | * Build a ``list`` of :class:`tgvoip.Endpoint` objects from ``call.connection`` (single) and ``call.alternative_connections`` (another list) 23 | * Call :meth:`tgvoip.VoIPController.set_remote_endpoints` (arguments are: ``endpoints, call.p2p_allowed, False, call.protocol.max_layer``) 24 | * Call :meth:`tgvoip.VoIPController.start` 25 | * Call :meth:`tgvoip.VoIPController.connect` 26 | 27 | 28 | Discarding call 29 | --------------- 30 | * Build ``peer``: ``inputPhoneCall(id=call.id, access_hash=call.access_hash)`` 31 | * Get call duration using :attr:`tgvoip.VoIPController.call_duration` 32 | * Get connection ID using :meth:`tgvoip.VoIPController.get_preferred_relay_id` 33 | * Build a suitable ``reason`` object (types are: ``phoneCallDiscardReasonBusy``, ``phoneCallDiscardReasonDisconnect``, ``phoneCallDiscardReasonHangup``, ``phoneCallDiscardReasonMissed``) 34 | * Invoke ``phone.discardCall(peer, duration, connection_id, reason)``. You might get ``CALL_ALREADY_DECLINED`` error, this is fine 35 | * Destroy the :class:`tgvoip.VoIPController` object 36 | 37 | 38 | Ending conversation 39 | ------------------- 40 | * Send call rating and debug log if call ended normally (not failed): `TBD` 41 | * Destroy the :class:`tgvoip.VoIPController` object, everything will be done automatically 42 | 43 | 44 | Making outgoing calls 45 | --------------------- 46 | * Get a ``user_id`` object for user you want to call (of type ``inputPeerUser``) 47 | * Request a Diffie-Hellman config using ``messages.getDhConfig(version=0, random_length=256)`` 48 | * Check received config using :meth:`tgvoip.utils.check_dhc`. If check is not passed, do not make the call. You might want to cache received config because check is expensive 49 | * Choose a random value ``a``, ``1 < a < dhc.p-1`` 50 | * Calculate ``g_a``: ``pow(dhc.g, a, dhc.p)`` 51 | * Calculate ``g_a_hash``: ``sha256(g_a)`` 52 | * Choose a random value ``random_id``, ``0 <= random_id <= 0x7fffffff-1`` 53 | * Invoke ``phone.requestCall(user_id, random_id, g_a_hash, protocol)`` 54 | * Wait for an update with ``phoneCallAccepted`` object, it means that other party has accepted the call. You also might get a ``phoneCallDiscarded`` object, it means that other party has declined the call 55 | * If you have got a ``phoneCallDiscarded`` object, stop the :class:`tgvoip.VoIPController`. Otherwise, continue 56 | * Check a ``g_b`` value from received ``phoneCallAccepted`` (later referred as ``call``) object using :meth:`tgvoip.utils.check_g`. If check is not passed, stop the call 57 | * Calculate ``auth_key``: ``pow(call.g_b, a, dhc.p)`` 58 | * Calculate ``key_fingerprint`` using :meth:`tgvoip.utils.calc_fingerprint` 59 | * Build ``peer``: ``inputPhoneCall(id=call.id, access_hash=call.access_hash)`` 60 | * Invoke ``phone.confirmCall(key_fingerprint, peer, g_a, protocol)`` 61 | * Start the conversation 62 | 63 | 64 | Receiving calls 65 | --------------- 66 | * You will receive an update containing ``phoneCallRequested`` object (later referred as ``call``). You might discard it right away (use ``0`` for duration and connection_id) 67 | * Request a Diffie-Hellman config using ``messages.getDhConfig(version=0, random_length=256)`` 68 | * Check received config using :meth:`tgvoip.utils.check_dhc`. If check is not passed, do not make the call. You might want to cache received config because check is expensive 69 | * Choose a random value ``b``, ``1 < b < dhc.p-1`` 70 | * Calculate ``g_b``: ``pow(dhc.g, b, dhc.p)`` 71 | * Save ``call.g_a_hash`` 72 | * Build ``peer``: ``inputPhoneCall(id=call.id, access_hash=call.access_hash)`` 73 | * Invoke ``phone.acceptCall(peer, g_b, protocol)``. You might get ``CALL_ALREADY_DISCARDED`` or ``CALL_ALREADY_ACCEPTED`` errors, then you should stop current conversation. Also, if response contains ``phoneCallDiscarded`` object you should stop the call 74 | * Wait for an update with ``phoneCall`` object (later referred as ``call``) 75 | * Check that ``call.g_a_or_b`` is not empty and ``sha256(call.g_a_or_b)`` equals to ``g_a_hash`` you saved before. If it doesn't match, stop the call 76 | * Check a ``call.g_a_or_b`` value object using :meth:`tgvoip.utils.check_g` (second argument is ``dhc.p``). If check is not passed, stop the call 77 | * Calculate ``auth_key``: ``pow(call.g_a_or_b, b, dhc.p)`` 78 | * Calculate ``key_fingerprint`` using :meth:`tgvoip.utils.calc_fingerprint` 79 | * Check that ``key_fingerprint`` you have just calculated matches ``call.key_fingerprint``. If it doesn't match, stop the call 80 | * Start the conversation 81 | 82 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # PytgVoIP - Telegram VoIP Library for Python 4 | # Copyright (C) 2020 bakatrouble 5 | # 6 | # This file is part of PytgVoIP. 7 | # 8 | # PytgVoIP is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # PytgVoIP is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with PytgVoIP. If not, see . 20 | 21 | 22 | import multiprocessing 23 | import os 24 | import re 25 | import sys 26 | import platform 27 | import subprocess 28 | import shutil 29 | 30 | from setuptools import setup, Extension 31 | from setuptools.command.build_ext import build_ext 32 | 33 | 34 | def check_libraries(): 35 | args = 'gcc -lssl -lopus'.split() 36 | with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as process: 37 | stdout, stderr = process.communicate() 38 | match = re.findall(r'cannot find -l(\w+)', stderr.decode()) 39 | if match: 40 | raise RuntimeError( 41 | 'Following libraries are not installed: {}\nFor installation guide refer to ' 42 | 'https://pytgvoip.readthedocs.io/en/latest/guides/install.html'.format(', '.join(match)) 43 | ) 44 | 45 | 46 | class CMakeExtension(Extension): 47 | def __init__(self, name, sourcedir=''): 48 | Extension.__init__(self, name, sources=[]) 49 | self.sourcedir = os.path.abspath(sourcedir) 50 | 51 | 52 | class CMakeBuild(build_ext): 53 | def run(self): 54 | try: 55 | out = subprocess.check_output(['cmake', '--version']) 56 | except OSError: 57 | raise RuntimeError("CMake must be installed to build the following extensions: " + 58 | ", ".join(e.name for e in self.extensions)) 59 | 60 | if platform.system() != 'Windows': 61 | check_libraries() 62 | 63 | for ext in self.extensions: 64 | self.build_extension(ext) 65 | 66 | def build_extension(self, ext): 67 | extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) 68 | cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, 69 | '-DPYTHON_EXECUTABLE=' + sys.executable] 70 | 71 | cfg = 'Release' 72 | build_args = ['--config', cfg, '--target', '_tgvoip'] 73 | 74 | if platform.system() == "Windows": 75 | cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] 76 | if sys.maxsize > 2**32: 77 | cmake_args += ['-A', 'x64'] 78 | else: 79 | cmake_args += ['-A', 'Win32'] 80 | build_args += ['--', '/m:{}'.format(multiprocessing.cpu_count() + 1)] 81 | else: 82 | cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] 83 | build_args += ['--', '-j{}'.format(multiprocessing.cpu_count() + 1)] 84 | 85 | env = os.environ.copy() 86 | env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), 87 | self.distribution.get_version()) 88 | if not os.path.exists(self.build_temp): 89 | os.makedirs(self.build_temp) 90 | subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env) 91 | subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp) 92 | shutil.copy(os.path.join('src', '_tgvoip.pyi'), extdir) 93 | 94 | 95 | def get_version(): 96 | init_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'src', 'tgvoip', '__init__.py') 97 | with open(init_path, encoding='utf-8') as f: 98 | version = re.findall(r"__version__ = '(.+)'", f.read())[0] 99 | if os.environ.get('BUILD') is None and 'pip' not in __file__: 100 | version += '+develop' 101 | return version 102 | 103 | 104 | def get_long_description(): 105 | with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'README.md'), encoding='utf-8') as f: 106 | return f.read() 107 | 108 | 109 | setup( 110 | name='pytgvoip', 111 | version=get_version(), 112 | license='LGPLv3+', 113 | author='bakatrouble', 114 | author_email='bakatrouble@gmail.com', 115 | description='Telegram VoIP Library for Python', 116 | long_description=get_long_description(), 117 | long_description_content_type='text/markdown', 118 | url='https://github.com/bakatrouble/pytgvoip', 119 | keywords='telegram messenger voip library python', 120 | project_urls={ 121 | 'Tracker': 'https://github.com/bakatrouble/pytgvoip/issues', 122 | 'Community': 'https:/t.me/pytgvoip', 123 | 'Source': 'https://github.com/bakatrouble/pytgvoip', 124 | }, 125 | python_required='~=3.5', 126 | ext_modules=[CMakeExtension('_tgvoip')], 127 | packages=['tgvoip'], 128 | package_dir={'tgvoip': 'src/tgvoip'}, 129 | cmdclass={'build_ext': CMakeBuild}, 130 | zip_safe=False, 131 | classifiers=[ 132 | 'Development Status :: 3 - Alpha', 133 | 'Intended Audience :: Developers', 134 | 'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)', 135 | 'Operating System :: OS Independent', 136 | 'Programming Language :: Python', 137 | 'Programming Language :: Python :: 3', 138 | 'Programming Language :: Python :: 3 :: Only', 139 | 'Programming Language :: Python :: 3.5', 140 | 'Programming Language :: Python :: 3.6', 141 | 'Programming Language :: Python :: 3.7', 142 | 'Programming Language :: Python :: Implementation', 143 | 'Programming Language :: Python :: Implementation :: CPython', 144 | 'Programming Language :: C++', 145 | 'Topic :: Internet', 146 | 'Topic :: Communications', 147 | 'Topic :: Communications :: Internet Phone', 148 | 'Topic :: Software Development :: Libraries', 149 | 'Topic :: Software Development :: Libraries :: Python Modules', 150 | ], 151 | ) 152 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | import os 16 | import re 17 | import sys 18 | sys.path.insert(0, os.path.abspath('../src')) 19 | 20 | with open('../src/tgvoip/__init__.py', encoding='utf-8') as f: 21 | __version__ = re.findall(r"__version__ = '(.+)'", f.read())[0] 22 | 23 | # -- Project information ----------------------------------------------------- 24 | 25 | project = 'pytgvoip' 26 | copyright = '2019, bakatrouble' 27 | author = 'bakatrouble' 28 | 29 | # The short X.Y version 30 | version = 'version ' + __version__ 31 | # The full version, including alpha/beta/rc tags 32 | release = __version__ 33 | 34 | 35 | # -- General configuration --------------------------------------------------- 36 | 37 | # If your documentation needs a minimal Sphinx version, state it here. 38 | # 39 | # needs_sphinx = '1.0' 40 | 41 | # Add any Sphinx extension module names here, as strings. They can be 42 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 43 | # ones. 44 | extensions = [ 45 | 'sphinx.ext.autodoc', 46 | 'sphinx.ext.coverage', 47 | 'sphinx.ext.napoleon', 48 | 'sphinx.ext.todo', 49 | 'sphinx.ext.viewcode', 50 | 'sphinx.ext.autosummary', 51 | ] 52 | 53 | # Add any paths that contain templates here, relative to this directory. 54 | templates_path = ['_templates'] 55 | 56 | # The suffix(es) of source filenames. 57 | # You can specify multiple suffix as a list of string: 58 | # 59 | # source_suffix = ['.rst', '.md'] 60 | source_suffix = '.rst' 61 | 62 | # The master toctree document. 63 | master_doc = 'index' 64 | 65 | # The language for content autogenerated by Sphinx. Refer to documentation 66 | # for a list of supported languages. 67 | # 68 | # This is also used if you do content translation via gettext catalogs. 69 | # Usually you set "language" from the command line for these cases. 70 | language = None 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. 74 | # This pattern also affects html_static_path and html_extra_path. 75 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 76 | 77 | # The name of the Pygments (syntax highlighting) style to use. 78 | pygments_style = 'tango' 79 | 80 | autodoc_member_order = 'bysource' 81 | autodoc_mock_imports = ['_tgvoip'] 82 | 83 | 84 | # -- Options for HTML output ------------------------------------------------- 85 | 86 | # The theme to use for HTML and HTML Help pages. See the documentation for 87 | # a list of builtin themes. 88 | # 89 | html_theme = 'sphinx_rtd_theme' 90 | 91 | # Theme options are theme-specific and customize the look and feel of a theme 92 | # further. For a list of options available for each theme, see the 93 | # documentation. 94 | # 95 | # html_theme_options = {} 96 | 97 | # Add any paths that contain custom static files (such as style sheets) here, 98 | # relative to this directory. They are copied after the builtin static files, 99 | # so a file named "default.css" will overwrite the builtin "default.css". 100 | html_static_path = ['_static'] 101 | 102 | # Custom sidebar templates, must be a dictionary that maps document names 103 | # to template names. 104 | # 105 | # The default sidebars (for documents that don't match any pattern) are 106 | # defined by theme itself. Builtin themes are using these templates by 107 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 108 | # 'searchbox.html']``. 109 | # 110 | # html_sidebars = {} 111 | 112 | html_style = 'css/my_theme.css' 113 | 114 | 115 | # -- Options for HTMLHelp output --------------------------------------------- 116 | 117 | # Output file base name for HTML help builder. 118 | htmlhelp_basename = 'pytgvoipdoc' 119 | 120 | 121 | # -- Options for LaTeX output ------------------------------------------------ 122 | 123 | latex_elements = { 124 | # The paper size ('letterpaper' or 'a4paper'). 125 | # 126 | # 'papersize': 'letterpaper', 127 | 128 | # The font size ('10pt', '11pt' or '12pt'). 129 | # 130 | # 'pointsize': '10pt', 131 | 132 | # Additional stuff for the LaTeX preamble. 133 | # 134 | # 'preamble': '', 135 | 136 | # Latex figure (float) alignment 137 | # 138 | # 'figure_align': 'htbp', 139 | } 140 | 141 | # Grouping the document tree into LaTeX files. List of tuples 142 | # (source start file, target name, title, 143 | # author, documentclass [howto, manual, or own class]). 144 | latex_documents = [ 145 | (master_doc, 'pytgvoip.tex', 'pytgvoip Documentation', 146 | 'bakatrouble', 'manual'), 147 | ] 148 | 149 | 150 | # -- Options for manual page output ------------------------------------------ 151 | 152 | # One entry per manual page. List of tuples 153 | # (source start file, name, description, authors, manual section). 154 | man_pages = [ 155 | (master_doc, 'pytgvoip', 'pytgvoip Documentation', 156 | [author], 1) 157 | ] 158 | 159 | 160 | # -- Options for Texinfo output ---------------------------------------------- 161 | 162 | # Grouping the document tree into Texinfo files. List of tuples 163 | # (source start file, target name, title, author, 164 | # dir menu entry, description, category) 165 | texinfo_documents = [ 166 | (master_doc, 'pytgvoip', 'pytgvoip Documentation', 167 | author, 'pytgvoip', 'One line description of project.', 168 | 'Miscellaneous'), 169 | ] 170 | 171 | 172 | # -- Options for Epub output ------------------------------------------------- 173 | 174 | # Bibliographic Dublin Core info. 175 | epub_title = project 176 | 177 | # The unique identifier of the text. This can be a ISBN number 178 | # or the project homepage. 179 | # 180 | # epub_identifier = '' 181 | 182 | # A unique identification for the text. 183 | # 184 | # epub_uid = '' 185 | 186 | # A list of files that should not be packed into the epub file. 187 | epub_exclude_files = ['search.html'] 188 | 189 | 190 | # -- Extension configuration ------------------------------------------------- 191 | 192 | # -- Options for todo extension ---------------------------------------------- 193 | 194 | # If true, `todo` and `todoList` produce output, else they produce nothing. 195 | todo_include_todos = True 196 | -------------------------------------------------------------------------------- /src/_tgvoip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PytgVoIP - Telegram VoIP Library for Python 3 | * Copyright (C) 2020 bakatrouble 4 | * 5 | * This file is part of PytgVoIP. 6 | * 7 | * PytgVoIP is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * PytgVoIP is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with PytgVoIP. If not, see . 19 | */ 20 | 21 | 22 | #ifndef PYLIBTGVOIP_LIBRARY_H 23 | #define PYLIBTGVOIP_LIBRARY_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace pybind11 { 33 | class not_implemented_error : public std::exception {}; 34 | }; 35 | 36 | namespace py = pybind11; 37 | 38 | enum NetType { 39 | NET_TYPE_UNKNOWN = tgvoip::NET_TYPE_UNKNOWN, 40 | NET_TYPE_GPRS = tgvoip::NET_TYPE_GPRS, 41 | NET_TYPE_EDGE = tgvoip::NET_TYPE_EDGE, 42 | NET_TYPE_3G = tgvoip::NET_TYPE_3G, 43 | NET_TYPE_HSPA = tgvoip::NET_TYPE_HSPA, 44 | NET_TYPE_LTE = tgvoip::NET_TYPE_LTE, 45 | NET_TYPE_WIFI = tgvoip::NET_TYPE_WIFI, 46 | NET_TYPE_ETHERNET = tgvoip::NET_TYPE_ETHERNET, 47 | NET_TYPE_OTHER_HIGH_SPEED = tgvoip::NET_TYPE_OTHER_HIGH_SPEED, 48 | NET_TYPE_OTHER_LOW_SPEED = tgvoip::NET_TYPE_OTHER_LOW_SPEED, 49 | NET_TYPE_DIALUP = tgvoip::NET_TYPE_DIALUP, 50 | NET_TYPE_OTHER_MOBILE = tgvoip::NET_TYPE_OTHER_MOBILE, 51 | }; 52 | 53 | enum CallState { 54 | STATE_WAIT_INIT = tgvoip::STATE_WAIT_INIT, 55 | STATE_WAIT_INIT_ACK = tgvoip::STATE_WAIT_INIT_ACK, 56 | STATE_ESTABLISHED = tgvoip::STATE_ESTABLISHED, 57 | STATE_FAILED = tgvoip::STATE_FAILED, 58 | STATE_RECONNECTING = tgvoip::STATE_RECONNECTING, 59 | }; 60 | 61 | enum DataSaving { 62 | DATA_SAVING_NEVER = tgvoip::DATA_SAVING_NEVER, 63 | DATA_SAVING_MOBILE = tgvoip::DATA_SAVING_MOBILE, 64 | DATA_SAVING_ALWAYS = tgvoip::DATA_SAVING_ALWAYS, 65 | }; 66 | 67 | enum CallError { 68 | ERROR_UNKNOWN = tgvoip::ERROR_UNKNOWN, 69 | ERROR_INCOMPATIBLE = tgvoip::ERROR_INCOMPATIBLE, 70 | ERROR_TIMEOUT = tgvoip::ERROR_TIMEOUT, 71 | ERROR_AUDIO_IO = tgvoip::ERROR_AUDIO_IO, 72 | ERROR_PROXY = tgvoip::ERROR_PROXY, 73 | }; 74 | 75 | struct Stats { 76 | uint64_t bytes_sent_wifi; 77 | uint64_t bytes_sent_mobile; 78 | uint64_t bytes_recvd_wifi; 79 | uint64_t bytes_recvd_mobile; 80 | }; 81 | 82 | struct Endpoint { 83 | Endpoint(int64_t id, std::string ip, std::string ipv6, uint16_t port, const std::string &peer_tag); 84 | int64_t id; 85 | std::string ip; 86 | std::string ipv6; 87 | uint16_t port; 88 | py::bytes peer_tag; 89 | }; 90 | 91 | class VoIPController { 92 | public: 93 | VoIPController(); 94 | explicit VoIPController(const std::string &_persistent_state_file); 95 | virtual ~VoIPController(); 96 | void init(); 97 | void start(); 98 | void connect(); 99 | void set_proxy(const std::string &address, uint16_t port, const std::string &username, const std::string &password); 100 | void set_encryption_key(char *key, bool is_outgoing); 101 | void set_remote_endpoints(std::list endpoints, bool allow_p2p, bool tcp, int connection_max_layer); 102 | std::string get_debug_string(); 103 | void set_network_type(NetType type); 104 | void set_mic_mute(bool mute); 105 | void set_config(double recv_timeout, double init_timeout, DataSaving data_saving_mode, bool enable_aec, 106 | bool enable_ns, bool enable_agc, 107 | #ifndef _WIN32 108 | const std::string &log_file_path, const std::string &status_dump_path, 109 | #else 110 | const std::wstring &log_file_path, const std::wstring &status_dump_path, 111 | #endif 112 | bool log_packet_stats); 113 | void debug_ctl(int request, int param); 114 | long get_preferred_relay_id(); 115 | CallError get_last_error(); 116 | Stats get_stats(); 117 | std::string get_debug_log(); 118 | void set_audio_output_gain_control_enabled(bool enabled); 119 | void set_echo_cancellation_strength(int strength); 120 | int get_peer_capabilities(); 121 | bool need_rate(); 122 | 123 | /* static std::vector enumerate_audio_inputs(); 124 | static std::vector enumerate_audio_outputs(); 125 | void set_current_audio_input(std::string &id); 126 | void set_current_audio_output(std::string &id); 127 | std::string get_current_audio_input_id(); 128 | std::string get_current_audio_output_id(); */ 129 | 130 | // callbacks 131 | virtual void _handle_state_change(CallState state); 132 | virtual void _handle_signal_bars_change(int count); 133 | void send_audio_frame(int16_t *buf, size_t size); 134 | void recv_audio_frame(int16_t *buf, size_t size); 135 | virtual char *_send_audio_frame_impl(unsigned long len); 136 | virtual void _recv_audio_frame_impl(const py::bytes &frame); 137 | 138 | static std::string get_version(const py::object& /* cls */); 139 | static int connection_max_layer(const py::object& /* cls */); 140 | 141 | bool _native_io_get(); 142 | void _native_io_set(bool status); 143 | bool play(std::string &path); 144 | void play_on_hold(std::vector &path); 145 | bool set_output_file(std::string &path); 146 | void clear_play_queue(); 147 | void clear_hold_queue(); 148 | void unset_output_file(); 149 | void _send_audio_frame_native_impl(int16_t *buf, size_t size); 150 | void _recv_audio_frame_native_impl(int16_t *buf, size_t size); 151 | 152 | std::string persistent_state_file; 153 | 154 | private: 155 | tgvoip::VoIPController *ctrl{}; 156 | tgvoip::Mutex output_mutex; 157 | tgvoip::Mutex input_mutex; 158 | 159 | bool native_io = false; 160 | std::queue input_files; 161 | std::queue hold_files; 162 | FILE *output_file = nullptr; 163 | }; 164 | 165 | class PyVoIPController : public VoIPController { 166 | using VoIPController::VoIPController; 167 | 168 | void _handle_state_change(CallState state) override { 169 | PYBIND11_OVERLOAD(void, VoIPController, _handle_state_change, state); 170 | }; 171 | void _handle_signal_bars_change(int count) override { 172 | PYBIND11_OVERLOAD(void, VoIPController, _handle_signal_bars_change, count); 173 | }; 174 | char *_send_audio_frame_impl(unsigned long len) override { 175 | PYBIND11_OVERLOAD(char *, VoIPController, _send_audio_frame_impl, len); 176 | }; 177 | void _recv_audio_frame_impl(const py::bytes &frame) override { 178 | PYBIND11_OVERLOAD(void, VoIPController, _recv_audio_frame_impl, frame); 179 | }; 180 | }; 181 | 182 | class VoIPServerConfig { 183 | public: 184 | static void set_config(std::string &json_str); 185 | }; 186 | 187 | #endif -------------------------------------------------------------------------------- /ci_scripts/install.ps1: -------------------------------------------------------------------------------- 1 | # Sample script to install Python and pip under Windows 2 | # Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer 3 | # License: CC0 1.0 Universal: https://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | $MINICONDA_URL = "https://repo.continuum.io/miniconda/" 6 | $BASE_URL = "https://www.python.org/ftp/python/" 7 | $GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" 8 | $GET_PIP_PATH = "C:\get-pip.py" 9 | 10 | $PYTHON_PRERELEASE_REGEX = @" 11 | (?x) 12 | (?\d+) 13 | \. 14 | (?\d+) 15 | \. 16 | (?\d+) 17 | (?[a-z]{1,2}\d+) 18 | "@ 19 | 20 | 21 | function Download ($filename, $url) { 22 | $webclient = New-Object System.Net.WebClient 23 | 24 | $basedir = $pwd.Path + "\" 25 | $filepath = $basedir + $filename 26 | if (Test-Path $filename) { 27 | Write-Host "Reusing" $filepath 28 | return $filepath 29 | } 30 | 31 | # Download and retry up to 3 times in case of network transient errors. 32 | Write-Host "Downloading" $filename "from" $url 33 | $retry_attempts = 2 34 | for ($i = 0; $i -lt $retry_attempts; $i++) { 35 | try { 36 | $webclient.DownloadFile($url, $filepath) 37 | break 38 | } 39 | Catch [Exception]{ 40 | Start-Sleep 1 41 | } 42 | } 43 | if (Test-Path $filepath) { 44 | Write-Host "File saved at" $filepath 45 | } else { 46 | # Retry once to get the error message if any at the last try 47 | $webclient.DownloadFile($url, $filepath) 48 | } 49 | return $filepath 50 | } 51 | 52 | 53 | function ParsePythonVersion ($python_version) { 54 | if ($python_version -match $PYTHON_PRERELEASE_REGEX) { 55 | return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro, 56 | $matches.prerelease) 57 | } 58 | $version_obj = [version]$python_version 59 | return ($version_obj.major, $version_obj.minor, $version_obj.build, "") 60 | } 61 | 62 | 63 | function DownloadPython ($python_version, $platform_suffix) { 64 | $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version 65 | 66 | if (($major -le 2 -and $micro -eq 0) ` 67 | -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) ` 68 | ) { 69 | $dir = "$major.$minor" 70 | $python_version = "$major.$minor$prerelease" 71 | } else { 72 | $dir = "$major.$minor.$micro" 73 | } 74 | 75 | if ($prerelease) { 76 | if (($major -le 2) ` 77 | -or ($major -eq 3 -and $minor -eq 1) ` 78 | -or ($major -eq 3 -and $minor -eq 2) ` 79 | -or ($major -eq 3 -and $minor -eq 3) ` 80 | ) { 81 | $dir = "$dir/prev" 82 | } 83 | } 84 | 85 | if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) { 86 | $ext = "msi" 87 | if ($platform_suffix) { 88 | $platform_suffix = ".$platform_suffix" 89 | } 90 | } else { 91 | $ext = "exe" 92 | if ($platform_suffix) { 93 | $platform_suffix = "-$platform_suffix" 94 | } 95 | } 96 | 97 | $filename = "python-$python_version$platform_suffix.$ext" 98 | $url = "$BASE_URL$dir/$filename" 99 | $filepath = Download $filename $url 100 | return $filepath 101 | } 102 | 103 | 104 | function InstallPython ($python_version, $architecture, $python_home) { 105 | Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home 106 | if (Test-Path $python_home) { 107 | Write-Host $python_home "already exists, skipping." 108 | return $false 109 | } 110 | if ($architecture -eq "32") { 111 | $platform_suffix = "" 112 | } else { 113 | $platform_suffix = "amd64" 114 | } 115 | $installer_path = DownloadPython $python_version $platform_suffix 116 | $installer_ext = [System.IO.Path]::GetExtension($installer_path) 117 | Write-Host "Installing $installer_path to $python_home" 118 | $install_log = $python_home + ".log" 119 | if ($installer_ext -eq '.msi') { 120 | InstallPythonMSI $installer_path $python_home $install_log 121 | } else { 122 | InstallPythonEXE $installer_path $python_home $install_log 123 | } 124 | if (Test-Path $python_home) { 125 | Write-Host "Python $python_version ($architecture) installation complete" 126 | } else { 127 | Write-Host "Failed to install Python in $python_home" 128 | Get-Content -Path $install_log 129 | Exit 1 130 | } 131 | } 132 | 133 | 134 | function InstallPythonEXE ($exepath, $python_home, $install_log) { 135 | $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home" 136 | RunCommand $exepath $install_args 137 | } 138 | 139 | 140 | function InstallPythonMSI ($msipath, $python_home, $install_log) { 141 | $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home" 142 | $uninstall_args = "/qn /x $msipath" 143 | RunCommand "msiexec.exe" $install_args 144 | if (-not(Test-Path $python_home)) { 145 | Write-Host "Python seems to be installed else-where, reinstalling." 146 | RunCommand "msiexec.exe" $uninstall_args 147 | RunCommand "msiexec.exe" $install_args 148 | } 149 | } 150 | 151 | function RunCommand ($command, $command_args) { 152 | Write-Host $command $command_args 153 | Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru 154 | } 155 | 156 | 157 | function InstallPip ($python_home) { 158 | $pip_path = $python_home + "\Scripts\pip.exe" 159 | $python_path = $python_home + "\python.exe" 160 | if (-not(Test-Path $pip_path)) { 161 | Write-Host "Installing pip..." 162 | $webclient = New-Object System.Net.WebClient 163 | $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) 164 | Write-Host "Executing:" $python_path $GET_PIP_PATH 165 | & $python_path $GET_PIP_PATH 166 | } else { 167 | Write-Host "pip already installed." 168 | } 169 | } 170 | 171 | 172 | function DownloadMiniconda ($python_version, $platform_suffix) { 173 | if ($python_version -eq "3.4") { 174 | $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe" 175 | } else { 176 | $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe" 177 | } 178 | $url = $MINICONDA_URL + $filename 179 | $filepath = Download $filename $url 180 | return $filepath 181 | } 182 | 183 | 184 | function InstallMiniconda ($python_version, $architecture, $python_home) { 185 | Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home 186 | if (Test-Path $python_home) { 187 | Write-Host $python_home "already exists, skipping." 188 | return $false 189 | } 190 | if ($architecture -eq "32") { 191 | $platform_suffix = "x86" 192 | } else { 193 | $platform_suffix = "x86_64" 194 | } 195 | $filepath = DownloadMiniconda $python_version $platform_suffix 196 | Write-Host "Installing" $filepath "to" $python_home 197 | $install_log = $python_home + ".log" 198 | $args = "/S /D=$python_home" 199 | Write-Host $filepath $args 200 | Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru 201 | if (Test-Path $python_home) { 202 | Write-Host "Python $python_version ($architecture) installation complete" 203 | } else { 204 | Write-Host "Failed to install Python in $python_home" 205 | Get-Content -Path $install_log 206 | Exit 1 207 | } 208 | } 209 | 210 | 211 | function InstallMinicondaPip ($python_home) { 212 | $pip_path = $python_home + "\Scripts\pip.exe" 213 | $conda_path = $python_home + "\Scripts\conda.exe" 214 | if (-not(Test-Path $pip_path)) { 215 | Write-Host "Installing pip..." 216 | $args = "install --yes pip" 217 | Write-Host $conda_path $args 218 | Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru 219 | } else { 220 | Write-Host "pip already installed." 221 | } 222 | } 223 | 224 | function main () { 225 | InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON 226 | InstallPip $env:PYTHON 227 | } 228 | 229 | main 230 | -------------------------------------------------------------------------------- /COPYING.lesser: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /src/_tgvoip_module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PytgVoIP - Telegram VoIP Library for Python 3 | * Copyright (C) 2020 bakatrouble 4 | * 5 | * This file is part of PytgVoIP. 6 | * 7 | * PytgVoIP is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * PytgVoIP is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with PytgVoIP. If not, see . 19 | */ 20 | 21 | 22 | #include "_tgvoip.h" 23 | #include 24 | #include 25 | 26 | PYBIND11_MODULE(_tgvoip, m) { 27 | // py::options options; 28 | // options.disable_function_signatures(); 29 | 30 | py::register_exception_translator([](std::exception_ptr p) { 31 | try { 32 | if (p) std::rethrow_exception(p); 33 | } catch (const py::not_implemented_error &e) { 34 | PyErr_SetString(PyExc_NotImplementedError, ""); 35 | } 36 | }); 37 | 38 | py::enum_(m, "NetType") 39 | .value("UNKNOWN", NetType::NET_TYPE_UNKNOWN) 40 | .value("GPRS", NetType::NET_TYPE_GPRS) 41 | .value("EDGE", NetType::NET_TYPE_EDGE) 42 | .value("NET_3G", NetType::NET_TYPE_3G) 43 | .value("HSPA", NetType::NET_TYPE_HSPA) 44 | .value("LTE", NetType::NET_TYPE_LTE) 45 | .value("WIFI", NetType::NET_TYPE_WIFI) 46 | .value("ETHERNET", NetType::NET_TYPE_ETHERNET) 47 | .value("OTHER_HIGH_SPEED", NetType::NET_TYPE_OTHER_HIGH_SPEED) 48 | .value("OTHER_LOW_SPEED", NetType::NET_TYPE_OTHER_LOW_SPEED) 49 | .value("DIALUP", NetType::NET_TYPE_DIALUP) 50 | .value("OTHER_MOBILE", NetType::NET_TYPE_OTHER_MOBILE) 51 | .export_values(); 52 | 53 | py::enum_(m, "CallState") 54 | .value("WAIT_INIT", CallState::STATE_WAIT_INIT) 55 | .value("WAIT_INIT_ACK", CallState::STATE_WAIT_INIT_ACK) 56 | .value("ESTABLISHED", CallState::STATE_ESTABLISHED) 57 | .value("FAILED", CallState::STATE_FAILED) 58 | .value("RECONNECTING", CallState::STATE_RECONNECTING) 59 | .export_values(); 60 | 61 | py::enum_(m, "DataSaving") 62 | .value("NEVER", DataSaving::DATA_SAVING_NEVER) 63 | .value("MOBILE", DataSaving::DATA_SAVING_MOBILE) 64 | .value("ALWAYS", DataSaving::DATA_SAVING_ALWAYS) 65 | .export_values(); 66 | 67 | py::enum_(m, "CallError") 68 | .value("UNKNOWN", CallError::ERROR_UNKNOWN) 69 | .value("INCOMPATIBLE", CallError::ERROR_INCOMPATIBLE) 70 | .value("TIMEOUT", CallError::ERROR_TIMEOUT) 71 | .value("AUDIO_IO", CallError::ERROR_AUDIO_IO) 72 | .value("PROXY", CallError::ERROR_PROXY) 73 | .export_values(); 74 | 75 | py::class_(m, "Stats") 76 | .def_readonly("bytes_sent_wifi", &Stats::bytes_sent_wifi) 77 | .def_readonly("bytes_sent_mobile", &Stats::bytes_sent_mobile) 78 | .def_readonly("bytes_recvd_wifi", &Stats::bytes_recvd_wifi) 79 | .def_readonly("bytes_recvd_mobile", &Stats::bytes_recvd_mobile) 80 | .def("__repr__", [](const Stats &s) { 81 | std::ostringstream repr; 82 | repr << "<_tgvoip.Stats "; 83 | repr << "bytes_sent_wifi=" << s.bytes_sent_wifi << " "; 84 | repr << "bytes_sent_mobile=" << s.bytes_sent_mobile << " "; 85 | repr << "bytes_recvd_wifi=" << s.bytes_recvd_wifi << " "; 86 | repr << "bytes_recvd_mobile=" << s.bytes_recvd_mobile << ">"; 87 | return repr.str(); 88 | }); 89 | 90 | py::class_(m, "Endpoint") 91 | .def(py::init()) 92 | .def_readwrite("_id", &Endpoint::id) 93 | .def_readwrite("ip", &Endpoint::ip) 94 | .def_readwrite("ipv6", &Endpoint::ipv6) 95 | .def_readwrite("port", &Endpoint::port) 96 | .def_readwrite("peer_tag", &Endpoint::peer_tag) 97 | .def("__repr__", [](const Endpoint &e) { 98 | std::ostringstream repr; 99 | repr << "<_tgvoip.Endpoint "; 100 | repr << "_id=" << e.id << " "; 101 | repr << "ip=\"" << e.ip << "\" "; 102 | repr << "ipv6=\"" << e.ipv6 << "\" "; 103 | repr << "port=" << e.port << ">"; 104 | // repr << "peer_tag=" << e.peer_tag << ">"; 105 | return repr.str(); 106 | }); 107 | 108 | /* py::class_(m, "AudioInputDevice") 109 | .def_readonly("_id", &tgvoip::AudioInputDevice::id) 110 | .def_readonly("display_name", &tgvoip::AudioInputDevice::displayName) 111 | .def("__repr__", [](const tgvoip::AudioInputDevice &d) { 112 | std::ostringstream repr; 113 | repr << "<_tgvoip.AudioInputDevice "; 114 | repr << "_id=\"" << d.id << "\" "; 115 | repr << "display_name=\"" << d.displayName << "\">"; 116 | return repr.str(); 117 | }); 118 | 119 | py::class_(m, "AudioOutputDevice") 120 | .def_readonly("_id", &tgvoip::AudioOutputDevice::id) 121 | .def_readonly("display_name", &tgvoip::AudioOutputDevice::displayName) 122 | .def("__repr__", [](const tgvoip::AudioOutputDevice &d) { 123 | std::ostringstream repr; 124 | repr << "<_tgvoip.AudioOutputDevice "; 125 | repr << "_id=\"" << d.id << "\" "; 126 | repr << "display_name=\"" << d.displayName << "\">"; 127 | return repr.str(); 128 | }); */ 129 | 130 | py::class_(m, "VoIPController") 131 | .def(py::init<>()) 132 | .def(py::init()) 133 | .def("_init", &VoIPController::init) 134 | .def("start", &VoIPController::start, "Start VoIP controller") 135 | .def("connect", &VoIPController::connect, "Start call") 136 | .def("set_proxy", &VoIPController::set_proxy) 137 | .def("set_encryption_key", &VoIPController::set_encryption_key) 138 | .def("set_remote_endpoints", &VoIPController::set_remote_endpoints) 139 | .def("get_debug_string", &VoIPController::get_debug_string, "Get debug string") 140 | .def("set_network_type", &VoIPController::set_network_type, "Set network type") 141 | .def("set_mic_mute", &VoIPController::set_mic_mute) 142 | .def("set_config", &VoIPController::set_config) 143 | .def("debug_ctl", &VoIPController::debug_ctl) 144 | .def("get_preferred_relay_id", &VoIPController::get_preferred_relay_id) 145 | .def("get_last_error", &VoIPController::get_last_error) 146 | .def("get_stats", &VoIPController::get_stats) 147 | .def("get_debug_log", &VoIPController::get_debug_log) 148 | .def("set_audio_output_gain_control_enabled", &VoIPController::set_audio_output_gain_control_enabled) 149 | .def("set_echo_cancellation_strength", &VoIPController::set_echo_cancellation_strength) 150 | .def("get_peer_capabilities", &VoIPController::get_peer_capabilities) 151 | .def("need_rate", &VoIPController::need_rate) 152 | 153 | /* .def("enumerate_audio_inputs", &VoIPController::enumerate_audio_inputs) 154 | .def("enumerate_audio_outputs", &VoIPController::enumerate_audio_outputs) 155 | .def("set_current_audio_input", &VoIPController::set_current_audio_input) 156 | .def("set_current_audio_output", &VoIPController::set_current_audio_output) 157 | .def("get_current_audio_input_id", &VoIPController::get_current_audio_input_id) 158 | .def("get_current_audio_output_id", &VoIPController::get_current_audio_output_id) */ 159 | 160 | /* .def("_handle_state_change", &VoIPController::_handle_state_change) 161 | .def("_handle_signal_bars_change", &VoIPController::_handle_signal_bars_change) 162 | .def("_send_audio_frame_impl", &VoIPController::_send_audio_frame_impl) 163 | .def("_recv_audio_frame_impl", &VoIPController::_recv_audio_frame_impl) */ 164 | 165 | .def("_native_io_get", &VoIPController::_native_io_get) 166 | .def("_native_io_set", &VoIPController::_native_io_set) 167 | .def("play", &VoIPController::play) 168 | .def("play_on_hold", &VoIPController::play_on_hold) 169 | .def("set_output_file", &VoIPController::set_output_file) 170 | .def("clear_play_queue", &VoIPController::clear_play_queue) 171 | .def("clear_hold_queue", &VoIPController::clear_hold_queue) 172 | .def("unset_output_file", &VoIPController::unset_output_file) 173 | 174 | .def_readonly("persistent_state_file", &VoIPController::persistent_state_file) 175 | .def_property_readonly_static("LIBTGVOIP_VERSION", &VoIPController::get_version) 176 | .def_property_readonly_static("CONNECTION_MAX_LAYER", &VoIPController::connection_max_layer); 177 | 178 | py::class_(m, "VoIPServerConfig") 179 | .def_static("set_config", &VoIPServerConfig::set_config); 180 | 181 | #ifdef VERSION_INFO 182 | m.attr("__version__") = VERSION_INFO; 183 | #else 184 | m.attr("__version__") = "dev"; 185 | #endif 186 | } 187 | -------------------------------------------------------------------------------- /src/_tgvoip.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PytgVoIP - Telegram VoIP Library for Python 3 | * Copyright (C) 2020 bakatrouble 4 | * 5 | * This file is part of PytgVoIP. 6 | * 7 | * PytgVoIP is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * PytgVoIP is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with PytgVoIP. If not, see . 19 | */ 20 | 21 | 22 | #include "_tgvoip.h" 23 | #include 24 | #include 25 | // #include 26 | 27 | Endpoint::Endpoint(int64_t id, std::string ip, std::string ipv6, uint16_t port, const std::string &peer_tag) 28 | : id(id), ip(std::move(ip)), ipv6(std::move(ipv6)), port(port), peer_tag(peer_tag) {} 29 | 30 | VoIPController::VoIPController() { 31 | ctrl = nullptr; 32 | output_file = nullptr; 33 | native_io = false; 34 | } 35 | 36 | VoIPController::VoIPController(const std::string &_persistent_state_file) : VoIPController() { 37 | if (!_persistent_state_file.empty()) 38 | persistent_state_file = _persistent_state_file; 39 | } 40 | 41 | void VoIPController::init() { 42 | ctrl = new tgvoip::VoIPController(); 43 | ctrl->implData = (void *)this; 44 | tgvoip::VoIPController::Callbacks callbacks {}; 45 | callbacks.connectionStateChanged = [](tgvoip::VoIPController *ctrl, int state) { 46 | ((VoIPController *)ctrl->implData)->_handle_state_change(CallState(state)); 47 | }; 48 | callbacks.signalBarCountChanged = [](tgvoip::VoIPController *ctrl, int count) { 49 | ((VoIPController *)ctrl->implData)->_handle_signal_bars_change(count); 50 | }; 51 | callbacks.groupCallKeyReceived = nullptr; 52 | callbacks.groupCallKeySent = nullptr; 53 | callbacks.upgradeToGroupCallRequested = nullptr; 54 | ctrl->SetCallbacks(callbacks); 55 | ctrl->SetAudioDataCallbacks( 56 | [this](int16_t *buf, size_t size) { 57 | this->send_audio_frame(buf, size); 58 | }, 59 | [this](int16_t *buf, size_t size) { 60 | this->recv_audio_frame(buf, size); 61 | }, 62 | [](int16_t *buf, size_t size) {} 63 | ); 64 | 65 | if (!persistent_state_file.empty()) { 66 | FILE *f = fopen(persistent_state_file.c_str(), "r"); 67 | if (f) { 68 | fseek(f, 0, SEEK_END); 69 | auto len = static_cast(ftell(f)); 70 | fseek(f, 0, SEEK_SET); 71 | if(len<1024*512 && len>0){ 72 | auto fbuf = static_cast(malloc(len)); 73 | fread(fbuf, 1, len, f); 74 | std::vector state(fbuf, fbuf+len); 75 | free(fbuf); 76 | ctrl->SetPersistentState(state); 77 | } 78 | fclose(f); 79 | } 80 | } 81 | } 82 | 83 | VoIPController::~VoIPController() { 84 | ctrl->Stop(); 85 | std::vector state = ctrl->GetPersistentState(); 86 | delete ctrl; 87 | clear_play_queue(); 88 | clear_hold_queue(); 89 | unset_output_file(); 90 | if (!persistent_state_file.empty()) { 91 | FILE *f = fopen(persistent_state_file.c_str(), "w"); 92 | if (f) { 93 | fwrite(state.data(), 1, state.size(), f); 94 | fclose(f); 95 | } 96 | } 97 | } 98 | 99 | void VoIPController::start() { 100 | ctrl->Start(); 101 | } 102 | 103 | void VoIPController::connect() { 104 | ctrl->Connect(); 105 | } 106 | 107 | void VoIPController::set_proxy(const std::string &address, uint16_t port, const std::string &username, const std::string &password) { 108 | ctrl->SetProxy(tgvoip::PROXY_SOCKS5, address, port, username, password); 109 | } 110 | 111 | void VoIPController::set_encryption_key(char *key, bool is_outgoing) { 112 | ctrl->SetEncryptionKey(key, is_outgoing); 113 | } 114 | 115 | void VoIPController::set_remote_endpoints(std::list endpoints, bool allow_p2p, bool tcp, int connection_max_layer) { 116 | std::vector eps; 117 | for (auto const &ep : endpoints) { 118 | tgvoip::IPv4Address v4addr(ep.ip); 119 | tgvoip::IPv6Address v6addr("::0"); 120 | if (!ep.ipv6.empty()) 121 | v6addr = tgvoip::IPv6Address(ep.ipv6); 122 | std::string peer_tag = ep.peer_tag; 123 | unsigned char p_tag[16]; 124 | if (!peer_tag.empty()) 125 | memcpy(p_tag, peer_tag.c_str(), 16); 126 | eps.emplace_back(tgvoip::Endpoint(ep.id, ep.port, v4addr, v6addr, 127 | tcp ? tgvoip::Endpoint::Type::TCP_RELAY : tgvoip::Endpoint::Type::UDP_RELAY, p_tag)); 128 | } 129 | ctrl->SetRemoteEndpoints(eps, allow_p2p, connection_max_layer); 130 | } 131 | 132 | std::string VoIPController::get_debug_string() { 133 | return ctrl->GetDebugString(); 134 | } 135 | 136 | void VoIPController::set_network_type(NetType type) { 137 | ctrl->SetNetworkType(type); 138 | } 139 | 140 | void VoIPController::set_mic_mute(bool mute) { 141 | ctrl->SetMicMute(mute); 142 | } 143 | 144 | void VoIPController::set_config(double init_timeout, double recv_timeout, DataSaving data_saving_mode, bool enable_aec, 145 | bool enable_ns, bool enable_agc, 146 | #ifndef _WIN32 147 | const std::string &log_file_path, const std::string &status_dump_path, 148 | #else 149 | const std::wstring &log_file_path, const std::wstring &status_dump_path, 150 | #endif 151 | bool log_packet_stats) { 152 | tgvoip::VoIPController::Config cfg; 153 | cfg.initTimeout = init_timeout; 154 | cfg.recvTimeout = recv_timeout; 155 | cfg.dataSaving = data_saving_mode; 156 | cfg.enableAEC = enable_aec; 157 | cfg.enableNS = enable_ns; 158 | cfg.enableAGC = enable_agc; 159 | cfg.enableCallUpgrade = false; 160 | if (!log_file_path.empty()) 161 | cfg.logFilePath = log_file_path; 162 | if (!status_dump_path.empty()) 163 | cfg.statsDumpFilePath = status_dump_path; 164 | cfg.logPacketStats = log_packet_stats; 165 | ctrl->SetConfig(cfg); 166 | } 167 | 168 | void VoIPController::debug_ctl(int request, int param) { 169 | ctrl->DebugCtl(request, param); 170 | } 171 | 172 | long VoIPController::get_preferred_relay_id() { 173 | return ctrl->GetPreferredRelayID(); 174 | } 175 | 176 | CallError VoIPController::get_last_error() { 177 | return CallError(ctrl->GetLastError()); 178 | } 179 | 180 | Stats VoIPController::get_stats() { 181 | tgvoip::VoIPController::TrafficStats _stats {}; 182 | ctrl->GetStats(&_stats); 183 | return Stats { 184 | _stats.bytesSentWifi, 185 | _stats.bytesSentMobile, 186 | _stats.bytesRecvdWifi, 187 | _stats.bytesRecvdMobile, 188 | }; 189 | } 190 | 191 | std::string VoIPController::get_debug_log() { 192 | return ctrl->GetDebugLog(); 193 | } 194 | 195 | void VoIPController::set_audio_output_gain_control_enabled(bool enabled) { 196 | ctrl->SetAudioOutputGainControlEnabled(enabled); 197 | } 198 | 199 | void VoIPController::set_echo_cancellation_strength(int strength) { 200 | ctrl->SetEchoCancellationStrength(strength); 201 | } 202 | 203 | int VoIPController::get_peer_capabilities() { 204 | return ctrl->GetPeerCapabilities(); 205 | } 206 | 207 | bool VoIPController::need_rate() { 208 | return ctrl->NeedRate(); 209 | } 210 | 211 | /* std::vector VoIPController::enumerate_audio_inputs() { 212 | return tgvoip::VoIPController::EnumerateAudioInputs(); 213 | } 214 | 215 | std::vector VoIPController::enumerate_audio_outputs() { 216 | return tgvoip::VoIPController::EnumerateAudioOutputs(); 217 | } 218 | 219 | void VoIPController::set_current_audio_input(std::string &id) { 220 | ctrl->SetCurrentAudioInput(id); 221 | } 222 | 223 | void VoIPController::set_current_audio_output(std::string &id) { 224 | ctrl->SetCurrentAudioOutput(id); 225 | } 226 | 227 | std::string VoIPController::get_current_audio_input_id() { 228 | return ctrl->GetCurrentAudioInputID(); 229 | } 230 | 231 | std::string VoIPController::get_current_audio_output_id() { 232 | return ctrl->GetCurrentAudioOutputID(); 233 | } */ 234 | 235 | void VoIPController::_handle_state_change(CallState state) { 236 | throw py::not_implemented_error(); 237 | } 238 | 239 | void VoIPController::_handle_signal_bars_change(int count) { 240 | throw py::not_implemented_error(); 241 | } 242 | 243 | void VoIPController::send_audio_frame(int16_t *buf, size_t size) { 244 | tgvoip::MutexGuard m(input_mutex); 245 | // auto start = std::chrono::high_resolution_clock::now(); 246 | if (native_io) { 247 | this->_send_audio_frame_native_impl(buf, size); 248 | } else { 249 | char *frame = this->_send_audio_frame_impl(sizeof(int16_t) * size); 250 | if (frame != nullptr) { 251 | memcpy(buf, frame, sizeof(int16_t) * size); 252 | } 253 | } 254 | // auto finish = std::chrono::high_resolution_clock::now(); 255 | // std::cout << "send: " << std::chrono::duration_cast(finish - start).count() << std::endl; 256 | } 257 | 258 | char *VoIPController::_send_audio_frame_impl(unsigned long len) { return (char *)""; } 259 | 260 | void VoIPController::_send_audio_frame_native_impl(int16_t *buf, size_t size) { 261 | if (!input_files.empty()) { 262 | size_t read_size = fread(buf, sizeof(int16_t), size, input_files.front()); 263 | if (read_size != size) { 264 | fclose(input_files.front()); 265 | input_files.pop(); 266 | size_t read_offset = read_size % size; 267 | memset(buf + read_offset, 0, size - read_offset); 268 | } 269 | } else if (!hold_files.empty()) { 270 | size_t read_size = fread(buf, sizeof(int16_t), size, hold_files.front()); 271 | if (read_size != size) { 272 | fseek(hold_files.front(), 0, SEEK_SET); 273 | hold_files.push(hold_files.front()); 274 | hold_files.pop(); 275 | size_t read_offset = read_size % size; 276 | memset(buf + read_offset, 0, size - read_offset); 277 | } 278 | } 279 | } 280 | 281 | void VoIPController::recv_audio_frame(int16_t *buf, size_t size) { 282 | tgvoip::MutexGuard m(output_mutex); 283 | // auto start = std::chrono::high_resolution_clock::now(); 284 | if (buf != nullptr) { 285 | if (native_io) { 286 | this->_recv_audio_frame_native_impl(buf, size); 287 | } else { 288 | std::string frame((const char *) buf, sizeof(int16_t) * size); 289 | this->_recv_audio_frame_impl(frame); 290 | } 291 | } 292 | // auto finish = std::chrono::high_resolution_clock::now(); 293 | // std::cout << "recv: " << std::chrono::duration_cast(finish - start).count() << std::endl; 294 | } 295 | 296 | void VoIPController::_recv_audio_frame_impl(const py::bytes &frame) {} 297 | 298 | void VoIPController::_recv_audio_frame_native_impl(int16_t *buf, size_t size) { 299 | if (output_file != nullptr) { 300 | size_t written_size = fwrite(buf, sizeof(int16_t), size, output_file); 301 | if (written_size != size) { 302 | std::cerr << "Written size (" << written_size << ") does not match expected (" << size << ")" << std::endl; 303 | } 304 | } 305 | } 306 | 307 | std::string VoIPController::get_version(const py::object& /* cls */) { 308 | return tgvoip::VoIPController::GetVersion(); 309 | } 310 | 311 | int VoIPController::connection_max_layer(const py::object& /* cls */) { 312 | return tgvoip::VoIPController::GetConnectionMaxLayer(); 313 | } 314 | 315 | bool VoIPController::_native_io_get() { 316 | return native_io; 317 | } 318 | 319 | void VoIPController::_native_io_set(bool status) { 320 | native_io = status; 321 | } 322 | 323 | bool VoIPController::play(std::string &path) { 324 | FILE *tmp = fopen(path.c_str(), "rb"); 325 | if (tmp == nullptr) { 326 | std::cerr << "Unable to open file " << path << " for reading" << std::endl; 327 | return false; 328 | } 329 | tgvoip::MutexGuard m(input_mutex); 330 | input_files.push(tmp); 331 | return true; 332 | } 333 | 334 | void VoIPController::play_on_hold(std::vector &paths) { 335 | clear_hold_queue(); 336 | tgvoip::MutexGuard m(input_mutex); 337 | for (auto &path : paths) { 338 | FILE *tmp = fopen(path.c_str(), "rb"); 339 | if (tmp == nullptr) { 340 | std::cerr << "Unable to open file " << path << " for reading" << std::endl; 341 | } else { 342 | hold_files.push(tmp); 343 | } 344 | } 345 | } 346 | 347 | bool VoIPController::set_output_file(std::string &path) { 348 | FILE *tmp = fopen(path.c_str(), "wb"); 349 | if (tmp == nullptr) { 350 | std::cerr << "Unable to open file " << path << " for writing" << std::endl; 351 | return false; 352 | } 353 | unset_output_file(); 354 | tgvoip::MutexGuard m(output_mutex); 355 | output_file = tmp; 356 | return true; 357 | } 358 | 359 | void VoIPController::clear_play_queue() { 360 | tgvoip::MutexGuard m(input_mutex); 361 | while (!input_files.empty()) { 362 | fclose(input_files.front()); 363 | input_files.pop(); 364 | } 365 | } 366 | 367 | void VoIPController::clear_hold_queue() { 368 | tgvoip::MutexGuard m(input_mutex); 369 | while (!hold_files.empty()) { 370 | fclose(hold_files.front()); 371 | hold_files.pop(); 372 | } 373 | } 374 | 375 | void VoIPController::unset_output_file() { 376 | if (output_file != nullptr) { 377 | tgvoip::MutexGuard m(output_mutex); 378 | fclose(output_file); 379 | output_file = nullptr; 380 | } 381 | } 382 | 383 | void VoIPServerConfig::set_config(std::string &json_str) { 384 | tgvoip::ServerConfig::GetSharedInstance()->Update(json_str); 385 | } 386 | -------------------------------------------------------------------------------- /src/tgvoip/utils.py: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | 20 | import hashlib 21 | import time 22 | from typing import List, Union 23 | 24 | """ 25 | .. module:: utils 26 | :synopsis: Utility functions for pytgvoip 27 | """ 28 | 29 | twoe1984 = 1 << 1984 # 2^1984 https://core.telegram.org/api/end-to-end#sending-a-request 30 | emojis = ( 31 | ('\U0001f609', 'WINKING_FACE'), 32 | ('\U0001f60d', 'SMILING_FACE_WITH_HEART_EYES'), 33 | ('\U0001f61b', 'FACE_WITH_TONGUE'), 34 | ('\U0001f62d', 'LOUDLY_CRYING_FACE'), 35 | ('\U0001f631', 'FACE_SCREAMING_IN_FEAR'), 36 | ('\U0001f621', 'POUTING_FACE'), 37 | ('\U0001f60e', 'SMILING_FACE_WITH_SUNGLASSES'), 38 | ('\U0001f634', 'SLEEPING_FACE'), 39 | ('\U0001f635', 'DIZZY_FACE'), 40 | ('\U0001f608', 'SMILING_FACE_WITH_HORNS'), 41 | ('\U0001f62c', 'GRIMACING_FACE'), 42 | ('\U0001f607', 'SMILING_FACE_WITH_HALO'), 43 | ('\U0001f60f', 'SMIRKING_FACE'), 44 | ('\U0001f46e', 'POLICE_OFFICER'), 45 | ('\U0001f477', 'CONSTRUCTION_WORKER'), 46 | ('\U0001f482', 'GUARD'), 47 | ('\U0001f476', 'BABY'), 48 | ('\U0001f468', 'MAN'), 49 | ('\U0001f469', 'WOMAN'), 50 | ('\U0001f474', 'OLD_MAN'), 51 | ('\U0001f475', 'OLD_WOMAN'), 52 | ('\U0001f63b', 'SMILING_CAT_FACE_WITH_HEART_EYES'), 53 | ('\U0001f63d', 'KISSING_CAT_FACE'), 54 | ('\U0001f640', 'WEARY_CAT_FACE'), 55 | ('\U0001f47a', 'GOBLIN'), 56 | ('\U0001f648', 'SEE_NO_EVIL_MONKEY'), 57 | ('\U0001f649', 'HEAR_NO_EVIL_MONKEY'), 58 | ('\U0001f64a', 'SPEAK_NO_EVIL_MONKEY'), 59 | ('\U0001f480', 'SKULL'), 60 | ('\U0001f47d', 'ALIEN'), 61 | ('\U0001f4a9', 'PILE_OF_POO'), 62 | ('\U0001f525', 'FIRE'), 63 | ('\U0001f4a5', 'COLLISION'), 64 | ('\U0001f4a4', 'ZZZ'), 65 | ('\U0001f442', 'EAR'), 66 | ('\U0001f440', 'EYES'), 67 | ('\U0001f443', 'NOSE'), 68 | ('\U0001f445', 'TONGUE'), 69 | ('\U0001f444', 'MOUTH'), 70 | ('\U0001f44d', 'THUMBS_UP'), 71 | ('\U0001f44e', 'THUMBS_DOWN'), 72 | ('\U0001f44c', 'OK_HAND'), 73 | ('\U0001f44a', 'ONCOMING_FIST'), 74 | ('\u270c', 'VICTORY_HAND'), 75 | ('\u270b', 'RAISED_HAND'), 76 | ('\U0001f450', 'OPEN_HANDS'), 77 | ('\U0001f446', 'BACKHAND_INDEX_POINTING_UP'), 78 | ('\U0001f447', 'BACKHAND_INDEX_POINTING_DOWN'), 79 | ('\U0001f449', 'BACKHAND_INDEX_POINTING_RIGHT'), 80 | ('\U0001f448', 'BACKHAND_INDEX_POINTING_LEFT'), 81 | ('\U0001f64f', 'FOLDED_HANDS'), 82 | ('\U0001f44f', 'CLAPPING_HANDS'), 83 | ('\U0001f4aa', 'FLEXED_BICEPS'), 84 | ('\U0001f6b6', 'PERSON_WALKING'), 85 | ('\U0001f3c3', 'PERSON_RUNNING'), 86 | ('\U0001f483', 'WOMAN_DANCING'), 87 | ('\U0001f46b', 'MAN_AND_WOMAN_HOLDING_HANDS'), 88 | ('\U0001f46a', 'FAMILY'), 89 | ('\U0001f46c', 'TWO_MEN_HOLDING_HANDS'), 90 | ('\U0001f46d', 'TWO_WOMEN_HOLDING_HANDS'), 91 | ('\U0001f485', 'NAIL_POLISH'), 92 | ('\U0001f3a9', 'TOP_HAT'), 93 | ('\U0001f451', 'CROWN'), 94 | ('\U0001f452', 'WOMAN_S_HAT'), 95 | ('\U0001f45f', 'RUNNING_SHOE'), 96 | ('\U0001f45e', 'MAN_S_SHOE'), 97 | ('\U0001f460', 'HIGH_HEELED_SHOE'), 98 | ('\U0001f455', 'T_SHIRT'), 99 | ('\U0001f457', 'DRESS'), 100 | ('\U0001f456', 'JEANS'), 101 | ('\U0001f459', 'BIKINI'), 102 | ('\U0001f45c', 'HANDBAG'), 103 | ('\U0001f453', 'GLASSES'), 104 | ('\U0001f380', 'RIBBON'), 105 | ('\U0001f484', 'LIPSTICK'), 106 | ('\U0001f49b', 'YELLOW_HEART'), 107 | ('\U0001f499', 'BLUE_HEART'), 108 | ('\U0001f49c', 'PURPLE_HEART'), 109 | ('\U0001f49a', 'GREEN_HEART'), 110 | ('\U0001f48d', 'RING'), 111 | ('\U0001f48e', 'GEM_STONE'), 112 | ('\U0001f436', 'DOG_FACE'), 113 | ('\U0001f43a', 'WOLF_FACE'), 114 | ('\U0001f431', 'CAT_FACE'), 115 | ('\U0001f42d', 'MOUSE_FACE'), 116 | ('\U0001f439', 'HAMSTER_FACE'), 117 | ('\U0001f430', 'RABBIT_FACE'), 118 | ('\U0001f438', 'FROG_FACE'), 119 | ('\U0001f42f', 'TIGER_FACE'), 120 | ('\U0001f428', 'KOALA'), 121 | ('\U0001f43b', 'BEAR_FACE'), 122 | ('\U0001f437', 'PIG_FACE'), 123 | ('\U0001f42e', 'COW_FACE'), 124 | ('\U0001f417', 'BOAR'), 125 | ('\U0001f434', 'HORSE_FACE'), 126 | ('\U0001f411', 'EWE'), 127 | ('\U0001f418', 'ELEPHANT'), 128 | ('\U0001f43c', 'PANDA_FACE'), 129 | ('\U0001f427', 'PENGUIN'), 130 | ('\U0001f425', 'FRONT_FACING_BABY_CHICK'), 131 | ('\U0001f414', 'CHICKEN'), 132 | ('\U0001f40d', 'SNAKE'), 133 | ('\U0001f422', 'TURTLE'), 134 | ('\U0001f41b', 'BUG'), 135 | ('\U0001f41d', 'HONEYBEE'), 136 | ('\U0001f41c', 'ANT'), 137 | ('\U0001f41e', 'LADY_BEETLE'), 138 | ('\U0001f40c', 'SNAIL'), 139 | ('\U0001f419', 'OCTOPUS'), 140 | ('\U0001f41a', 'SPIRAL_SHELL'), 141 | ('\U0001f41f', 'FISH'), 142 | ('\U0001f42c', 'DOLPHIN'), 143 | ('\U0001f40b', 'WHALE'), 144 | ('\U0001f410', 'GOAT'), 145 | ('\U0001f40a', 'CROCODILE'), 146 | ('\U0001f42b', 'TWO_HUMP_CAMEL'), 147 | ('\U0001f340', 'FOUR_LEAF_CLOVER'), 148 | ('\U0001f339', 'ROSE'), 149 | ('\U0001f33b', 'SUNFLOWER'), 150 | ('\U0001f341', 'MAPLE_LEAF'), 151 | ('\U0001f33e', 'SHEAF_OF_RICE'), 152 | ('\U0001f344', 'MUSHROOM'), 153 | ('\U0001f335', 'CACTUS'), 154 | ('\U0001f334', 'PALM_TREE'), 155 | ('\U0001f333', 'DECIDUOUS_TREE'), 156 | ('\U0001f31e', 'SUN_WITH_FACE'), 157 | ('\U0001f31a', 'NEW_MOON_FACE'), 158 | ('\U0001f319', 'CRESCENT_MOON'), 159 | ('\U0001f30e', 'GLOBE_SHOWING_AMERICAS'), 160 | ('\U0001f30b', 'VOLCANO'), 161 | ('\u26a1', 'HIGH_VOLTAGE'), 162 | ('\u2614', 'UMBRELLA_WITH_RAIN_DROPS'), 163 | ('\u2744', 'SNOWFLAKE'), 164 | ('\u26c4', 'SNOWMAN_WITHOUT_SNOW'), 165 | ('\U0001f300', 'CYCLONE'), 166 | ('\U0001f308', 'RAINBOW'), 167 | ('\U0001f30a', 'WATER_WAVE'), 168 | ('\U0001f393', 'GRADUATION_CAP'), 169 | ('\U0001f386', 'FIREWORKS'), 170 | ('\U0001f383', 'JACK_O_LANTERN'), 171 | ('\U0001f47b', 'GHOST'), 172 | ('\U0001f385', 'SANTA_CLAUS'), 173 | ('\U0001f384', 'CHRISTMAS_TREE'), 174 | ('\U0001f381', 'WRAPPED_GIFT'), 175 | ('\U0001f388', 'BALLOON'), 176 | ('\U0001f52e', 'CRYSTAL_BALL'), 177 | ('\U0001f3a5', 'MOVIE_CAMERA'), 178 | ('\U0001f4f7', 'CAMERA'), 179 | ('\U0001f4bf', 'OPTICAL_DISK'), 180 | ('\U0001f4bb', 'LAPTOP_COMPUTER'), 181 | ('\u260e', 'TELEPHONE'), 182 | ('\U0001f4e1', 'SATELLITE_ANTENNA'), 183 | ('\U0001f4fa', 'TELEVISION'), 184 | ('\U0001f4fb', 'RADIO'), 185 | ('\U0001f509', 'SPEAKER_MEDIUM_VOLUME'), 186 | ('\U0001f514', 'BELL'), 187 | ('\u23f3', 'HOURGLASS_NOT_DONE'), 188 | ('\u23f0', 'ALARM_CLOCK'), 189 | ('\u231a', 'WATCH'), 190 | ('\U0001f512', 'LOCKED'), 191 | ('\U0001f511', 'KEY'), 192 | ('\U0001f50e', 'MAGNIFYING_GLASS_TILTED_RIGHT'), 193 | ('\U0001f4a1', 'LIGHT_BULB'), 194 | ('\U0001f526', 'FLASHLIGHT'), 195 | ('\U0001f50c', 'ELECTRIC_PLUG'), 196 | ('\U0001f50b', 'BATTERY'), 197 | ('\U0001f6bf', 'SHOWER'), 198 | ('\U0001f6bd', 'TOILET'), 199 | ('\U0001f527', 'WRENCH'), 200 | ('\U0001f528', 'HAMMER'), 201 | ('\U0001f6aa', 'DOOR'), 202 | ('\U0001f6ac', 'CIGARETTE'), 203 | ('\U0001f4a3', 'BOMB'), 204 | ('\U0001f52b', 'PISTOL'), 205 | ('\U0001f52a', 'KITCHEN_KNIFE'), 206 | ('\U0001f48a', 'PILL'), 207 | ('\U0001f489', 'SYRINGE'), 208 | ('\U0001f4b0', 'MONEY_BAG'), 209 | ('\U0001f4b5', 'DOLLAR_BANKNOTE'), 210 | ('\U0001f4b3', 'CREDIT_CARD'), 211 | ('\u2709', 'ENVELOPE'), 212 | ('\U0001f4eb', 'CLOSED_MAILBOX_WITH_RAISED_FLAG'), 213 | ('\U0001f4e6', 'PACKAGE'), 214 | ('\U0001f4c5', 'CALENDAR'), 215 | ('\U0001f4c1', 'FILE_FOLDER'), 216 | ('\u2702', 'SCISSORS'), 217 | ('\U0001f4cc', 'PUSHPIN'), 218 | ('\U0001f4ce', 'PAPERCLIP'), 219 | ('\u2712', 'BLACK_NIB'), 220 | ('\u270f', 'PENCIL'), 221 | ('\U0001f4d0', 'TRIANGULAR_RULER'), 222 | ('\U0001f4da', 'BOOKS'), 223 | ('\U0001f52c', 'MICROSCOPE'), 224 | ('\U0001f52d', 'TELESCOPE'), 225 | ('\U0001f3a8', 'ARTIST_PALETTE'), 226 | ('\U0001f3ac', 'CLAPPER_BOARD'), 227 | ('\U0001f3a4', 'MICROPHONE'), 228 | ('\U0001f3a7', 'HEADPHONE'), 229 | ('\U0001f3b5', 'MUSICAL_NOTE'), 230 | ('\U0001f3b9', 'MUSICAL_KEYBOARD'), 231 | ('\U0001f3bb', 'VIOLIN'), 232 | ('\U0001f3ba', 'TRUMPET'), 233 | ('\U0001f3b8', 'GUITAR'), 234 | ('\U0001f47e', 'ALIEN_MONSTER'), 235 | ('\U0001f3ae', 'VIDEO_GAME'), 236 | ('\U0001f0cf', 'JOKER'), 237 | ('\U0001f3b2', 'GAME_DIE'), 238 | ('\U0001f3af', 'DIRECT_HIT'), 239 | ('\U0001f3c8', 'AMERICAN_FOOTBALL'), 240 | ('\U0001f3c0', 'BASKETBALL'), 241 | ('\u26bd', 'SOCCER_BALL'), 242 | ('\u26be', 'BASEBALL'), 243 | ('\U0001f3be', 'TENNIS'), 244 | ('\U0001f3b1', 'POOL_8_BALL'), 245 | ('\U0001f3c9', 'RUGBY_FOOTBALL'), 246 | ('\U0001f3b3', 'BOWLING'), 247 | ('\U0001f3c1', 'CHEQUERED_FLAG'), 248 | ('\U0001f3c7', 'HORSE_RACING'), 249 | ('\U0001f3c6', 'TROPHY'), 250 | ('\U0001f3ca', 'PERSON_SWIMMING'), 251 | ('\U0001f3c4', 'PERSON_SURFING'), 252 | ('\u2615', 'HOT_BEVERAGE'), 253 | ('\U0001f37c', 'BABY_BOTTLE'), 254 | ('\U0001f37a', 'BEER_MUG'), 255 | ('\U0001f377', 'WINE_GLASS'), 256 | ('\U0001f374', 'FORK_AND_KNIFE'), 257 | ('\U0001f355', 'PIZZA'), 258 | ('\U0001f354', 'HAMBURGER'), 259 | ('\U0001f35f', 'FRENCH_FRIES'), 260 | ('\U0001f357', 'POULTRY_LEG'), 261 | ('\U0001f371', 'BENTO_BOX'), 262 | ('\U0001f35a', 'COOKED_RICE'), 263 | ('\U0001f35c', 'STEAMING_BOWL'), 264 | ('\U0001f361', 'DANGO'), 265 | ('\U0001f373', 'COOKING'), 266 | ('\U0001f35e', 'BREAD'), 267 | ('\U0001f369', 'DOUGHNUT'), 268 | ('\U0001f366', 'SOFT_ICE_CREAM'), 269 | ('\U0001f382', 'BIRTHDAY_CAKE'), 270 | ('\U0001f370', 'SHORTCAKE'), 271 | ('\U0001f36a', 'COOKIE'), 272 | ('\U0001f36b', 'CHOCOLATE_BAR'), 273 | ('\U0001f36d', 'LOLLIPOP'), 274 | ('\U0001f36f', 'HONEY_POT'), 275 | ('\U0001f34e', 'RED_APPLE'), 276 | ('\U0001f34f', 'GREEN_APPLE'), 277 | ('\U0001f34a', 'TANGERINE'), 278 | ('\U0001f34b', 'LEMON'), 279 | ('\U0001f352', 'CHERRIES'), 280 | ('\U0001f347', 'GRAPES'), 281 | ('\U0001f349', 'WATERMELON'), 282 | ('\U0001f353', 'STRAWBERRY'), 283 | ('\U0001f351', 'PEACH'), 284 | ('\U0001f34c', 'BANANA'), 285 | ('\U0001f350', 'PEAR'), 286 | ('\U0001f34d', 'PINEAPPLE'), 287 | ('\U0001f346', 'EGGPLANT'), 288 | ('\U0001f345', 'TOMATO'), 289 | ('\U0001f33d', 'EAR_OF_CORN'), 290 | ('\U0001f3e1', 'HOUSE_WITH_GARDEN'), 291 | ('\U0001f3e5', 'HOSPITAL'), 292 | ('\U0001f3e6', 'BANK'), 293 | ('\u26ea', 'CHURCH'), 294 | ('\U0001f3f0', 'CASTLE'), 295 | ('\u26fa', 'TENT'), 296 | ('\U0001f3ed', 'FACTORY'), 297 | ('\U0001f5fb', 'MOUNT_FUJI'), 298 | ('\U0001f5fd', 'STATUE_OF_LIBERTY'), 299 | ('\U0001f3a0', 'CAROUSEL_HORSE'), 300 | ('\U0001f3a1', 'FERRIS_WHEEL'), 301 | ('\u26f2', 'FOUNTAIN'), 302 | ('\U0001f3a2', 'ROLLER_COASTER'), 303 | ('\U0001f6a2', 'SHIP'), 304 | ('\U0001f6a4', 'SPEEDBOAT'), 305 | ('\u2693', 'ANCHOR'), 306 | ('\U0001f680', 'ROCKET'), 307 | ('\u2708', 'AIRPLANE'), 308 | ('\U0001f681', 'HELICOPTER'), 309 | ('\U0001f682', 'LOCOMOTIVE'), 310 | ('\U0001f68b', 'TRAM_CAR'), 311 | ('\U0001f68e', 'TROLLEYBUS'), 312 | ('\U0001f68c', 'BUS'), 313 | ('\U0001f699', 'SPORT_UTILITY_VEHICLE'), 314 | ('\U0001f697', 'AUTOMOBILE'), 315 | ('\U0001f695', 'TAXI'), 316 | ('\U0001f69b', 'ARTICULATED_LORRY'), 317 | ('\U0001f6a8', 'POLICE_CAR_LIGHT'), 318 | ('\U0001f694', 'ONCOMING_POLICE_CAR'), 319 | ('\U0001f692', 'FIRE_ENGINE'), 320 | ('\U0001f691', 'AMBULANCE'), 321 | ('\U0001f6b2', 'BICYCLE'), 322 | ('\U0001f6a0', 'MOUNTAIN_CABLEWAY'), 323 | ('\U0001f69c', 'TRACTOR'), 324 | ('\U0001f6a6', 'VERTICAL_TRAFFIC_LIGHT'), 325 | ('\u26a0', 'WARNING'), 326 | ('\U0001f6a7', 'CONSTRUCTION'), 327 | ('\u26fd', 'FUEL_PUMP'), 328 | ('\U0001f3b0', 'SLOT_MACHINE'), 329 | ('\U0001f5ff', 'MOAI'), 330 | ('\U0001f3aa', 'CIRCUS_TENT'), 331 | ('\U0001f3ad', 'PERFORMING_ARTS'), 332 | ('\U0001f1ef\\U0001f1f5', 'JAPAN'), 333 | ('\U0001f1f0\\U0001f1f7', 'SOUTH_KOREA'), 334 | ('\U0001f1e9\\U0001f1ea', 'GERMANY'), 335 | ('\U0001f1e8\\U0001f1f3', 'CHINA'), 336 | ('\U0001f1fa\\U0001f1f8', 'UNITED_STATES'), 337 | ('\U0001f1eb\\U0001f1f7', 'FRANCE'), 338 | ('\U0001f1ea\\U0001f1f8', 'SPAIN'), 339 | ('\U0001f1ee\\U0001f1f9', 'ITALY'), 340 | ('\U0001f1f7\\U0001f1fa', 'RUSSIA'), 341 | ('\U0001f1ec\\U0001f1e7', 'UNITED_KINGDOM'), 342 | ('1\u20e3', 'KEYCAP_ONE'), 343 | ('2\u20e3', 'KEYCAP_TWO'), 344 | ('3\u20e3', 'KEYCAP_THREE'), 345 | ('4\u20e3', 'KEYCAP_FOUR'), 346 | ('5\u20e3', 'KEYCAP_FIVE'), 347 | ('6\u20e3', 'KEYCAP_SIX'), 348 | ('7\u20e3', 'KEYCAP_SEVEN'), 349 | ('8\u20e3', 'KEYCAP_EIGHT'), 350 | ('9\u20e3', 'KEYCAP_NINE'), 351 | ('0\u20e3', 'KEYCAP_ZERO'), 352 | ('\U0001f51f', 'KEYCAP_10'), 353 | ('\u2757', 'EXCLAMATION_MARK'), 354 | ('\u2753', 'QUESTION_MARK'), 355 | ('\u2665', 'HEART_SUIT'), 356 | ('\u2666', 'DIAMOND_SUIT'), 357 | ('\U0001f4af', 'HUNDRED_POINTS'), 358 | ('\U0001f517', 'LINK'), 359 | ('\U0001f531', 'TRIDENT_EMBLEM'), 360 | ('\U0001f534', 'RED_CIRCLE'), 361 | ('\U0001f535', 'BLUE_CIRCLE'), 362 | ('\U0001f536', 'LARGE_ORANGE_DIAMOND'), 363 | ('\U0001f537', 'LARGE_BLUE_DIAMOND'), 364 | ) 365 | common_prime = b'\xC7\x1C\xAE\xB9\xC6\xB1\xC9\x04\x8E\x6C\x52\x2F\x70\xF1\x3F\x73\x98\x0D\x40\x23\x8E\x3E\x21\xC1\x49' \ 366 | b'\x34\xD0\x37\x56\x3D\x93\x0F\x48\x19\x8A\x0A\xA7\xC1\x40\x58\x22\x94\x93\xD2\x25\x30\xF4\xDB\xFA\x33' \ 367 | b'\x6F\x6E\x0A\xC9\x25\x13\x95\x43\xAE\xD4\x4C\xCE\x7C\x37\x20\xFD\x51\xF6\x94\x58\x70\x5A\xC6\x8C\xD4' \ 368 | b'\xFE\x6B\x6B\x13\xAB\xDC\x97\x46\x51\x29\x69\x32\x84\x54\xF1\x8F\xAF\x8C\x59\x5F\x64\x24\x77\xFE\x96' \ 369 | b'\xBB\x2A\x94\x1D\x5B\xCD\x1D\x4A\xC8\xCC\x49\x88\x07\x08\xFA\x9B\x37\x8E\x3C\x4F\x3A\x90\x60\xBE\xE6' \ 370 | b'\x7C\xF9\xA4\xA4\xA6\x95\x81\x10\x51\x90\x7E\x16\x27\x53\xB5\x6B\x0F\x6B\x41\x0D\xBA\x74\xD8\xA8\x4B' \ 371 | b'\x2A\x14\xB3\x14\x4E\x0E\xF1\x28\x47\x54\xFD\x17\xED\x95\x0D\x59\x65\xB4\xB9\xDD\x46\x58\x2D\xB1\x17' \ 372 | b'\x8D\x16\x9C\x6B\xC4\x65\xB0\xD6\xFF\x9C\xA3\x92\x8F\xEF\x5B\x9A\xE4\xE4\x18\xFC\x15\xE8\x3E\xBE\xA0' \ 373 | b'\xF8\x7F\xA9\xFF\x5E\xED\x70\x05\x0D\xED\x28\x49\xF4\x7B\xF9\x59\xD9\x56\x85\x0C\xE9\x29\x85\x1F\x0D' \ 374 | b'\x81\x15\xF6\x35\xB1\x05\xEE\x2E\x4E\x15\xD0\x4B\x24\x54\xBF\x6F\x4F\xAD\xF0\x34\xB1\x04\x03\x11\x9C' \ 375 | b'\xD8\xE3\xB9\x2F\xCC\x5B' 376 | 377 | 378 | def i2b(value: int) -> bytes: 379 | """ 380 | Convert integer value to bytes 381 | 382 | Args: 383 | value (``int``): 384 | Value to convert 385 | 386 | Returns: 387 | Resulting ``bytes`` object 388 | """ 389 | return int.to_bytes( 390 | value, 391 | length=(value.bit_length() + 8 - 1) // 8, # 8 bits per byte, 392 | byteorder='big', 393 | signed=False 394 | ) 395 | 396 | 397 | def b2i(value: bytes) -> int: 398 | """ 399 | Convert bytes value to integer 400 | 401 | Args: 402 | value (``bytes``): 403 | Value to convert 404 | 405 | Returns: 406 | Resulting ``int`` object 407 | """ 408 | return int.from_bytes(value, 'big') 409 | 410 | 411 | def check_dhc(g: int, p: int) -> None: 412 | """ 413 | Security checks for Diffie-Hellman prime and generator. Ported from Java implementation for Android 414 | 415 | Args: 416 | g (``int``): DH generator 417 | p (``int``): DH prime 418 | 419 | Raises: 420 | :class:`ValueError` if checks are not passed 421 | """ 422 | if not 2 <= g <= 7: 423 | raise ValueError() 424 | 425 | if p.bit_length() != 2048 or p < 0: 426 | raise ValueError() 427 | 428 | if ( 429 | g == 2 and p % 8 != 7 or # p % 8 = 7 for g = 2 430 | g == 3 and p % 3 != 2 or # p % 3 = 2 for g = 3 431 | g == 5 and p % 5 not in (1, 4) or # p % 5 = 1 or 4 for g = 5 432 | g == 6 and p % 24 not in (19, 23) or # p % 24 = 19 or 23 for g = 6 433 | g == 7 and p % 7 not in (3, 5, 6) # p % 7 = 3, 5 or 6 for g = 7 434 | ): 435 | raise ValueError() 436 | 437 | if i2b(p) == common_prime: 438 | return 439 | 440 | # let's assume that (p - 1) / 2 is prime because checking its primality is an expensive operation... 441 | 442 | 443 | def check_g(g_x: int, p: int) -> None: 444 | """ 445 | Check g\_ numbers 446 | 447 | Args: 448 | g_x: g\_ number to check 449 | p: DH prime 450 | 451 | Raises: 452 | :class:`ValueError` if checks are not passed 453 | """ 454 | if not (1 < g_x < p - 1): 455 | raise ValueError('g_x is invalid (1 < g_x < p - 1 is false)') 456 | if not (twoe1984 < g_x < p - twoe1984): 457 | raise ValueError('g_x is invalid (2^1984 < g_x < p - 2^1984 is false)') 458 | 459 | 460 | def calc_fingerprint(key: bytes) -> int: 461 | """ 462 | Calculate key fingerprint 463 | 464 | Args: 465 | key (``bytes``): 466 | Key to generate fingerprint for 467 | 468 | Returns: 469 | :class:`int` object representing a key fingerprint 470 | """ 471 | return int.from_bytes( 472 | bytes(hashlib.sha1(key).digest()[-8:]), 'little', signed=True 473 | ) 474 | 475 | 476 | def generate_visualization(key: Union[bytes, int], part2: Union[bytes, int]) -> (List[str], List[str]): 477 | """ 478 | Generate emoji visualization of key 479 | 480 | https://core.telegram.org/api/end-to-end/voice-calls#key-verification 481 | 482 | Args: 483 | key (``bytes`` | ``int``): 484 | Call auth key 485 | 486 | part2 (``bytes`` | ``int``): 487 | `g_a` value of the caller 488 | 489 | Returns: 490 | A tuple containing two lists (of emoji strings and of their text representations) 491 | """ 492 | if isinstance(key, int): 493 | key = i2b(key) 494 | if isinstance(part2, int): 495 | part2 = i2b(part2) 496 | 497 | visualization = [] 498 | visualization_text = [] 499 | vis_src = hashlib.sha256(key + part2).digest() 500 | for i in range(0, len(vis_src), 8): 501 | number = vis_src[i:i+8] 502 | number = i2b(number[0] & 0x7f) + number[1:] 503 | idx = int.from_bytes(number, 'big') % len(emojis) 504 | visualization.append(emojis[idx][0]) 505 | visualization_text.append(emojis[idx][1]) 506 | return visualization, visualization_text 507 | 508 | 509 | def get_real_elapsed_time() -> float: 510 | """ 511 | Get current performance counter value 512 | 513 | Returns: 514 | Time to use for measuring call duration 515 | """ 516 | return time.perf_counter() 517 | -------------------------------------------------------------------------------- /src/tgvoip/tgvoip.py: -------------------------------------------------------------------------------- 1 | # PytgVoIP - Telegram VoIP Library for Python 2 | # Copyright (C) 2020 bakatrouble 3 | # 4 | # This file is part of PytgVoIP. 5 | # 6 | # PytgVoIP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published 8 | # by the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PytgVoIP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with PytgVoIP. If not, see . 18 | 19 | import json 20 | import os 21 | import sys 22 | from datetime import datetime 23 | from enum import Enum 24 | from typing import Union, List 25 | 26 | from _tgvoip import ( 27 | NetType as _NetType, 28 | DataSaving as _DataSaving, 29 | CallState as _CallState, 30 | CallError as _CallError, 31 | Stats, 32 | Endpoint, 33 | VoIPController as _VoIPController, 34 | VoIPServerConfig as _VoIPServerConfig 35 | ) 36 | 37 | from tgvoip.utils import get_real_elapsed_time 38 | 39 | 40 | # docstring magic ahead 41 | 42 | 43 | class NetType(Enum): 44 | """ 45 | An enumeration of network types 46 | 47 | Members: 48 | * UNKNOWN = 0 49 | * GPRS = 1 50 | * EDGE = 2 51 | * NET_3G = 3 52 | * HSPA = 4 53 | * LTE = 5 54 | * WIFI = 6 55 | * ETHERNET = 7 56 | * OTHER_HIGH_SPEED = 8 57 | * OTHER_LOW_SPEED = 9 58 | * DIALUP = 10 59 | * OTHER_MOBILE = 11 60 | """ 61 | 62 | UNKNOWN = _NetType.UNKNOWN 63 | GPRS = _NetType.GPRS 64 | EDGE = _NetType.EDGE 65 | NET_3G = _NetType.NET_3G 66 | HSPA = _NetType.HSPA 67 | LTE = _NetType.LTE 68 | WIFI = _NetType.WIFI 69 | ETHERNET = _NetType.ETHERNET 70 | OTHER_HIGH_SPEED = _NetType.OTHER_HIGH_SPEED 71 | OTHER_LOW_SPEED = _NetType.OTHER_LOW_SPEED 72 | DIALUP = _NetType.DIALUP 73 | OTHER_MOBILE = _NetType.OTHER_MOBILE 74 | 75 | 76 | class CallState(Enum): 77 | """ 78 | An enumeration of call states 79 | 80 | Members: 81 | * WAIT_INIT = 1 82 | * WAIT_INIT_ACK = 2 83 | * ESTABLISHED = 3 84 | * FAILED = 4 85 | * RECONNECTING = 5 86 | * HANGING_UP = 10 87 | * ENDED = 11 88 | * EXCHANGING_KEYS = 12 89 | * WAITING = 13 90 | * REQUESTING = 14 91 | * WAITING_INCOMING = 15 92 | * RINGING = 16 93 | * BUSY = 17 94 | """ 95 | 96 | WAIT_INIT = _CallState.WAIT_INIT 97 | WAIT_INIT_ACK = _CallState.WAIT_INIT_ACK 98 | ESTABLISHED = _CallState.ESTABLISHED 99 | FAILED = _CallState.FAILED 100 | RECONNECTING = _CallState.RECONNECTING 101 | HANGING_UP = 10 102 | ENDED = 11 103 | EXCHANGING_KEYS = 12 104 | WAITING = 13 105 | REQUESTING = 14 106 | WAITING_INCOMING = 15 107 | RINGING = 16 108 | BUSY = 17 109 | 110 | 111 | class DataSaving(Enum): 112 | """ 113 | An enumeration of data saving modes 114 | 115 | Members: 116 | * NEVER = 0 117 | * MOBILE = 1 118 | * ALWAYS = 2 119 | """ 120 | NEVER = _DataSaving.NEVER 121 | MOBILE = _DataSaving.MOBILE 122 | ALWAYS = _DataSaving.ALWAYS 123 | 124 | 125 | class CallError(Enum): 126 | """ 127 | An enumeration of call errors 128 | 129 | Members: 130 | * UNKNOWN = 0 131 | * INCOMPATIBLE = 1 132 | * TIMEOUT = 2 133 | * AUDIO_IO = 3 134 | * PROXY = 4 135 | """ 136 | UNKNOWN = _CallError.UNKNOWN 137 | INCOMPATIBLE = _CallError.INCOMPATIBLE 138 | TIMEOUT = _CallError.TIMEOUT 139 | AUDIO_IO = _CallError.AUDIO_IO 140 | PROXY = _CallError.PROXY 141 | 142 | 143 | class VoIPController(_VoIPController): 144 | """ 145 | A wrapper around C++ wrapper for libtgvoip ``VoIPController`` 146 | 147 | Args: 148 | persistent_state_file (``str``, *optional*): ?, empty to not use 149 | debug (``bool``, *optional*): Modifies logging behavior 150 | logs_dir (``str``, *optional*): Logs directory 151 | 152 | Class attributes: 153 | LIBTGVOIP_VERSION 154 | Used ``libtgvoip`` version 155 | 156 | CONNECTION_MAX_LAYER 157 | Maximum layer supported by used ``libtgvoip`` version 158 | 159 | Attributes: 160 | persistent_state_file: 161 | Value set in the constructor 162 | 163 | call_state_changed_handlers: 164 | ``list`` of call state change callbacks, callbacks receive a :class:`CallState` object as argument 165 | 166 | signal_bars_changed_handlers 167 | ``list`` of signal bars count change callbacks, callbacks receive an ``int`` object as argument 168 | """ 169 | 170 | def __init__(self, persistent_state_file: str = '', debug=False, logs_dir='logs'): 171 | super().__init__(persistent_state_file) # _VoIPController.__init__(self, persistent_state_file) 172 | self.debug = debug 173 | self.logs_dir = logs_dir 174 | self.start_time = 0 175 | self.send_audio_frame_callback = lambda length: b'' 176 | self.recv_audio_frame_callback = lambda frame: ... 177 | self.call_state_changed_handlers = [] 178 | self.signal_bars_changed_handlers = [] 179 | self._init() 180 | 181 | @property 182 | def call_duration(self) -> int: 183 | """ 184 | Current call duration in seconds as ``int`` if call was started, otherwise 0 185 | """ 186 | return int(get_real_elapsed_time() - self.start_time) if self.start_time else 0 187 | 188 | def start(self): 189 | """ 190 | Start the controller 191 | """ 192 | super().start() 193 | 194 | def connect(self): 195 | """ 196 | Start the call 197 | """ 198 | super().connect() 199 | 200 | def set_proxy(self, address: str, port: int = 1080, username: str = '', password: str = ''): 201 | """ 202 | Set SOCKS5 proxy config 203 | 204 | Args: 205 | address (``str``): Proxy hostname or IP address 206 | port (``int``, *optional*): Proxy port 207 | username (``int``, *optional*): Proxy username 208 | password (``int``, *optional*): Proxy password 209 | 210 | Raises: 211 | :class:`ValueError` if :attr:`address` is empty 212 | """ 213 | if not address: 214 | raise ValueError('address can\'t be empty') 215 | super().set_proxy(address, port, username, password) 216 | 217 | def set_encryption_key(self, key: bytes, is_outgoing: bool): 218 | """ 219 | Set call auth key 220 | 221 | Args: 222 | key (``bytes``): Auth key, must be exactly 256 bytes 223 | is_outgoing (``bool``): Is call outgoing 224 | 225 | Raises: 226 | :class:`ValueError` if provided auth key has wrong length 227 | """ 228 | if len(key) != 256: 229 | raise ValueError('key length must be exactly 256 bytes but is {}'.format(len(key))) 230 | super().set_encryption_key(key, is_outgoing) 231 | 232 | def set_remote_endpoints(self, endpoints: List[Endpoint], allow_p2p: bool, tcp: bool, connection_max_layer: int): 233 | """ 234 | Set remote endpoints received in call object from Telegram. 235 | 236 | Usually it's ``[call.connection] + call.alternative_connections``. 237 | 238 | You must build :class:`Endpoint` objects from MTProto :class:`phoneConnection` objects and pass them in list. 239 | 240 | Args: 241 | endpoints (``list`` of :class:`Endpoint`): List of endpoints 242 | allow_p2p (``bool``): Is p2p connection allowed, usually `call.p2p_allowed` value is used 243 | tcp (``bool``): Connect via TCP, not recommended 244 | connection_max_layer (``int``): Use a value provided by :attr:`VoIPController.CONNECTION_MAX_LAYER` 245 | 246 | Raises: 247 | :class:`ValueError` if either no endpoints are provided or endpoints without IPv4 or with wrong \ 248 | ``peer_tag`` (must be either ``None`` or have length of 16 bytes) are detected 249 | """ 250 | if not endpoints: 251 | raise ValueError('endpoints len is 0') 252 | for ep in endpoints: 253 | if ep.ip is None or not len(ep.ip): 254 | raise ValueError('endpoint {} has empty/null ipv4'.format(ep)) 255 | if ep.peer_tag is not None and len(ep.peer_tag) != 16: 256 | raise ValueError('endpoint {} has peer_tag of wrong length'.format(ep)) 257 | super().set_remote_endpoints(endpoints, allow_p2p, tcp, connection_max_layer) 258 | 259 | def get_debug_string(self) -> str: 260 | """ 261 | Get debug string 262 | 263 | Returns: 264 | ``str`` containing debug info 265 | """ 266 | return super().get_debug_string() 267 | 268 | def set_network_type(self, _type: NetType): 269 | """ 270 | Set network type 271 | 272 | Args: 273 | _type (:class:`NetType`): Network type to set 274 | """ 275 | super().set_network_type(_NetType(_type.value)) 276 | 277 | def set_mic_mute(self, mute: bool): 278 | """ 279 | Set "microphone" state. If muted, audio is not being sent 280 | 281 | Args: 282 | mute (``bool``): Whether to mute "microphone" 283 | """ 284 | super().set_mic_mute(mute) 285 | 286 | def set_config(self, 287 | recv_timeout: float, 288 | init_timeout: float, 289 | data_saving_mode: DataSaving, 290 | call_id: int, 291 | enable_aec: bool = True, 292 | enable_ns: bool = True, 293 | enable_agc: bool = True, 294 | log_file_path: str = None, 295 | status_dump_path: str = None, 296 | log_packet_stats: bool = None): 297 | """ 298 | Set call config 299 | 300 | Args: 301 | recv_timeout (``float``): 302 | Packet receive timeout, usually value received from ``help.getConfig()`` is used 303 | 304 | init_timeout (``float``): 305 | Packet init timeout, usually value received from ``help.getConfig()`` is used 306 | 307 | data_saving_mode (:class:`DataSaving`): Data saving mode 308 | 309 | call_id (``int``): Call ID 310 | 311 | enable_aec (``bool``, *optional*): 312 | Whether to enable automatic echo cancellation, defaults to ``True`` 313 | 314 | enable_ns (``bool``, *optional*): 315 | Whether to enable noise suppression, defaults to ``True`` 316 | 317 | enable_agc (``bool``, *optional*): 318 | Whether to enable automatic gain control, defaults to ``True`` 319 | 320 | log_file_path (``str``, *optional*): 321 | Call log file path, calculated automatically if not provided 322 | 323 | status_dump_path (``str``, *optional*): 324 | Status dump path, calculated automatically if not provided and ``debug`` is enabled 325 | 326 | log_packet_stats (``bool``, *optional*): 327 | Whether to log packet stats, defaults to ``debug`` value 328 | """ 329 | if log_file_path is None: 330 | if self.debug: 331 | log_file_path = self._get_log_file_path('voip{}'.format(call_id)) 332 | else: 333 | log_file_path = self._get_log_file_path_for_call_id(call_id) # wtf? 334 | if status_dump_path is None: 335 | status_dump_path = self._get_log_file_path('voip_stats') if self.debug else '' 336 | if log_packet_stats is None: 337 | log_packet_stats = self.debug 338 | super().set_config(recv_timeout, init_timeout, _DataSaving(data_saving_mode.value), enable_aec, enable_ns, enable_agc, 339 | log_file_path, status_dump_path, log_packet_stats) 340 | 341 | def debug_ctl(self, request: int, param: int): 342 | """ 343 | Debugging options 344 | 345 | Args: 346 | request (``int``): 347 | Option (``1`` for max bitrate, ``2`` for packet loss (in percents), ``3`` for toggling p2p, \ 348 | ``4`` for toggling echo cancelling) 349 | 350 | param (``int``): 351 | Numeric value for options 1 and 2, ``0`` or ``1`` for options 3 and 4 352 | """ 353 | super().debug_ctl(request, param) 354 | 355 | def get_preferred_relay_id(self) -> int: 356 | """ 357 | Get preferred relay ID (used in ``discardCall`` MTProto request) 358 | 359 | Returns: 360 | ``int`` ID 361 | """ 362 | return super().get_preferred_relay_id() 363 | 364 | def get_last_error(self) -> CallError: 365 | """ 366 | Get last error type 367 | 368 | Returns: 369 | :class:`CallError` matching last occurred error type 370 | """ 371 | return CallError(super().get_last_error()) 372 | 373 | def get_stats(self) -> Stats: 374 | """ 375 | Get call stats 376 | 377 | Returns: 378 | :class:`Stats` object 379 | """ 380 | return super().get_stats() 381 | 382 | def get_debug_log(self) -> str: 383 | """ 384 | Get debug log 385 | 386 | Returns: 387 | JSON ``str`` containing debug log 388 | """ 389 | return super().get_debug_log() 390 | 391 | def set_audio_output_gain_control_enabled(self, enabled: bool): 392 | """ 393 | Toggle output gain control 394 | 395 | Args: 396 | enabled (``bool``): Whether to enable output gain control 397 | """ 398 | super().set_audio_output_gain_control_enabled(enabled) 399 | 400 | def set_echo_cancellation_strength(self, strength: int): 401 | """ 402 | Set echo cancellation strength, does nothing currently but was in Java bindings (?) 403 | 404 | Args: 405 | strength (``int``): Strength value 406 | """ 407 | super().set_echo_cancellation_strength(strength) 408 | 409 | def get_peer_capabilities(self) -> int: 410 | """ 411 | Get peer capabilities 412 | 413 | Returns: 414 | ``int`` with bit mask, looks like it is used only for experimental features (group, video calls) 415 | """ 416 | return super().get_peer_capabilities() 417 | 418 | def need_rate(self) -> bool: 419 | """ 420 | Get whether the call needs rating 421 | 422 | Returns: 423 | ``bool`` value 424 | """ 425 | return super().need_rate() 426 | 427 | @property 428 | def native_io(self) -> bool: 429 | """ 430 | Get native I/O status (file I/O implemented in C++) 431 | 432 | Returns: 433 | ``bool`` status (enabled or not) 434 | """ 435 | return self._native_io_get() 436 | 437 | @native_io.setter 438 | def native_io(self, val: bool) -> None: 439 | """ 440 | Set native I/O status (file I/O implemented in C++) 441 | 442 | Args: 443 | val (``bool``): Status value 444 | """ 445 | self._native_io_set(val) 446 | 447 | def play(self, path: str) -> bool: 448 | """ 449 | Add a file to play queue for native I/O 450 | 451 | Args: 452 | path (``str``): File path 453 | 454 | Returns: 455 | ``bool`` whether opening the file was successful. File is not added to queue on failure. 456 | """ 457 | return super().play(path) 458 | 459 | def play_on_hold(self, paths: List[str]) -> None: 460 | """ 461 | Replace the hold queue for native I/O 462 | 463 | Args: 464 | paths (``list`` of ``str``): List of file paths 465 | """ 466 | super().play_on_hold(paths) 467 | 468 | def set_output_file(self, path: str) -> bool: 469 | """ 470 | Set output file for native I/O 471 | 472 | Args: 473 | path (``str``): File path 474 | 475 | Returns: 476 | ``bool`` whether opening the file was successful. Output file is not replaced on failure. 477 | """ 478 | return super().set_output_file(path) 479 | 480 | def clear_play_queue(self) -> None: 481 | """ 482 | Clear the play queue for native I/O 483 | """ 484 | super().clear_play_queue() 485 | 486 | def clear_hold_queue(self) -> None: 487 | """ 488 | Clear the hold queue for native I/O 489 | """ 490 | super().clear_hold_queue() 491 | 492 | def unset_output_file(self) -> None: 493 | """ 494 | Unset the output file for native I/O 495 | """ 496 | super().unset_output_file() 497 | 498 | # native code callback 499 | def _handle_state_change(self, state: _CallState): 500 | state = CallState(state) 501 | 502 | if state == CallState.ESTABLISHED and not self.start_time: 503 | self.start_time = get_real_elapsed_time() 504 | 505 | for handler in self.call_state_changed_handlers: 506 | callable(handler) and handler(state) 507 | 508 | # native code callback 509 | def _handle_signal_bars_change(self, count: int): 510 | for handler in self.signal_bars_changed_handlers: 511 | callable(handler) and handler(count) 512 | 513 | def update_state(self, state: CallState): 514 | """ 515 | Manually update state (only triggers handlers) 516 | 517 | Args: 518 | state (:class:`CallState`): State to set 519 | """ 520 | self._handle_state_change(state) 521 | 522 | def set_send_audio_frame_callback(self, func: callable): 523 | """ 524 | Set callback providing audio data to send 525 | 526 | Should accept one argument (``int`` length of requested audio frame) and return ``bytes`` object with audio \ 527 | data encoded in 16-bit signed PCM 528 | 529 | If returned object has insufficient length, it will be automatically padded with zero bytes 530 | 531 | Args: 532 | func (``callable``): Callback function 533 | """ 534 | self.send_audio_frame_callback = func 535 | 536 | def _send_audio_frame_impl(self, length: int): 537 | frame = b'' 538 | if callable(self.send_audio_frame_callback): 539 | frame = self.send_audio_frame_callback(length) 540 | return frame.ljust(length, b'\0') 541 | 542 | def set_recv_audio_frame_callback(self, func: callable): 543 | """ 544 | Set callback receiving incoming audio data 545 | 546 | Should accept one argument (``bytes``) with audio data encoded in 16-bit signed PCM 547 | 548 | Args: 549 | func (``callable``): Callback function 550 | """ 551 | self.recv_audio_frame_callback = func 552 | 553 | def _recv_audio_frame_impl(self, frame: bytes): 554 | if callable(self.recv_audio_frame_callback): 555 | self.recv_audio_frame_callback(frame) 556 | 557 | def _get_log_file_path(self, name: str) -> str: 558 | os.makedirs(self.logs_dir, exist_ok=True) 559 | now = datetime.now() 560 | fname = '{}_{}_{}_{}_{}_{}_{}.txt'.format(now.year, now.month, now.day, now.hour, now.minute, now.second, name) 561 | return os.path.abspath(os.path.join(self.logs_dir, fname)) 562 | 563 | def _get_log_file_path_for_call_id(self, call_id: int) -> str: 564 | os.makedirs(self.logs_dir, exist_ok=True) 565 | # Java version cleans up old logs (*.log) for non-debug version here (leaves 20 latest) 566 | return os.path.abspath(os.path.join(self.logs_dir, '{}.log'.format(call_id))) 567 | 568 | 569 | class VoIPServerConfig(_VoIPServerConfig): 570 | """ 571 | Global server config class. This class contains default config in its source 572 | """ 573 | 574 | # default config 575 | config = { 576 | 'audio_max_bitrate': 20000, 577 | 'audio_max_bitrate_gprs': 8000, 578 | 'audio_max_bitrate_edge': 16000, 579 | 'audio_max_bitrate_saving': 8000, 580 | 'audio_init_bitrate': 16000, 581 | 'audio_init_bitrate_gprs': 8000, 582 | 'audio_init_bitrate_edge': 8000, 583 | 'audio_init_bitrate_saving': 8000, 584 | 'audio_bitrate_step_incr': 1000, 585 | 'audio_bitrate_step_decr': 1000, 586 | 'audio_min_bitrate': 8000, 587 | 'relay_switch_threshold': 0.8, 588 | 'p2p_to_relay_switch_threshold': 0.6, 589 | 'relay_to_p2p_switch_threshold': 0.8, 590 | 'reconnecting_state_timeout': 2.0, 591 | 'rate_flags': 0xFFFFFFFF, 592 | 'rate_min_rtt': 0.6, 593 | 'rate_min_send_loss': 0.2, 594 | 'packet_loss_for_extra_ec': 0.02, 595 | 'max_unsent_stream_packets': 2, 596 | } 597 | 598 | @classmethod 599 | def set_config(cls, _json: Union[str, dict]): 600 | """ 601 | Set global server config 602 | 603 | Args: 604 | _json (``str`` | ``dict``): either JSON-encoded object or ``dict`` containing config values. \ 605 | Might be received from MTProto ``phone.getCallConfig()`` call, if not set default values are used 606 | 607 | Raises: 608 | Prints an error to ``stderr`` if JSON parsing (for ``str`` argument) or encoding (for ``dict`` argument) \ 609 | has occurred 610 | """ 611 | try: 612 | if isinstance(_json, dict): 613 | _json = json.dumps(_json) 614 | cls.config.update(json.loads(_json)) 615 | _VoIPServerConfig.set_config(_json) 616 | except json.JSONDecodeError as e: 617 | print('Error parsing VoIP config', e, file=sys.stderr) 618 | except TypeError as e: 619 | print('Error building JSON', e, file=sys.stderr) 620 | 621 | @classmethod 622 | def set_bitrate_config(cls, init_bitrate: int = 16000, max_bitrate: int = 20000, min_bitrate: int = 8000, 623 | decrease_step: int = 1000, increase_step: int = 1000): 624 | """ 625 | Helper method for setting bitrate options 626 | 627 | Args: 628 | init_bitrate (``int``): Initial bitrate value 629 | max_bitrate (``int``): Maximum bitrate value 630 | min_bitrate (``int``): Minimum bitrate value 631 | decrease_step (``int``): Bitrate decrease step 632 | increase_step (``int``): Bitrate increase step 633 | 634 | Raises: 635 | Same as :meth:`set_config` 636 | """ 637 | cls.set_config({ 638 | 'audio_init_bitrate': init_bitrate, 639 | 'audio_max_bitrate': max_bitrate, 640 | 'audio_min_bitrate': min_bitrate, 641 | 'audio_bitrate_step_decr': decrease_step, 642 | 'audio_bitrate_step_incr': increase_step, 643 | }) 644 | 645 | 646 | __all__ = ['NetType', 'DataSaving', 'CallState', 'CallError', 'Stats', 'Endpoint', 'VoIPController', 647 | 'VoIPServerConfig'] 648 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /src/libtgvoip.cmake: -------------------------------------------------------------------------------- 1 | # This file is part of Telegram Desktop, 2 | # the official desktop application for the Telegram messaging service. 3 | # 4 | # For license and copyright information please follow this link: 5 | # https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 6 | 7 | if (TDESKTOP_USE_PACKAGED_TGVOIP) 8 | add_library(lib_tgvoip INTERFACE IMPORTED GLOBAL) 9 | add_library(tdesktop::lib_tgvoip ALIAS lib_tgvoip) 10 | 11 | find_package(PkgConfig REQUIRED) 12 | pkg_check_modules(TGVOIP REQUIRED tgvoip) 13 | 14 | target_include_directories(lib_tgvoip INTERFACE ${TGVOIP_INCLUDE_DIRS}) 15 | target_link_libraries(lib_tgvoip INTERFACE ${TGVOIP_LIBRARIES}) 16 | else() 17 | add_library(lib_tgvoip STATIC) 18 | init_target(lib_tgvoip) 19 | add_library(tdesktop::lib_tgvoip ALIAS lib_tgvoip) 20 | 21 | if (NOT APPLE) 22 | # On macOS if you build libtgvoip with C++17 it uses std::optional 23 | # instead of absl::optional and when it uses optional::value, the 24 | # build fails, because optional::value is available starting with 25 | # macOS 10.14+. This way we force using absl::optional. 26 | target_compile_features(lib_tgvoip PUBLIC cxx_std_17) 27 | endif() 28 | 29 | set(tgvoip_loc ${third_party_loc}/libtgvoip) 30 | 31 | nice_target_sources(lib_tgvoip ${tgvoip_loc} 32 | PRIVATE 33 | BlockingQueue.cpp 34 | BlockingQueue.h 35 | Buffers.cpp 36 | Buffers.h 37 | CongestionControl.cpp 38 | CongestionControl.h 39 | EchoCanceller.cpp 40 | EchoCanceller.h 41 | JitterBuffer.cpp 42 | JitterBuffer.h 43 | logging.cpp 44 | logging.h 45 | MediaStreamItf.cpp 46 | MediaStreamItf.h 47 | OpusDecoder.cpp 48 | OpusDecoder.h 49 | OpusEncoder.cpp 50 | OpusEncoder.h 51 | threading.h 52 | TgVoip.cpp 53 | TgVoip.h 54 | VoIPController.cpp 55 | VoIPGroupController.cpp 56 | VoIPController.h 57 | PrivateDefines.h 58 | VoIPServerConfig.cpp 59 | VoIPServerConfig.h 60 | audio/AudioInput.cpp 61 | audio/AudioInput.h 62 | audio/AudioOutput.cpp 63 | audio/AudioOutput.h 64 | audio/Resampler.cpp 65 | audio/Resampler.h 66 | NetworkSocket.cpp 67 | NetworkSocket.h 68 | PacketReassembler.cpp 69 | PacketReassembler.h 70 | MessageThread.cpp 71 | MessageThread.h 72 | audio/AudioIO.cpp 73 | audio/AudioIO.h 74 | video/ScreamCongestionController.cpp 75 | video/ScreamCongestionController.h 76 | video/VideoSource.cpp 77 | video/VideoSource.h 78 | video/VideoRenderer.cpp 79 | video/VideoRenderer.h 80 | json11.cpp 81 | json11.hpp 82 | 83 | # Windows 84 | os/windows/NetworkSocketWinsock.cpp 85 | os/windows/NetworkSocketWinsock.h 86 | # os/windows/AudioInputWave.cpp 87 | # os/windows/AudioInputWave.h 88 | # os/windows/AudioOutputWave.cpp 89 | # os/windows/AudioOutputWave.h 90 | # os/windows/AudioOutputWASAPI.cpp 91 | # os/windows/AudioOutputWASAPI.h 92 | # os/windows/AudioInputWASAPI.cpp 93 | # os/windows/AudioInputWASAPI.h 94 | os/windows/WindowsSpecific.cpp 95 | os/windows/WindowsSpecific.h 96 | 97 | # macOS 98 | os/darwin/AudioInputAudioUnit.cpp 99 | os/darwin/AudioInputAudioUnit.h 100 | os/darwin/AudioOutputAudioUnit.cpp 101 | os/darwin/AudioOutputAudioUnit.h 102 | os/darwin/AudioInputAudioUnitOSX.cpp 103 | os/darwin/AudioInputAudioUnitOSX.h 104 | os/darwin/AudioOutputAudioUnitOSX.cpp 105 | os/darwin/AudioOutputAudioUnitOSX.h 106 | os/darwin/AudioUnitIO.cpp 107 | os/darwin/AudioUnitIO.h 108 | os/darwin/DarwinSpecific.mm 109 | os/darwin/DarwinSpecific.h 110 | 111 | # Linux 112 | # os/linux/AudioInputALSA.cpp 113 | # os/linux/AudioInputALSA.h 114 | # os/linux/AudioOutputALSA.cpp 115 | # os/linux/AudioOutputALSA.h 116 | # os/linux/AudioOutputPulse.cpp 117 | # os/linux/AudioOutputPulse.h 118 | # os/linux/AudioInputPulse.cpp 119 | # os/linux/AudioInputPulse.h 120 | # os/linux/AudioPulse.cpp 121 | # os/linux/AudioPulse.h 122 | 123 | # POSIX 124 | os/posix/NetworkSocketPosix.cpp 125 | os/posix/NetworkSocketPosix.h 126 | 127 | # WebRTC APM 128 | webrtc_dsp/system_wrappers/include/field_trial.h 129 | webrtc_dsp/system_wrappers/include/cpu_features_wrapper.h 130 | webrtc_dsp/system_wrappers/include/asm_defines.h 131 | webrtc_dsp/system_wrappers/include/metrics.h 132 | webrtc_dsp/system_wrappers/include/compile_assert_c.h 133 | webrtc_dsp/system_wrappers/source/field_trial.cc 134 | webrtc_dsp/system_wrappers/source/metrics.cc 135 | webrtc_dsp/system_wrappers/source/cpu_features.cc 136 | webrtc_dsp/typedefs.h 137 | webrtc_dsp/absl/strings/internal/memutil.h 138 | webrtc_dsp/absl/strings/internal/memutil.cc 139 | webrtc_dsp/absl/strings/string_view.cc 140 | webrtc_dsp/absl/strings/ascii.h 141 | webrtc_dsp/absl/strings/ascii.cc 142 | webrtc_dsp/absl/strings/string_view.h 143 | webrtc_dsp/absl/types/optional.h 144 | webrtc_dsp/absl/types/bad_optional_access.h 145 | webrtc_dsp/absl/types/bad_optional_access.cc 146 | webrtc_dsp/absl/types/optional.cc 147 | webrtc_dsp/absl/memory/memory.h 148 | webrtc_dsp/absl/meta/type_traits.h 149 | webrtc_dsp/absl/algorithm/algorithm.h 150 | webrtc_dsp/absl/container/inlined_vector.h 151 | webrtc_dsp/absl/base/policy_checks.h 152 | webrtc_dsp/absl/base/port.h 153 | webrtc_dsp/absl/base/config.h 154 | webrtc_dsp/absl/base/internal/raw_logging.cc 155 | webrtc_dsp/absl/base/internal/throw_delegate.cc 156 | webrtc_dsp/absl/base/internal/invoke.h 157 | webrtc_dsp/absl/base/internal/inline_variable.h 158 | webrtc_dsp/absl/base/internal/atomic_hook.h 159 | webrtc_dsp/absl/base/internal/identity.h 160 | webrtc_dsp/absl/base/internal/raw_logging.h 161 | webrtc_dsp/absl/base/internal/throw_delegate.h 162 | webrtc_dsp/absl/base/attributes.h 163 | webrtc_dsp/absl/base/macros.h 164 | webrtc_dsp/absl/base/optimization.h 165 | webrtc_dsp/absl/base/log_severity.h 166 | webrtc_dsp/absl/utility/utility.h 167 | webrtc_dsp/rtc_base/string_to_number.h 168 | webrtc_dsp/rtc_base/constructormagic.h 169 | webrtc_dsp/rtc_base/race_checker.cc 170 | webrtc_dsp/rtc_base/strings/string_builder.h 171 | webrtc_dsp/rtc_base/strings/string_builder.cc 172 | webrtc_dsp/rtc_base/event_tracer.h 173 | webrtc_dsp/rtc_base/stringencode.h 174 | webrtc_dsp/rtc_base/memory/aligned_malloc.cc 175 | webrtc_dsp/rtc_base/memory/aligned_malloc.h 176 | webrtc_dsp/rtc_base/timeutils.cc 177 | webrtc_dsp/rtc_base/event.h 178 | webrtc_dsp/rtc_base/ignore_wundef.h 179 | webrtc_dsp/rtc_base/stringutils.h 180 | webrtc_dsp/rtc_base/arraysize.h 181 | webrtc_dsp/rtc_base/platform_file.cc 182 | webrtc_dsp/rtc_base/swap_queue.h 183 | webrtc_dsp/rtc_base/string_to_number.cc 184 | webrtc_dsp/rtc_base/trace_event.h 185 | webrtc_dsp/rtc_base/checks.h 186 | webrtc_dsp/rtc_base/deprecation.h 187 | webrtc_dsp/rtc_base/thread_checker_impl.cc 188 | webrtc_dsp/rtc_base/sanitizer.h 189 | webrtc_dsp/rtc_base/scoped_ref_ptr.h 190 | webrtc_dsp/rtc_base/logging.h 191 | webrtc_dsp/rtc_base/logging_mac.h 192 | webrtc_dsp/rtc_base/logging_mac.mm 193 | webrtc_dsp/rtc_base/timeutils.h 194 | webrtc_dsp/rtc_base/atomicops.h 195 | webrtc_dsp/rtc_base/stringencode.cc 196 | webrtc_dsp/rtc_base/stringutils.cc 197 | webrtc_dsp/rtc_base/checks.cc 198 | webrtc_dsp/rtc_base/numerics/safe_minmax.h 199 | webrtc_dsp/rtc_base/numerics/safe_conversions.h 200 | webrtc_dsp/rtc_base/numerics/safe_conversions_impl.h 201 | webrtc_dsp/rtc_base/numerics/safe_compare.h 202 | webrtc_dsp/rtc_base/system/unused.h 203 | webrtc_dsp/rtc_base/system/inline.h 204 | webrtc_dsp/rtc_base/system/ignore_warnings.h 205 | webrtc_dsp/rtc_base/system/asm_defines.h 206 | webrtc_dsp/rtc_base/system/rtc_export.h 207 | webrtc_dsp/rtc_base/system/arch.h 208 | webrtc_dsp/rtc_base/platform_thread.cc 209 | webrtc_dsp/rtc_base/platform_thread.h 210 | webrtc_dsp/rtc_base/platform_thread_types.h 211 | webrtc_dsp/rtc_base/protobuf_utils.h 212 | webrtc_dsp/rtc_base/thread_annotations.h 213 | webrtc_dsp/rtc_base/gtest_prod_util.h 214 | webrtc_dsp/rtc_base/function_view.h 215 | webrtc_dsp/rtc_base/criticalsection.h 216 | webrtc_dsp/rtc_base/criticalsection.cc 217 | webrtc_dsp/rtc_base/platform_thread_types.cc 218 | webrtc_dsp/rtc_base/refcount.h 219 | webrtc_dsp/rtc_base/event.cc 220 | webrtc_dsp/rtc_base/thread_checker_impl.h 221 | webrtc_dsp/rtc_base/event_tracer.cc 222 | webrtc_dsp/rtc_base/compile_assert_c.h 223 | webrtc_dsp/rtc_base/logging_webrtc.cc 224 | webrtc_dsp/rtc_base/type_traits.h 225 | webrtc_dsp/rtc_base/platform_file.h 226 | webrtc_dsp/rtc_base/refcounter.h 227 | webrtc_dsp/rtc_base/logging_mac.h 228 | webrtc_dsp/rtc_base/thread_checker.h 229 | webrtc_dsp/rtc_base/race_checker.h 230 | webrtc_dsp/rtc_base/refcountedobject.h 231 | webrtc_dsp/third_party/rnnoise/src/rnn_vad_weights.cc 232 | webrtc_dsp/third_party/rnnoise/src/rnn_activations.h 233 | webrtc_dsp/third_party/rnnoise/src/kiss_fft.h 234 | webrtc_dsp/third_party/rnnoise/src/kiss_fft.cc 235 | webrtc_dsp/third_party/rnnoise/src/rnn_vad_weights.h 236 | webrtc_dsp/api/audio/audio_frame.cc 237 | webrtc_dsp/api/audio/echo_canceller3_config.h 238 | webrtc_dsp/api/audio/echo_control.h 239 | webrtc_dsp/api/audio/audio_frame.h 240 | webrtc_dsp/api/audio/echo_canceller3_config.cc 241 | webrtc_dsp/api/audio/echo_canceller3_factory.h 242 | webrtc_dsp/api/audio/echo_canceller3_factory.cc 243 | webrtc_dsp/api/array_view.h 244 | webrtc_dsp/modules/third_party/fft/fft.h 245 | webrtc_dsp/modules/third_party/fft/fft.c 246 | webrtc_dsp/modules/audio_coding/codecs/isac/bandwidth_info.h 247 | webrtc_dsp/modules/audio_coding/codecs/isac/main/include/isac.h 248 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c 249 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c 250 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c 251 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c 252 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h 253 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filterbanks.c 254 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/entropy_coding.h 255 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_vad.h 256 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/settings.h 257 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/transform.c 258 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h 259 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines.h 260 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/crc.h 261 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_filter.c 262 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c 263 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filter_functions.c 264 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode.c 265 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lattice.c 266 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/intialize.c 267 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_tables.c 268 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c 269 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c 270 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_float_type.h 271 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h 272 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode.c 273 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c 274 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h 275 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c 276 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/codec.h 277 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h 278 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h 279 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h 280 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/entropy_coding.c 281 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_vad.c 282 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/structs.h 283 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filter_functions.h 284 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h 285 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_filter.h 286 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines.c 287 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/crc.c 288 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c 289 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h 290 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode_bwe.c 291 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c 292 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h 293 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c 294 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac.c 295 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h 296 | webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_tables.h 297 | webrtc_dsp/modules/audio_processing/rms_level.cc 298 | webrtc_dsp/modules/audio_processing/echo_detector/moving_max.h 299 | webrtc_dsp/modules/audio_processing/echo_detector/circular_buffer.h 300 | webrtc_dsp/modules/audio_processing/echo_detector/normalized_covariance_estimator.h 301 | webrtc_dsp/modules/audio_processing/echo_detector/normalized_covariance_estimator.cc 302 | webrtc_dsp/modules/audio_processing/echo_detector/moving_max.cc 303 | webrtc_dsp/modules/audio_processing/echo_detector/circular_buffer.cc 304 | webrtc_dsp/modules/audio_processing/echo_detector/mean_variance_estimator.cc 305 | webrtc_dsp/modules/audio_processing/echo_detector/mean_variance_estimator.h 306 | webrtc_dsp/modules/audio_processing/gain_control_for_experimental_agc.h 307 | webrtc_dsp/modules/audio_processing/splitting_filter.cc 308 | webrtc_dsp/modules/audio_processing/gain_control_impl.cc 309 | webrtc_dsp/modules/audio_processing/rms_level.h 310 | webrtc_dsp/modules/audio_processing/ns/ns_core.h 311 | webrtc_dsp/modules/audio_processing/ns/nsx_core.c 312 | webrtc_dsp/modules/audio_processing/ns/noise_suppression_x.c 313 | webrtc_dsp/modules/audio_processing/ns/nsx_core_c.c 314 | webrtc_dsp/modules/audio_processing/ns/defines.h 315 | webrtc_dsp/modules/audio_processing/ns/noise_suppression.h 316 | webrtc_dsp/modules/audio_processing/ns/ns_core.c 317 | webrtc_dsp/modules/audio_processing/ns/nsx_core.h 318 | webrtc_dsp/modules/audio_processing/ns/windows_private.h 319 | webrtc_dsp/modules/audio_processing/ns/noise_suppression_x.h 320 | webrtc_dsp/modules/audio_processing/ns/noise_suppression.c 321 | webrtc_dsp/modules/audio_processing/ns/nsx_defines.h 322 | webrtc_dsp/modules/audio_processing/residual_echo_detector.h 323 | webrtc_dsp/modules/audio_processing/audio_processing_impl.h 324 | webrtc_dsp/modules/audio_processing/audio_buffer.cc 325 | webrtc_dsp/modules/audio_processing/typing_detection.cc 326 | webrtc_dsp/modules/audio_processing/render_queue_item_verifier.h 327 | webrtc_dsp/modules/audio_processing/include/audio_generator.h 328 | webrtc_dsp/modules/audio_processing/include/config.h 329 | webrtc_dsp/modules/audio_processing/include/audio_frame_view.h 330 | webrtc_dsp/modules/audio_processing/include/mock_audio_processing.h 331 | webrtc_dsp/modules/audio_processing/include/gain_control.h 332 | webrtc_dsp/modules/audio_processing/include/audio_generator_factory.h 333 | webrtc_dsp/modules/audio_processing/include/audio_processing_statistics.cc 334 | webrtc_dsp/modules/audio_processing/include/audio_generator_factory.cc 335 | webrtc_dsp/modules/audio_processing/include/aec_dump.cc 336 | webrtc_dsp/modules/audio_processing/include/aec_dump.h 337 | webrtc_dsp/modules/audio_processing/include/audio_processing_statistics.h 338 | webrtc_dsp/modules/audio_processing/include/audio_processing.h 339 | webrtc_dsp/modules/audio_processing/include/audio_processing.cc 340 | webrtc_dsp/modules/audio_processing/include/config.cc 341 | webrtc_dsp/modules/audio_processing/agc2/interpolated_gain_curve.h 342 | webrtc_dsp/modules/audio_processing/agc2/biquad_filter.h 343 | webrtc_dsp/modules/audio_processing/agc2/interpolated_gain_curve.cc 344 | webrtc_dsp/modules/audio_processing/agc2/agc2_common.cc 345 | webrtc_dsp/modules/audio_processing/agc2/agc2_testing_common.h 346 | webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator.h 347 | webrtc_dsp/modules/audio_processing/agc2/gain_applier.cc 348 | webrtc_dsp/modules/audio_processing/agc2/signal_classifier.h 349 | webrtc_dsp/modules/audio_processing/agc2/adaptive_agc.cc 350 | webrtc_dsp/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc 351 | webrtc_dsp/modules/audio_processing/agc2/limiter.cc 352 | webrtc_dsp/modules/audio_processing/agc2/saturation_protector.cc 353 | webrtc_dsp/modules/audio_processing/agc2/vector_float_frame.h 354 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features_internal.cc 355 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/sequence_buffer.h 356 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/rnn.h 357 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/rnn.cc 358 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/test_utils.h 359 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_info.h 360 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/lp_residual.h 361 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/ring_buffer.h 362 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc 363 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer.h 364 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features.h 365 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/features_extraction.h 366 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/common.h 367 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features_internal.h 368 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/fft_util.h 369 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features.cc 370 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h 371 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search.cc 372 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search.h 373 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/features_extraction.cc 374 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/fft_util.cc 375 | webrtc_dsp/modules/audio_processing/agc2/rnn_vad/lp_residual.cc 376 | webrtc_dsp/modules/audio_processing/agc2/fixed_gain_controller.h 377 | webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator_agc.cc 378 | webrtc_dsp/modules/audio_processing/agc2/vector_float_frame.cc 379 | webrtc_dsp/modules/audio_processing/agc2/down_sampler.h 380 | webrtc_dsp/modules/audio_processing/agc2/noise_level_estimator.cc 381 | webrtc_dsp/modules/audio_processing/agc2/agc2_testing_common.cc 382 | webrtc_dsp/modules/audio_processing/agc2/fixed_digital_level_estimator.cc 383 | webrtc_dsp/modules/audio_processing/agc2/fixed_gain_controller.cc 384 | webrtc_dsp/modules/audio_processing/agc2/saturation_protector.h 385 | webrtc_dsp/modules/audio_processing/agc2/vad_with_level.cc 386 | webrtc_dsp/modules/audio_processing/agc2/limiter_db_gain_curve.cc 387 | webrtc_dsp/modules/audio_processing/agc2/agc2_common.h 388 | webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator_agc.h 389 | webrtc_dsp/modules/audio_processing/agc2/adaptive_digital_gain_applier.h 390 | webrtc_dsp/modules/audio_processing/agc2/vad_with_level.h 391 | webrtc_dsp/modules/audio_processing/agc2/limiter_db_gain_curve.h 392 | webrtc_dsp/modules/audio_processing/agc2/fixed_digital_level_estimator.h 393 | webrtc_dsp/modules/audio_processing/agc2/adaptive_agc.h 394 | webrtc_dsp/modules/audio_processing/agc2/gain_applier.h 395 | webrtc_dsp/modules/audio_processing/agc2/down_sampler.cc 396 | webrtc_dsp/modules/audio_processing/agc2/noise_level_estimator.h 397 | webrtc_dsp/modules/audio_processing/agc2/signal_classifier.cc 398 | webrtc_dsp/modules/audio_processing/agc2/noise_spectrum_estimator.cc 399 | webrtc_dsp/modules/audio_processing/agc2/compute_interpolated_gain_curve.cc 400 | webrtc_dsp/modules/audio_processing/agc2/compute_interpolated_gain_curve.h 401 | webrtc_dsp/modules/audio_processing/agc2/biquad_filter.cc 402 | webrtc_dsp/modules/audio_processing/agc2/noise_spectrum_estimator.h 403 | webrtc_dsp/modules/audio_processing/agc2/limiter.h 404 | webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator.cc 405 | webrtc_dsp/modules/audio_processing/transient/moving_moments.cc 406 | webrtc_dsp/modules/audio_processing/transient/transient_detector.h 407 | webrtc_dsp/modules/audio_processing/transient/wpd_tree.cc 408 | webrtc_dsp/modules/audio_processing/transient/transient_suppressor.h 409 | webrtc_dsp/modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h 410 | webrtc_dsp/modules/audio_processing/transient/common.h 411 | webrtc_dsp/modules/audio_processing/transient/wpd_node.h 412 | webrtc_dsp/modules/audio_processing/transient/moving_moments.h 413 | webrtc_dsp/modules/audio_processing/transient/wpd_tree.h 414 | webrtc_dsp/modules/audio_processing/transient/wpd_node.cc 415 | webrtc_dsp/modules/audio_processing/transient/transient_suppressor.cc 416 | webrtc_dsp/modules/audio_processing/transient/transient_detector.cc 417 | webrtc_dsp/modules/audio_processing/transient/dyadic_decimator.h 418 | webrtc_dsp/modules/audio_processing/low_cut_filter.cc 419 | webrtc_dsp/modules/audio_processing/noise_suppression_impl.h 420 | webrtc_dsp/modules/audio_processing/level_estimator_impl.cc 421 | webrtc_dsp/modules/audio_processing/three_band_filter_bank.cc 422 | webrtc_dsp/modules/audio_processing/aec/echo_cancellation.cc 423 | webrtc_dsp/modules/audio_processing/aec/aec_resampler.h 424 | webrtc_dsp/modules/audio_processing/aec/aec_resampler.cc 425 | webrtc_dsp/modules/audio_processing/aec/echo_cancellation.h 426 | webrtc_dsp/modules/audio_processing/aec/aec_core.cc 427 | webrtc_dsp/modules/audio_processing/aec/aec_core.h 428 | webrtc_dsp/modules/audio_processing/aec/aec_core_optimized_methods.h 429 | webrtc_dsp/modules/audio_processing/aec/aec_core_sse2.cc 430 | webrtc_dsp/modules/audio_processing/aec/aec_common.h 431 | webrtc_dsp/modules/audio_processing/voice_detection_impl.h 432 | webrtc_dsp/modules/audio_processing/voice_detection_impl.cc 433 | webrtc_dsp/modules/audio_processing/echo_cancellation_impl.cc 434 | webrtc_dsp/modules/audio_processing/gain_control_for_experimental_agc.cc 435 | webrtc_dsp/modules/audio_processing/agc/agc.cc 436 | webrtc_dsp/modules/audio_processing/agc/loudness_histogram.cc 437 | webrtc_dsp/modules/audio_processing/agc/agc_manager_direct.cc 438 | webrtc_dsp/modules/audio_processing/agc/legacy/analog_agc.h 439 | webrtc_dsp/modules/audio_processing/agc/legacy/gain_control.h 440 | webrtc_dsp/modules/audio_processing/agc/legacy/digital_agc.h 441 | webrtc_dsp/modules/audio_processing/agc/legacy/analog_agc.c 442 | webrtc_dsp/modules/audio_processing/agc/legacy/digital_agc.c 443 | webrtc_dsp/modules/audio_processing/agc/utility.cc 444 | webrtc_dsp/modules/audio_processing/agc/mock_agc.h 445 | webrtc_dsp/modules/audio_processing/agc/loudness_histogram.h 446 | webrtc_dsp/modules/audio_processing/agc/gain_map_internal.h 447 | webrtc_dsp/modules/audio_processing/agc/utility.h 448 | webrtc_dsp/modules/audio_processing/agc/agc_manager_direct.h 449 | webrtc_dsp/modules/audio_processing/agc/agc.h 450 | webrtc_dsp/modules/audio_processing/common.h 451 | webrtc_dsp/modules/audio_processing/audio_processing_impl.cc 452 | webrtc_dsp/modules/audio_processing/audio_buffer.h 453 | webrtc_dsp/modules/audio_processing/echo_control_mobile_impl.h 454 | webrtc_dsp/modules/audio_processing/splitting_filter.h 455 | webrtc_dsp/modules/audio_processing/low_cut_filter.h 456 | webrtc_dsp/modules/audio_processing/audio_generator/file_audio_generator.h 457 | webrtc_dsp/modules/audio_processing/audio_generator/file_audio_generator.cc 458 | webrtc_dsp/modules/audio_processing/gain_controller2.cc 459 | webrtc_dsp/modules/audio_processing/three_band_filter_bank.h 460 | webrtc_dsp/modules/audio_processing/residual_echo_detector.cc 461 | webrtc_dsp/modules/audio_processing/echo_cancellation_impl.h 462 | webrtc_dsp/modules/audio_processing/noise_suppression_impl.cc 463 | webrtc_dsp/modules/audio_processing/level_estimator_impl.h 464 | webrtc_dsp/modules/audio_processing/gain_controller2.h 465 | webrtc_dsp/modules/audio_processing/aecm/aecm_core.h 466 | webrtc_dsp/modules/audio_processing/aecm/aecm_defines.h 467 | webrtc_dsp/modules/audio_processing/aecm/aecm_core.cc 468 | webrtc_dsp/modules/audio_processing/aecm/aecm_core_c.cc 469 | webrtc_dsp/modules/audio_processing/aecm/echo_control_mobile.h 470 | webrtc_dsp/modules/audio_processing/aecm/echo_control_mobile.cc 471 | webrtc_dsp/modules/audio_processing/aec3/render_reverb_model.cc 472 | webrtc_dsp/modules/audio_processing/aec3/downsampled_render_buffer.h 473 | webrtc_dsp/modules/audio_processing/aec3/subtractor_output_analyzer.h 474 | webrtc_dsp/modules/audio_processing/aec3/reverb_model_fallback.cc 475 | webrtc_dsp/modules/audio_processing/aec3/residual_echo_estimator.h 476 | webrtc_dsp/modules/audio_processing/aec3/shadow_filter_update_gain.h 477 | webrtc_dsp/modules/audio_processing/aec3/echo_remover_metrics.cc 478 | webrtc_dsp/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc 479 | webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer2.cc 480 | webrtc_dsp/modules/audio_processing/aec3/aec_state.h 481 | webrtc_dsp/modules/audio_processing/aec3/suppression_filter.h 482 | webrtc_dsp/modules/audio_processing/aec3/echo_path_variability.cc 483 | webrtc_dsp/modules/audio_processing/aec3/frame_blocker.cc 484 | webrtc_dsp/modules/audio_processing/aec3/subtractor.cc 485 | webrtc_dsp/modules/audio_processing/aec3/block_delay_buffer.h 486 | webrtc_dsp/modules/audio_processing/aec3/adaptive_fir_filter.h 487 | webrtc_dsp/modules/audio_processing/aec3/cascaded_biquad_filter.h 488 | webrtc_dsp/modules/audio_processing/aec3/matched_filter.h 489 | webrtc_dsp/modules/audio_processing/aec3/subtractor_output.h 490 | webrtc_dsp/modules/audio_processing/aec3/render_signal_analyzer.h 491 | webrtc_dsp/modules/audio_processing/aec3/aec3_fft.cc 492 | webrtc_dsp/modules/audio_processing/aec3/aec3_fft.h 493 | webrtc_dsp/modules/audio_processing/aec3/echo_remover_metrics.h 494 | webrtc_dsp/modules/audio_processing/aec3/fullband_erle_estimator.cc 495 | webrtc_dsp/modules/audio_processing/aec3/suppression_filter.cc 496 | webrtc_dsp/modules/audio_processing/aec3/block_processor.cc 497 | webrtc_dsp/modules/audio_processing/aec3/filter_analyzer.h 498 | webrtc_dsp/modules/audio_processing/aec3/subtractor.h 499 | webrtc_dsp/modules/audio_processing/aec3/echo_path_delay_estimator.h 500 | webrtc_dsp/modules/audio_processing/aec3/subband_erle_estimator.cc 501 | webrtc_dsp/modules/audio_processing/aec3/render_delay_controller_metrics.cc 502 | webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer.cc 503 | webrtc_dsp/modules/audio_processing/aec3/block_processor_metrics.h 504 | webrtc_dsp/modules/audio_processing/aec3/vector_buffer.cc 505 | webrtc_dsp/modules/audio_processing/aec3/erl_estimator.cc 506 | webrtc_dsp/modules/audio_processing/aec3/aec_state.cc 507 | webrtc_dsp/modules/audio_processing/aec3/adaptive_fir_filter.cc 508 | webrtc_dsp/modules/audio_processing/aec3/fft_data.h 509 | webrtc_dsp/modules/audio_processing/aec3/render_delay_controller.cc 510 | webrtc_dsp/modules/audio_processing/aec3/skew_estimator.cc 511 | webrtc_dsp/modules/audio_processing/aec3/render_delay_controller_metrics.h 512 | webrtc_dsp/modules/audio_processing/aec3/comfort_noise_generator.h 513 | webrtc_dsp/modules/audio_processing/aec3/echo_path_delay_estimator.cc 514 | webrtc_dsp/modules/audio_processing/aec3/erl_estimator.h 515 | webrtc_dsp/modules/audio_processing/aec3/echo_remover.h 516 | webrtc_dsp/modules/audio_processing/aec3/block_framer.cc 517 | webrtc_dsp/modules/audio_processing/aec3/erle_estimator.cc 518 | webrtc_dsp/modules/audio_processing/aec3/reverb_model.cc 519 | webrtc_dsp/modules/audio_processing/aec3/cascaded_biquad_filter.cc 520 | webrtc_dsp/modules/audio_processing/aec3/matrix_buffer.h 521 | webrtc_dsp/modules/audio_processing/aec3/render_buffer.cc 522 | webrtc_dsp/modules/audio_processing/aec3/reverb_model_estimator.h 523 | webrtc_dsp/modules/audio_processing/aec3/subtractor_output.cc 524 | webrtc_dsp/modules/audio_processing/aec3/stationarity_estimator.cc 525 | webrtc_dsp/modules/audio_processing/aec3/render_signal_analyzer.cc 526 | webrtc_dsp/modules/audio_processing/aec3/echo_path_variability.h 527 | webrtc_dsp/modules/audio_processing/aec3/moving_average.h 528 | webrtc_dsp/modules/audio_processing/aec3/render_reverb_model.h 529 | webrtc_dsp/modules/audio_processing/aec3/subtractor_output_analyzer.cc 530 | webrtc_dsp/modules/audio_processing/aec3/suppression_gain.cc 531 | webrtc_dsp/modules/audio_processing/aec3/echo_audibility.cc 532 | webrtc_dsp/modules/audio_processing/aec3/block_processor_metrics.cc 533 | webrtc_dsp/modules/audio_processing/aec3/render_delay_controller.h 534 | webrtc_dsp/modules/audio_processing/aec3/suppression_gain.h 535 | webrtc_dsp/modules/audio_processing/aec3/moving_average.cc 536 | webrtc_dsp/modules/audio_processing/aec3/erle_estimator.h 537 | webrtc_dsp/modules/audio_processing/aec3/subband_erle_estimator.h 538 | webrtc_dsp/modules/audio_processing/aec3/reverb_model_estimator.cc 539 | webrtc_dsp/modules/audio_processing/aec3/aec3_common.cc 540 | webrtc_dsp/modules/audio_processing/aec3/residual_echo_estimator.cc 541 | webrtc_dsp/modules/audio_processing/aec3/block_processor.h 542 | webrtc_dsp/modules/audio_processing/aec3/fullband_erle_estimator.h 543 | webrtc_dsp/modules/audio_processing/aec3/matched_filter.cc 544 | webrtc_dsp/modules/audio_processing/aec3/stationarity_estimator.h 545 | webrtc_dsp/modules/audio_processing/aec3/echo_canceller3.h 546 | webrtc_dsp/modules/audio_processing/aec3/skew_estimator.h 547 | webrtc_dsp/modules/audio_processing/aec3/reverb_decay_estimator.cc 548 | webrtc_dsp/modules/audio_processing/aec3/render_delay_controller2.cc 549 | webrtc_dsp/modules/audio_processing/aec3/render_buffer.h 550 | webrtc_dsp/modules/audio_processing/aec3/suppression_gain_limiter.cc 551 | webrtc_dsp/modules/audio_processing/aec3/main_filter_update_gain.cc 552 | webrtc_dsp/modules/audio_processing/aec3/echo_remover.cc 553 | webrtc_dsp/modules/audio_processing/aec3/reverb_model_fallback.h 554 | webrtc_dsp/modules/audio_processing/aec3/downsampled_render_buffer.cc 555 | webrtc_dsp/modules/audio_processing/aec3/vector_buffer.h 556 | webrtc_dsp/modules/audio_processing/aec3/matrix_buffer.cc 557 | webrtc_dsp/modules/audio_processing/aec3/reverb_frequency_response.h 558 | webrtc_dsp/modules/audio_processing/aec3/echo_audibility.h 559 | webrtc_dsp/modules/audio_processing/aec3/fft_buffer.h 560 | webrtc_dsp/modules/audio_processing/aec3/block_processor2.cc 561 | webrtc_dsp/modules/audio_processing/aec3/echo_canceller3.cc 562 | webrtc_dsp/modules/audio_processing/aec3/block_delay_buffer.cc 563 | webrtc_dsp/modules/audio_processing/aec3/aec3_common.h 564 | webrtc_dsp/modules/audio_processing/aec3/fft_buffer.cc 565 | webrtc_dsp/modules/audio_processing/aec3/vector_math.h 566 | webrtc_dsp/modules/audio_processing/aec3/decimator.h 567 | webrtc_dsp/modules/audio_processing/aec3/frame_blocker.h 568 | webrtc_dsp/modules/audio_processing/aec3/block_framer.h 569 | webrtc_dsp/modules/audio_processing/aec3/suppression_gain_limiter.h 570 | webrtc_dsp/modules/audio_processing/aec3/delay_estimate.h 571 | webrtc_dsp/modules/audio_processing/aec3/comfort_noise_generator.cc 572 | webrtc_dsp/modules/audio_processing/aec3/reverb_model.h 573 | webrtc_dsp/modules/audio_processing/aec3/main_filter_update_gain.h 574 | webrtc_dsp/modules/audio_processing/aec3/matched_filter_lag_aggregator.h 575 | webrtc_dsp/modules/audio_processing/aec3/shadow_filter_update_gain.cc 576 | webrtc_dsp/modules/audio_processing/aec3/filter_analyzer.cc 577 | webrtc_dsp/modules/audio_processing/aec3/reverb_decay_estimator.h 578 | webrtc_dsp/modules/audio_processing/aec3/reverb_frequency_response.cc 579 | webrtc_dsp/modules/audio_processing/aec3/decimator.cc 580 | webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer.h 581 | webrtc_dsp/modules/audio_processing/echo_control_mobile_impl.cc 582 | webrtc_dsp/modules/audio_processing/gain_control_impl.h 583 | webrtc_dsp/modules/audio_processing/typing_detection.h 584 | webrtc_dsp/modules/audio_processing/logging/apm_data_dumper.cc 585 | webrtc_dsp/modules/audio_processing/logging/apm_data_dumper.h 586 | webrtc_dsp/modules/audio_processing/vad/voice_activity_detector.cc 587 | webrtc_dsp/modules/audio_processing/vad/standalone_vad.cc 588 | webrtc_dsp/modules/audio_processing/vad/vad_audio_proc_internal.h 589 | webrtc_dsp/modules/audio_processing/vad/pitch_internal.cc 590 | webrtc_dsp/modules/audio_processing/vad/vad_circular_buffer.cc 591 | webrtc_dsp/modules/audio_processing/vad/vad_circular_buffer.h 592 | webrtc_dsp/modules/audio_processing/vad/pitch_based_vad.h 593 | webrtc_dsp/modules/audio_processing/vad/vad_audio_proc.cc 594 | webrtc_dsp/modules/audio_processing/vad/pole_zero_filter.cc 595 | webrtc_dsp/modules/audio_processing/vad/pole_zero_filter.h 596 | webrtc_dsp/modules/audio_processing/vad/pitch_based_vad.cc 597 | webrtc_dsp/modules/audio_processing/vad/gmm.h 598 | webrtc_dsp/modules/audio_processing/vad/common.h 599 | webrtc_dsp/modules/audio_processing/vad/vad_audio_proc.h 600 | webrtc_dsp/modules/audio_processing/vad/voice_gmm_tables.h 601 | webrtc_dsp/modules/audio_processing/vad/noise_gmm_tables.h 602 | webrtc_dsp/modules/audio_processing/vad/pitch_internal.h 603 | webrtc_dsp/modules/audio_processing/vad/gmm.cc 604 | webrtc_dsp/modules/audio_processing/vad/standalone_vad.h 605 | webrtc_dsp/modules/audio_processing/vad/voice_activity_detector.h 606 | webrtc_dsp/modules/audio_processing/utility/delay_estimator_internal.h 607 | webrtc_dsp/modules/audio_processing/utility/ooura_fft.cc 608 | webrtc_dsp/modules/audio_processing/utility/ooura_fft.h 609 | webrtc_dsp/modules/audio_processing/utility/delay_estimator_wrapper.cc 610 | webrtc_dsp/modules/audio_processing/utility/ooura_fft_sse2.cc 611 | webrtc_dsp/modules/audio_processing/utility/delay_estimator.cc 612 | webrtc_dsp/modules/audio_processing/utility/block_mean_calculator.h 613 | webrtc_dsp/modules/audio_processing/utility/block_mean_calculator.cc 614 | webrtc_dsp/modules/audio_processing/utility/delay_estimator.h 615 | webrtc_dsp/modules/audio_processing/utility/ooura_fft_tables_common.h 616 | webrtc_dsp/modules/audio_processing/utility/delay_estimator_wrapper.h 617 | webrtc_dsp/common_audio/mocks/mock_smoothing_filter.h 618 | webrtc_dsp/common_audio/wav_file.h 619 | webrtc_dsp/common_audio/window_generator.cc 620 | webrtc_dsp/common_audio/channel_buffer.cc 621 | webrtc_dsp/common_audio/fir_filter_factory.cc 622 | webrtc_dsp/common_audio/sparse_fir_filter.h 623 | webrtc_dsp/common_audio/fir_filter_sse.h 624 | webrtc_dsp/common_audio/window_generator.h 625 | webrtc_dsp/common_audio/ring_buffer.h 626 | webrtc_dsp/common_audio/fir_filter.h 627 | webrtc_dsp/common_audio/include/audio_util.h 628 | webrtc_dsp/common_audio/wav_header.cc 629 | webrtc_dsp/common_audio/real_fourier_ooura.cc 630 | webrtc_dsp/common_audio/audio_util.cc 631 | webrtc_dsp/common_audio/real_fourier_ooura.h 632 | webrtc_dsp/common_audio/fir_filter_sse.cc 633 | webrtc_dsp/common_audio/smoothing_filter.h 634 | webrtc_dsp/common_audio/resampler/push_sinc_resampler.cc 635 | webrtc_dsp/common_audio/resampler/sinc_resampler.h 636 | webrtc_dsp/common_audio/resampler/resampler.cc 637 | webrtc_dsp/common_audio/resampler/sinc_resampler_sse.cc 638 | webrtc_dsp/common_audio/resampler/include/push_resampler.h 639 | webrtc_dsp/common_audio/resampler/include/resampler.h 640 | webrtc_dsp/common_audio/resampler/push_sinc_resampler.h 641 | webrtc_dsp/common_audio/resampler/push_resampler.cc 642 | webrtc_dsp/common_audio/resampler/sinusoidal_linear_chirp_source.h 643 | webrtc_dsp/common_audio/resampler/sinc_resampler.cc 644 | webrtc_dsp/common_audio/resampler/sinusoidal_linear_chirp_source.cc 645 | webrtc_dsp/common_audio/fir_filter_factory.h 646 | webrtc_dsp/common_audio/audio_converter.h 647 | webrtc_dsp/common_audio/wav_file.cc 648 | webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c 649 | webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h 650 | webrtc_dsp/common_audio/third_party/fft4g/fft4g.c 651 | webrtc_dsp/common_audio/third_party/fft4g/fft4g.h 652 | webrtc_dsp/common_audio/audio_converter.cc 653 | webrtc_dsp/common_audio/real_fourier.cc 654 | webrtc_dsp/common_audio/channel_buffer.h 655 | webrtc_dsp/common_audio/real_fourier.h 656 | webrtc_dsp/common_audio/sparse_fir_filter.cc 657 | webrtc_dsp/common_audio/smoothing_filter.cc 658 | webrtc_dsp/common_audio/fir_filter_c.cc 659 | webrtc_dsp/common_audio/ring_buffer.c 660 | webrtc_dsp/common_audio/fir_filter_c.h 661 | webrtc_dsp/common_audio/signal_processing/complex_fft_tables.h 662 | webrtc_dsp/common_audio/signal_processing/complex_fft.c 663 | webrtc_dsp/common_audio/signal_processing/filter_ma_fast_q12.c 664 | webrtc_dsp/common_audio/signal_processing/levinson_durbin.c 665 | webrtc_dsp/common_audio/signal_processing/dot_product_with_scale.cc 666 | webrtc_dsp/common_audio/signal_processing/auto_corr_to_refl_coef.c 667 | webrtc_dsp/common_audio/signal_processing/resample_by_2_internal.c 668 | webrtc_dsp/common_audio/signal_processing/energy.c 669 | webrtc_dsp/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c 670 | webrtc_dsp/common_audio/signal_processing/downsample_fast.c 671 | webrtc_dsp/common_audio/signal_processing/splitting_filter1.c 672 | webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12.c 673 | webrtc_dsp/common_audio/signal_processing/spl_init.c 674 | webrtc_dsp/common_audio/signal_processing/lpc_to_refl_coef.c 675 | webrtc_dsp/common_audio/signal_processing/cross_correlation.c 676 | webrtc_dsp/common_audio/signal_processing/include/signal_processing_library.h 677 | webrtc_dsp/common_audio/signal_processing/include/real_fft.h 678 | webrtc_dsp/common_audio/signal_processing/include/spl_inl.h 679 | webrtc_dsp/common_audio/signal_processing/division_operations.c 680 | webrtc_dsp/common_audio/signal_processing/auto_correlation.c 681 | webrtc_dsp/common_audio/signal_processing/get_scaling_square.c 682 | webrtc_dsp/common_audio/signal_processing/dot_product_with_scale.h 683 | webrtc_dsp/common_audio/signal_processing/resample_by_2_internal.h 684 | webrtc_dsp/common_audio/signal_processing/resample.c 685 | webrtc_dsp/common_audio/signal_processing/min_max_operations.c 686 | webrtc_dsp/common_audio/signal_processing/refl_coef_to_lpc.c 687 | webrtc_dsp/common_audio/signal_processing/filter_ar.c 688 | webrtc_dsp/common_audio/signal_processing/vector_scaling_operations.c 689 | webrtc_dsp/common_audio/signal_processing/resample_fractional.c 690 | webrtc_dsp/common_audio/signal_processing/real_fft.c 691 | webrtc_dsp/common_audio/signal_processing/ilbc_specific_functions.c 692 | webrtc_dsp/common_audio/signal_processing/complex_bit_reverse.c 693 | webrtc_dsp/common_audio/signal_processing/randomization_functions.c 694 | webrtc_dsp/common_audio/signal_processing/copy_set_operations.c 695 | webrtc_dsp/common_audio/signal_processing/resample_by_2.c 696 | webrtc_dsp/common_audio/signal_processing/get_hanning_window.c 697 | webrtc_dsp/common_audio/signal_processing/resample_48khz.c 698 | webrtc_dsp/common_audio/signal_processing/spl_inl.c 699 | webrtc_dsp/common_audio/signal_processing/spl_sqrt.c 700 | webrtc_dsp/common_audio/wav_header.h 701 | webrtc_dsp/common_audio/vad/vad_sp.c 702 | webrtc_dsp/common_audio/vad/vad.cc 703 | webrtc_dsp/common_audio/vad/webrtc_vad.c 704 | webrtc_dsp/common_audio/vad/vad_core.h 705 | webrtc_dsp/common_audio/vad/include/vad.h 706 | webrtc_dsp/common_audio/vad/include/webrtc_vad.h 707 | webrtc_dsp/common_audio/vad/vad_gmm.h 708 | webrtc_dsp/common_audio/vad/vad_filterbank.c 709 | webrtc_dsp/common_audio/vad/vad_core.c 710 | webrtc_dsp/common_audio/vad/vad_sp.h 711 | webrtc_dsp/common_audio/vad/vad_filterbank.h 712 | webrtc_dsp/common_audio/vad/vad_gmm.c 713 | 714 | # ARM/NEON sources 715 | # TODO check if there's a good way to make these compile with ARM ports of TDesktop 716 | # webrtc_dsp/modules/audio_processing/ns/nsx_core_neon.c 717 | # webrtc_dsp/modules/audio_processing/aec/aec_core_neon.cc 718 | # webrtc_dsp/modules/audio_processing/aecm/aecm_core_neon.cc 719 | # webrtc_dsp/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h 720 | # webrtc_dsp/modules/audio_processing/utility/ooura_fft_neon.cc 721 | # webrtc_dsp/common_audio/fir_filter_neon.cc 722 | # webrtc_dsp/common_audio/resampler/sinc_resampler_neon.cc 723 | # webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S 724 | # webrtc_dsp/common_audio/fir_filter_neon.h 725 | # webrtc_dsp/common_audio/signal_processing/downsample_fast_neon.c 726 | # webrtc_dsp/common_audio/signal_processing/complex_bit_reverse_arm.S 727 | # webrtc_dsp/common_audio/signal_processing/include/spl_inl_armv7.h 728 | # webrtc_dsp/common_audio/signal_processing/min_max_operations_neon.c 729 | # webrtc_dsp/common_audio/signal_processing/cross_correlation_neon.c 730 | # webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12_armv7.S 731 | ) 732 | 733 | target_compile_definitions(lib_tgvoip 734 | PUBLIC 735 | WEBRTC_APM_DEBUG_DUMP=0 736 | TGVOIP_USE_DESKTOP_DSP 737 | WEBRTC_NS_FLOAT 738 | ) 739 | 740 | if (WIN32) 741 | target_compile_options(lib_tgvoip 742 | PRIVATE 743 | /wd4005 744 | /wd4244 # conversion from 'int' to 'float', possible loss of data (several in webrtc) 745 | /wd5055 # operator '>' deprecated between enumerations and floating-point types 746 | ) 747 | target_compile_definitions(lib_tgvoip 748 | PUBLIC 749 | WEBRTC_WIN 750 | ) 751 | elseif (APPLE) 752 | target_compile_definitions(lib_tgvoip 753 | PUBLIC 754 | WEBRTC_POSIX 755 | WEBRTC_MAC 756 | TARGET_OS_OSX 757 | TARGET_OSX 758 | ) 759 | if (build_macstore) 760 | target_compile_definitions(lib_tgvoip 761 | PUBLIC 762 | TGVOIP_NO_OSX_PRIVATE_API 763 | ) 764 | endif() 765 | else() 766 | target_compile_options(lib_tgvoip 767 | PRIVATE 768 | -Wno-unknown-pragmas 769 | -Wno-error=sequence-point 770 | -Wno-error=unused-result 771 | ) 772 | if (build_linux32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*") 773 | target_compile_options(lib_tgvoip PRIVATE -msse2) 774 | endif() 775 | target_compile_definitions(lib_tgvoip 776 | PUBLIC 777 | WEBRTC_POSIX 778 | WEBRTC_LINUX 779 | ) 780 | endif() 781 | 782 | if (NOT WIN32) 783 | target_compile_definitions(lib_tgvoip PRIVATE TGVOIP_USE_INSTALLED_OPUS) 784 | endif() 785 | 786 | target_include_directories(lib_tgvoip 787 | PUBLIC 788 | ${tgvoip_loc} 789 | PRIVATE 790 | ${tgvoip_loc}/webrtc_dsp 791 | ) 792 | 793 | target_link_libraries(lib_tgvoip 794 | PRIVATE 795 | desktop-app::external_openssl 796 | desktop-app::external_opus 797 | ) 798 | endif() 799 | --------------------------------------------------------------------------------