mirror of
https://github.com/godotengine/webrtc-native.git
synced 2026-01-06 06:09:45 +03:00
Compare commits
54 Commits
0.1
...
history/ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c18112f5d | ||
|
|
c37cc530e7 | ||
|
|
13ab33af36 | ||
|
|
3bdf6cdc13 | ||
|
|
072ba5c1d0 | ||
|
|
7cb6d6c846 | ||
|
|
c0b31562f5 | ||
|
|
69f92fa26c | ||
|
|
d06e536d12 | ||
|
|
68a892d9f3 | ||
|
|
72b337e32c | ||
|
|
eeabf0a844 | ||
|
|
04fbae6ce3 | ||
|
|
ce3f086ec4 | ||
|
|
00ac03c8e7 | ||
|
|
fa5296a4e4 | ||
|
|
189c353264 | ||
|
|
e44c42fde8 | ||
|
|
524fdde8f2 | ||
|
|
673a4c1a1c | ||
|
|
cf98eb2e7a | ||
|
|
7b92ab2a7b | ||
|
|
e120cc7ed6 | ||
|
|
da20ebf397 | ||
|
|
3711ad23f6 | ||
|
|
001be78500 | ||
|
|
416ea27305 | ||
|
|
65bb4cb9ae | ||
|
|
3014c3099f | ||
|
|
c1c7ae5081 | ||
|
|
9e287f7cee | ||
|
|
a374cf4510 | ||
|
|
9ee98ff0e9 | ||
|
|
f26a1d8e83 | ||
|
|
7a62fe467b | ||
|
|
74f2c78db5 | ||
|
|
db6d416eba | ||
|
|
5f9e74f2fb | ||
|
|
bd8e139ccc | ||
|
|
61e45cb083 | ||
|
|
6983019cab | ||
|
|
54cbe83c56 | ||
|
|
20f8f89c2c | ||
|
|
4b22741255 | ||
|
|
5769d8b2de | ||
|
|
423454086e | ||
|
|
599ed98f6c | ||
|
|
f5ebac4519 | ||
|
|
3e64a42b14 | ||
|
|
f2cf2e5340 | ||
|
|
1763d278e0 | ||
|
|
8e46eed9e8 | ||
|
|
6c0831b6c6 | ||
|
|
c30ddd9b22 |
128
.clang-format
Normal file
128
.clang-format
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# Commented out parameters are those with the same value as base LLVM style
|
||||||
|
# We can uncomment them if we want to change their value, or enforce the
|
||||||
|
# chosen value in case the base style changes (last sync: Clang 6.0.1).
|
||||||
|
---
|
||||||
|
### General config, applies to all languages ###
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: DontAlign
|
||||||
|
# AlignConsecutiveAssignments: false
|
||||||
|
# AlignConsecutiveDeclarations: false
|
||||||
|
# AlignEscapedNewlines: Right
|
||||||
|
# AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
# AllowShortBlocksOnASingleLine: false
|
||||||
|
# AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
# AllowShortIfStatementsOnASingleLine: false
|
||||||
|
# AllowShortLoopsOnASingleLine: false
|
||||||
|
# AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
# AlwaysBreakAfterReturnType: None
|
||||||
|
# AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
# AlwaysBreakTemplateDeclarations: false
|
||||||
|
# BinPackArguments: true
|
||||||
|
# BinPackParameters: true
|
||||||
|
# BraceWrapping:
|
||||||
|
# AfterClass: false
|
||||||
|
# AfterControlStatement: false
|
||||||
|
# AfterEnum: false
|
||||||
|
# AfterFunction: false
|
||||||
|
# AfterNamespace: false
|
||||||
|
# AfterObjCDeclaration: false
|
||||||
|
# AfterStruct: false
|
||||||
|
# AfterUnion: false
|
||||||
|
# AfterExternBlock: false
|
||||||
|
# BeforeCatch: false
|
||||||
|
# BeforeElse: false
|
||||||
|
# IndentBraces: false
|
||||||
|
# SplitEmptyFunction: true
|
||||||
|
# SplitEmptyRecord: true
|
||||||
|
# SplitEmptyNamespace: true
|
||||||
|
# BreakBeforeBinaryOperators: None
|
||||||
|
# BreakBeforeBraces: Attach
|
||||||
|
# BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
# BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
# BreakStringLiterals: true
|
||||||
|
ColumnLimit: 0
|
||||||
|
# CommentPragmas: '^ IWYU pragma:'
|
||||||
|
# CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 8
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
# DerivePointerAlignment: false
|
||||||
|
# DisableFormat: false
|
||||||
|
# ExperimentalAutoDetectBinPacking: false
|
||||||
|
# FixNamespaceComments: true
|
||||||
|
# ForEachMacros:
|
||||||
|
# - foreach
|
||||||
|
# - Q_FOREACH
|
||||||
|
# - BOOST_FOREACH
|
||||||
|
# IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '".*"'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 3
|
||||||
|
# IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
# IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
# IndentWrappedFunctionNames: false
|
||||||
|
# JavaScriptQuotes: Leave
|
||||||
|
# JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
# MacroBlockBegin: ''
|
||||||
|
# MacroBlockEnd: ''
|
||||||
|
# MaxEmptyLinesToKeep: 1
|
||||||
|
# NamespaceIndentation: None
|
||||||
|
# PenaltyBreakAssignment: 2
|
||||||
|
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
# PenaltyBreakComment: 300
|
||||||
|
# PenaltyBreakFirstLessLess: 120
|
||||||
|
# PenaltyBreakString: 1000
|
||||||
|
# PenaltyExcessCharacter: 1000000
|
||||||
|
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
# PointerAlignment: Right
|
||||||
|
# RawStringFormats:
|
||||||
|
# - Delimiter: pb
|
||||||
|
# Language: TextProto
|
||||||
|
# BasedOnStyle: google
|
||||||
|
# ReflowComments: true
|
||||||
|
# SortIncludes: true
|
||||||
|
# SortUsingDeclarations: true
|
||||||
|
# SpaceAfterCStyleCast: false
|
||||||
|
# SpaceAfterTemplateKeyword: true
|
||||||
|
# SpaceBeforeAssignmentOperators: true
|
||||||
|
# SpaceBeforeParens: ControlStatements
|
||||||
|
# SpaceInEmptyParentheses: false
|
||||||
|
# SpacesBeforeTrailingComments: 1
|
||||||
|
# SpacesInAngles: false
|
||||||
|
# SpacesInContainerLiterals: true
|
||||||
|
# SpacesInCStyleCastParentheses: false
|
||||||
|
# SpacesInParentheses: false
|
||||||
|
# SpacesInSquareBrackets: false
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Always
|
||||||
|
---
|
||||||
|
### C++ specific config ###
|
||||||
|
Language: Cpp
|
||||||
|
Standard: Cpp11
|
||||||
|
---
|
||||||
|
### ObjC specific config ###
|
||||||
|
Language: ObjC
|
||||||
|
Standard: Cpp11
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
# ObjCSpaceAfterProperty: false
|
||||||
|
# ObjCSpaceBeforeProtocolList: true
|
||||||
|
---
|
||||||
|
### Java specific config ###
|
||||||
|
Language: Java
|
||||||
|
# BreakAfterJavaFieldAnnotations: false
|
||||||
|
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
|
||||||
|
...
|
||||||
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Report a bug in the WebRTC native plugin.
|
||||||
|
body:
|
||||||
|
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
- Write a descriptive issue title above.
|
||||||
|
- Search [open](https://github.com/godotengine/webrtc-native/issues) and [closed](https://github.com/godotengine/webrtc-native/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
|
||||||
|
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Godot version
|
||||||
|
description: >
|
||||||
|
Specify the Git commit hash if using a development or non-official build.
|
||||||
|
If you use a custom build, please test if your issue is reproducible in official builds too.
|
||||||
|
placeholder: 3.3.stable, 4.0.dev (3041becc6)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Plugin version
|
||||||
|
description: >
|
||||||
|
Specify the Git commit hash if using a development or non-official build.
|
||||||
|
If you use a custom build, please test if your issue is reproducible in official builds too.
|
||||||
|
placeholder: 0.3, 0.5, 0.6.dev (072ba5c)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: System information
|
||||||
|
description: |
|
||||||
|
Specify the OS version, and when relevant hardware information.
|
||||||
|
placeholder: Android 10, Fairphone 3+.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Issue description
|
||||||
|
description: |
|
||||||
|
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
|
||||||
|
You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: |
|
||||||
|
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
|
||||||
|
If you include a minimal reproduction project below, you can detail how to use it here.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Minimal reproduction project
|
||||||
|
description: |
|
||||||
|
A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
|
||||||
|
Drag and drop a ZIP archive to upload it.
|
||||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
|
||||||
|
contact_links:
|
||||||
|
- name: Godot proposals
|
||||||
|
url: https://github.com/godotengine/godot-proposals
|
||||||
|
about: Please submit feature proposals about the WebRTC exposed API on the Godot proposals repository, not here.
|
||||||
51
.github/actions/webrtc-download/action.yml
vendored
Normal file
51
.github/actions/webrtc-download/action.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: 'Get WebRTC Library'
|
||||||
|
description: 'Get pre-build statically linked WebRTC library from Faless/webrtc-builds'
|
||||||
|
inputs:
|
||||||
|
repo:
|
||||||
|
description: 'Base repository'
|
||||||
|
required: true
|
||||||
|
default: "godotengine/webrtc-actions"
|
||||||
|
release:
|
||||||
|
description: 'Release tag'
|
||||||
|
required: true
|
||||||
|
default: '4472-33644-92ba70c'
|
||||||
|
webrtc-base-name:
|
||||||
|
description: 'The WebRTC version'
|
||||||
|
required: true
|
||||||
|
default: "webrtc-33644-92ba70c"
|
||||||
|
out-dir:
|
||||||
|
description: 'Directory where to extract the library'
|
||||||
|
required: true
|
||||||
|
default: "webrtc"
|
||||||
|
platform:
|
||||||
|
description: 'Platform to download'
|
||||||
|
required: true
|
||||||
|
archs:
|
||||||
|
description: 'Space separated list of architecture to fetch'
|
||||||
|
required: true
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- shell: bash
|
||||||
|
env:
|
||||||
|
RTC_BASE_URL: https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.release }}/${{ inputs.webrtc-base-name }}
|
||||||
|
run: |
|
||||||
|
cd ${{ inputs.out-dir }}
|
||||||
|
|
||||||
|
libplat=${{ inputs.platform }}
|
||||||
|
if [ "${{ inputs.platform }}" = "windows" ]; then
|
||||||
|
libplat=win
|
||||||
|
elif [ "${{ inputs.platform }}" = "osx" ]; then
|
||||||
|
libplat=mac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for arch in ${{ inputs.archs }}
|
||||||
|
do
|
||||||
|
echo "Downloading ${{ env.RTC_BASE_URL }}-${{ inputs.platform }}-${arch}.tar.gz"
|
||||||
|
curl -L ${{ env.RTC_BASE_URL }}-${libplat}-${arch}.tar.gz -o ${arch}.tar.gz
|
||||||
|
tar -xzf ${arch}.tar.gz
|
||||||
|
done
|
||||||
|
|
||||||
|
mv lib ${{ inputs.platform }}
|
||||||
|
ls -l
|
||||||
|
ls -l *
|
||||||
222
.github/workflows/build_release.yml
vendored
Normal file
222
.github/workflows/build_release.yml
vendored
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
name: 🔧 Build -> Package 📦
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
static-checks:
|
||||||
|
name: 📊 Static Checks (clang-format, black format, file format)
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -qq dos2unix recode clang-format-11
|
||||||
|
sudo update-alternatives --remove-all clang-format
|
||||||
|
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-11 100
|
||||||
|
sudo pip3 install black==20.8b1 pygments
|
||||||
|
|
||||||
|
- name: File formatting checks (file_format.sh)
|
||||||
|
run: |
|
||||||
|
bash ./misc/scripts/file_format.sh
|
||||||
|
|
||||||
|
- name: Style checks via clang-format (clang_format.sh)
|
||||||
|
run: |
|
||||||
|
bash ./misc/scripts/clang_format.sh
|
||||||
|
|
||||||
|
- name: Python style checks via black (black_format.sh)
|
||||||
|
run: |
|
||||||
|
bash ./misc/scripts/black_format.sh
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
name: 🔧 Build
|
||||||
|
needs: static-checks
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
# Android
|
||||||
|
- platform: android
|
||||||
|
arch: 'x86'
|
||||||
|
sconsflags: 'android_arch=x86'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
- platform: android
|
||||||
|
arch: 'x64'
|
||||||
|
sconsflags: 'android_arch=x86_64'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
- platform: android
|
||||||
|
arch: 'arm'
|
||||||
|
sconsflags: 'android_arch=armv7'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
- platform: android
|
||||||
|
arch: 'arm64'
|
||||||
|
sconsflags: 'android_arch=arm64v8'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
|
||||||
|
# iOS
|
||||||
|
- platform: ios
|
||||||
|
arch: 'x64'
|
||||||
|
sconsflags: 'ios_arch=x86_64 ios_simulator=true'
|
||||||
|
os: 'macos-latest'
|
||||||
|
- platform: ios
|
||||||
|
arch: 'arm'
|
||||||
|
sconsflags: 'ios_arch=armv7'
|
||||||
|
os: 'macos-latest'
|
||||||
|
- platform: ios
|
||||||
|
arch: 'arm64'
|
||||||
|
sconsflags: 'ios_arch=arm64'
|
||||||
|
os: 'macos-latest'
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
- platform: linux
|
||||||
|
arch: 'x86'
|
||||||
|
sconsflags: 'bits=32'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
- platform: linux
|
||||||
|
arch: 'x64'
|
||||||
|
sconsflags: 'bits=64'
|
||||||
|
os: 'ubuntu-20.04'
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
- platform: osx
|
||||||
|
arch: 'x64'
|
||||||
|
sconsflags: 'bits=64'
|
||||||
|
os: 'macos-latest'
|
||||||
|
- platform: osx
|
||||||
|
arch: 'arm64'
|
||||||
|
sconsflags: 'bits=64 macos_arch=arm64 macos_sdk_path=/Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk/'
|
||||||
|
os: 'macos-10.15'
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
- platform: windows
|
||||||
|
arch: 'x86'
|
||||||
|
sconsflags: 'bits=32'
|
||||||
|
os: 'windows-latest'
|
||||||
|
msvc_arch: amd64_x86
|
||||||
|
- platform: windows
|
||||||
|
arch: 'x64'
|
||||||
|
sconsflags: 'bits=64'
|
||||||
|
os: 'windows-latest'
|
||||||
|
msvc_arch: amd64
|
||||||
|
|
||||||
|
env:
|
||||||
|
SCONSFLAGS: ${{ matrix.sconsflags }} platform=${{ matrix.platform }} --jobs=2
|
||||||
|
NDK_VERSION: 22b
|
||||||
|
ANDROID_NDK_ROOT: ${{github.workspace}}/android-ndk-r22b
|
||||||
|
MSVC_VARS: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat'
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Cache NDK
|
||||||
|
id: cache-ndk
|
||||||
|
if: ${{ matrix.platform == 'android' }}
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ env.ANDROID_NDK_ROOT }}
|
||||||
|
key: ndk-${{ env.NDK_VERSION }}
|
||||||
|
|
||||||
|
- name: Download NDK
|
||||||
|
if: ${{ matrix.platform == 'android' && steps.cache-ndk.outputs.cache-hit != 'true' }}
|
||||||
|
id: setup-ndk
|
||||||
|
run: |
|
||||||
|
cd ${{ github.workspace }}
|
||||||
|
curl -L https://dl.google.com/android/repository/android-ndk-r${{ env.NDK_VERSION }}-linux-x86_64.zip -o ndk.zip
|
||||||
|
unzip ndk.zip
|
||||||
|
ls
|
||||||
|
|
||||||
|
- name: Setup MSVC build environment for ${{ matrix.msvc_arch }}
|
||||||
|
if: ${{ matrix.platform == 'windows' }}
|
||||||
|
run: "'${{ env.MSVC_VARS }}' ${{ matrix.msvc_arch }}"
|
||||||
|
|
||||||
|
- name: Install Linux build dependencies
|
||||||
|
if: ${{ matrix.platform == 'linux' }}
|
||||||
|
run: |
|
||||||
|
sudo apt-get install build-essential gcc-multilib wget g++-multilib
|
||||||
|
|
||||||
|
- name: Set up Python 3.x
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
architecture: 'x64'
|
||||||
|
|
||||||
|
- name: Configuring Python packages
|
||||||
|
run: |
|
||||||
|
python -c "import sys; print(sys.version)"
|
||||||
|
python -m pip install scons
|
||||||
|
python --version
|
||||||
|
scons --version
|
||||||
|
|
||||||
|
- name: Get WebRTC package for ${{ matrix.platform }} - ${{ matrix.arch }}
|
||||||
|
uses: ./.github/actions/webrtc-download
|
||||||
|
with:
|
||||||
|
platform: ${{ matrix.platform }}
|
||||||
|
archs: ${{ matrix.arch }}
|
||||||
|
|
||||||
|
- name: Fix godot-cpp revision and file names for OSX arm64 build.
|
||||||
|
if: ${{ matrix.platform == 'osx' && matrix.arch == 'arm64' }}
|
||||||
|
run: |
|
||||||
|
cd godot-cpp
|
||||||
|
git checkout e08ecdc28c5409cb5366027227e996c342dcee93
|
||||||
|
rm -rf src/gen/
|
||||||
|
rm -rf include/gen/
|
||||||
|
mkdir bin
|
||||||
|
ln -s libgodot-cpp.osx.debug.64.a bin/libgodot-cpp.osx.debug.arm64.a
|
||||||
|
ln -s libgodot-cpp.osx.release.64.a bin/libgodot-cpp.osx.release.arm64.a
|
||||||
|
|
||||||
|
- name: Compilation ${{ matrix.platform }} - ${{ matrix.arch }} - godot-cpp
|
||||||
|
run: |
|
||||||
|
scons -C godot-cpp target=debug generate_bindings=yes
|
||||||
|
scons -C godot-cpp target=release
|
||||||
|
|
||||||
|
- name: Compilation ${{ matrix.platform }} - ${{ matrix.arch }} - webrtc-native
|
||||||
|
run: |
|
||||||
|
scons target=debug
|
||||||
|
scons target=release
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ github.job }}-${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
|
path: bin/*
|
||||||
|
|
||||||
|
package:
|
||||||
|
name: 📦 Package
|
||||||
|
needs: build
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
|
||||||
|
- name: Package artifacts for release
|
||||||
|
run: |
|
||||||
|
mkdir release
|
||||||
|
cd release
|
||||||
|
for name in webrtc webrtc_debug
|
||||||
|
do
|
||||||
|
mkdir -p ${name}/lib/
|
||||||
|
find ../artifacts -wholename "*/${name}/lib/*" | xargs cp -t ${name}/lib/
|
||||||
|
find ../artifacts -wholename "*/${name}/${name}.tres" | head -n 1 | xargs cp -t ${name}/
|
||||||
|
done
|
||||||
|
|
||||||
|
zip -r godot-webrtc-native-release.zip webrtc
|
||||||
|
zip -r godot-webrtc-native-debug.zip webrtc_debug
|
||||||
|
ls -R
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: godot-webrtc-native-debug.zip
|
||||||
|
path: release/godot-webrtc-native-debug.zip
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: godot-webrtc-native-release.zip
|
||||||
|
path: release/godot-webrtc-native-release.zip
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ bin/*
|
|||||||
*.lib
|
*.lib
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
*.obj
|
*.obj
|
||||||
|
*.swp
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "godot-cpp"]
|
||||||
|
path = godot-cpp
|
||||||
|
url = https://github.com/GodotNativeTools/godot-cpp
|
||||||
71
README.md
71
README.md
@@ -0,0 +1,71 @@
|
|||||||
|
# GDNative WebRTC plugin for Godot
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
| **Download latest binary version** | [**GitHub**](https://github.com/godotengine/webrtc-native/releases) |
|
||||||
|
| --- | --- |
|
||||||
|
|
||||||
|
### Compiling
|
||||||
|
|
||||||
|
Clone this repository with the following command to checkout both [godot-cpp](https://github.com/godotengine/godot-cpp) and [godot-headers](https://github.com/godotengine/godot-headers) dependencies.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone --recurse-submodules https://github.com/godotengine/webrtc-native.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if you wish to use a specific branch, add the -b option to the clone command:
|
||||||
|
```
|
||||||
|
$ git clone --recurse-submodules -b 3.2 https://github.com/godotengine/webrtc-native.git
|
||||||
|
```
|
||||||
|
|
||||||
|
If you already checked out the branch use the following commands to update the dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
Right now our directory structure should look like this:
|
||||||
|
```
|
||||||
|
webrtc-native/
|
||||||
|
├─bin/
|
||||||
|
├─godot-cpp/
|
||||||
|
| └─godot-headers/
|
||||||
|
├─src/
|
||||||
|
└─webrtc/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiling the cpp bindings library
|
||||||
|
First, we need to compile our cpp bindings library:
|
||||||
|
```
|
||||||
|
$ cd godot-cpp
|
||||||
|
$ scons platform=<your platform> generate_bindings=yes
|
||||||
|
$ cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
> Replace `<your platform>` with either `windows`, `linux` or `osx`.
|
||||||
|
|
||||||
|
> Include `use_llvm=yes` for using clang++
|
||||||
|
|
||||||
|
> Include `target=runtime` to build a runtime build (windows only at the moment)
|
||||||
|
|
||||||
|
> Include `target=release` or `target=debug` for release or debug build.
|
||||||
|
|
||||||
|
> The resulting library will be created in `godot-cpp/bin/`, take note of its name as it will be different depending on platform.
|
||||||
|
|
||||||
|
### Building WebRTC
|
||||||
|
|
||||||
|
Building WebRTC is quite a complex task, involves huge downloads and long build times, and produces multiple output libraries that needs to bundled together.
|
||||||
|
|
||||||
|
To make things easier, a set of [GitHub Actions](https://docs.github.com/en/actions) are used to generate the library for this plugin, [available in this repository](https://github.com/godotengine/webrtc-actions).
|
||||||
|
|
||||||
|
Alternatively, [**download the latest pre-compiled libraries**](https://github.com/godotengine/webrtc-actions/releases).
|
||||||
|
|
||||||
|
Extract content of `include` into `webrtc/include` and content of `bin` into `webrtc/<your platform>`
|
||||||
|
|
||||||
|
### Compiling the plugin.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ scons platform=<your platform> target=<your target>
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated library and associated `tres` will be placed in `bin/webrtc/` or `bin/webrtc_debug/` according to the desired target. You simply need to copy that folder to the root folder of your project.
|
||||||
|
|||||||
402
SConstruct
402
SConstruct
@@ -1,79 +1,278 @@
|
|||||||
#!python
|
#!python
|
||||||
|
|
||||||
import os, sys, platform, json
|
import os, sys, platform, json, subprocess
|
||||||
|
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
|
||||||
|
def decode_utf8(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
def decode_utf8(x):
|
||||||
|
return codecs.utf_8_decode(x)[0]
|
||||||
|
|
||||||
|
|
||||||
def add_sources(sources, dirpath, extension):
|
def add_sources(sources, dirpath, extension):
|
||||||
for f in os.listdir(dirpath):
|
for f in os.listdir(dirpath):
|
||||||
if f.endswith('.' + extension):
|
if f.endswith("." + extension):
|
||||||
sources.append(dirpath + '/' + f)
|
sources.append(dirpath + "/" + f)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_gdnative_lib(target, source, env):
|
||||||
|
for t in target:
|
||||||
|
with open(t.srcnode().path, "w") as w:
|
||||||
|
w.write(
|
||||||
|
decode_utf8(source[0].get_contents())
|
||||||
|
.replace("{GDNATIVE_PATH}", os.path.splitext(t.name)[0])
|
||||||
|
.replace("{TARGET}", env["target"])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
env = Environment()
|
env = Environment()
|
||||||
host_platform = platform.system()
|
|
||||||
target_platform = ARGUMENTS.get('p', ARGUMENTS.get('platform', 'linux'))
|
|
||||||
target_arch = ARGUMENTS.get('a', ARGUMENTS.get('arch', '64'))
|
|
||||||
# default to debug build, must be same setting as used for cpp_bindings
|
|
||||||
target = ARGUMENTS.get('target', 'debug')
|
|
||||||
# Local dependency paths, adapt them to your setup
|
|
||||||
godot_headers = ARGUMENTS.get('headers', '../godot_headers')
|
|
||||||
godot_cpp = ARGUMENTS.get('godot-cpp', '../godot-cpp')
|
|
||||||
result_path = 'bin'
|
|
||||||
result_name = 'webrtc_native'
|
|
||||||
|
|
||||||
if target_platform == 'linux':
|
target_arch = ARGUMENTS.get("b", ARGUMENTS.get("bits", "64"))
|
||||||
result_name += '.linux.' + target + '.' + target_arch
|
target_platform = ARGUMENTS.get("p", ARGUMENTS.get("platform", "linux"))
|
||||||
|
if target_platform == "windows":
|
||||||
env['CXX']='g++'
|
|
||||||
if ARGUMENTS.get('use_llvm', 'no') == 'yes':
|
|
||||||
env['CXX'] = 'clang++'
|
|
||||||
|
|
||||||
env.Append(CCFLAGS = [ '-fPIC', '-g', '-O3', '-std=c++14', '-Wwrite-strings' ])
|
|
||||||
|
|
||||||
if target_arch == '32':
|
|
||||||
env.Append(CCFLAGS = [ '-m32' ])
|
|
||||||
env.Append(LINKFLAGS = [ '-m32' ])
|
|
||||||
elif target_arch == '64':
|
|
||||||
env.Append(CCFLAGS = [ '-m64' ])
|
|
||||||
env.Append(LINKFLAGS = [ '-m64' ])
|
|
||||||
|
|
||||||
elif target_platform == 'windows':
|
|
||||||
# This makes sure to keep the session environment variables on windows,
|
# This makes sure to keep the session environment variables on windows,
|
||||||
# that way you can run scons in a vs 2017 prompt and it will find all the required tools
|
# that way you can run scons in a vs 2017 prompt and it will find all the required tools
|
||||||
if (target_arch == '64'):
|
if target_arch == "64":
|
||||||
env = Environment(ENV = os.environ, TARGET_ARCH='amd64')
|
env = Environment(ENV=os.environ, TARGET_ARCH="amd64")
|
||||||
else:
|
else:
|
||||||
env = Environment(ENV = os.environ, TARGET_ARCH='x86')
|
env = Environment(ENV=os.environ, TARGET_ARCH="x86")
|
||||||
|
|
||||||
result_name += '.windows.' + target + '.' + target_arch
|
env.Append(BUILDERS={"GDNativeLibBuilder": Builder(action=gen_gdnative_lib)})
|
||||||
|
|
||||||
if host_platform == 'Windows':
|
customs = ["custom.py"]
|
||||||
#result_name += '.lib'
|
opts = Variables(customs, ARGUMENTS)
|
||||||
|
|
||||||
env.Append(LINKFLAGS = [ '/WX' ])
|
opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler", False))
|
||||||
if target == 'debug':
|
opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release")))
|
||||||
env.Append(CCFLAGS = ['/EHsc', '/D_DEBUG', '/MDd' ])
|
|
||||||
|
opts.Add(EnumVariable("android_arch", "Target Android architecture", "armv7", ["armv7", "arm64v8", "x86", "x86_64"]))
|
||||||
|
opts.Add(
|
||||||
|
"android_api_level",
|
||||||
|
"Target Android API level",
|
||||||
|
"18" if ARGUMENTS.get("android_arch", "armv7") in ["armv7", "x86"] else "21",
|
||||||
|
)
|
||||||
|
opts.Add(
|
||||||
|
"ANDROID_NDK_ROOT",
|
||||||
|
"Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.",
|
||||||
|
os.environ.get("ANDROID_NDK_ROOT", None),
|
||||||
|
)
|
||||||
|
|
||||||
|
opts.Add(EnumVariable("ios_arch", "Target iOS architecture", "arm64", ["armv7", "arm64", "x86_64"]))
|
||||||
|
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
|
||||||
|
opts.Add(
|
||||||
|
"IPHONEPATH",
|
||||||
|
"Path to iPhone toolchain",
|
||||||
|
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
|
||||||
|
)
|
||||||
|
opts.Add("macos_sdk_path", "macOS SDK path", "")
|
||||||
|
opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "x86_64", ["x86_64", "arm64"]))
|
||||||
|
|
||||||
|
# Update environment (parse options)
|
||||||
|
opts.Update(env)
|
||||||
|
|
||||||
|
target = env["target"]
|
||||||
|
|
||||||
|
if target_platform == "android":
|
||||||
|
target_arch = env["android_arch"]
|
||||||
|
elif target_platform == "ios":
|
||||||
|
target_arch = env["ios_arch"]
|
||||||
|
|
||||||
|
host_platform = platform.system()
|
||||||
|
# Local dependency paths, adapt them to your setup
|
||||||
|
godot_headers = ARGUMENTS.get("headers", "godot-cpp/godot-headers")
|
||||||
|
godot_cpp_headers = ARGUMENTS.get("godot_cpp_headers", "godot-cpp/include")
|
||||||
|
godot_cpp_lib_dir = ARGUMENTS.get("godot_cpp_lib_dir", "godot-cpp/bin")
|
||||||
|
result_path = os.path.join("bin", "webrtc" if env["target"] == "release" else "webrtc_debug", "lib")
|
||||||
|
lib_prefix = ""
|
||||||
|
|
||||||
|
# Convenience check to enforce the use_llvm overrides when CXX is clang(++)
|
||||||
|
if "CXX" in env and "clang" in os.path.basename(env["CXX"]):
|
||||||
|
env["use_llvm"] = True
|
||||||
|
|
||||||
|
if target_platform == "linux":
|
||||||
|
env["CXX"] = "g++"
|
||||||
|
|
||||||
|
# LLVM
|
||||||
|
if env["use_llvm"]:
|
||||||
|
if "clang++" not in os.path.basename(env["CXX"]):
|
||||||
|
env["CC"] = "clang"
|
||||||
|
env["CXX"] = "clang++"
|
||||||
|
env["LINK"] = "clang++"
|
||||||
|
|
||||||
|
if env["target"] == "debug":
|
||||||
|
env.Prepend(CCFLAGS=["-g3"])
|
||||||
|
env.Append(LINKFLAGS=["-rdynamic"])
|
||||||
|
else:
|
||||||
|
env.Prepend(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
|
env.Append(CCFLAGS=["-fPIC", "-std=c++14"])
|
||||||
|
|
||||||
|
if target_arch == "32":
|
||||||
|
env.Append(CCFLAGS=["-m32"])
|
||||||
|
env.Append(LINKFLAGS=["-m32"])
|
||||||
|
elif target_arch == "64":
|
||||||
|
env.Append(CCFLAGS=["-m64"])
|
||||||
|
env.Append(LINKFLAGS=["-m64"])
|
||||||
|
# i386 does not like static libstdc++
|
||||||
|
env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
|
||||||
|
|
||||||
|
elif target_platform == "windows":
|
||||||
|
if host_platform == "Windows":
|
||||||
|
|
||||||
|
lib_prefix = "lib"
|
||||||
|
env.Append(LINKFLAGS=["/WX"])
|
||||||
|
if target == "debug":
|
||||||
|
env.Append(CCFLAGS=["/EHsc", "/D_DEBUG", "/MDd"])
|
||||||
else:
|
else:
|
||||||
env.Append(CCFLAGS = ['/O2', '/EHsc', '/DNDEBUG', '/MD' ])
|
env.Append(CCFLAGS=["/O2", "/EHsc", "/DNDEBUG", "/MD"])
|
||||||
else:
|
else:
|
||||||
if target_arch == '32':
|
if target_arch == "32":
|
||||||
env['CXX']='i686-w64-mingw32-g++'
|
env["CXX"] = "i686-w64-mingw32-g++"
|
||||||
elif target_arch == '64':
|
elif target_arch == "64":
|
||||||
env['CXX']='x86_64-w64-mingw32-g++'
|
env["CXX"] = "x86_64-w64-mingw32-g++"
|
||||||
|
|
||||||
env.Append(CCFLAGS = [ '-g', '-O3', '-std=c++14', '-Wwrite-strings' ])
|
if env["target"] == "debug":
|
||||||
env.Append(LINKFLAGS = [ '--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++' ])
|
env.Append(CCFLAGS=["-Og", "-g"])
|
||||||
|
elif env["target"] == "release":
|
||||||
|
env.Append(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
elif target_platform == 'osx':
|
env.Append(CCFLAGS=["-std=c++14", "-Wwrite-strings"])
|
||||||
if ARGUMENTS.get('use_llvm', 'no') == 'yes':
|
env.Append(LINKFLAGS=["--static", "-Wl,--no-undefined", "-static-libgcc", "-static-libstdc++"])
|
||||||
env['CXX'] = 'clang++'
|
|
||||||
|
elif target_platform == "osx":
|
||||||
|
if env["use_llvm"]:
|
||||||
|
env["CXX"] = "clang++"
|
||||||
|
|
||||||
# Only 64-bits is supported for OS X
|
# Only 64-bits is supported for OS X
|
||||||
target_arch = '64'
|
target_arch = "64"
|
||||||
result_name += '.osx.' + target + '.' + target_arch
|
if env["macos_arch"] != "x86_64":
|
||||||
|
target_arch = "arm64"
|
||||||
|
|
||||||
env.Append(CCFLAGS = [ '-g','-O3', '-std=c++14', '-arch', 'x86_64' ])
|
env.Append(CCFLAGS=["-std=c++14", "-arch", env["macos_arch"]])
|
||||||
env.Append(LINKFLAGS = [ '-arch', 'x86_64', '-framework', 'Cocoa', '-Wl,-undefined,dynamic_lookup' ])
|
env.Append(LINKFLAGS=["-arch", env["macos_arch"], "-framework", "Cocoa", "-Wl,-undefined,dynamic_lookup"])
|
||||||
|
|
||||||
|
if env["macos_sdk_path"]:
|
||||||
|
env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]])
|
||||||
|
env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]])
|
||||||
|
|
||||||
|
if env["target"] == "debug":
|
||||||
|
env.Append(CCFLAGS=["-Og", "-g"])
|
||||||
|
elif env["target"] == "release":
|
||||||
|
env.Append(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
|
elif target_platform == "ios":
|
||||||
|
if env["ios_simulator"]:
|
||||||
|
sdk_name = "iphonesimulator"
|
||||||
|
env.Append(CCFLAGS=["-mios-simulator-version-min=10.0"])
|
||||||
|
env["LIBSUFFIX"] = ".simulator" + env["LIBSUFFIX"]
|
||||||
|
else:
|
||||||
|
sdk_name = "iphoneos"
|
||||||
|
env.Append(CCFLAGS=["-miphoneos-version-min=10.0"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
sdk_path = decode_utf8(subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip())
|
||||||
|
except (subprocess.CalledProcessError, OSError):
|
||||||
|
raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
|
||||||
|
|
||||||
|
compiler_path = env["IPHONEPATH"] + "/usr/bin/"
|
||||||
|
env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
|
||||||
|
|
||||||
|
env["CC"] = compiler_path + "clang"
|
||||||
|
env["CXX"] = compiler_path + "clang++"
|
||||||
|
env["AR"] = compiler_path + "ar"
|
||||||
|
env["RANLIB"] = compiler_path + "ranlib"
|
||||||
|
|
||||||
|
env.Append(CCFLAGS=["-std=c++14", "-arch", env["ios_arch"], "-isysroot", sdk_path])
|
||||||
|
env.Append(
|
||||||
|
LINKFLAGS=["-arch", env["ios_arch"], "-Wl,-undefined,dynamic_lookup", "-isysroot", sdk_path, "-F" + sdk_path]
|
||||||
|
)
|
||||||
|
|
||||||
|
if env["target"] == "debug":
|
||||||
|
env.Append(CCFLAGS=["-Og", "-g"])
|
||||||
|
elif env["target"] == "release":
|
||||||
|
env.Append(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
|
|
||||||
|
elif target_platform == "android":
|
||||||
|
# Verify NDK root
|
||||||
|
if not "ANDROID_NDK_ROOT" in env:
|
||||||
|
raise ValueError(
|
||||||
|
"To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate API level
|
||||||
|
api_level = int(env["android_api_level"])
|
||||||
|
if target_arch in ["arm64v8", "x86_64"] and api_level < 21:
|
||||||
|
print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
|
||||||
|
env["android_api_level"] = "21"
|
||||||
|
api_level = 21
|
||||||
|
|
||||||
|
# Setup toolchain
|
||||||
|
toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/"
|
||||||
|
if host_platform == "Windows":
|
||||||
|
toolchain += "windows"
|
||||||
|
import platform as pltfm
|
||||||
|
|
||||||
|
if pltfm.machine().endswith("64"):
|
||||||
|
toolchain += "-x86_64"
|
||||||
|
elif host_platform == "Linux":
|
||||||
|
toolchain += "linux-x86_64"
|
||||||
|
elif host_platform == "Darwin":
|
||||||
|
toolchain += "darwin-x86_64"
|
||||||
|
|
||||||
|
# Get architecture info
|
||||||
|
arch_info_table = {
|
||||||
|
"armv7": {
|
||||||
|
"march": "armv7-a",
|
||||||
|
"target": "armv7a-linux-androideabi",
|
||||||
|
"tool_path": "arm-linux-androideabi",
|
||||||
|
"compiler_path": "armv7a-linux-androideabi",
|
||||||
|
"ccflags": ["-mfpu=neon"],
|
||||||
|
},
|
||||||
|
"arm64v8": {
|
||||||
|
"march": "armv8-a",
|
||||||
|
"target": "aarch64-linux-android",
|
||||||
|
"tool_path": "aarch64-linux-android",
|
||||||
|
"compiler_path": "aarch64-linux-android",
|
||||||
|
"ccflags": [],
|
||||||
|
},
|
||||||
|
"x86": {
|
||||||
|
"march": "i686",
|
||||||
|
"target": "i686-linux-android",
|
||||||
|
"tool_path": "i686-linux-android",
|
||||||
|
"compiler_path": "i686-linux-android",
|
||||||
|
"ccflags": ["-mstackrealign"],
|
||||||
|
},
|
||||||
|
"x86_64": {
|
||||||
|
"march": "x86-64",
|
||||||
|
"target": "x86_64-linux-android",
|
||||||
|
"tool_path": "x86_64-linux-android",
|
||||||
|
"compiler_path": "x86_64-linux-android",
|
||||||
|
"ccflags": [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
arch_info = arch_info_table[target_arch]
|
||||||
|
|
||||||
|
# Setup tools
|
||||||
|
env["CC"] = toolchain + "/bin/clang"
|
||||||
|
env["CXX"] = toolchain + "/bin/clang++"
|
||||||
|
|
||||||
|
env.Append(
|
||||||
|
CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
|
||||||
|
)
|
||||||
|
env.Append(CCFLAGS=arch_info["ccflags"])
|
||||||
|
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
|
||||||
|
|
||||||
|
if env["target"] == "debug":
|
||||||
|
env.Append(CCFLAGS=["-Og", "-g"])
|
||||||
|
elif env["target"] == "release":
|
||||||
|
env.Append(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("No valid target platform selected.")
|
print("No valid target platform selected.")
|
||||||
@@ -81,32 +280,41 @@ else:
|
|||||||
|
|
||||||
# Godot CPP bindings
|
# Godot CPP bindings
|
||||||
env.Append(CPPPATH=[godot_headers])
|
env.Append(CPPPATH=[godot_headers])
|
||||||
env.Append(CPPPATH=[godot_cpp + '/include', godot_cpp + '/include/core', godot_cpp + '/include/gen'])
|
env.Append(CPPPATH=[godot_cpp_headers, godot_cpp_headers + "/core", godot_cpp_headers + "/gen"])
|
||||||
env.Append(LIBPATH=[godot_cpp + '/bin'])
|
env.Append(LIBPATH=[godot_cpp_lib_dir])
|
||||||
env.Append(LIBS=['godot-cpp'])
|
env.Append(
|
||||||
|
LIBS=[
|
||||||
|
"%sgodot-cpp.%s.%s.%s%s"
|
||||||
|
% (lib_prefix, target_platform, target, target_arch, ".simulator" if env["ios_simulator"] else "")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# WebRTC stuff
|
# WebRTC stuff
|
||||||
webrtc_dir = "webrtc"
|
webrtc_dir = "webrtc"
|
||||||
lib_name = 'libwebrtc_full'
|
lib_name = "libwebrtc_full"
|
||||||
lib_path = webrtc_dir + '/lib'
|
lib_path = os.path.join(webrtc_dir, target_platform)
|
||||||
|
|
||||||
if target_arch == '64':
|
lib_path += {
|
||||||
lib_path += '/x64'
|
"32": "/x86",
|
||||||
elif target_arch == '32':
|
"64": "/x64",
|
||||||
lib_path += '/x86'
|
"armv7": "/arm",
|
||||||
|
"arm64v8": "/arm64",
|
||||||
|
"arm64": "/arm64",
|
||||||
|
"x86": "/x86",
|
||||||
|
"x86_64": "/x64",
|
||||||
|
}[target_arch]
|
||||||
|
|
||||||
if target == 'debug':
|
if target == "debug":
|
||||||
lib_path += '/Debug'
|
lib_path += "/Debug"
|
||||||
else:
|
else:
|
||||||
lib_path += '/Release'
|
lib_path += "/Release"
|
||||||
|
|
||||||
env.Append(CPPPATH=[webrtc_dir + "/include"])
|
env.Append(CPPPATH=[webrtc_dir + "/include", webrtc_dir + "/include/third_party/abseil-cpp"])
|
||||||
#env.Append(CPPPATH=[lib_path])
|
|
||||||
|
|
||||||
if target_platform == "linux":
|
if target_platform == "linux":
|
||||||
env.Append(LIBS=[lib_name])
|
env.Append(LIBS=[lib_name, "atomic"])
|
||||||
env.Append(LIBPATH=[lib_path])
|
env.Append(LIBPATH=[lib_path])
|
||||||
#env.Append(CCFLAGS=["-std=c++11"])
|
# env.Append(CCFLAGS=["-std=c++11"])
|
||||||
env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_LINUX"])
|
env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_LINUX"])
|
||||||
env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
|
env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
|
||||||
|
|
||||||
@@ -118,26 +326,62 @@ elif target_platform == "windows":
|
|||||||
env.Append(LIBPATH=[lib_path])
|
env.Append(LIBPATH=[lib_path])
|
||||||
# Mostly "gcc"
|
# Mostly "gcc"
|
||||||
else:
|
else:
|
||||||
env.Append(CCFLAGS=["-DWINVER=0x0603", "-D_WIN32_WINNT=0x0603", "-DWEBRTC_WIN", "-DWIN32_LEAN_AND_MEAN", "-DNOMINMAX", "-DRTC_UNUSED=", "-DNO_RETURN="])
|
env.Append(
|
||||||
|
CCFLAGS=[
|
||||||
|
"-DWINVER=0x0603",
|
||||||
|
"-D_WIN32_WINNT=0x0603",
|
||||||
|
"-DWEBRTC_WIN",
|
||||||
|
"-DWIN32_LEAN_AND_MEAN",
|
||||||
|
"-DNOMINMAX",
|
||||||
|
"-DRTC_UNUSED=",
|
||||||
|
"-DNO_RETURN=",
|
||||||
|
]
|
||||||
|
)
|
||||||
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in ["secur32", "advapi32", "winmm", lib_name]])
|
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in ["secur32", "advapi32", "winmm", lib_name]])
|
||||||
env.Append(LIBPATH=[lib_path])
|
env.Append(LIBPATH=[lib_path])
|
||||||
|
|
||||||
elif target_platform == "osx":
|
elif target_platform == "osx":
|
||||||
env.Append(LIBS=[lib_name])
|
env.Append(LIBS=[lib_name])
|
||||||
env.Append(LIBPATH=[lib_path])
|
env.Append(LIBPATH=[lib_path])
|
||||||
|
env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_MAC"])
|
||||||
|
env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
|
||||||
|
|
||||||
# Godot CPP bindings
|
elif target_platform == "ios":
|
||||||
env.Append(CPPPATH=[godot_headers])
|
env.Append(LIBS=[lib_name])
|
||||||
env.Append(CPPPATH=[godot_cpp + '/include', godot_cpp + '/include/core', godot_cpp + '/include/gen'])
|
env.Append(LIBPATH=[lib_path])
|
||||||
env.Append(LIBPATH=[godot_cpp + '/bin'])
|
env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_MAC", "-DWEBRTC_IOS"])
|
||||||
env.Append(LIBS=['godot-cpp'])
|
env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
|
||||||
|
|
||||||
|
elif target_platform == "android":
|
||||||
|
env.Append(LIBS=["log"])
|
||||||
|
env.Append(LIBS=[lib_name])
|
||||||
|
env.Append(LIBPATH=[lib_path])
|
||||||
|
env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_LINUX", "-DWEBRTC_ANDROID"])
|
||||||
|
env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
|
||||||
|
|
||||||
|
if target_arch == "arm64v8":
|
||||||
|
env.Append(CCFLAGS=["-DWEBRTC_ARCH_ARM64", "-DWEBRTC_HAS_NEON"])
|
||||||
|
elif target_arch == "armv7":
|
||||||
|
env.Append(CCFLAGS=["-DWEBRTC_ARCH_ARM", "-DWEBRTC_ARCH_ARM_V7", "-DWEBRTC_HAS_NEON"])
|
||||||
|
|
||||||
# Our includes and sources
|
# Our includes and sources
|
||||||
env.Append(CPPPATH=['src/'])
|
env.Append(CPPPATH=["src/"])
|
||||||
sources = []
|
sources = []
|
||||||
add_sources(sources, 'src/', 'cpp')
|
add_sources(sources, "src/", "cpp")
|
||||||
add_sources(sources, 'src/net/', 'cpp')
|
add_sources(sources, "src/net/", "cpp")
|
||||||
|
|
||||||
|
# Suffix
|
||||||
|
suffix = ".%s.%s" % (target, target_arch)
|
||||||
|
env["SHOBJSUFFIX"] = suffix + env["SHOBJSUFFIX"]
|
||||||
|
|
||||||
# Make the shared library
|
# Make the shared library
|
||||||
|
result_name = "webrtc_native.%s.%s.%s" % (target_platform, target, target_arch) + env["SHLIBSUFFIX"]
|
||||||
|
|
||||||
library = env.SharedLibrary(target=os.path.join(result_path, result_name), source=sources)
|
library = env.SharedLibrary(target=os.path.join(result_path, result_name), source=sources)
|
||||||
Default(library)
|
Default(library)
|
||||||
|
|
||||||
|
# GDNativeLibrary
|
||||||
|
gdnlib = "webrtc"
|
||||||
|
if target != "release":
|
||||||
|
gdnlib += "_debug"
|
||||||
|
Default(env.GDNativeLibBuilder([os.path.join("bin", gdnlib, gdnlib + ".tres")], ["misc/gdnlib.tres"]))
|
||||||
|
|||||||
1
godot-cpp
Submodule
1
godot-cpp
Submodule
Submodule godot-cpp added at 77d41fa179
28
misc/gdnlib.tres
Normal file
28
misc/gdnlib.tres
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
[gd_resource type="GDNativeLibrary" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
singleton = true
|
||||||
|
reloadable = false
|
||||||
|
entry/OSX.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.64.dylib"
|
||||||
|
entry/OSX.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.arm64.dylib"
|
||||||
|
entry/Windows.64 = "res://{GDNATIVE_PATH}/lib/webrtc_native.windows.{TARGET}.64.dll"
|
||||||
|
entry/Windows.32 = "res://{GDNATIVE_PATH}/lib/webrtc_native.windows.{TARGET}.32.dll"
|
||||||
|
entry/X11.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.64.so"
|
||||||
|
entry/X11.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.32.so"
|
||||||
|
entry/Server.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.64.so"
|
||||||
|
entry/Server.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.32.so"
|
||||||
|
entry/Android.armeabi-v7a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.armv7.so"
|
||||||
|
entry/Android.arm64-v8a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm64v8.so"
|
||||||
|
entry/Android.x64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86_64.so"
|
||||||
|
entry/Android.x86 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86.so"
|
||||||
|
entry/iOS.armv7 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.armv7.dylib"
|
||||||
|
entry/iOS.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.arm64.dylib"
|
||||||
|
entry/iOS.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.x86_64.dylib"
|
||||||
|
dependency/Windows.64 = [ ]
|
||||||
|
dependency/Windows.32 = [ ]
|
||||||
|
dependency/X11.64 = [ ]
|
||||||
|
dependency/X11.32 = [ ]
|
||||||
|
dependency/Server.64 = [ ]
|
||||||
|
dependency/Server.32 = [ ]
|
||||||
|
dependency/Android.armeabi-v7a = [ ]
|
||||||
|
dependency/Android.arm64-v8a = [ ]
|
||||||
34
misc/scripts/black_format.sh
Executable file
34
misc/scripts/black_format.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script runs black on all Python files in the repo.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
# Apply black.
|
||||||
|
echo -e "Formatting Python files..."
|
||||||
|
PY_FILES=$(find \( -path "./.git" \
|
||||||
|
-o -path "./webrtc" \
|
||||||
|
-o -path "./godot-cpp" \
|
||||||
|
\) -prune \
|
||||||
|
-o \( -name "SConstruct" \
|
||||||
|
-o -name "SCsub" \
|
||||||
|
-o -name "*.py" \
|
||||||
|
\) -print)
|
||||||
|
black -l 120 $PY_FILES
|
||||||
|
|
||||||
|
git diff > patch.patch
|
||||||
|
|
||||||
|
# If no patch has been generated all is OK, clean up, and exit.
|
||||||
|
if [ ! -s patch.patch ] ; then
|
||||||
|
printf "Files in this commit comply with the black style rules.\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A patch has been created, notify the user, clean up, and exit.
|
||||||
|
printf "\n*** The following differences were found between the code "
|
||||||
|
printf "and the formatting rules:\n\n"
|
||||||
|
cat patch.patch
|
||||||
|
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 1
|
||||||
58
misc/scripts/clang_format.sh
Executable file
58
misc/scripts/clang_format.sh
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script runs clang-format and fixes copyright headers on all relevant files in the repo.
|
||||||
|
# This is the primary script responsible for fixing style violations.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
CLANG_FORMAT_FILE_EXTS=(".c" ".h" ".cpp" ".hpp" ".cc" ".hh" ".cxx" ".m" ".mm" ".inc" ".java" ".glsl")
|
||||||
|
|
||||||
|
# Loops through all text files tracked by Git.
|
||||||
|
git grep -zIl '' |
|
||||||
|
while IFS= read -rd '' f; do
|
||||||
|
# Exclude some files.
|
||||||
|
if [[ "$f" == "thirdparty"* ]]; then
|
||||||
|
continue
|
||||||
|
elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
|
||||||
|
continue
|
||||||
|
elif [[ "$f" == *"-so_wrap."* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do
|
||||||
|
if [[ "$f" == *"$extension" ]]; then
|
||||||
|
# Run clang-format.
|
||||||
|
clang-format -i "$f"
|
||||||
|
# Fix copyright headers, but not all files get them.
|
||||||
|
if [[ "$f" == *"inc" ]]; then
|
||||||
|
continue 2
|
||||||
|
elif [[ "$f" == *"glsl" ]]; then
|
||||||
|
continue 2
|
||||||
|
elif [[ "$f" == *"theme_data.h" ]]; then
|
||||||
|
continue 2
|
||||||
|
elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/input/InputManager"* ]]; then
|
||||||
|
continue 2
|
||||||
|
fi
|
||||||
|
python misc/scripts/copyright_headers.py "$f"
|
||||||
|
continue 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
git diff > patch.patch
|
||||||
|
|
||||||
|
# If no patch has been generated all is OK, clean up, and exit.
|
||||||
|
if [ ! -s patch.patch ] ; then
|
||||||
|
printf "Files in this commit comply with the clang-format style rules.\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A patch has been created, notify the user, clean up, and exit.
|
||||||
|
printf "\n*** The following differences were found between the code "
|
||||||
|
printf "and the formatting rules:\n\n"
|
||||||
|
cat patch.patch
|
||||||
|
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 1
|
||||||
95
misc/scripts/copyright_headers.py
Executable file
95
misc/scripts/copyright_headers.py
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
header = """\
|
||||||
|
/*************************************************************************/
|
||||||
|
/* $filename */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
"""
|
||||||
|
|
||||||
|
fname = sys.argv[1]
|
||||||
|
|
||||||
|
# Handle replacing $filename with actual filename and keep alignment
|
||||||
|
fsingle = fname.strip()
|
||||||
|
if fsingle.find("/") != -1:
|
||||||
|
fsingle = fsingle[fsingle.rfind("/") + 1 :]
|
||||||
|
rep_fl = "$filename"
|
||||||
|
rep_fi = fsingle
|
||||||
|
len_fl = len(rep_fl)
|
||||||
|
len_fi = len(rep_fi)
|
||||||
|
# Pad with spaces to keep alignment
|
||||||
|
if len_fi < len_fl:
|
||||||
|
for x in range(len_fl - len_fi):
|
||||||
|
rep_fi += " "
|
||||||
|
elif len_fl < len_fi:
|
||||||
|
for x in range(len_fi - len_fl):
|
||||||
|
rep_fl += " "
|
||||||
|
if header.find(rep_fl) != -1:
|
||||||
|
text = header.replace(rep_fl, rep_fi)
|
||||||
|
else:
|
||||||
|
text = header.replace("$filename", fsingle)
|
||||||
|
text += "\n"
|
||||||
|
|
||||||
|
# We now have the proper header, so we want to ignore the one in the original file
|
||||||
|
# and potentially empty lines and badly formatted lines, while keeping comments that
|
||||||
|
# come after the header, and then keep everything non-header unchanged.
|
||||||
|
# To do so, we skip empty lines that may be at the top in a first pass.
|
||||||
|
# In a second pass, we skip all consecutive comment lines starting with "/*",
|
||||||
|
# then we can append the rest (step 2).
|
||||||
|
|
||||||
|
fileread = open(fname.strip(), "r")
|
||||||
|
line = fileread.readline()
|
||||||
|
header_done = False
|
||||||
|
|
||||||
|
while line.strip() == "": # Skip empty lines at the top
|
||||||
|
line = fileread.readline()
|
||||||
|
|
||||||
|
if line.find("/**********") == -1: # Godot header starts this way
|
||||||
|
# Maybe starting with a non-Godot comment, abort header magic
|
||||||
|
header_done = True
|
||||||
|
|
||||||
|
while not header_done: # Handle header now
|
||||||
|
if line.find("/*") != 0: # No more starting with a comment
|
||||||
|
header_done = True
|
||||||
|
if line.strip() != "":
|
||||||
|
text += line
|
||||||
|
line = fileread.readline()
|
||||||
|
|
||||||
|
while line != "": # Dump everything until EOF
|
||||||
|
text += line
|
||||||
|
line = fileread.readline()
|
||||||
|
|
||||||
|
fileread.close()
|
||||||
|
|
||||||
|
# Write
|
||||||
|
filewrite = open(fname.strip(), "w")
|
||||||
|
filewrite.write(text)
|
||||||
|
filewrite.close()
|
||||||
48
misc/scripts/file_format.sh
Executable file
48
misc/scripts/file_format.sh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script ensures proper POSIX text file formatting and a few other things.
|
||||||
|
# This is supplementary to clang_format.sh and black_format.sh, but should be
|
||||||
|
# run before them.
|
||||||
|
|
||||||
|
# We need dos2unix and recode.
|
||||||
|
if [ ! -x "$(command -v dos2unix)" -o ! -x "$(command -v recode)" ]; then
|
||||||
|
printf "Install 'dos2unix' and 'recode' to use this script.\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
# Loops through all text files tracked by Git.
|
||||||
|
git grep -zIl '' |
|
||||||
|
while IFS= read -rd '' f; do
|
||||||
|
# Exclude some types of files.
|
||||||
|
if [[ "$f" == "webrtc"* ]]; then
|
||||||
|
continue
|
||||||
|
elif [[ "$f" == "godot-cpp"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Ensure that files are UTF-8 formatted.
|
||||||
|
recode UTF-8 "$f" 2> /dev/null
|
||||||
|
# Ensure that files have LF line endings and do not contain a BOM.
|
||||||
|
dos2unix "$f" 2> /dev/null
|
||||||
|
# Remove trailing space characters and ensures that files end
|
||||||
|
# with newline characters. -l option handles newlines conveniently.
|
||||||
|
perl -i -ple 's/\s*$//g' "$f"
|
||||||
|
done
|
||||||
|
|
||||||
|
git diff > patch.patch
|
||||||
|
|
||||||
|
# If no patch has been generated all is OK, clean up, and exit.
|
||||||
|
if [ ! -s patch.patch ] ; then
|
||||||
|
printf "Files in this commit comply with the formatting rules.\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A patch has been created, notify the user, clean up, and exit.
|
||||||
|
printf "\n*** The following differences were found between the code "
|
||||||
|
printf "and the formatting rules:\n\n"
|
||||||
|
cat patch.patch
|
||||||
|
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||||
|
rm -f patch.patch
|
||||||
|
exit 1
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
WebRTCLibPeer::GodotCSDO::GodotCSDO(WebRTCLibPeer *parent) {
|
|
||||||
this->parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotCSDO::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
|
|
||||||
// serialize this offer and send it to the remote peer:
|
|
||||||
std::string sdp; // sdp = session description protocol
|
|
||||||
desc->ToString(&sdp);
|
|
||||||
parent->queue_signal("offer_created", 2, desc->type().c_str(), sdp.c_str());
|
|
||||||
};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotCSDO::OnFailure(const std::string &error){};
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
WebRTCLibPeer::GodotDCO::GodotDCO(WebRTCLibPeer *parent) {
|
|
||||||
this->parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnMessage(const webrtc::DataBuffer &buffer) {
|
|
||||||
const uint8_t *data = buffer.data.data<uint8_t>();
|
|
||||||
uint8_t *memory_controlled_buffer = new uint8_t[buffer.data.size()];
|
|
||||||
|
|
||||||
std::copy(data, data + buffer.data.size(), memory_controlled_buffer);
|
|
||||||
parent->queue_packet(memory_controlled_buffer, buffer.data.size());
|
|
||||||
};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnStateChange(){};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnBufferedAmountChange(uint64_t previous_amount){};
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
WebRTCLibPeer::GodotPCO::GodotPCO(WebRTCLibPeer *parent) {
|
|
||||||
this->parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnRenegotiationNeeded() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
|
|
||||||
// Serialize the candidate and send it to the remote peer:
|
|
||||||
|
|
||||||
godot::Dictionary candidateSDP;
|
|
||||||
|
|
||||||
godot::String candidateSdpMidName = candidate->sdp_mid().c_str();
|
|
||||||
int candidateSdpMlineIndexName = candidate->sdp_mline_index();
|
|
||||||
std::string sdp;
|
|
||||||
candidate->ToString(&sdp);
|
|
||||||
godot::String candidateSdpName = sdp.c_str();
|
|
||||||
|
|
||||||
parent->queue_signal("new_ice_candidate",
|
|
||||||
3,
|
|
||||||
candidateSdpMidName,
|
|
||||||
candidateSdpMlineIndexName,
|
|
||||||
candidateSdpName);
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
WebRTCLibPeer::GodotSSDO::GodotSSDO(WebRTCLibPeer *parent) {
|
|
||||||
this->parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotSSDO::OnSuccess(){};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotSSDO::OnFailure(const std::string &error){};
|
|
||||||
215
src/WebRTCLibDataChannel.cpp
Normal file
215
src/WebRTCLibDataChannel.cpp
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCLibDataChannel.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
|
||||||
|
#include "GDNativeLibrary.hpp"
|
||||||
|
#include "NativeScript.hpp"
|
||||||
|
|
||||||
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
|
// Channel observer
|
||||||
|
WebRTCLibDataChannel::ChannelObserver::ChannelObserver(WebRTCLibDataChannel *parent) {
|
||||||
|
this->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::ChannelObserver::OnMessage(const webrtc::DataBuffer &buffer) {
|
||||||
|
parent->queue_packet(buffer.data.data<uint8_t>(), buffer.data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::ChannelObserver::OnStateChange() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::ChannelObserver::OnBufferedAmountChange(uint64_t previous_amount) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataChannel
|
||||||
|
WebRTCLibDataChannel *WebRTCLibDataChannel::new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
|
||||||
|
// Invalid channel result in NULL return
|
||||||
|
ERR_FAIL_COND_V(p_channel.get() == nullptr, NULL);
|
||||||
|
|
||||||
|
// Instance a WebRTCDataChannelGDNative object
|
||||||
|
godot::WebRTCDataChannelGDNative *out = godot::WebRTCDataChannelGDNative::_new();
|
||||||
|
// Set our implementation as it's script
|
||||||
|
godot::NativeScript *script = godot::NativeScript::_new();
|
||||||
|
script->set_library(godot::detail::get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib));
|
||||||
|
script->set_class_name("WebRTCLibDataChannel");
|
||||||
|
out->set_script(script);
|
||||||
|
|
||||||
|
// Bind the data channel to the ScriptInstance userdata (our script)
|
||||||
|
WebRTCLibDataChannel *tmp = out->cast_to<WebRTCLibDataChannel>(out);
|
||||||
|
tmp->bind_channel(p_channel);
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
|
||||||
|
ERR_FAIL_COND(p_channel.get() == nullptr);
|
||||||
|
|
||||||
|
channel = p_channel;
|
||||||
|
label = p_channel->label();
|
||||||
|
protocol = p_channel->protocol();
|
||||||
|
channel->RegisterObserver(&observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::queue_packet(const uint8_t *data, uint32_t size) {
|
||||||
|
mutex->lock();
|
||||||
|
|
||||||
|
godot::PoolByteArray packet;
|
||||||
|
packet.resize(size);
|
||||||
|
{
|
||||||
|
godot::PoolByteArray::Write w = packet.write();
|
||||||
|
memcpy(w.ptr(), data, size);
|
||||||
|
}
|
||||||
|
packet_queue.push(packet);
|
||||||
|
|
||||||
|
mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::set_write_mode(godot_int mode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_write_mode() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::was_string_packet() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::ChannelState WebRTCLibDataChannel::get_ready_state() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, STATE_CLOSED);
|
||||||
|
return (ChannelState)channel->state();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *WebRTCLibDataChannel::get_label() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, "");
|
||||||
|
return label.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::is_ordered() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, false);
|
||||||
|
return channel->ordered();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_id() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, -1);
|
||||||
|
return channel->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_max_packet_life_time() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, 0);
|
||||||
|
return channel->maxRetransmitTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_max_retransmits() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, 0);
|
||||||
|
return channel->maxRetransmits();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *WebRTCLibDataChannel::get_protocol() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, "");
|
||||||
|
return protocol.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::is_negotiated() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, false);
|
||||||
|
return channel->negotiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_buffered_amount() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, 0);
|
||||||
|
return channel->buffered_amount();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibDataChannel::poll() {
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::close() {
|
||||||
|
if (channel.get() != nullptr) {
|
||||||
|
channel->Close();
|
||||||
|
channel->UnregisterObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibDataChannel::get_packet(const uint8_t **r_buffer, int *r_len) {
|
||||||
|
ERR_FAIL_COND_V(packet_queue.empty(), GODOT_ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
mutex->lock();
|
||||||
|
|
||||||
|
// Update current packet and pop queue
|
||||||
|
current_packet = packet_queue.front();
|
||||||
|
packet_queue.pop();
|
||||||
|
// Set out buffer and size (buffer will be gone at next get_packet or close)
|
||||||
|
*r_buffer = current_packet.read().ptr();
|
||||||
|
*r_len = current_packet.size();
|
||||||
|
|
||||||
|
mutex->unlock();
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibDataChannel::put_packet(const uint8_t *p_buffer, int p_len) {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, GODOT_ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
webrtc::DataBuffer webrtc_buffer(rtc::CopyOnWriteBuffer(p_buffer, p_len), true);
|
||||||
|
ERR_FAIL_COND_V(!channel->Send(webrtc_buffer), GODOT_FAILED);
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_available_packet_count() const {
|
||||||
|
return packet_queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_max_packet_size() const {
|
||||||
|
return 1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::_register_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::WebRTCLibDataChannel() :
|
||||||
|
observer(this) {
|
||||||
|
mutex = new std::mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::~WebRTCLibDataChannel() {
|
||||||
|
close();
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
delete mutex;
|
||||||
|
}
|
||||||
107
src/WebRTCLibDataChannel.hpp
Normal file
107
src/WebRTCLibDataChannel.hpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCLibDataChannel.hpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_DATA_CHANNEL_H
|
||||||
|
#define WEBRTC_DATA_CHANNEL_H
|
||||||
|
|
||||||
|
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
|
||||||
|
|
||||||
|
#include "api/peer_connection_interface.h" // interface for all things needed from WebRTC
|
||||||
|
#include "media/base/media_engine.h" // needed for CreateModularPeerConnectionFactory
|
||||||
|
|
||||||
|
#include "PoolArrays.hpp"
|
||||||
|
#include "net/WebRTCDataChannelNative.hpp"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace godot_webrtc {
|
||||||
|
|
||||||
|
class WebRTCLibDataChannel : public WebRTCDataChannelNative {
|
||||||
|
GODOT_CLASS(WebRTCLibDataChannel, WebRTCDataChannelNative);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ChannelObserver : public webrtc::DataChannelObserver {
|
||||||
|
public:
|
||||||
|
WebRTCLibDataChannel *parent;
|
||||||
|
|
||||||
|
ChannelObserver(WebRTCLibDataChannel *parent);
|
||||||
|
void OnMessage(const webrtc::DataBuffer &buffer) override;
|
||||||
|
void OnStateChange() override; // UNUSED
|
||||||
|
void OnBufferedAmountChange(uint64_t previous_amount) override; // UNUSED
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelObserver observer;
|
||||||
|
rtc::scoped_refptr<webrtc::DataChannelInterface> channel;
|
||||||
|
|
||||||
|
std::mutex *mutex;
|
||||||
|
std::queue<godot::PoolByteArray> packet_queue;
|
||||||
|
godot::PoolByteArray current_packet;
|
||||||
|
std::string label;
|
||||||
|
std::string protocol;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WebRTCLibDataChannel *new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
|
||||||
|
static void _register_methods();
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
|
||||||
|
void bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
|
||||||
|
void queue_packet(const uint8_t *data, uint32_t size);
|
||||||
|
|
||||||
|
/* WebRTCDataChannel */
|
||||||
|
void set_write_mode(godot_int mode);
|
||||||
|
godot_int get_write_mode() const;
|
||||||
|
bool was_string_packet() const;
|
||||||
|
|
||||||
|
ChannelState get_ready_state() const;
|
||||||
|
const char *get_label() const;
|
||||||
|
bool is_ordered() const;
|
||||||
|
int get_id() const;
|
||||||
|
int get_max_packet_life_time() const;
|
||||||
|
int get_max_retransmits() const;
|
||||||
|
const char *get_protocol() const;
|
||||||
|
bool is_negotiated() const;
|
||||||
|
int get_buffered_amount() const;
|
||||||
|
|
||||||
|
godot_error poll();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
/* PacketPeer */
|
||||||
|
virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len);
|
||||||
|
virtual godot_error put_packet(const uint8_t *p_buffer, int p_len);
|
||||||
|
virtual godot_int get_available_packet_count() const;
|
||||||
|
virtual godot_int get_max_packet_size() const;
|
||||||
|
|
||||||
|
WebRTCLibDataChannel();
|
||||||
|
~WebRTCLibDataChannel();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot_webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_DATA_CHANNEL_H
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
void WebRTCLibPeer::set_write_mode(godot_int mode) {
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_write_mode() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebRTCLibPeer::was_string_packet() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_connection_state() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::create_offer() {
|
|
||||||
peer_connection->CreateOffer(
|
|
||||||
ptr_csdo, // CreateSessionDescriptionObserver* observer,
|
|
||||||
nullptr // webrtc::PeerConnectionInterface::RTCOfferAnswerOptions() // const MediaConstraintsInterface* constraints
|
|
||||||
);
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_remote_description(const char *type, const char *sdp) {
|
|
||||||
godot_error err = set_description(type, sdp, false); //false meaning !isLocal because it is remote
|
|
||||||
peer_connection->CreateAnswer(ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_local_description(const char *type, const char *sdp) {
|
|
||||||
return set_description(type, sdp, true); // isLocal == true
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
|
||||||
webrtc::SdpParseError *error = nullptr;
|
|
||||||
webrtc::IceCandidateInterface *candidate = webrtc::CreateIceCandidate(
|
|
||||||
sdpMidName,
|
|
||||||
sdpMlineIndexName,
|
|
||||||
sdpName,
|
|
||||||
error);
|
|
||||||
|
|
||||||
// @TODO do something if there's an error (if error, or if !candidate)
|
|
||||||
if (error || !candidate)
|
|
||||||
std::cout << "ERROR with creating ICE candidate (" << error << ")\n";
|
|
||||||
|
|
||||||
if (!peer_connection->AddIceCandidate(candidate))
|
|
||||||
ERR_PRINT("Error with adding ICE candidate");
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::poll() {
|
|
||||||
std::function<void()> signal;
|
|
||||||
while (!signal_queue.empty()) {
|
|
||||||
mutex_signal_queue->lock();
|
|
||||||
signal = signal_queue.front();
|
|
||||||
signal_queue.pop();
|
|
||||||
mutex_signal_queue->unlock();
|
|
||||||
|
|
||||||
signal();
|
|
||||||
}
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::get_packet(const uint8_t **r_buffer, int *r_len) {
|
|
||||||
if (packet_queue_size == 0)
|
|
||||||
return GODOT_ERR_UNAVAILABLE;
|
|
||||||
mutex_packet_queue->lock();
|
|
||||||
uint8_t *current_packet = packet_queue.front();
|
|
||||||
*r_buffer = current_packet;
|
|
||||||
*r_len = packet_sizes_queue.front();
|
|
||||||
|
|
||||||
packet_queue.pop();
|
|
||||||
packet_sizes_queue.pop();
|
|
||||||
mutex_packet_queue->unlock();
|
|
||||||
|
|
||||||
--packet_queue_size;
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::put_packet(const uint8_t *p_buffer, int p_len) {
|
|
||||||
webrtc::DataBuffer webrtc_buffer(rtc::CopyOnWriteBuffer(p_buffer, p_len), true);
|
|
||||||
data_channel->Send(webrtc_buffer);
|
|
||||||
return GODOT_OK; // @TODO properly return any Error we may get.
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_available_packet_count() const {
|
|
||||||
return packet_queue_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_max_packet_size() const {
|
|
||||||
return 1200;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::_register_methods() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::_init() {
|
|
||||||
register_interface(&interface);
|
|
||||||
|
|
||||||
// initialize variables:
|
|
||||||
mutex_signal_queue = new std::mutex;
|
|
||||||
mutex_packet_queue = new std::mutex;
|
|
||||||
packet_queue_size = 0;
|
|
||||||
|
|
||||||
// create a PeerConnectionFactoryInterface:
|
|
||||||
signaling_thread = new rtc::Thread;
|
|
||||||
signaling_thread->Start();
|
|
||||||
pc_factory = webrtc::CreateModularPeerConnectionFactory(
|
|
||||||
nullptr, // rtc::Thread* network_thread,
|
|
||||||
nullptr, // rtc::Thread* worker_thread,
|
|
||||||
signaling_thread,
|
|
||||||
nullptr, // std::unique_ptr<cricket::MediaEngineInterface> media_engine,
|
|
||||||
nullptr, // std::unique_ptr<CallFactoryInterface> call_factory,
|
|
||||||
nullptr // std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory
|
|
||||||
);
|
|
||||||
if (pc_factory.get() == nullptr) { // PeerConnectionFactory couldn't be created. Fail the method call.
|
|
||||||
ERR_PRINT("PeerConnectionFactory could not be created");
|
|
||||||
// return GODOT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create PeerConnection configuration and add the ice servers:
|
|
||||||
webrtc::PeerConnectionInterface::RTCConfiguration configuration;
|
|
||||||
//webrtc::PeerConnectionInterface::IceServer ice_server;
|
|
||||||
|
|
||||||
//ice_server.uri = "stun:stun.l.google.com:19302"; // @FIXME allow user to input ice servers
|
|
||||||
//configuration.servers.push_back(ice_server);
|
|
||||||
|
|
||||||
// create a PeerConnection object:
|
|
||||||
peer_connection = pc_factory->CreatePeerConnection(configuration, nullptr, nullptr, &pco);
|
|
||||||
if (peer_connection.get() == nullptr) { // PeerConnection couldn't be created. Fail the method call.
|
|
||||||
ERR_PRINT("PeerConnection could not be created");
|
|
||||||
// return GODOT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a DataChannel
|
|
||||||
webrtc::DataChannelInit data_channel_config;
|
|
||||||
data_channel_config.negotiated = true; // True if the channel has been externally negotiated
|
|
||||||
data_channel_config.id = 0;
|
|
||||||
|
|
||||||
data_channel = peer_connection->CreateDataChannel("channel", &data_channel_config);
|
|
||||||
// @TODO (NONESSENTIAL) create data_channel check. fail function call if data_channel isn't created
|
|
||||||
data_channel->RegisterObserver(&dco);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCLibPeer::WebRTCLibPeer() :
|
|
||||||
dco(this),
|
|
||||||
pco(this),
|
|
||||||
ptr_csdo(new rtc::RefCountedObject<GodotCSDO>(this)),
|
|
||||||
ptr_ssdo(new rtc::RefCountedObject<GodotSSDO>(this)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCLibPeer::~WebRTCLibPeer() {
|
|
||||||
if (_owner) {
|
|
||||||
register_interface(NULL);
|
|
||||||
}
|
|
||||||
delete mutex_signal_queue;
|
|
||||||
delete mutex_packet_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1, const godot::Variant &p_arg2, const godot::Variant &p_arg3) {
|
|
||||||
mutex_signal_queue->lock();
|
|
||||||
signal_queue.push(
|
|
||||||
[this, p_name, p_argc, p_arg1, p_arg2, p_arg3] {
|
|
||||||
if (p_argc == 2)
|
|
||||||
emit_signal(p_name, p_arg1, p_arg2);
|
|
||||||
else
|
|
||||||
emit_signal(p_name, p_arg1, p_arg2, p_arg3);
|
|
||||||
});
|
|
||||||
mutex_signal_queue->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::queue_packet(uint8_t *buffer, int buffer_size) {
|
|
||||||
mutex_packet_queue->lock();
|
|
||||||
packet_queue.push(buffer);
|
|
||||||
packet_sizes_queue.push(buffer_size);
|
|
||||||
++packet_queue_size;
|
|
||||||
mutex_packet_queue->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_description(const char *type, const char *sdp, bool isLocal) {
|
|
||||||
// webrtc::SdpType type = (isOffer) ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer;
|
|
||||||
godot::String string_sdp = sdp;
|
|
||||||
|
|
||||||
webrtc::SdpType sdptype = (godot::String(type) == godot::String("offer")) ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer;
|
|
||||||
std::unique_ptr<webrtc::SessionDescriptionInterface> desc =
|
|
||||||
webrtc::CreateSessionDescription(sdptype, sdp);
|
|
||||||
|
|
||||||
if (isLocal) {
|
|
||||||
peer_connection->SetLocalDescription(
|
|
||||||
ptr_ssdo, // @TODO (NONESSENTIAL, OPTIONAL) replace this with DummySetSessionDescriptionObserver::Create()
|
|
||||||
desc.release());
|
|
||||||
} else {
|
|
||||||
peer_connection->SetRemoteDescription(
|
|
||||||
ptr_ssdo, // @TODO (NONESSENTIAL, OPTIONAL) replace this with DummySetSessionDescriptionObserver::Create()
|
|
||||||
desc.release());
|
|
||||||
}
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#ifndef WEBRTC_PEER_H
|
|
||||||
#define WEBRTC_PEER_H
|
|
||||||
|
|
||||||
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
|
|
||||||
|
|
||||||
#include "api/peerconnectioninterface.h" // interface for all things needed from WebRTC
|
|
||||||
#include "media/base/mediaengine.h" // needed for CreateModularPeerConnectionFactory
|
|
||||||
#include <functional> // std::function
|
|
||||||
#include <mutex> // mutex @TODO replace std::mutex with Godot mutex
|
|
||||||
|
|
||||||
#include "net/WebRTCPeerNative.hpp"
|
|
||||||
|
|
||||||
namespace godot_webrtc {
|
|
||||||
|
|
||||||
class WebRTCLibPeer : public WebRTCPeerNative {
|
|
||||||
GODOT_CLASS(WebRTCLibPeer, WebRTCPeerNative);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void _register_methods();
|
|
||||||
|
|
||||||
void _init();
|
|
||||||
|
|
||||||
void set_write_mode(godot_int mode);
|
|
||||||
godot_int get_write_mode() const;
|
|
||||||
bool was_string_packet() const;
|
|
||||||
godot_int get_connection_state() const;
|
|
||||||
|
|
||||||
godot_error create_offer();
|
|
||||||
godot_error set_remote_description(const char *type, const char *sdp);
|
|
||||||
godot_error set_local_description(const char *type, const char *sdp);
|
|
||||||
godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName);
|
|
||||||
godot_error poll();
|
|
||||||
|
|
||||||
/* WebRTCPeer */
|
|
||||||
virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len);
|
|
||||||
virtual godot_error put_packet(const uint8_t *p_buffer, int p_len);
|
|
||||||
virtual godot_int get_available_packet_count() const;
|
|
||||||
virtual godot_int get_max_packet_size() const;
|
|
||||||
|
|
||||||
WebRTCLibPeer();
|
|
||||||
~WebRTCLibPeer();
|
|
||||||
|
|
||||||
/* helper functions */
|
|
||||||
|
|
||||||
void queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1 = godot::Variant(), const godot::Variant &p_arg2 = godot::Variant(), const godot::Variant &p_arg3 = godot::Variant());
|
|
||||||
// void queue_signal(godot::StringName p_name, Variant_ARG_LIST);
|
|
||||||
void queue_packet(uint8_t *, int);
|
|
||||||
godot_error set_description(const char *type, const char *sdp, bool isLocal);
|
|
||||||
|
|
||||||
/** DataChannelObserver callback functions **/
|
|
||||||
class GodotDCO : public webrtc::DataChannelObserver {
|
|
||||||
public:
|
|
||||||
WebRTCLibPeer *parent;
|
|
||||||
|
|
||||||
GodotDCO(WebRTCLibPeer *parent);
|
|
||||||
void OnMessage(const webrtc::DataBuffer &buffer) override;
|
|
||||||
void OnStateChange() override; // UNUSED
|
|
||||||
void OnBufferedAmountChange(uint64_t previous_amount) override; // UNUSED
|
|
||||||
};
|
|
||||||
|
|
||||||
/** PeerConnectionObserver callback functions **/
|
|
||||||
class GodotPCO : public webrtc::PeerConnectionObserver {
|
|
||||||
public:
|
|
||||||
WebRTCLibPeer *parent;
|
|
||||||
|
|
||||||
GodotPCO(WebRTCLibPeer *parent);
|
|
||||||
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override;
|
|
||||||
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
|
||||||
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
|
||||||
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override;
|
|
||||||
void OnRenegotiationNeeded() override;
|
|
||||||
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override;
|
|
||||||
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override;
|
|
||||||
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** CreateSessionDescriptionObserver callback functions **/
|
|
||||||
class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
|
|
||||||
public:
|
|
||||||
WebRTCLibPeer *parent;
|
|
||||||
|
|
||||||
GodotCSDO(WebRTCLibPeer *parent);
|
|
||||||
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
|
|
||||||
void OnFailure(const std::string &error) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** SetSessionDescriptionObserver callback functions **/
|
|
||||||
class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
|
|
||||||
public:
|
|
||||||
WebRTCLibPeer *parent;
|
|
||||||
|
|
||||||
GodotSSDO(WebRTCLibPeer *parent);
|
|
||||||
void OnSuccess() override;
|
|
||||||
void OnFailure(const std::string &error) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
GodotDCO dco;
|
|
||||||
GodotPCO pco;
|
|
||||||
rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
|
|
||||||
rtc::scoped_refptr<GodotCSDO> ptr_csdo;
|
|
||||||
|
|
||||||
std::mutex *mutex_signal_queue;
|
|
||||||
std::mutex *mutex_packet_queue;
|
|
||||||
int packet_queue_size;
|
|
||||||
std::queue<uint8_t *> packet_queue;
|
|
||||||
std::queue<int> packet_sizes_queue;
|
|
||||||
std::queue<std::function<void()> > signal_queue;
|
|
||||||
|
|
||||||
rtc::Thread *signaling_thread;
|
|
||||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
|
|
||||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
|
|
||||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace godot_webrtc
|
|
||||||
|
|
||||||
#endif // WEBRTC_PEER_H
|
|
||||||
312
src/WebRTCLibPeerConnection.cpp
Normal file
312
src/WebRTCLibPeerConnection.cpp
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCLibPeerConnection.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
#include "WebRTCDataChannel.hpp"
|
||||||
|
#include "WebRTCDataChannelGDNative.hpp"
|
||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
|
||||||
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
|
std::unique_ptr<rtc::Thread> WebRTCLibPeerConnection::signaling_thread = nullptr;
|
||||||
|
|
||||||
|
// PeerConnectionObserver
|
||||||
|
void WebRTCLibPeerConnection::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
|
||||||
|
godot::Dictionary candidateSDP;
|
||||||
|
godot::String candidateSdpMidName = candidate->sdp_mid().c_str();
|
||||||
|
int candidateSdpMlineIndexName = candidate->sdp_mline_index();
|
||||||
|
std::string sdp;
|
||||||
|
candidate->ToString(&sdp);
|
||||||
|
godot::String candidateSdpName = sdp.c_str();
|
||||||
|
parent->queue_signal("ice_candidate_created", 3, candidateSdpMidName, candidateSdpMlineIndexName, candidateSdpName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSessionDescriptionObserver
|
||||||
|
void WebRTCLibPeerConnection::GodotSSDO::OnSuccess() {
|
||||||
|
if (make_offer) {
|
||||||
|
make_offer = false;
|
||||||
|
parent->peer_connection->CreateAnswer(parent->ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSessionDescriptionObserver
|
||||||
|
void WebRTCLibPeerConnection::GodotCSDO::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
|
||||||
|
// serialize this offer and send it to the remote peer:
|
||||||
|
std::string sdp;
|
||||||
|
desc->ToString(&sdp);
|
||||||
|
parent->queue_signal("session_description_created", 2, desc->type().c_str(), sdp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::initialize_signaling() {
|
||||||
|
if (signaling_thread.get() == nullptr) {
|
||||||
|
signaling_thread = rtc::Thread::Create();
|
||||||
|
}
|
||||||
|
signaling_thread->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::deinitialize_signaling() {
|
||||||
|
if (signaling_thread.get() != nullptr) {
|
||||||
|
signaling_thread->Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error _parse_ice_server(webrtc::PeerConnectionInterface::RTCConfiguration &r_config, godot::Dictionary p_server) {
|
||||||
|
godot::Variant v;
|
||||||
|
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||||
|
godot::String url;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!p_server.has("urls"), GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
// Parse mandatory URL
|
||||||
|
v = p_server["urls"];
|
||||||
|
if (v.get_type() == godot::Variant::STRING) {
|
||||||
|
url = v;
|
||||||
|
ice_server.urls.push_back(url.utf8().get_data());
|
||||||
|
} else if (v.get_type() == godot::Variant::ARRAY) {
|
||||||
|
godot::Array names = v;
|
||||||
|
for (int j = 0; j < names.size(); j++) {
|
||||||
|
v = names[j];
|
||||||
|
ERR_FAIL_COND_V(v.get_type() != godot::Variant::STRING, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
url = v;
|
||||||
|
ice_server.urls.push_back(url.utf8().get_data());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V(GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
// Parse credentials (only meaningful for TURN, only support password)
|
||||||
|
if (p_server.has("username") && (v = p_server["username"]) && v.get_type() == godot::Variant::STRING) {
|
||||||
|
ice_server.username = (v.operator godot::String()).utf8().get_data();
|
||||||
|
}
|
||||||
|
if (p_server.has("credential") && (v = p_server["credential"]) && v.get_type() == godot::Variant::STRING) {
|
||||||
|
ice_server.password = (v.operator godot::String()).utf8().get_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
r_config.servers.push_back(ice_server);
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error _parse_channel_config(webrtc::DataChannelInit &r_config, godot::Dictionary p_dict) {
|
||||||
|
godot::Variant v;
|
||||||
|
#define _SET_N(PROP, PNAME, TYPE) \
|
||||||
|
if (p_dict.has(#PROP)) { \
|
||||||
|
v = p_dict[#PROP]; \
|
||||||
|
if (v.get_type() == godot::Variant::TYPE) \
|
||||||
|
r_config.PNAME = v; \
|
||||||
|
}
|
||||||
|
#define _SET(PROP, TYPE) _SET_N(PROP, PROP, TYPE)
|
||||||
|
_SET(negotiated, BOOL);
|
||||||
|
_SET(id, INT);
|
||||||
|
_SET_N(maxPacketLifeTime, maxRetransmitTime, INT);
|
||||||
|
_SET(maxRetransmits, INT);
|
||||||
|
_SET(ordered, BOOL);
|
||||||
|
#undef _SET
|
||||||
|
if (p_dict.has("protocol") && (v = p_dict["protocol"]) && v.get_type() == godot::Variant::STRING) {
|
||||||
|
r_config.protocol = v.operator godot::String().utf8().get_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID makes sense only when negotiated is true (and must be set in that case)
|
||||||
|
ERR_FAIL_COND_V(r_config.negotiated ? r_config.id == -1 : r_config.id != -1, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
// Only one of maxRetransmits and maxRetransmitTime can be set on a channel.
|
||||||
|
ERR_FAIL_COND_V(r_config.maxRetransmits && r_config.maxRetransmitTime, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::ConnectionState WebRTCLibPeerConnection::get_connection_state() const {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, STATE_CLOSED);
|
||||||
|
|
||||||
|
webrtc::PeerConnectionInterface::IceConnectionState state = peer_connection->ice_connection_state();
|
||||||
|
switch (state) {
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionNew:
|
||||||
|
return STATE_NEW;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionChecking:
|
||||||
|
return STATE_CONNECTING;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionConnected:
|
||||||
|
return STATE_CONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
|
||||||
|
return STATE_CONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionFailed:
|
||||||
|
return STATE_FAILED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
|
||||||
|
return STATE_DISCONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionClosed:
|
||||||
|
return STATE_CLOSED;
|
||||||
|
default:
|
||||||
|
return STATE_CLOSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::initialize(const godot_dictionary *p_config) {
|
||||||
|
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||||
|
godot::Dictionary d = *(godot::Dictionary *)p_config;
|
||||||
|
godot::Variant v;
|
||||||
|
if (d.has("iceServers") && (v = d["iceServers"]) && v.get_type() == godot::Variant::ARRAY) {
|
||||||
|
godot::Array servers = v;
|
||||||
|
for (int i = 0; i < servers.size(); i++) {
|
||||||
|
v = servers[i];
|
||||||
|
ERR_FAIL_COND_V(v.get_type() != godot::Variant::DICTIONARY, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
godot_error err;
|
||||||
|
godot::Dictionary server = v;
|
||||||
|
err = _parse_ice_server(config, server);
|
||||||
|
ERR_FAIL_COND_V(err != GODOT_OK, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _create_pc(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_object *WebRTCLibPeerConnection::create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config) {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, NULL);
|
||||||
|
|
||||||
|
// Read config from dictionary
|
||||||
|
webrtc::DataChannelInit config;
|
||||||
|
godot::Dictionary d = *(godot::Dictionary *)p_channel_config;
|
||||||
|
godot_error err = _parse_channel_config(config, d);
|
||||||
|
ERR_FAIL_COND_V(err != GODOT_OK, NULL);
|
||||||
|
|
||||||
|
WebRTCLibDataChannel *wrapper = WebRTCLibDataChannel::new_data_channel(peer_connection->CreateDataChannel(p_channel, &config));
|
||||||
|
ERR_FAIL_COND_V(wrapper == NULL, NULL);
|
||||||
|
return wrapper->_owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::create_offer() {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
peer_connection->CreateOffer(ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _MAKE_DESC(TYPE, SDP) webrtc::CreateSessionDescription((godot::String(TYPE) == godot::String("offer") ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer), SDP)
|
||||||
|
godot_error WebRTCLibPeerConnection::set_remote_description(const char *type, const char *sdp) {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
std::unique_ptr<webrtc::SessionDescriptionInterface> desc = _MAKE_DESC(type, sdp);
|
||||||
|
if (desc->GetType() == webrtc::SdpType::kOffer) {
|
||||||
|
ptr_ssdo->make_offer = true;
|
||||||
|
}
|
||||||
|
peer_connection->SetRemoteDescription(ptr_ssdo, desc.release());
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::set_local_description(const char *type, const char *sdp) {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
std::unique_ptr<webrtc::SessionDescriptionInterface> desc = _MAKE_DESC(type, sdp);
|
||||||
|
peer_connection->SetLocalDescription(ptr_ssdo, desc.release());
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
#undef _MAKE_DESC
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
|
||||||
|
webrtc::SdpParseError *error = nullptr;
|
||||||
|
webrtc::IceCandidateInterface *candidate = webrtc::CreateIceCandidate(
|
||||||
|
sdpMidName,
|
||||||
|
sdpMlineIndexName,
|
||||||
|
sdpName,
|
||||||
|
error);
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(error || !candidate, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
ERR_FAIL_COND_V(!peer_connection->AddIceCandidate(candidate), GODOT_FAILED);
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::poll() {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
|
||||||
|
while (!signal_queue.empty()) {
|
||||||
|
mutex_signal_queue->lock();
|
||||||
|
Signal signal = signal_queue.front();
|
||||||
|
signal_queue.pop();
|
||||||
|
mutex_signal_queue->unlock();
|
||||||
|
signal.emit(this);
|
||||||
|
}
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::close() {
|
||||||
|
if (peer_connection.get() != nullptr) {
|
||||||
|
peer_connection->Close();
|
||||||
|
}
|
||||||
|
peer_connection = nullptr;
|
||||||
|
while (!signal_queue.empty()) {
|
||||||
|
signal_queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::_register_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
|
||||||
|
// initialize variables:
|
||||||
|
mutex_signal_queue = new std::mutex;
|
||||||
|
|
||||||
|
// create a PeerConnectionFactoryInterface:
|
||||||
|
webrtc::PeerConnectionFactoryDependencies deps;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(signaling_thread.get() == nullptr);
|
||||||
|
deps.signaling_thread = signaling_thread.get();
|
||||||
|
pc_factory = webrtc::CreateModularPeerConnectionFactory(std::move(deps));
|
||||||
|
|
||||||
|
// Create peer connection with default configuration.
|
||||||
|
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||||
|
_create_pc(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::_create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config) {
|
||||||
|
ERR_FAIL_COND_V(pc_factory.get() == nullptr, GODOT_ERR_BUG);
|
||||||
|
peer_connection = nullptr;
|
||||||
|
peer_connection = pc_factory->CreatePeerConnection(config, nullptr, nullptr, &pco);
|
||||||
|
if (peer_connection.get() == nullptr) { // PeerConnection couldn't be created. Fail the method call.
|
||||||
|
ERR_PRINT("PeerConnection could not be created");
|
||||||
|
return GODOT_FAILED;
|
||||||
|
}
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::WebRTCLibPeerConnection() :
|
||||||
|
pco(this),
|
||||||
|
ptr_csdo(new rtc::RefCountedObject<GodotCSDO>(this)),
|
||||||
|
ptr_ssdo(new rtc::RefCountedObject<GodotSSDO>(this)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::~WebRTCLibPeerConnection() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
delete mutex_signal_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1, const godot::Variant &p_arg2, const godot::Variant &p_arg3) {
|
||||||
|
mutex_signal_queue->lock();
|
||||||
|
const godot::Variant argv[3] = { p_arg1, p_arg2, p_arg3 };
|
||||||
|
signal_queue.push(Signal(p_name, p_argc, argv));
|
||||||
|
mutex_signal_queue->unlock();
|
||||||
|
}
|
||||||
167
src/WebRTCLibPeerConnection.hpp
Normal file
167
src/WebRTCLibPeerConnection.hpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCLibPeerConnection.hpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_PEER_H
|
||||||
|
#define WEBRTC_PEER_H
|
||||||
|
|
||||||
|
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
|
||||||
|
|
||||||
|
#include "api/peer_connection_interface.h" // interface for all things needed from WebRTC
|
||||||
|
#include "media/base/media_engine.h" // needed for CreateModularPeerConnectionFactory
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
|
namespace godot_webrtc {
|
||||||
|
|
||||||
|
class WebRTCLibPeerConnection : public WebRTCPeerConnectionNative {
|
||||||
|
GODOT_CLASS(WebRTCLibPeerConnection, WebRTCPeerConnectionNative);
|
||||||
|
|
||||||
|
private:
|
||||||
|
godot_error _create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config);
|
||||||
|
|
||||||
|
static std::unique_ptr<rtc::Thread> signaling_thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void _register_methods();
|
||||||
|
static void initialize_signaling();
|
||||||
|
static void deinitialize_signaling();
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
|
||||||
|
ConnectionState get_connection_state() const;
|
||||||
|
|
||||||
|
godot_error initialize(const godot_dictionary *p_config);
|
||||||
|
godot_object *create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config);
|
||||||
|
godot_error create_offer();
|
||||||
|
godot_error set_remote_description(const char *type, const char *sdp);
|
||||||
|
godot_error set_local_description(const char *type, const char *sdp);
|
||||||
|
godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName);
|
||||||
|
godot_error poll();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection();
|
||||||
|
~WebRTCLibPeerConnection();
|
||||||
|
|
||||||
|
/* helper functions */
|
||||||
|
private:
|
||||||
|
void queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1 = godot::Variant(), const godot::Variant &p_arg2 = godot::Variant(), const godot::Variant &p_arg3 = godot::Variant());
|
||||||
|
void queue_packet(uint8_t *, int);
|
||||||
|
|
||||||
|
/** PeerConnectionObserver callback functions **/
|
||||||
|
class GodotPCO : public webrtc::PeerConnectionObserver {
|
||||||
|
public:
|
||||||
|
WebRTCLibPeerConnection *parent;
|
||||||
|
|
||||||
|
GodotPCO(WebRTCLibPeerConnection *p_parent) {
|
||||||
|
parent = p_parent;
|
||||||
|
}
|
||||||
|
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;
|
||||||
|
|
||||||
|
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override {}
|
||||||
|
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {}
|
||||||
|
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {}
|
||||||
|
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override {}
|
||||||
|
void OnRenegotiationNeeded() override {}
|
||||||
|
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {}
|
||||||
|
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** CreateSessionDescriptionObserver callback functions **/
|
||||||
|
class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
|
||||||
|
public:
|
||||||
|
WebRTCLibPeerConnection *parent = nullptr;
|
||||||
|
|
||||||
|
GodotCSDO(WebRTCLibPeerConnection *p_parent) {
|
||||||
|
parent = p_parent;
|
||||||
|
}
|
||||||
|
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
|
||||||
|
void OnFailure(webrtc::RTCError error) override {
|
||||||
|
ERR_PRINT(godot::String(error.message()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** SetSessionDescriptionObserver callback functions **/
|
||||||
|
class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
|
||||||
|
public:
|
||||||
|
WebRTCLibPeerConnection *parent = nullptr;
|
||||||
|
bool make_offer = false;
|
||||||
|
|
||||||
|
GodotSSDO(WebRTCLibPeerConnection *p_parent) {
|
||||||
|
parent = p_parent;
|
||||||
|
}
|
||||||
|
void OnSuccess() override;
|
||||||
|
void OnFailure(webrtc::RTCError error) override {
|
||||||
|
make_offer = false;
|
||||||
|
ERR_PRINT(godot::String(error.message()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Signal {
|
||||||
|
godot::String method;
|
||||||
|
godot::Variant argv[3];
|
||||||
|
int argc = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Signal(godot::String p_method, int p_argc, const godot::Variant *p_argv) {
|
||||||
|
method = p_method;
|
||||||
|
argc = p_argc;
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
argv[i] = p_argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit(godot::Object *p_object) {
|
||||||
|
if (argc == 0) {
|
||||||
|
p_object->emit_signal(method);
|
||||||
|
} else if (argc == 1) {
|
||||||
|
p_object->emit_signal(method, argv[0]);
|
||||||
|
} else if (argc == 2) {
|
||||||
|
p_object->emit_signal(method, argv[0], argv[1]);
|
||||||
|
} else if (argc == 3) {
|
||||||
|
p_object->emit_signal(method, argv[0], argv[1], argv[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GodotPCO pco;
|
||||||
|
rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
|
||||||
|
rtc::scoped_refptr<GodotCSDO> ptr_csdo;
|
||||||
|
|
||||||
|
std::mutex *mutex_signal_queue = nullptr;
|
||||||
|
std::queue<Signal> signal_queue;
|
||||||
|
|
||||||
|
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
|
||||||
|
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot_webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_PEER_H
|
||||||
120
src/init.cpp
120
src/init.cpp
@@ -1,25 +1,135 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
/*************************************************************************/
|
||||||
#include "net/WebRTCPeerNative.hpp"
|
/* init.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
#include <gdnative_api_struct.gen.h>
|
#include <gdnative_api_struct.gen.h>
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Singleton */
|
||||||
|
static bool _singleton = false;
|
||||||
|
static const godot_object *_singleton_lib = NULL;
|
||||||
|
static const godot_gdnative_core_api_struct *_singleton_api = NULL;
|
||||||
|
static godot_class_constructor _create_ns_cb = NULL;
|
||||||
|
static godot_method_bind *_set_script_mb = NULL;
|
||||||
|
static godot_method_bind *_set_class_name_mb = NULL;
|
||||||
|
static godot_method_bind *_set_library_mb = NULL;
|
||||||
|
|
||||||
|
void unregistered() {
|
||||||
|
_singleton = false; // We are no longer the active singleton
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_peer_connection_wp(godot_object *out) {
|
||||||
|
ERR_FAIL_COND_V(!_singleton, GODOT_FAILED);
|
||||||
|
// Create Script
|
||||||
|
godot_object *script = _create_ns_cb();
|
||||||
|
ERR_FAIL_COND_V(!script, GODOT_FAILED);
|
||||||
|
|
||||||
|
const void *args[] = { (void *)_singleton_lib };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_library_mb, script, args, nullptr);
|
||||||
|
|
||||||
|
godot_string s;
|
||||||
|
_singleton_api->godot_string_new(&s);
|
||||||
|
_singleton_api->godot_string_parse_utf8(&s, "WebRTCLibPeerConnection");
|
||||||
|
const void *args2[] = { (void *)&s };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_class_name_mb, script, args2, nullptr);
|
||||||
|
_singleton_api->godot_string_destroy(&s);
|
||||||
|
|
||||||
|
// Bind script to Object
|
||||||
|
const void *args3[] = { (void *)script };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_script_mb, out, args3, nullptr);
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_net_webrtc_library library = {
|
||||||
|
{ 3, 2 },
|
||||||
|
&unregistered,
|
||||||
|
&create_peer_connection_wp,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" void GDN_EXPORT godot_gdnative_singleton() {
|
||||||
|
if (WebRTCPeerConnectionNative::_net_api) {
|
||||||
|
ERR_FAIL_COND(!godot::gdnlib);
|
||||||
|
_singleton_lib = godot::gdnlib;
|
||||||
|
ERR_FAIL_COND(!godot::api);
|
||||||
|
_singleton_api = godot::api;
|
||||||
|
_create_ns_cb = godot::api->godot_get_class_constructor("NativeScript");
|
||||||
|
ERR_FAIL_COND(!_create_ns_cb);
|
||||||
|
_set_script_mb = godot::api->godot_method_bind_get_method("Object", "set_script");
|
||||||
|
ERR_FAIL_COND(!_set_script_mb);
|
||||||
|
_set_class_name_mb = godot::api->godot_method_bind_get_method("NativeScript", "set_class_name");
|
||||||
|
ERR_FAIL_COND(!_set_class_name_mb);
|
||||||
|
_set_library_mb = godot::api->godot_method_bind_get_method("NativeScript", "set_library");
|
||||||
|
ERR_FAIL_COND(!_set_library_mb);
|
||||||
|
// If registration is successful _singleton will be set to true
|
||||||
|
_singleton = WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(&library) == GODOT_OK;
|
||||||
|
if (!_singleton)
|
||||||
|
ERR_PRINT("Failed initializing webrtc singleton library");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Godot export stuff */
|
/* Godot export stuff */
|
||||||
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
||||||
const godot_gdnative_core_api_struct *api = o->api_struct;
|
const godot_gdnative_core_api_struct *api = o->api_struct;
|
||||||
for (int i = 0; i < api->num_extensions; i++) {
|
for (int i = 0; i < api->num_extensions; i++) {
|
||||||
if (api->extensions[i]->type == GDNATIVE_EXT_NET) {
|
if (api->extensions[i]->type != GDNATIVE_EXT_NET)
|
||||||
WebRTCPeerNative::_net_api = (godot_gdnative_ext_net_api_struct *)api->extensions[i];
|
continue;
|
||||||
|
|
||||||
|
const godot_gdnative_ext_net_api_struct *net_api = (godot_gdnative_ext_net_api_struct *)api->extensions[i];
|
||||||
|
|
||||||
|
if (!net_api->next)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (net_api->next->version.major == 3 && net_api->next->version.minor == 2) {
|
||||||
|
WebRTCPeerConnectionNative::_net_api = (const godot_gdnative_ext_net_3_2_api_struct *)net_api->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
godot_webrtc::WebRTCLibPeerConnection::initialize_signaling();
|
||||||
godot::Godot::gdnative_init(o);
|
godot::Godot::gdnative_init(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
|
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
|
||||||
|
if (_singleton) { // If we are the active singleton, unregister
|
||||||
|
WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(NULL);
|
||||||
|
}
|
||||||
|
godot_webrtc::WebRTCLibPeerConnection::deinitialize_signaling();
|
||||||
godot::Godot::gdnative_terminate(o);
|
godot::Godot::gdnative_terminate(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
||||||
godot::Godot::nativescript_init(handle);
|
godot::Godot::nativescript_init(handle);
|
||||||
|
|
||||||
godot::register_class<godot_webrtc::WebRTCLibPeer>();
|
godot::register_class<godot_webrtc::WebRTCLibPeerConnection>();
|
||||||
|
godot::register_class<godot_webrtc::WebRTCLibDataChannel>();
|
||||||
}
|
}
|
||||||
|
|||||||
126
src/net/WebRTCDataChannelNative.cpp
Normal file
126
src/net/WebRTCDataChannelNative.cpp
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCDataChannelNative.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "WebRTCDataChannelNative.hpp"
|
||||||
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
|
void WebRTCDataChannelNative::register_interface(const godot_net_webrtc_data_channel *p_interface) {
|
||||||
|
ERR_FAIL_COND(!WebRTCPeerConnectionNative::_net_api);
|
||||||
|
WebRTCPeerConnectionNative::_net_api->godot_net_bind_webrtc_data_channel(_owner, p_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCDataChannelNative::_register_methods() {}
|
||||||
|
|
||||||
|
void WebRTCDataChannelNative::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCDataChannelNative::~WebRTCDataChannelNative() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The C interface that implements WebRTCDataChannel.
|
||||||
|
* In this case it forwards calls to our C++ class, but could be plain C,
|
||||||
|
* and you could use void *user for any kind of state struct pointer you have.
|
||||||
|
*/
|
||||||
|
godot_error get_packet_wdc(void *user, const uint8_t **r_buffer, int *r_len) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_packet(r_buffer, r_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error put_packet_wdc(void *user, const uint8_t *p_buffer, int p_len) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->put_packet(p_buffer, p_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_available_packet_count_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_available_packet_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_max_packet_size_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_max_packet_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_write_mode_wdc(void *user, godot_int write_mode) {
|
||||||
|
((WebRTCDataChannelNative *)user)->set_write_mode(write_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_write_mode_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_write_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool was_string_packet_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->was_string_packet();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_ready_state_wdc(const void *user) {
|
||||||
|
return (godot_int)(((WebRTCDataChannelNative *)user)->get_ready_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_label_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_label();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ordered_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->is_ordered();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_id_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_max_packet_life_time_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_max_packet_life_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_max_retransmits_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_max_retransmits();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_protocol_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_protocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_negotiated_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->is_negotiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_buffered_amount_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_buffered_amount();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error poll_wdc(void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_wdc(void *user) {
|
||||||
|
((WebRTCDataChannelNative *)user)->close();
|
||||||
|
}
|
||||||
139
src/net/WebRTCDataChannelNative.hpp
Normal file
139
src/net/WebRTCDataChannelNative.hpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCDataChannelNative.hpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
|
#define WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
|
|
||||||
|
#include <Godot.hpp>
|
||||||
|
#include <Reference.hpp>
|
||||||
|
#include <WebRTCDataChannelGDNative.hpp>
|
||||||
|
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Forward declare interface functions */
|
||||||
|
godot_error get_packet_wdc(void *, const uint8_t **, int *);
|
||||||
|
godot_error put_packet_wdc(void *, const uint8_t *, int);
|
||||||
|
godot_int get_available_packet_count_wdc(const void *);
|
||||||
|
godot_int get_max_packet_size_wdc(const void *);
|
||||||
|
|
||||||
|
void set_write_mode_wdc(void *, godot_int);
|
||||||
|
godot_int get_write_mode_wdc(const void *);
|
||||||
|
bool was_string_packet_wdc(const void *);
|
||||||
|
godot_int get_ready_state_wdc(const void *);
|
||||||
|
const char *get_label_wdc(const void *);
|
||||||
|
bool is_ordered_wdc(const void *);
|
||||||
|
int get_id_wdc(const void *);
|
||||||
|
int get_max_packet_life_time_wdc(const void *);
|
||||||
|
int get_max_retransmits_wdc(const void *);
|
||||||
|
const char *get_protocol_wdc(const void *);
|
||||||
|
bool is_negotiated_wdc(const void *);
|
||||||
|
int get_buffered_amount_wdc(const void *);
|
||||||
|
godot_error poll_wdc(void *);
|
||||||
|
void close_wdc(void *);
|
||||||
|
|
||||||
|
#if GODOT_NET_WEBRTC_API_MAJOR == 3 && GODOT_NET_WEBRTC_API_MINOR < 4
|
||||||
|
extern "C" {
|
||||||
|
/* Extensions to WebRTCDataChannel */
|
||||||
|
typedef struct {
|
||||||
|
int (*get_buffered_amount)(const void *);
|
||||||
|
|
||||||
|
void *next; /* For extension? */
|
||||||
|
} godot_net_webrtc_data_channel_ext;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class WebRTCDataChannelNative : public godot::WebRTCDataChannelGDNative {
|
||||||
|
GODOT_CLASS(WebRTCDataChannelNative, godot::WebRTCDataChannelGDNative);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
godot_net_webrtc_data_channel_ext interface_ext = {
|
||||||
|
&get_buffered_amount_wdc,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
godot_net_webrtc_data_channel interface = {
|
||||||
|
{ 3, 1 },
|
||||||
|
this,
|
||||||
|
|
||||||
|
&get_packet_wdc,
|
||||||
|
&put_packet_wdc,
|
||||||
|
&get_available_packet_count_wdc,
|
||||||
|
&get_max_packet_size_wdc,
|
||||||
|
|
||||||
|
&set_write_mode_wdc,
|
||||||
|
&get_write_mode_wdc,
|
||||||
|
&was_string_packet_wdc,
|
||||||
|
&get_ready_state_wdc,
|
||||||
|
&get_label_wdc,
|
||||||
|
&is_ordered_wdc,
|
||||||
|
&get_id_wdc,
|
||||||
|
&get_max_packet_life_time_wdc,
|
||||||
|
&get_max_retransmits_wdc,
|
||||||
|
&get_protocol_wdc,
|
||||||
|
&is_negotiated_wdc,
|
||||||
|
|
||||||
|
&poll_wdc,
|
||||||
|
&close_wdc,
|
||||||
|
&interface_ext,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void _register_methods();
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
void register_interface(const godot_net_webrtc_data_channel *interface);
|
||||||
|
|
||||||
|
virtual void set_write_mode(godot_int mode) = 0;
|
||||||
|
virtual godot_int get_write_mode() const = 0;
|
||||||
|
virtual bool was_string_packet() const = 0;
|
||||||
|
|
||||||
|
virtual ChannelState get_ready_state() const = 0;
|
||||||
|
virtual const char *get_label() const = 0;
|
||||||
|
virtual bool is_ordered() const = 0;
|
||||||
|
virtual int get_id() const = 0;
|
||||||
|
virtual int get_max_packet_life_time() const = 0;
|
||||||
|
virtual int get_max_retransmits() const = 0;
|
||||||
|
virtual const char *get_protocol() const = 0;
|
||||||
|
virtual bool is_negotiated() const = 0;
|
||||||
|
virtual int get_buffered_amount() const = 0;
|
||||||
|
|
||||||
|
virtual godot_error poll() = 0;
|
||||||
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
/* PacketPeer */
|
||||||
|
virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len) = 0;
|
||||||
|
virtual godot_error put_packet(const uint8_t *p_buffer, int p_len) = 0;
|
||||||
|
virtual godot_int get_available_packet_count() const = 0;
|
||||||
|
virtual godot_int get_max_packet_size() const = 0;
|
||||||
|
|
||||||
|
~WebRTCDataChannelNative();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
95
src/net/WebRTCPeerConnectionNative.cpp
Normal file
95
src/net/WebRTCPeerConnectionNative.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCPeerConnectionNative.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
|
const godot_gdnative_ext_net_3_2_api_struct *WebRTCPeerConnectionNative::_net_api = NULL;
|
||||||
|
|
||||||
|
void WebRTCPeerConnectionNative::register_interface(const godot_net_webrtc_peer_connection *p_interface) {
|
||||||
|
ERR_FAIL_COND(!_net_api);
|
||||||
|
_net_api->godot_net_bind_webrtc_peer_connection(_owner, p_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCPeerConnectionNative::_register_methods() {}
|
||||||
|
|
||||||
|
void WebRTCPeerConnectionNative::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCPeerConnectionNative::~WebRTCPeerConnectionNative() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The C interface that implements WebRTCPeerConnection.
|
||||||
|
* In this case it forwards calls to our C++ class, but could be plain C,
|
||||||
|
* and you could use void *user for any kind of state struct pointer you have.
|
||||||
|
*/
|
||||||
|
godot_int get_connection_state_wp(const void *user) {
|
||||||
|
return (godot_int)((WebRTCPeerConnectionNative *)user)->get_connection_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error initialize_wp(void *user, const godot_dictionary *p_config) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->initialize(p_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_object *create_data_channel_wp(void *user, const char *p_channel, const godot_dictionary *p_channel_config) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->create_data_channel(p_channel, p_channel_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_offer_wp(void *user) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->create_offer();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_answer_wp(void *user) {
|
||||||
|
return GODOT_ERR_UNAVAILABLE; // Not implemented, not used yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error set_remote_description_wp(void *user, const char *type, const char *sdp) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->set_remote_description(type, sdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error set_local_description_wp(void *user, const char *type, const char *sdp) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->set_local_description(type, sdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error add_ice_candidate_wp(void *user, const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->add_ice_candidate(sdpMidName, sdpMlineIndexName, sdpName);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error poll_wp(void *user) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_wp(void *user) {
|
||||||
|
((WebRTCPeerConnectionNative *)user)->close();
|
||||||
|
}
|
||||||
96
src/net/WebRTCPeerConnectionNative.hpp
Normal file
96
src/net/WebRTCPeerConnectionNative.hpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* WebRTCPeerConnectionNative.hpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_PEER_NATIVE
|
||||||
|
#define WEBRTC_PEER_NATIVE
|
||||||
|
|
||||||
|
#include <Godot.hpp>
|
||||||
|
#include <Reference.hpp>
|
||||||
|
#include <WebRTCPeerConnectionGDNative.hpp>
|
||||||
|
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Forward declare interface functions */
|
||||||
|
godot_int get_connection_state_wp(const void *);
|
||||||
|
|
||||||
|
godot_error initialize_wp(void *, const godot_dictionary *);
|
||||||
|
godot_object *create_data_channel_wp(void *, const char *, const godot_dictionary *);
|
||||||
|
godot_error create_offer_wp(void *);
|
||||||
|
godot_error create_answer_wp(void *);
|
||||||
|
godot_error set_remote_description_wp(void *, const char *, const char *);
|
||||||
|
godot_error set_local_description_wp(void *, const char *, const char *);
|
||||||
|
godot_error add_ice_candidate_wp(void *, const char *, int, const char *);
|
||||||
|
godot_error poll_wp(void *);
|
||||||
|
void close_wp(void *);
|
||||||
|
|
||||||
|
class WebRTCPeerConnectionNative : public godot::WebRTCPeerConnectionGDNative {
|
||||||
|
GODOT_CLASS(WebRTCPeerConnectionNative, godot::WebRTCPeerConnectionGDNative);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
godot_net_webrtc_peer_connection interface = {
|
||||||
|
{ 3, 1 },
|
||||||
|
this,
|
||||||
|
|
||||||
|
&get_connection_state_wp,
|
||||||
|
|
||||||
|
&initialize_wp,
|
||||||
|
&create_data_channel_wp,
|
||||||
|
&create_offer_wp,
|
||||||
|
&create_answer_wp,
|
||||||
|
&set_remote_description_wp,
|
||||||
|
&set_local_description_wp,
|
||||||
|
&add_ice_candidate_wp,
|
||||||
|
&poll_wp,
|
||||||
|
&close_wp,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void _register_methods();
|
||||||
|
static const godot_gdnative_ext_net_3_2_api_struct *_net_api;
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
void register_interface(const godot_net_webrtc_peer_connection *interface);
|
||||||
|
|
||||||
|
virtual ConnectionState get_connection_state() const = 0;
|
||||||
|
|
||||||
|
virtual godot_error initialize(const godot_dictionary *p_config) = 0;
|
||||||
|
virtual godot_object *create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config) = 0;
|
||||||
|
virtual godot_error create_offer() = 0;
|
||||||
|
virtual godot_error set_remote_description(const char *type, const char *sdp) = 0;
|
||||||
|
virtual godot_error set_local_description(const char *type, const char *sdp) = 0;
|
||||||
|
virtual godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) = 0;
|
||||||
|
virtual godot_error poll() = 0;
|
||||||
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
~WebRTCPeerConnectionNative();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_PEER_NATIVE
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#include "WebRTCPeerNative.hpp"
|
|
||||||
|
|
||||||
const godot_gdnative_ext_net_api_struct *WebRTCPeerNative::_net_api = NULL;
|
|
||||||
|
|
||||||
void WebRTCPeerNative::register_interface(const godot_net_webrtc_peer *p_interface) {
|
|
||||||
ERR_FAIL_COND(!_net_api);
|
|
||||||
_net_api->godot_net_bind_webrtc_peer(_owner, p_interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCPeerNative::_register_methods() {}
|
|
||||||
|
|
||||||
void WebRTCPeerNative::_init() {
|
|
||||||
register_interface(&interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCPeerNative::~WebRTCPeerNative() {
|
|
||||||
if (_owner) {
|
|
||||||
register_interface(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The C interface that implements WebRTCPeer.
|
|
||||||
* In this case it forwards calls to our C++ class, but could be plain C,
|
|
||||||
* and you could use void *user for any kind of state struct pointer you have.
|
|
||||||
*/
|
|
||||||
godot_error get_packet_wp(void *user, const uint8_t **r_buffer, int *r_len) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_packet(r_buffer, r_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error put_packet_wp(void *user, const uint8_t *p_buffer, int p_len) {
|
|
||||||
return ((WebRTCPeerNative *)user)->put_packet(p_buffer, p_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_available_packet_count_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_available_packet_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_max_packet_size_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_max_packet_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_write_mode_wp(void *user, godot_int write_mode) {
|
|
||||||
((WebRTCPeerNative *)user)->set_write_mode(write_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_write_mode_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_write_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool was_string_packet_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->was_string_packet();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_connection_state_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_connection_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error create_offer_wp(void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->create_offer();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error set_remote_description_wp(void *user, const char *type, const char *sdp) {
|
|
||||||
return ((WebRTCPeerNative *)user)->set_remote_description(type, sdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error set_local_description_wp(void *user, const char *type, const char *sdp) {
|
|
||||||
return ((WebRTCPeerNative *)user)->set_local_description(type, sdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error add_ice_candidate_wp(void *user, const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
|
||||||
return ((WebRTCPeerNative *)user)->add_ice_candidate(sdpMidName, sdpMlineIndexName, sdpName);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error poll_wp(void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->poll();
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#ifndef WEBRTC_PEER_NATIVE
|
|
||||||
#define WEBRTC_PEER_NATIVE
|
|
||||||
|
|
||||||
#include <Godot.hpp>
|
|
||||||
#include <Reference.hpp>
|
|
||||||
#include <WebRTCPeerGDNative.hpp>
|
|
||||||
|
|
||||||
#include <net/godot_net.h>
|
|
||||||
|
|
||||||
/* Forward declare interface functions */
|
|
||||||
godot_error get_packet_wp(void *, const uint8_t **, int *);
|
|
||||||
godot_error put_packet_wp(void *, const uint8_t *, int);
|
|
||||||
godot_int get_available_packet_count_wp(const void *);
|
|
||||||
godot_int get_max_packet_size_wp(const void *);
|
|
||||||
|
|
||||||
void set_write_mode_wp(void *, godot_int);
|
|
||||||
godot_int get_write_mode_wp(const void *);
|
|
||||||
bool was_string_packet_wp(const void *);
|
|
||||||
godot_int get_connection_state_wp(const void *);
|
|
||||||
|
|
||||||
godot_error create_offer_wp(void *);
|
|
||||||
godot_error set_remote_description_wp(void *, const char *, const char *);
|
|
||||||
godot_error set_local_description_wp(void *, const char *, const char *);
|
|
||||||
godot_error add_ice_candidate_wp(void *, const char *, int, const char *);
|
|
||||||
godot_error poll_wp(void *);
|
|
||||||
|
|
||||||
class WebRTCPeerNative : public godot::WebRTCPeerGDNative {
|
|
||||||
GODOT_CLASS(WebRTCPeerNative, godot::WebRTCPeerGDNative);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
godot_net_webrtc_peer interface = {
|
|
||||||
{ 3, 1 },
|
|
||||||
this,
|
|
||||||
|
|
||||||
&get_packet_wp,
|
|
||||||
&put_packet_wp,
|
|
||||||
&get_available_packet_count_wp,
|
|
||||||
&get_max_packet_size_wp,
|
|
||||||
|
|
||||||
&set_write_mode_wp,
|
|
||||||
&get_write_mode_wp,
|
|
||||||
&was_string_packet_wp,
|
|
||||||
&get_connection_state_wp,
|
|
||||||
|
|
||||||
&create_offer_wp,
|
|
||||||
&set_remote_description_wp,
|
|
||||||
&set_local_description_wp,
|
|
||||||
&add_ice_candidate_wp,
|
|
||||||
&poll_wp,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void _register_methods();
|
|
||||||
static const godot_gdnative_ext_net_api_struct *_net_api;
|
|
||||||
|
|
||||||
void _init();
|
|
||||||
void register_interface(const godot_net_webrtc_peer *interface);
|
|
||||||
|
|
||||||
virtual void set_write_mode(godot_int mode) = 0;
|
|
||||||
virtual godot_int get_write_mode() const = 0;
|
|
||||||
virtual bool was_string_packet() const = 0;
|
|
||||||
virtual godot_int get_connection_state() const = 0;
|
|
||||||
|
|
||||||
virtual godot_error create_offer() = 0;
|
|
||||||
virtual godot_error set_remote_description(const char *type, const char *sdp) = 0;
|
|
||||||
virtual godot_error set_local_description(const char *type, const char *sdp) = 0;
|
|
||||||
virtual godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) = 0;
|
|
||||||
virtual godot_error poll() = 0;
|
|
||||||
|
|
||||||
/* PacketPeer */
|
|
||||||
virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len) = 0;
|
|
||||||
virtual godot_error put_packet(const uint8_t *p_buffer, int p_len) = 0;
|
|
||||||
virtual godot_int get_available_packet_count() const = 0;
|
|
||||||
virtual godot_int get_max_packet_size() const = 0;
|
|
||||||
|
|
||||||
~WebRTCPeerNative();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WEBRTC_PEER_NATIVE
|
|
||||||
2
webrtc/lib/.gitignore
vendored
2
webrtc/lib/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
||||||
Reference in New Issue
Block a user