@livekit/react-native 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +15 -6
  2. package/android/build.gradle +1 -1
  3. package/android/gradle/wrapper/gradle-wrapper.properties +3 -1
  4. package/android/gradlew +29 -14
  5. package/android/gradlew.bat +19 -16
  6. package/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt +14 -1
  7. package/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt +10 -0
  8. package/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt +2 -2
  9. package/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt +20 -0
  10. package/lib/commonjs/audio/AudioManager.js +4 -27
  11. package/lib/commonjs/audio/AudioManager.js.map +1 -1
  12. package/lib/commonjs/audio/AudioSession.js +55 -23
  13. package/lib/commonjs/audio/AudioSession.js.map +1 -1
  14. package/lib/commonjs/components/LiveKitRoom.js +3 -6
  15. package/lib/commonjs/components/LiveKitRoom.js.map +1 -1
  16. package/lib/commonjs/components/VideoTrack.js +30 -66
  17. package/lib/commonjs/components/VideoTrack.js.map +1 -1
  18. package/lib/commonjs/components/VideoView.js +32 -63
  19. package/lib/commonjs/components/VideoView.js.map +1 -1
  20. package/lib/commonjs/components/ViewPortDetector.js +15 -62
  21. package/lib/commonjs/components/ViewPortDetector.js.map +1 -1
  22. package/lib/commonjs/hooks.js +6 -63
  23. package/lib/commonjs/hooks.js.map +1 -1
  24. package/lib/commonjs/index.js +10 -85
  25. package/lib/commonjs/index.js.map +1 -1
  26. package/lib/commonjs/logger.js +4 -14
  27. package/lib/commonjs/logger.js.map +1 -1
  28. package/lib/commonjs/polyfills/EncoderDecoderTogether.min.js +105 -0
  29. package/lib/commonjs/polyfills/EncoderDecoderTogether.min.js.map +1 -0
  30. package/lib/commonjs/useParticipant.js +5 -13
  31. package/lib/commonjs/useParticipant.js.map +1 -1
  32. package/lib/commonjs/useRoom.js +17 -33
  33. package/lib/commonjs/useRoom.js.map +1 -1
  34. package/lib/module/audio/AudioManager.js +3 -17
  35. package/lib/module/audio/AudioManager.js.map +1 -1
  36. package/lib/module/audio/AudioSession.js +54 -16
  37. package/lib/module/audio/AudioSession.js.map +1 -1
  38. package/lib/module/components/LiveKitRoom.js +1 -0
  39. package/lib/module/components/LiveKitRoom.js.map +1 -1
  40. package/lib/module/components/VideoTrack.js +18 -44
  41. package/lib/module/components/VideoTrack.js.map +1 -1
  42. package/lib/module/components/VideoView.js +18 -42
  43. package/lib/module/components/VideoView.js.map +1 -1
  44. package/lib/module/components/ViewPortDetector.js +13 -54
  45. package/lib/module/components/ViewPortDetector.js.map +1 -1
  46. package/lib/module/hooks.js +1 -2
  47. package/lib/module/hooks.js.map +1 -1
  48. package/lib/module/index.js +6 -24
  49. package/lib/module/index.js.map +1 -1
  50. package/lib/module/logger.js +2 -6
  51. package/lib/module/logger.js.map +1 -1
  52. package/lib/module/polyfills/EncoderDecoderTogether.min.js +105 -0
  53. package/lib/module/polyfills/EncoderDecoderTogether.min.js.map +1 -0
  54. package/lib/module/useParticipant.js +5 -11
  55. package/lib/module/useParticipant.js.map +1 -1
  56. package/lib/module/useRoom.js +17 -30
  57. package/lib/module/useRoom.js.map +1 -1
  58. package/lib/typescript/babel.config.d.ts +1 -0
  59. package/lib/typescript/docs/assets/icons.d.ts +0 -0
  60. package/lib/typescript/docs/assets/main.d.ts +0 -0
  61. package/lib/typescript/docs/assets/navigation.d.ts +0 -0
  62. package/lib/typescript/docs/assets/search.d.ts +0 -0
  63. package/lib/typescript/lib/commonjs/audio/AudioManager.d.ts +10 -0
  64. package/lib/typescript/lib/commonjs/audio/AudioSession.d.ts +33 -0
  65. package/lib/typescript/lib/commonjs/components/LiveKitRoom.d.ts +20 -0
  66. package/lib/typescript/lib/commonjs/components/VideoTrack.d.ts +8 -0
  67. package/lib/typescript/lib/commonjs/components/VideoView.d.ts +14 -0
  68. package/lib/typescript/lib/commonjs/components/ViewPortDetector.d.ts +30 -0
  69. package/lib/typescript/lib/commonjs/hooks.d.ts +29 -0
  70. package/lib/typescript/lib/commonjs/index.d.ts +10 -0
  71. package/lib/typescript/lib/commonjs/logger.d.ts +8 -0
  72. package/lib/typescript/lib/commonjs/useParticipant.d.ts +14 -0
  73. package/lib/typescript/lib/commonjs/useRoom.d.ts +16 -0
  74. package/lib/typescript/lib/module/audio/AudioManager.d.ts +9 -0
  75. package/lib/typescript/lib/module/audio/AudioSession.d.ts +31 -0
  76. package/lib/typescript/lib/module/components/LiveKitRoom.d.ts +22 -0
  77. package/lib/typescript/lib/module/components/VideoTrack.d.ts +9 -0
  78. package/lib/typescript/lib/module/components/VideoView.d.ts +9 -0
  79. package/lib/typescript/lib/module/components/ViewPortDetector.d.ts +29 -0
  80. package/lib/typescript/lib/module/hooks.d.ts +1 -0
  81. package/lib/typescript/lib/module/index.d.ts +18 -0
  82. package/lib/typescript/lib/module/logger.d.ts +8 -0
  83. package/lib/typescript/lib/module/polyfills/EncoderDecoderTogether.min.d.ts +0 -0
  84. package/lib/typescript/lib/module/useParticipant.d.ts +13 -0
  85. package/lib/typescript/lib/module/useRoom.d.ts +15 -0
  86. package/lib/typescript/scripts/bootstrap.d.ts +1 -0
  87. package/lib/typescript/{audio → src/audio}/AudioSession.d.ts +7 -9
  88. package/lib/typescript/{components → src/components}/LiveKitRoom.d.ts +1 -1
  89. package/lib/typescript/{components → src/components}/VideoTrack.d.ts +2 -2
  90. package/lib/typescript/{components → src/components}/VideoView.d.ts +3 -3
  91. package/lib/typescript/{components → src/components}/ViewPortDetector.d.ts +3 -3
  92. package/lib/typescript/src/hooks.d.ts +3 -0
  93. package/lib/typescript/src/index.d.ts +20 -0
  94. package/lib/typescript/{logger.d.ts → src/logger.d.ts} +2 -2
  95. package/lib/typescript/src/polyfills/EncoderDecoderTogether.min.d.ts +0 -0
  96. package/lib/typescript/{useRoom.d.ts → src/useRoom.d.ts} +1 -1
  97. package/package.json +22 -19
  98. package/src/audio/AudioSession.ts +0 -2
  99. package/src/components/LiveKitRoom.tsx +1 -1
  100. package/src/components/VideoTrack.tsx +7 -2
  101. package/src/components/VideoView.tsx +8 -3
  102. package/src/components/ViewPortDetector.tsx +4 -4
  103. package/src/hooks.ts +12 -9
  104. package/src/index.tsx +11 -9
  105. package/src/polyfills/EncoderDecoderTogether.min.js +6 -0
  106. package/src/useRoom.ts +1 -1
  107. package/lib/typescript/hooks.d.ts +0 -2
  108. package/lib/typescript/index.d.ts +0 -19
  109. /package/lib/typescript/{audio → src/audio}/AudioManager.d.ts +0 -0
  110. /package/lib/typescript/{useParticipant.d.ts → src/useParticipant.d.ts} +0 -0
package/README.md CHANGED
@@ -107,7 +107,7 @@ LiveKit is available on Expo through development builds. You can find our Expo p
107
107
 
108
108
  ## Example app
109
109
 
110
- We've included an [example app](example/) that you can try out.
110
+ You can try our standalone example app [here](https://github.com/livekit-examples/react-native-meet/).
111
111
 
112
112
  ## Usage
113
113
 
@@ -295,11 +295,20 @@ Enabling screenshare requires extra installation steps:
295
295
 
296
296
  Android screenshare requires a foreground service with type `mediaProjection` to be present.
297
297
 
298
- The example app uses [@voximplant/react-native-foreground-service](https://github.com/voximplant/react-native-foreground-service) for this.
299
- Ensure that the service is labelled a `mediaProjection` service like so:
298
+ The example app uses [@supersami/rn-foreground-service](https://github.com/Raja0sama/rn-foreground-service) for this.
299
+
300
+ Add the following permissions to your `AndroidManifest.xml` file:
301
+
302
+ ```xml
303
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
304
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
305
+ ```
306
+
307
+ Declare the the service and ensure it's labelled a `mediaProjection` service like so:
300
308
 
301
309
  ```xml
302
- <service android:name="com.voximplant.foregroundservice.VIForegroundService" android:foregroundServiceType="mediaProjection" />
310
+ <service android:name="com.supersami.foregroundservice.ForegroundService" android:foregroundServiceType="mediaProjection" />
311
+ <service android:name="com.supersami.foregroundservice.ForegroundServiceTask" />
303
312
  ```
304
313
 
305
314
  Once setup, start the foreground service prior to using screenshare.
@@ -370,8 +379,8 @@ Apache License 2.0
370
379
  <br/><table>
371
380
  <thead><tr><th colspan="2">LiveKit Ecosystem</th></tr></thead>
372
381
  <tbody>
373
- <tr><td>Real-time SDKs</td><td><a href="https://github.com/livekit/components-js">React Components</a> · <a href="https://github.com/livekit/client-sdk-js">JavaScript</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <b>React Native</b> · <a href="https://github.com/livekit/client-sdk-rust">Rust</a> · <a href="https://github.com/livekit/client-sdk-python">Python</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (web)</a> · <a href="https://github.com/livekit/client-sdk-unity">Unity (beta)</a></td></tr><tr></tr>
374
- <tr><td>Server APIs</td><td><a href="https://github.com/livekit/server-sdk-js">Node.js</a> · <a href="https://github.com/livekit/server-sdk-go">Golang</a> · <a href="https://github.com/livekit/server-sdk-ruby">Ruby</a> · <a href="https://github.com/livekit/server-sdk-kotlin">Java/Kotlin</a> · <a href="https://github.com/livekit/client-sdk-python">Python</a> · <a href="https://github.com/livekit/client-sdk-rust">Rust</a> · <a href="https://github.com/agence104/livekit-server-sdk-php">PHP (community)</a></td></tr><tr></tr>
382
+ <tr><td>Real-time SDKs</td><td><a href="https://github.com/livekit/components-js">React Components</a> · <a href="https://github.com/livekit/client-sdk-js">Browser</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <b>React Native</b> · <a href="https://github.com/livekit/rust-sdks">Rust</a> · <a href="https://github.com/livekit/node-sdks">Node.js</a> · <a href="https://github.com/livekit/python-sdks">Python</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (web)</a> · <a href="https://github.com/livekit/client-sdk-unity">Unity (beta)</a></td></tr><tr></tr>
383
+ <tr><td>Server APIs</td><td><a href="https://github.com/livekit/node-sdks">Node.js</a> · <a href="https://github.com/livekit/server-sdk-go">Golang</a> · <a href="https://github.com/livekit/server-sdk-ruby">Ruby</a> · <a href="https://github.com/livekit/server-sdk-kotlin">Java/Kotlin</a> · <a href="https://github.com/livekit/python-sdks">Python</a> · <a href="https://github.com/livekit/rust-sdks">Rust</a> · <a href="https://github.com/agence104/livekit-server-sdk-php">PHP (community)</a></td></tr><tr></tr>
375
384
  <tr><td>Agents Frameworks</td><td><a href="https://github.com/livekit/agents">Python</a> · <a href="https://github.com/livekit/agent-playground">Playground</a></td></tr><tr></tr>
376
385
  <tr><td>Services</td><td><a href="https://github.com/livekit/livekit">Livekit server</a> · <a href="https://github.com/livekit/egress">Egress</a> · <a href="https://github.com/livekit/ingress">Ingress</a> · <a href="https://github.com/livekit/sip">SIP</a></td></tr><tr></tr>
377
386
  <tr><td>Resources</td><td><a href="https://docs.livekit.io">Docs</a> · <a href="https://github.com/livekit-examples">Example apps</a> · <a href="https://livekit.io/cloud">Cloud</a> · <a href="https://docs.livekit.io/oss/deployment">Self-hosting</a> · <a href="https://github.com/livekit/livekit-cli">CLI</a></td></tr>
@@ -130,7 +130,7 @@ dependencies {
130
130
  api 'com.facebook.react:react-native:+'
131
131
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
132
132
  api 'com.github.davidliu:audioswitch:89582c47c9a04c62f90aa5e57251af4800a62c9a'
133
- api 'io.github.webrtc-sdk:android:114.5735.05'
133
+ api 'io.github.webrtc-sdk:android:125.6422.02'
134
134
  implementation project(':livekit_react-native-webrtc')
135
135
  implementation "androidx.annotation:annotation:1.4.0"
136
136
  }
@@ -1,5 +1,7 @@
1
1
  distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
- distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
4
+ networkTimeout=10000
5
+ validateDistributionUrl=true
4
6
  zipStoreBase=GRADLE_USER_HOME
5
7
  zipStorePath=wrapper/dists
package/android/gradlew CHANGED
@@ -55,7 +55,7 @@
55
55
  # Darwin, MinGW, and NonStop.
56
56
  #
57
57
  # (3) This script is generated from the Groovy template
58
- # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
58
+ # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59
59
  # within the Gradle project.
60
60
  #
61
61
  # You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,11 @@ do
80
80
  esac
81
81
  done
82
82
 
83
- APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84
-
85
- APP_NAME="Gradle"
83
+ # This is normally unused
84
+ # shellcheck disable=SC2034
86
85
  APP_BASE_NAME=${0##*/}
87
-
88
- # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89
- DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
86
+ # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
87
+ APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
90
88
 
91
89
  # Use the maximum available, or set MAX_FD != -1 to use that value.
92
90
  MAX_FD=maximum
@@ -133,22 +131,29 @@ location of your Java installation."
133
131
  fi
134
132
  else
135
133
  JAVACMD=java
136
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
134
+ if ! command -v java >/dev/null 2>&1
135
+ then
136
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137
137
 
138
138
  Please set the JAVA_HOME variable in your environment to match the
139
139
  location of your Java installation."
140
+ fi
140
141
  fi
141
142
 
142
143
  # Increase the maximum file descriptors if we can.
143
144
  if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144
145
  case $MAX_FD in #(
145
146
  max*)
147
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
148
+ # shellcheck disable=SC2039,SC3045
146
149
  MAX_FD=$( ulimit -H -n ) ||
147
150
  warn "Could not query maximum file descriptor limit"
148
151
  esac
149
152
  case $MAX_FD in #(
150
153
  '' | soft) :;; #(
151
154
  *)
155
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
156
+ # shellcheck disable=SC2039,SC3045
152
157
  ulimit -n "$MAX_FD" ||
153
158
  warn "Could not set maximum file descriptor limit to $MAX_FD"
154
159
  esac
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
193
198
  done
194
199
  fi
195
200
 
196
- # Collect all arguments for the java command;
197
- # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198
- # shell script including quotes and variable substitutions, so put them in
199
- # double quotes to make sure that they get re-expanded; and
200
- # * put everything else in single quotes, so that it's not re-expanded.
201
+
202
+ # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203
+ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204
+
205
+ # Collect all arguments for the java command:
206
+ # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
207
+ # and any embedded shellness will be escaped.
208
+ # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
209
+ # treated as '${Hostname}' itself on the command line.
201
210
 
202
211
  set -- \
203
212
  "-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -205,6 +214,12 @@ set -- \
205
214
  org.gradle.wrapper.GradleWrapperMain \
206
215
  "$@"
207
216
 
217
+ # Stop when "xargs" is not available.
218
+ if ! command -v xargs >/dev/null 2>&1
219
+ then
220
+ die "xargs is not available"
221
+ fi
222
+
208
223
  # Use "xargs" to parse quoted args.
209
224
  #
210
225
  # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
@@ -231,4 +246,4 @@ eval "set -- $(
231
246
  tr '\n' ' '
232
247
  )" '"$@"'
233
248
 
234
- exec "$JAVACMD" "$@"
249
+ exec "$JAVACMD" "$@"
@@ -14,7 +14,7 @@
14
14
  @rem limitations under the License.
15
15
  @rem
16
16
 
17
- @if "%DEBUG%" == "" @echo off
17
+ @if "%DEBUG%"=="" @echo off
18
18
  @rem ##########################################################################
19
19
  @rem
20
20
  @rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
25
25
  if "%OS%"=="Windows_NT" setlocal
26
26
 
27
27
  set DIRNAME=%~dp0
28
- if "%DIRNAME%" == "" set DIRNAME=.
28
+ if "%DIRNAME%"=="" set DIRNAME=.
29
+ @rem This is normally unused
29
30
  set APP_BASE_NAME=%~n0
30
31
  set APP_HOME=%DIRNAME%
31
32
 
@@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
40
41
 
41
42
  set JAVA_EXE=java.exe
42
43
  %JAVA_EXE% -version >NUL 2>&1
43
- if "%ERRORLEVEL%" == "0" goto execute
44
+ if %ERRORLEVEL% equ 0 goto execute
44
45
 
45
- echo.
46
- echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47
- echo.
48
- echo Please set the JAVA_HOME variable in your environment to match the
49
- echo location of your Java installation.
46
+ echo. 1>&2
47
+ echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
48
+ echo. 1>&2
49
+ echo Please set the JAVA_HOME variable in your environment to match the 1>&2
50
+ echo location of your Java installation. 1>&2
50
51
 
51
52
  goto fail
52
53
 
@@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56
57
 
57
58
  if exist "%JAVA_EXE%" goto execute
58
59
 
59
- echo.
60
- echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61
- echo.
62
- echo Please set the JAVA_HOME variable in your environment to match the
63
- echo location of your Java installation.
60
+ echo. 1>&2
61
+ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
62
+ echo. 1>&2
63
+ echo Please set the JAVA_HOME variable in your environment to match the 1>&2
64
+ echo location of your Java installation. 1>&2
64
65
 
65
66
  goto fail
66
67
 
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
75
76
 
76
77
  :end
77
78
  @rem End local scope for the variables with windows NT shell
78
- if "%ERRORLEVEL%"=="0" goto mainEnd
79
+ if %ERRORLEVEL% equ 0 goto mainEnd
79
80
 
80
81
  :fail
81
82
  rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82
83
  rem the _cmd.exe /c_ return code!
83
- if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84
- exit /b 1
84
+ set EXIT_CODE=%ERRORLEVEL%
85
+ if %EXIT_CODE% equ 0 set EXIT_CODE=1
86
+ if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87
+ exit /b %EXIT_CODE%
85
88
 
86
89
  :mainEnd
87
90
  if "%OS%"=="Windows_NT" endlocal
@@ -11,6 +11,17 @@ import org.webrtc.audio.JavaAudioDeviceModule
11
11
 
12
12
  object LiveKitReactNative {
13
13
 
14
+ private lateinit var adm: JavaAudioDeviceModule
15
+
16
+ val audioDeviceModule: JavaAudioDeviceModule
17
+ get() {
18
+ if(!::adm.isInitialized) {
19
+ throw IllegalStateException("Audio device module is not initialized! Did you remember to call LiveKitReactNative.setup in your Application.onCreate?")
20
+ }
21
+
22
+ return adm
23
+ }
24
+
14
25
  /**
15
26
  * Initializes components required for LiveKit to work on Android.
16
27
  *
@@ -26,10 +37,12 @@ object LiveKitReactNative {
26
37
 
27
38
  val useHardwareAudioProcessing = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
28
39
 
29
- options.audioDeviceModule = JavaAudioDeviceModule.builder(context)
40
+ adm = JavaAudioDeviceModule.builder(context)
30
41
  .setUseHardwareAcousticEchoCanceler(useHardwareAudioProcessing)
31
42
  .setUseHardwareNoiseSuppressor(useHardwareAudioProcessing)
32
43
  .setAudioAttributes(audioType.audioAttributes)
33
44
  .createAudioDeviceModule()
45
+
46
+ options.audioDeviceModule = adm
34
47
  }
35
48
  }
@@ -2,10 +2,12 @@ package com.livekit.reactnative
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
+ import android.media.AudioAttributes
5
6
  import com.facebook.react.bridge.*
6
7
  import com.livekit.reactnative.audio.AudioDeviceKind
7
8
  import com.livekit.reactnative.audio.AudioManagerUtils
8
9
  import com.livekit.reactnative.audio.AudioSwitchManager
10
+ import org.webrtc.audio.WebRtcAudioTrackHelper
9
11
 
10
12
 
11
13
  class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
@@ -32,6 +34,10 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
32
34
  if (androidConfig.hasKey("audioTypeOptions")) {
33
35
  val audioTypeOptions = androidConfig.getMap("audioTypeOptions") ?: return
34
36
 
37
+ val adm = LiveKitReactNative.audioDeviceModule
38
+ val oldAudioAttributes = WebRtcAudioTrackHelper.getAudioOutputAttributes(adm)
39
+ val attributesBuilder = AudioAttributes.Builder(oldAudioAttributes)
40
+
35
41
  if (audioTypeOptions.hasKey("manageAudioFocus")) {
36
42
  val manageFocus = audioTypeOptions.getBoolean("manageAudioFocus")
37
43
  audioManager.setManageAudioFocus(manageFocus)
@@ -68,6 +74,7 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
68
74
  val usageType = AudioManagerUtils.audioAttributesUsageTypeFromString(usageTypeString)
69
75
  if (usageType != null) {
70
76
  audioManager.setAudioAttributesUsageType(usageType)
77
+ attributesBuilder.setUsage(usageType)
71
78
  }
72
79
  }
73
80
  }
@@ -77,6 +84,7 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
77
84
  val contentType = AudioManagerUtils.audioAttributesContentTypeFromString(contentTypeString)
78
85
  if (contentType != null) {
79
86
  audioManager.setAudioAttributesContentType(contentType)
87
+ attributesBuilder.setContentType(contentType)
80
88
  }
81
89
  }
82
90
  }
@@ -85,6 +93,8 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
85
93
  val force = audioTypeOptions.getBoolean("forceHandleAudioRouting")
86
94
  audioManager.setForceHandleAudioRouting(force)
87
95
  }
96
+
97
+ WebRtcAudioTrackHelper.setAudioOutputAttributes(adm, attributesBuilder.build())
88
98
  }
89
99
  }
90
100
 
@@ -181,8 +181,8 @@ open class SimulcastVideoEncoderFactoryWrapper(
181
181
  return future.get()
182
182
  }
183
183
 
184
- override fun createNativeVideoEncoder(): Long {
185
- val future = executor.submit(Callable { return@Callable encoder.createNativeVideoEncoder() })
184
+ override fun createNative(webrtcEnvRef: Long): Long {
185
+ val future = executor.submit(Callable { return@Callable encoder.createNative(webrtcEnvRef) })
186
186
  return future.get()
187
187
  }
188
188
 
@@ -0,0 +1,20 @@
1
+ package org.webrtc.audio
2
+
3
+ import android.media.AudioAttributes
4
+
5
+ object WebRtcAudioTrackHelper {
6
+
7
+ fun getAudioOutputAttributes(adm: JavaAudioDeviceModule): AudioAttributes {
8
+ return adm.audioOutput.audioAttributes ?: AudioAttributes.Builder()
9
+ .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
10
+ .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
11
+ .build()
12
+ }
13
+
14
+ fun setAudioOutputAttributes(
15
+ adm: JavaAudioDeviceModule,
16
+ audioAttributes: AudioAttributes,
17
+ ) {
18
+ adm.audioOutput.audioAttributes = audioAttributes
19
+ }
20
+ }
@@ -4,21 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.useIOSAudioManagement = useIOSAudioManagement;
7
-
8
7
  var _react = require("react");
9
-
10
8
  var _reactNative = require("react-native");
11
-
12
9
  var _livekitClient = require("livekit-client");
13
-
14
10
  var _AudioSession = _interopRequireWildcard(require("./AudioSession"));
15
-
16
11
  var _ = require("..");
17
-
18
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
-
20
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
-
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
13
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
22
14
  /**
23
15
  * Handles setting the appropriate AVAudioSession options automatically
24
16
  * depending on the audio track states of the Room.
@@ -27,9 +19,7 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
27
19
  * @param preferSpeakerOutput
28
20
  * @param onConfigureNativeAudio A custom method for determining options used.
29
21
  */
30
- function useIOSAudioManagement(room) {
31
- let preferSpeakerOutput = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
32
- let onConfigureNativeAudio = arguments.length > 2 ? arguments[2] : undefined;
22
+ function useIOSAudioManagement(room, preferSpeakerOutput = true, onConfigureNativeAudio) {
33
23
  const [localTrackCount, setLocalTrackCount] = (0, _react.useState)(0);
34
24
  const [remoteTrackCount, setRemoteTrackCount] = (0, _react.useState)(0);
35
25
  const trackState = (0, _react.useMemo)(() => computeAudioTrackState(localTrackCount, remoteTrackCount), [localTrackCount, remoteTrackCount]);
@@ -38,7 +28,6 @@ function useIOSAudioManagement(room) {
38
28
  setLocalTrackCount(getLocalAudioTrackCount(room));
39
29
  setRemoteTrackCount(getRemoteAudioTrackCount(room));
40
30
  };
41
-
42
31
  recalculateTrackCounts();
43
32
  room.on(_livekitClient.RoomEvent.Connected, recalculateTrackCounts);
44
33
  return () => {
@@ -49,31 +38,24 @@ function useIOSAudioManagement(room) {
49
38
  if (_reactNative.Platform.OS !== 'ios') {
50
39
  return () => {};
51
40
  }
52
-
53
41
  let onLocalPublished = () => {
54
42
  setLocalTrackCount(localTrackCount + 1);
55
43
  };
56
-
57
44
  let onLocalUnpublished = () => {
58
45
  if (localTrackCount - 1 < 0) {
59
46
  _.log.warn('mismatched local audio track count! attempted to reduce track count below zero.');
60
47
  }
61
-
62
48
  setLocalTrackCount(Math.max(localTrackCount - 1, 0));
63
49
  };
64
-
65
50
  let onRemotePublished = () => {
66
51
  setRemoteTrackCount(remoteTrackCount + 1);
67
52
  };
68
-
69
53
  let onRemoteUnpublished = () => {
70
54
  if (remoteTrackCount - 1 < 0) {
71
55
  _.log.warn('mismatched remote audio track count! attempted to reduce track count below zero.');
72
56
  }
73
-
74
57
  setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
75
58
  };
76
-
77
59
  room.on(_livekitClient.RoomEvent.LocalTrackPublished, onLocalPublished).on(_livekitClient.RoomEvent.LocalTrackUnpublished, onLocalUnpublished).on(_livekitClient.RoomEvent.TrackPublished, onRemotePublished).on(_livekitClient.RoomEvent.TrackUnpublished, onRemoteUnpublished);
78
60
  return () => {
79
61
  room.off(_livekitClient.RoomEvent.LocalTrackPublished, onLocalPublished).off(_livekitClient.RoomEvent.LocalTrackUnpublished, onLocalUnpublished).off(_livekitClient.RoomEvent.TrackPublished, onRemotePublished).off(_livekitClient.RoomEvent.TrackUnpublished, onRemoteUnpublished);
@@ -83,14 +65,11 @@ function useIOSAudioManagement(room) {
83
65
  if (_reactNative.Platform.OS !== 'ios') {
84
66
  return;
85
67
  }
86
-
87
- let configFunc = onConfigureNativeAudio !== null && onConfigureNativeAudio !== void 0 ? onConfigureNativeAudio : _AudioSession.getDefaultAppleAudioConfigurationForMode;
68
+ let configFunc = onConfigureNativeAudio ?? _AudioSession.getDefaultAppleAudioConfigurationForMode;
88
69
  let audioConfig = configFunc(trackState, preferSpeakerOutput);
89
-
90
70
  _AudioSession.default.setAppleAudioConfiguration(audioConfig);
91
71
  }, [trackState, onConfigureNativeAudio, preferSpeakerOutput]);
92
72
  }
93
-
94
73
  function computeAudioTrackState(localTracks, remoteTracks) {
95
74
  if (localTracks > 0 && remoteTracks > 0) {
96
75
  return 'localAndRemote';
@@ -102,11 +81,9 @@ function computeAudioTrackState(localTracks, remoteTracks) {
102
81
  return 'none';
103
82
  }
104
83
  }
105
-
106
84
  function getLocalAudioTrackCount(room) {
107
85
  return room.localParticipant.audioTrackPublications.size;
108
86
  }
109
-
110
87
  function getRemoteAudioTrackCount(room) {
111
88
  var audioTracks = 0;
112
89
  room.remoteParticipants.forEach(participant => {
@@ -1 +1 @@
1
- {"version":3,"sources":["AudioManager.ts"],"names":["useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","remoteTrackCount","setRemoteTrackCount","trackState","computeAudioTrackState","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","RoomEvent","Connected","off","Platform","OS","onLocalPublished","onLocalUnpublished","log","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","getDefaultAppleAudioConfigurationForMode","audioConfig","AudioSession","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"mappings":"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","sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport { RoomEvent, Room } from 'livekit-client';\nimport AudioSession, {\n getDefaultAppleAudioConfigurationForMode,\n type AppleAudioConfiguration,\n type AudioTrackState,\n} from './AudioSession';\nimport { log } from '..';\n\n/**\n * Handles setting the appropriate AVAudioSession options automatically\n * depending on the audio track states of the Room.\n *\n * @param room\n * @param preferSpeakerOutput\n * @param onConfigureNativeAudio A custom method for determining options used.\n */\nexport function useIOSAudioManagement(\n room: Room,\n preferSpeakerOutput: boolean = true,\n onConfigureNativeAudio?: (\n trackState: AudioTrackState,\n preferSpeakerOutput: boolean\n ) => AppleAudioConfiguration\n) {\n const [localTrackCount, setLocalTrackCount] = useState(0);\n const [remoteTrackCount, setRemoteTrackCount] = useState(0);\n const trackState = useMemo(\n () => computeAudioTrackState(localTrackCount, remoteTrackCount),\n [localTrackCount, remoteTrackCount]\n );\n\n useEffect(() => {\n let recalculateTrackCounts = () => {\n setLocalTrackCount(getLocalAudioTrackCount(room));\n setRemoteTrackCount(getRemoteAudioTrackCount(room));\n };\n\n recalculateTrackCounts();\n\n room.on(RoomEvent.Connected, recalculateTrackCounts);\n\n return () => {\n room.off(RoomEvent.Connected, recalculateTrackCounts);\n };\n }, [room]);\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return () => {};\n }\n\n let onLocalPublished = () => {\n setLocalTrackCount(localTrackCount + 1);\n };\n let onLocalUnpublished = () => {\n if (localTrackCount - 1 < 0) {\n log.warn(\n 'mismatched local audio track count! attempted to reduce track count below zero.'\n );\n }\n setLocalTrackCount(Math.max(localTrackCount - 1, 0));\n };\n let onRemotePublished = () => {\n setRemoteTrackCount(remoteTrackCount + 1);\n };\n let onRemoteUnpublished = () => {\n if (remoteTrackCount - 1 < 0) {\n log.warn(\n 'mismatched remote audio track count! attempted to reduce track count below zero.'\n );\n }\n setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));\n };\n\n room\n .on(RoomEvent.LocalTrackPublished, onLocalPublished)\n .on(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .on(RoomEvent.TrackPublished, onRemotePublished)\n .on(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n\n return () => {\n room\n .off(RoomEvent.LocalTrackPublished, onLocalPublished)\n .off(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .off(RoomEvent.TrackPublished, onRemotePublished)\n .off(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n };\n }, [room, localTrackCount, remoteTrackCount]);\n\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return;\n }\n\n let configFunc =\n onConfigureNativeAudio ?? getDefaultAppleAudioConfigurationForMode;\n let audioConfig = configFunc(trackState, preferSpeakerOutput);\n AudioSession.setAppleAudioConfiguration(audioConfig);\n }, [trackState, onConfigureNativeAudio, preferSpeakerOutput]);\n}\n\nfunction computeAudioTrackState(\n localTracks: number,\n remoteTracks: number\n): AudioTrackState {\n if (localTracks > 0 && remoteTracks > 0) {\n return 'localAndRemote';\n } else if (localTracks > 0 && remoteTracks === 0) {\n return 'localOnly';\n } else if (localTracks === 0 && remoteTracks > 0) {\n return 'remoteOnly';\n } else {\n return 'none';\n }\n}\n\nfunction getLocalAudioTrackCount(room: Room): number {\n return room.localParticipant.audioTrackPublications.size;\n}\n\nfunction getRemoteAudioTrackCount(room: Room): number {\n var audioTracks = 0;\n room.remoteParticipants.forEach((participant) => {\n audioTracks += participant.audioTrackPublications.size;\n });\n\n return audioTracks;\n}\n"]}
1
+ {"version":3,"names":["_react","require","_reactNative","_livekitClient","_AudioSession","_interopRequireWildcard","_","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","useState","remoteTrackCount","setRemoteTrackCount","trackState","useMemo","computeAudioTrackState","useEffect","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","RoomEvent","Connected","off","Platform","OS","onLocalPublished","onLocalUnpublished","log","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","getDefaultAppleAudioConfigurationForMode","audioConfig","AudioSession","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"sources":["AudioManager.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport { RoomEvent, Room } from 'livekit-client';\nimport AudioSession, {\n getDefaultAppleAudioConfigurationForMode,\n type AppleAudioConfiguration,\n type AudioTrackState,\n} from './AudioSession';\nimport { log } from '..';\n\n/**\n * Handles setting the appropriate AVAudioSession options automatically\n * depending on the audio track states of the Room.\n *\n * @param room\n * @param preferSpeakerOutput\n * @param onConfigureNativeAudio A custom method for determining options used.\n */\nexport function useIOSAudioManagement(\n room: Room,\n preferSpeakerOutput: boolean = true,\n onConfigureNativeAudio?: (\n trackState: AudioTrackState,\n preferSpeakerOutput: boolean\n ) => AppleAudioConfiguration\n) {\n const [localTrackCount, setLocalTrackCount] = useState(0);\n const [remoteTrackCount, setRemoteTrackCount] = useState(0);\n const trackState = useMemo(\n () => computeAudioTrackState(localTrackCount, remoteTrackCount),\n [localTrackCount, remoteTrackCount]\n );\n\n useEffect(() => {\n let recalculateTrackCounts = () => {\n setLocalTrackCount(getLocalAudioTrackCount(room));\n setRemoteTrackCount(getRemoteAudioTrackCount(room));\n };\n\n recalculateTrackCounts();\n\n room.on(RoomEvent.Connected, recalculateTrackCounts);\n\n return () => {\n room.off(RoomEvent.Connected, recalculateTrackCounts);\n };\n }, [room]);\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return () => {};\n }\n\n let onLocalPublished = () => {\n setLocalTrackCount(localTrackCount + 1);\n };\n let onLocalUnpublished = () => {\n if (localTrackCount - 1 < 0) {\n log.warn(\n 'mismatched local audio track count! attempted to reduce track count below zero.'\n );\n }\n setLocalTrackCount(Math.max(localTrackCount - 1, 0));\n };\n let onRemotePublished = () => {\n setRemoteTrackCount(remoteTrackCount + 1);\n };\n let onRemoteUnpublished = () => {\n if (remoteTrackCount - 1 < 0) {\n log.warn(\n 'mismatched remote audio track count! attempted to reduce track count below zero.'\n );\n }\n setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));\n };\n\n room\n .on(RoomEvent.LocalTrackPublished, onLocalPublished)\n .on(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .on(RoomEvent.TrackPublished, onRemotePublished)\n .on(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n\n return () => {\n room\n .off(RoomEvent.LocalTrackPublished, onLocalPublished)\n .off(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .off(RoomEvent.TrackPublished, onRemotePublished)\n .off(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n };\n }, [room, localTrackCount, remoteTrackCount]);\n\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return;\n }\n\n let configFunc =\n onConfigureNativeAudio ?? getDefaultAppleAudioConfigurationForMode;\n let audioConfig = configFunc(trackState, preferSpeakerOutput);\n AudioSession.setAppleAudioConfiguration(audioConfig);\n }, [trackState, onConfigureNativeAudio, preferSpeakerOutput]);\n}\n\nfunction computeAudioTrackState(\n localTracks: number,\n remoteTracks: number\n): AudioTrackState {\n if (localTracks > 0 && remoteTracks > 0) {\n return 'localAndRemote';\n } else if (localTracks > 0 && remoteTracks === 0) {\n return 'localOnly';\n } else if (localTracks === 0 && remoteTracks > 0) {\n return 'remoteOnly';\n } else {\n return 'none';\n }\n}\n\nfunction getLocalAudioTrackCount(room: Room): number {\n return room.localParticipant.audioTrackPublications.size;\n}\n\nfunction getRemoteAudioTrackCount(room: Room): number {\n var audioTracks = 0;\n room.remoteParticipants.forEach((participant) => {\n audioTracks += participant.audioTrackPublications.size;\n });\n\n return audioTracks;\n}\n"],"mappings":"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","ignoreList":[]}